[DO NOT MERGE] Revert "Fix broken make target launcher_protoutil_lib Bug:26406415"
am: 8363faf9a8 -s ours
* commit '8363faf9a885933aca2ced9bb1c6f9aa4a43c9f7':
[DO NOT MERGE] Revert "Fix broken make target launcher_protoutil_lib Bug:26406415"
diff --git a/Android.mk b/Android.mk
index ec675c6..77cfd0c 100644
--- a/Android.mk
+++ b/Android.mk
@@ -33,7 +33,7 @@
LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/WallpaperPicker/res \
$(LOCAL_PATH)/res \
- $(LOCAL_PATH)/../../../prebuilts/sdk/current/support/v7/recyclerview/res
+ prebuilts/sdk/current/support/v7/recyclerview/res
LOCAL_PROGUARD_FLAG_FILES := proguard.flags
@@ -64,7 +64,7 @@
LOCAL_MODULE := launcher_protoutil_lib
LOCAL_IS_HOST_MODULE := true
LOCAL_JAR_MANIFEST := util/etc/manifest.txt
-LOCAL_STATIC_JAVA_LIBRARIES := host-libprotobuf-java-2.3.0-nano
+LOCAL_STATIC_JAVA_LIBRARIES := host-libprotobuf-java-nano
include $(BUILD_HOST_JAVA_LIBRARY)
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 48dcf4e..990bde0 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -81,6 +81,7 @@
android:theme="@style/Theme"
android:windowSoftInputMode="adjustPan"
android:screenOrientation="nosensor"
+ android:configChanges="keyboard|keyboardHidden|navigation"
android:resumeWhilePausing="true"
android:taskAffinity=""
android:enabled="true">
@@ -92,39 +93,6 @@
</intent-filter>
</activity>
- <!-- ENABLE_FOR_TESTING
-
- <activity
- android:name="com.android.launcher3.testing.LauncherExtension"
- android:launchMode="singleTask"
- android:clearTaskOnLaunch="true"
- android:stateNotNeeded="true"
- android:theme="@style/Theme"
- android:windowSoftInputMode="adjustPan"
- android:screenOrientation="nosensor"
- android:enabled="false">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.HOME" />
- <category android:name="android.intent.category.DEFAULT" />
- <category android:name="android.intent.category.MONKEY"/>
- </intent-filter>
- </activity>
-
- -->
-
- <activity
- android:name="com.android.launcher3.ToggleWeightWatcher"
- android:label="@string/toggle_weight_watcher"
- android:enabled="@bool/debug_memory_enabled"
- android:icon="@mipmap/ic_launcher_home">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.DEFAULT" />
- <category android:name="android.intent.category.LAUNCHER" />
- </intent-filter>
- </activity>
-
<activity
android:name="com.android.launcher3.WallpaperPickerActivity"
android:theme="@style/Theme.WallpaperPicker"
@@ -159,27 +127,6 @@
android:process=":settings_process">
</activity>
- <!-- Debugging tools -->
- <activity
- android:name="com.android.launcher3.MemoryDumpActivity"
- android:theme="@android:style/Theme.NoDisplay"
- android:label="@string/debug_memory_activity"
- android:enabled="@bool/debug_memory_enabled"
- android:excludeFromRecents="true"
- android:icon="@mipmap/ic_launcher_home"
- >
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.DEFAULT" />
- <category android:name="android.intent.category.LAUNCHER" />
- </intent-filter>
- </activity>
-
- <service android:name="com.android.launcher3.MemoryTracker"
- android:enabled="@bool/debug_memory_enabled"
- >
- </service>
-
<receiver
android:name="com.android.launcher3.WallpaperChangedReceiver">
<intent-filter>
@@ -219,5 +166,54 @@
<meta-data android:name="android.nfc.disable_beam_default"
android:value="true" />
+
+ <!-- ENABLE_FOR_TESTING
+
+ <activity
+ android:name="com.android.launcher3.testing.LauncherExtension"
+ android:launchMode="singleTask"
+ android:clearTaskOnLaunch="true"
+ android:stateNotNeeded="true"
+ android:theme="@style/Theme"
+ android:windowSoftInputMode="adjustPan"
+ android:screenOrientation="nosensor"
+ >
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.HOME" />
+ <category android:name="android.intent.category.DEFAULT" />
+ <category android:name="android.intent.category.MONKEY"/>
+ </intent-filter>
+ </activity>
+
+ <activity
+ android:name="com.android.launcher3.testing.MemoryDumpActivity"
+ android:theme="@android:style/Theme.NoDisplay"
+ android:label="* HPROF"
+ android:excludeFromRecents="true"
+ android:icon="@mipmap/ic_launcher_home"
+ >
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.DEFAULT" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+
+ <activity
+ android:name="com.android.launcher3.testing.ToggleWeightWatcher"
+ android:label="Show Mem"
+ android:icon="@mipmap/ic_launcher_home">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.DEFAULT" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+
+ <service android:name="com.android.launcher3.testing.MemoryTracker" />
+
+ -->
+
</application>
</manifest>
diff --git a/WallpaperPicker/res/values-af/strings.xml b/WallpaperPicker/res/values-af/strings.xml
index eb81640..bc87fe1 100644
--- a/WallpaperPicker/res/values-af/strings.xml
+++ b/WallpaperPicker/res/values-af/strings.xml
@@ -22,6 +22,7 @@
<string name="wallpaper_instructions" msgid="3524143401182707094">"Stel muurpapier"</string>
<string name="image_load_fail" msgid="7538534580694411837">"Kon nie prent laai nie"</string>
<string name="wallpaper_load_fail" msgid="4800700444605404650">"Kon nie prent as muurpapier laai nie"</string>
+ <string name="wallpaper_set_fail" msgid="7023180794008631780">"Kon nie prent as muurpapier stel nie"</string>
<plurals name="number_of_items_selected">
<item quantity="zero" msgid="9015111147509924344">"%1$d gekies"</item>
<item quantity="one" msgid="8409622005831789373">"%1$d gekies"</item>
diff --git a/WallpaperPicker/res/values-am/strings.xml b/WallpaperPicker/res/values-am/strings.xml
index 7e79385..23bf538 100644
--- a/WallpaperPicker/res/values-am/strings.xml
+++ b/WallpaperPicker/res/values-am/strings.xml
@@ -22,6 +22,7 @@
<string name="wallpaper_instructions" msgid="3524143401182707094">"ልጣፍ አዘጋጅ"</string>
<string name="image_load_fail" msgid="7538534580694411837">"ምስሉን መጫን አልተቻለም"</string>
<string name="wallpaper_load_fail" msgid="4800700444605404650">"ምስሉን እንደ ግድግዳ ወረቀት መጫን አልተቻለም"</string>
+ <string name="wallpaper_set_fail" msgid="7023180794008631780">"ምስሉን እንደ ግድግዳ ወረቀት ማዘጋጀት አልተቻለም"</string>
<plurals name="number_of_items_selected">
<item quantity="zero" msgid="9015111147509924344">"%1$d ተመርጧል"</item>
<item quantity="one" msgid="8409622005831789373">"%1$d ተመርጧል"</item>
diff --git a/WallpaperPicker/res/values-ar/strings.xml b/WallpaperPicker/res/values-ar/strings.xml
index 84fa104..db6834c 100644
--- a/WallpaperPicker/res/values-ar/strings.xml
+++ b/WallpaperPicker/res/values-ar/strings.xml
@@ -22,6 +22,7 @@
<string name="wallpaper_instructions" msgid="3524143401182707094">"تعيين الخلفية"</string>
<string name="image_load_fail" msgid="7538534580694411837">"تعذر تحميل الصورة"</string>
<string name="wallpaper_load_fail" msgid="4800700444605404650">"تعذر تحميل الصورة كخلفية"</string>
+ <string name="wallpaper_set_fail" msgid="7023180794008631780">"تعذر تعيين الصورة كخلفية"</string>
<plurals name="number_of_items_selected">
<item quantity="zero" msgid="9015111147509924344">"تم تحديد %1$d"</item>
<item quantity="one" msgid="8409622005831789373">"تم تحديد %1$d"</item>
diff --git a/WallpaperPicker/res/values-bg/strings.xml b/WallpaperPicker/res/values-bg/strings.xml
index 60ae302..bf2a83b 100644
--- a/WallpaperPicker/res/values-bg/strings.xml
+++ b/WallpaperPicker/res/values-bg/strings.xml
@@ -22,6 +22,7 @@
<string name="wallpaper_instructions" msgid="3524143401182707094">"Задаване на тапета"</string>
<string name="image_load_fail" msgid="7538534580694411837">"Изображението не можа да бъде заредено"</string>
<string name="wallpaper_load_fail" msgid="4800700444605404650">"Изображението не можа да бъде заредено като тапет"</string>
+ <string name="wallpaper_set_fail" msgid="7023180794008631780">"Изображението не можа да бъде зададено като тапет"</string>
<plurals name="number_of_items_selected">
<item quantity="zero" msgid="9015111147509924344">"Избрахте %1$d"</item>
<item quantity="one" msgid="8409622005831789373">"Избрахте %1$d"</item>
diff --git a/WallpaperPicker/res/values-bn-rBD/strings.xml b/WallpaperPicker/res/values-bn-rBD/strings.xml
index 74d7e57..1c4d3d4 100644
--- a/WallpaperPicker/res/values-bn-rBD/strings.xml
+++ b/WallpaperPicker/res/values-bn-rBD/strings.xml
@@ -22,6 +22,7 @@
<string name="wallpaper_instructions" msgid="3524143401182707094">"ওয়ালপেপার সেট করুন"</string>
<string name="image_load_fail" msgid="7538534580694411837">"চিত্র লোড করা যায়নি"</string>
<string name="wallpaper_load_fail" msgid="4800700444605404650">"ওয়ালপেপার হিসাবে চিত্র লোড করা যায়নি"</string>
+ <string name="wallpaper_set_fail" msgid="7023180794008631780">"ওয়ালপেপার হিসাবে চিত্র সেট করা যায়নি"</string>
<plurals name="number_of_items_selected">
<item quantity="zero" msgid="9015111147509924344">"%1$dটি নির্বাচন করা হয়েছে"</item>
<item quantity="one" msgid="8409622005831789373">"%1$dটি নির্বাচন করা হয়েছে"</item>
diff --git a/WallpaperPicker/res/values-ca/strings.xml b/WallpaperPicker/res/values-ca/strings.xml
index cbec762..9533ae9 100644
--- a/WallpaperPicker/res/values-ca/strings.xml
+++ b/WallpaperPicker/res/values-ca/strings.xml
@@ -22,6 +22,7 @@
<string name="wallpaper_instructions" msgid="3524143401182707094">"Estableix el fons de pantalla"</string>
<string name="image_load_fail" msgid="7538534580694411837">"No s\'ha pogut carregar la imatge."</string>
<string name="wallpaper_load_fail" msgid="4800700444605404650">"No s\'ha pogut carregar la imatge com a fons de pantalla."</string>
+ <string name="wallpaper_set_fail" msgid="7023180794008631780">"No s\'ha pogut definir la imatge com a fons de pantalla"</string>
<plurals name="number_of_items_selected">
<item quantity="zero" msgid="9015111147509924344">"Seleccionats: %1$d"</item>
<item quantity="one" msgid="8409622005831789373">"Seleccionats: %1$d"</item>
diff --git a/WallpaperPicker/res/values-cs/strings.xml b/WallpaperPicker/res/values-cs/strings.xml
index da0758e..aab8cc8 100644
--- a/WallpaperPicker/res/values-cs/strings.xml
+++ b/WallpaperPicker/res/values-cs/strings.xml
@@ -22,6 +22,7 @@
<string name="wallpaper_instructions" msgid="3524143401182707094">"Nastavit jako tapetu"</string>
<string name="image_load_fail" msgid="7538534580694411837">"Obrázek nelze načíst."</string>
<string name="wallpaper_load_fail" msgid="4800700444605404650">"Obrázek nelze načíst jako tapetu."</string>
+ <string name="wallpaper_set_fail" msgid="7023180794008631780">"Obrázek nelze nastavit jako tapetu"</string>
<plurals name="number_of_items_selected">
<item quantity="zero" msgid="9015111147509924344">"Vybráno: %1$d"</item>
<item quantity="one" msgid="8409622005831789373">"Vybráno: %1$d"</item>
diff --git a/WallpaperPicker/res/values-da/strings.xml b/WallpaperPicker/res/values-da/strings.xml
index 12c0fe8..10ef5b3 100644
--- a/WallpaperPicker/res/values-da/strings.xml
+++ b/WallpaperPicker/res/values-da/strings.xml
@@ -22,6 +22,7 @@
<string name="wallpaper_instructions" msgid="3524143401182707094">"Angiv baggrund"</string>
<string name="image_load_fail" msgid="7538534580694411837">"Billedet kunne ikke indlæses"</string>
<string name="wallpaper_load_fail" msgid="4800700444605404650">"Billedet kunne ikke indlæses som baggrund"</string>
+ <string name="wallpaper_set_fail" msgid="7023180794008631780">"Billedet kunne ikke indlæses som baggrund"</string>
<plurals name="number_of_items_selected">
<item quantity="zero" msgid="9015111147509924344">"%1$d er valgt"</item>
<item quantity="one" msgid="8409622005831789373">"%1$d er valgt"</item>
diff --git a/WallpaperPicker/res/values-de/strings.xml b/WallpaperPicker/res/values-de/strings.xml
index 3171b3f..be35b73 100644
--- a/WallpaperPicker/res/values-de/strings.xml
+++ b/WallpaperPicker/res/values-de/strings.xml
@@ -22,6 +22,7 @@
<string name="wallpaper_instructions" msgid="3524143401182707094">"Hintergrund auswählen"</string>
<string name="image_load_fail" msgid="7538534580694411837">"Bild konnte nicht geladen werden."</string>
<string name="wallpaper_load_fail" msgid="4800700444605404650">"Bild konnte nicht als Hintergrund geladen werden."</string>
+ <string name="wallpaper_set_fail" msgid="7023180794008631780">"Bild konnte nicht als Hintergrund festgelegt werden."</string>
<plurals name="number_of_items_selected">
<item quantity="zero" msgid="9015111147509924344">"%1$d ausgewählt"</item>
<item quantity="one" msgid="8409622005831789373">"%1$d ausgewählt"</item>
diff --git a/WallpaperPicker/res/values-el/strings.xml b/WallpaperPicker/res/values-el/strings.xml
index 2988bec..1d799a8 100644
--- a/WallpaperPicker/res/values-el/strings.xml
+++ b/WallpaperPicker/res/values-el/strings.xml
@@ -22,6 +22,7 @@
<string name="wallpaper_instructions" msgid="3524143401182707094">"Ορισμός ταπετσαρίας"</string>
<string name="image_load_fail" msgid="7538534580694411837">"Δεν ήταν δυνατή η φόρτωση της εικόνας"</string>
<string name="wallpaper_load_fail" msgid="4800700444605404650">"Δεν ήταν δυνατή η φόρτωση της εικόνας ως ταπετσαρία"</string>
+ <string name="wallpaper_set_fail" msgid="7023180794008631780">"Δεν ήταν δυνατός ο ορισμός της εικόνας ως ταπετσαρία"</string>
<plurals name="number_of_items_selected">
<item quantity="zero" msgid="9015111147509924344">"%1$d επιλεγμένα"</item>
<item quantity="one" msgid="8409622005831789373">"%1$d επιλεγμένα"</item>
diff --git a/WallpaperPicker/res/values-en-rAU/strings.xml b/WallpaperPicker/res/values-en-rAU/strings.xml
index 30450ee..a384ff6 100644
--- a/WallpaperPicker/res/values-en-rAU/strings.xml
+++ b/WallpaperPicker/res/values-en-rAU/strings.xml
@@ -22,6 +22,7 @@
<string name="wallpaper_instructions" msgid="3524143401182707094">"Set wallpaper"</string>
<string name="image_load_fail" msgid="7538534580694411837">"Couldn\'t load image"</string>
<string name="wallpaper_load_fail" msgid="4800700444605404650">"Couldn\'t load image as wallpaper"</string>
+ <string name="wallpaper_set_fail" msgid="7023180794008631780">"Couldn\'t set image as wallpaper"</string>
<plurals name="number_of_items_selected">
<item quantity="zero" msgid="9015111147509924344">"%1$d selected"</item>
<item quantity="one" msgid="8409622005831789373">"%1$d selected"</item>
diff --git a/WallpaperPicker/res/values-en-rGB/strings.xml b/WallpaperPicker/res/values-en-rGB/strings.xml
index 30450ee..a384ff6 100644
--- a/WallpaperPicker/res/values-en-rGB/strings.xml
+++ b/WallpaperPicker/res/values-en-rGB/strings.xml
@@ -22,6 +22,7 @@
<string name="wallpaper_instructions" msgid="3524143401182707094">"Set wallpaper"</string>
<string name="image_load_fail" msgid="7538534580694411837">"Couldn\'t load image"</string>
<string name="wallpaper_load_fail" msgid="4800700444605404650">"Couldn\'t load image as wallpaper"</string>
+ <string name="wallpaper_set_fail" msgid="7023180794008631780">"Couldn\'t set image as wallpaper"</string>
<plurals name="number_of_items_selected">
<item quantity="zero" msgid="9015111147509924344">"%1$d selected"</item>
<item quantity="one" msgid="8409622005831789373">"%1$d selected"</item>
diff --git a/WallpaperPicker/res/values-en-rIN/strings.xml b/WallpaperPicker/res/values-en-rIN/strings.xml
index 30450ee..a384ff6 100644
--- a/WallpaperPicker/res/values-en-rIN/strings.xml
+++ b/WallpaperPicker/res/values-en-rIN/strings.xml
@@ -22,6 +22,7 @@
<string name="wallpaper_instructions" msgid="3524143401182707094">"Set wallpaper"</string>
<string name="image_load_fail" msgid="7538534580694411837">"Couldn\'t load image"</string>
<string name="wallpaper_load_fail" msgid="4800700444605404650">"Couldn\'t load image as wallpaper"</string>
+ <string name="wallpaper_set_fail" msgid="7023180794008631780">"Couldn\'t set image as wallpaper"</string>
<plurals name="number_of_items_selected">
<item quantity="zero" msgid="9015111147509924344">"%1$d selected"</item>
<item quantity="one" msgid="8409622005831789373">"%1$d selected"</item>
diff --git a/WallpaperPicker/res/values-es-rUS/strings.xml b/WallpaperPicker/res/values-es-rUS/strings.xml
index c18ecb2..924ea56 100644
--- a/WallpaperPicker/res/values-es-rUS/strings.xml
+++ b/WallpaperPicker/res/values-es-rUS/strings.xml
@@ -22,6 +22,7 @@
<string name="wallpaper_instructions" msgid="3524143401182707094">"Establecer como fondo de pantalla"</string>
<string name="image_load_fail" msgid="7538534580694411837">"No se pudo cargar la imagen."</string>
<string name="wallpaper_load_fail" msgid="4800700444605404650">"No se pudo cargar la imagen como fondo de pantalla."</string>
+ <string name="wallpaper_set_fail" msgid="7023180794008631780">"No se pudo establecer la imagen como fondo de pantalla"</string>
<plurals name="number_of_items_selected">
<item quantity="zero" msgid="9015111147509924344">"%1$d seleccionado"</item>
<item quantity="one" msgid="8409622005831789373">"%1$d seleccionado"</item>
diff --git a/WallpaperPicker/res/values-es/strings.xml b/WallpaperPicker/res/values-es/strings.xml
index b7221af..8ecd3f4 100644
--- a/WallpaperPicker/res/values-es/strings.xml
+++ b/WallpaperPicker/res/values-es/strings.xml
@@ -22,6 +22,7 @@
<string name="wallpaper_instructions" msgid="3524143401182707094">"Establecer fondo"</string>
<string name="image_load_fail" msgid="7538534580694411837">"No se ha podido cargar la imagen"</string>
<string name="wallpaper_load_fail" msgid="4800700444605404650">"No se ha podido cargar la imagen como fondo de pantalla"</string>
+ <string name="wallpaper_set_fail" msgid="7023180794008631780">"No se ha podido establecer la imagen como fondo de pantalla"</string>
<plurals name="number_of_items_selected">
<item quantity="zero" msgid="9015111147509924344">"Seleccionados: %1$d"</item>
<item quantity="one" msgid="8409622005831789373">"Seleccionados: %1$d"</item>
diff --git a/WallpaperPicker/res/values-et-rEE/strings.xml b/WallpaperPicker/res/values-et-rEE/strings.xml
index 571a0ff..59ca770 100644
--- a/WallpaperPicker/res/values-et-rEE/strings.xml
+++ b/WallpaperPicker/res/values-et-rEE/strings.xml
@@ -22,6 +22,7 @@
<string name="wallpaper_instructions" msgid="3524143401182707094">"Määra taustapilt"</string>
<string name="image_load_fail" msgid="7538534580694411837">"Kujutist ei õnnestunud laadida"</string>
<string name="wallpaper_load_fail" msgid="4800700444605404650">"Kujutist ei õnnestunud taustapildina laadida"</string>
+ <string name="wallpaper_set_fail" msgid="7023180794008631780">"Kujutist ei õnnestunud taustapildiks määrata"</string>
<plurals name="number_of_items_selected">
<item quantity="zero" msgid="9015111147509924344">"Valitud on %1$d"</item>
<item quantity="one" msgid="8409622005831789373">"Valitud on %1$d"</item>
diff --git a/WallpaperPicker/res/values-eu-rES/strings.xml b/WallpaperPicker/res/values-eu-rES/strings.xml
index 45bf7a1..fb77b1a 100644
--- a/WallpaperPicker/res/values-eu-rES/strings.xml
+++ b/WallpaperPicker/res/values-eu-rES/strings.xml
@@ -22,6 +22,7 @@
<string name="wallpaper_instructions" msgid="3524143401182707094">"Ezarri horma-papera"</string>
<string name="image_load_fail" msgid="7538534580694411837">"Ezin izan da irudia kargatu"</string>
<string name="wallpaper_load_fail" msgid="4800700444605404650">"Ezin izan da irudia horma-paper gisa kargatu"</string>
+ <string name="wallpaper_set_fail" msgid="7023180794008631780">"Ezin izan da ezarri irudia horma-paper gisa"</string>
<plurals name="number_of_items_selected">
<item quantity="zero" msgid="9015111147509924344">"%1$d hautatuta"</item>
<item quantity="one" msgid="8409622005831789373">"%1$d hautatuta"</item>
diff --git a/WallpaperPicker/res/values-fa/strings.xml b/WallpaperPicker/res/values-fa/strings.xml
index 469ec12..da4b7a1 100644
--- a/WallpaperPicker/res/values-fa/strings.xml
+++ b/WallpaperPicker/res/values-fa/strings.xml
@@ -22,6 +22,7 @@
<string name="wallpaper_instructions" msgid="3524143401182707094">"تنظیم کاغذدیواری"</string>
<string name="image_load_fail" msgid="7538534580694411837">"تصویر بارگیری نشد"</string>
<string name="wallpaper_load_fail" msgid="4800700444605404650">"تصویر بهعنوان کاغذدیواری بارگیری نشد"</string>
+ <string name="wallpaper_set_fail" msgid="7023180794008631780">"تصویر بهعنوان کاغذدیواری تنظیم نشد"</string>
<plurals name="number_of_items_selected">
<item quantity="zero" msgid="9015111147509924344">"%1$d انتخاب شد"</item>
<item quantity="one" msgid="8409622005831789373">"%1$d انتخاب شد"</item>
diff --git a/WallpaperPicker/res/values-fi/strings.xml b/WallpaperPicker/res/values-fi/strings.xml
index c82d3e0..3c8f1f5 100644
--- a/WallpaperPicker/res/values-fi/strings.xml
+++ b/WallpaperPicker/res/values-fi/strings.xml
@@ -22,6 +22,7 @@
<string name="wallpaper_instructions" msgid="3524143401182707094">"Aseta taustakuva"</string>
<string name="image_load_fail" msgid="7538534580694411837">"Kuvan lataus epäonnistui"</string>
<string name="wallpaper_load_fail" msgid="4800700444605404650">"Kuvaa ei voitu ladata taustakuvaksi"</string>
+ <string name="wallpaper_set_fail" msgid="7023180794008631780">"Kuvan asettaminen taustakuvaksi epäonnistui."</string>
<plurals name="number_of_items_selected">
<item quantity="zero" msgid="9015111147509924344">"%1$d valittu"</item>
<item quantity="one" msgid="8409622005831789373">"%1$d valittu"</item>
diff --git a/WallpaperPicker/res/values-fr-rCA/strings.xml b/WallpaperPicker/res/values-fr-rCA/strings.xml
index 9256896..ba1d430 100644
--- a/WallpaperPicker/res/values-fr-rCA/strings.xml
+++ b/WallpaperPicker/res/values-fr-rCA/strings.xml
@@ -22,6 +22,7 @@
<string name="wallpaper_instructions" msgid="3524143401182707094">"Définir le fond d\'écran"</string>
<string name="image_load_fail" msgid="7538534580694411837">"Impossible de charger l\'image"</string>
<string name="wallpaper_load_fail" msgid="4800700444605404650">"Impossible de charger l\'image comme fond d\'écran"</string>
+ <string name="wallpaper_set_fail" msgid="7023180794008631780">"Impossible d\'utiliser l\'image comme fond d\'écran"</string>
<plurals name="number_of_items_selected">
<item quantity="zero" msgid="9015111147509924344">"%1$d sélectionné"</item>
<item quantity="one" msgid="8409622005831789373">"%1$d sélectionné"</item>
diff --git a/WallpaperPicker/res/values-fr/strings.xml b/WallpaperPicker/res/values-fr/strings.xml
index 479a7e4..9f3b525 100644
--- a/WallpaperPicker/res/values-fr/strings.xml
+++ b/WallpaperPicker/res/values-fr/strings.xml
@@ -22,6 +22,7 @@
<string name="wallpaper_instructions" msgid="3524143401182707094">"Définir comme fond d\'écran"</string>
<string name="image_load_fail" msgid="7538534580694411837">"Impossible de charger l\'image."</string>
<string name="wallpaper_load_fail" msgid="4800700444605404650">"Impossible de charger l\'image comme fond d\'écran."</string>
+ <string name="wallpaper_set_fail" msgid="7023180794008631780">"Impossible de définir l\'image comme fond d\'écran."</string>
<plurals name="number_of_items_selected">
<item quantity="zero" msgid="9015111147509924344">"%1$d élément sélectionné"</item>
<item quantity="one" msgid="8409622005831789373">"%1$d élément sélectionné"</item>
diff --git a/WallpaperPicker/res/values-gl-rES/strings.xml b/WallpaperPicker/res/values-gl-rES/strings.xml
index 0396b2f..5805489 100644
--- a/WallpaperPicker/res/values-gl-rES/strings.xml
+++ b/WallpaperPicker/res/values-gl-rES/strings.xml
@@ -22,6 +22,7 @@
<string name="wallpaper_instructions" msgid="3524143401182707094">"Establecer fondo de pantalla"</string>
<string name="image_load_fail" msgid="7538534580694411837">"Non se puido cargar a imaxe"</string>
<string name="wallpaper_load_fail" msgid="4800700444605404650">"Non se puido cargar a imaxe como fondo de pantalla"</string>
+ <string name="wallpaper_set_fail" msgid="7023180794008631780">"Non se puido definir a imaxe como fondo de pantalla"</string>
<plurals name="number_of_items_selected">
<item quantity="zero" msgid="9015111147509924344">"Seleccionaches %1$d"</item>
<item quantity="one" msgid="8409622005831789373">"Seleccionaches %1$d"</item>
diff --git a/WallpaperPicker/res/values-hi/strings.xml b/WallpaperPicker/res/values-hi/strings.xml
index 60834e1..6f610b5 100644
--- a/WallpaperPicker/res/values-hi/strings.xml
+++ b/WallpaperPicker/res/values-hi/strings.xml
@@ -22,6 +22,7 @@
<string name="wallpaper_instructions" msgid="3524143401182707094">"वॉलपेपर सेट करें"</string>
<string name="image_load_fail" msgid="7538534580694411837">"चित्र लोड नहीं किया जा सका"</string>
<string name="wallpaper_load_fail" msgid="4800700444605404650">"चित्र को वॉलपेपर के रूप में लोड नहीं किया जा सका"</string>
+ <string name="wallpaper_set_fail" msgid="7023180794008631780">"चित्र को वॉलपेपर के रूप में सेट नहीं किया जा सका"</string>
<plurals name="number_of_items_selected">
<item quantity="zero" msgid="9015111147509924344">"%1$d चयनित"</item>
<item quantity="one" msgid="8409622005831789373">"%1$d चयनित"</item>
diff --git a/WallpaperPicker/res/values-hr/strings.xml b/WallpaperPicker/res/values-hr/strings.xml
index 9ed702c..aaf5e1b 100644
--- a/WallpaperPicker/res/values-hr/strings.xml
+++ b/WallpaperPicker/res/values-hr/strings.xml
@@ -22,6 +22,7 @@
<string name="wallpaper_instructions" msgid="3524143401182707094">"Postavi pozadinu"</string>
<string name="image_load_fail" msgid="7538534580694411837">"Nije moguće učitati sliku"</string>
<string name="wallpaper_load_fail" msgid="4800700444605404650">"Nije moguće učitati sliku kao pozadinu"</string>
+ <string name="wallpaper_set_fail" msgid="7023180794008631780">"Postavljanje slike kao pozadine nije uspjelo"</string>
<plurals name="number_of_items_selected">
<item quantity="zero" msgid="9015111147509924344">"Odabrano je %1$d stavki"</item>
<item quantity="one" msgid="8409622005831789373">"Odabrana je %1$d stavka"</item>
diff --git a/WallpaperPicker/res/values-hu/strings.xml b/WallpaperPicker/res/values-hu/strings.xml
index d8b08fd..06c0952 100644
--- a/WallpaperPicker/res/values-hu/strings.xml
+++ b/WallpaperPicker/res/values-hu/strings.xml
@@ -22,6 +22,7 @@
<string name="wallpaper_instructions" msgid="3524143401182707094">"Háttérkép beállítása"</string>
<string name="image_load_fail" msgid="7538534580694411837">"A kép betöltése nem sikerült"</string>
<string name="wallpaper_load_fail" msgid="4800700444605404650">"A kép betöltése háttérképként nem sikerült"</string>
+ <string name="wallpaper_set_fail" msgid="7023180794008631780">"A kép beállítása háttérképként nem sikerült"</string>
<plurals name="number_of_items_selected">
<item quantity="zero" msgid="9015111147509924344">"%1$d kiválasztva"</item>
<item quantity="one" msgid="8409622005831789373">"%1$d kiválasztva"</item>
diff --git a/WallpaperPicker/res/values-hy-rAM/strings.xml b/WallpaperPicker/res/values-hy-rAM/strings.xml
index 027b841..f68d49f 100644
--- a/WallpaperPicker/res/values-hy-rAM/strings.xml
+++ b/WallpaperPicker/res/values-hy-rAM/strings.xml
@@ -22,6 +22,7 @@
<string name="wallpaper_instructions" msgid="3524143401182707094">"Սահմանել պաստառը"</string>
<string name="image_load_fail" msgid="7538534580694411837">"Չհաջողվեց բեռնել նկարը"</string>
<string name="wallpaper_load_fail" msgid="4800700444605404650">"Չհաջողվեց նկարը սահմանել որպես պաստառ"</string>
+ <string name="wallpaper_set_fail" msgid="7023180794008631780">"Չհաջողվեց նկարը դնել որպես պաստառ"</string>
<plurals name="number_of_items_selected">
<item quantity="zero" msgid="9015111147509924344">"%1$d ընտրված"</item>
<item quantity="one" msgid="8409622005831789373">"%1$d ընտրված"</item>
diff --git a/WallpaperPicker/res/values-in/strings.xml b/WallpaperPicker/res/values-in/strings.xml
index 9155452..634eb1f 100644
--- a/WallpaperPicker/res/values-in/strings.xml
+++ b/WallpaperPicker/res/values-in/strings.xml
@@ -22,6 +22,7 @@
<string name="wallpaper_instructions" msgid="3524143401182707094">"Setel wallpaper"</string>
<string name="image_load_fail" msgid="7538534580694411837">"Tidak dapat memuat gambar"</string>
<string name="wallpaper_load_fail" msgid="4800700444605404650">"Tidak dapat memuat gambar sebagai wallpaper"</string>
+ <string name="wallpaper_set_fail" msgid="7023180794008631780">"Tidak dapat menyetel gambar sebagai wallpaper"</string>
<plurals name="number_of_items_selected">
<item quantity="zero" msgid="9015111147509924344">"%1$d dipilih"</item>
<item quantity="one" msgid="8409622005831789373">"%1$d dipilih"</item>
diff --git a/WallpaperPicker/res/values-is-rIS/strings.xml b/WallpaperPicker/res/values-is-rIS/strings.xml
index 69e6cd4..eac44ec 100644
--- a/WallpaperPicker/res/values-is-rIS/strings.xml
+++ b/WallpaperPicker/res/values-is-rIS/strings.xml
@@ -22,6 +22,7 @@
<string name="wallpaper_instructions" msgid="3524143401182707094">"Velja veggfóður"</string>
<string name="image_load_fail" msgid="7538534580694411837">"Ekki var hægt að hlaða mynd"</string>
<string name="wallpaper_load_fail" msgid="4800700444605404650">"Ekki var hægt að hlaða mynd sem veggfóður"</string>
+ <string name="wallpaper_set_fail" msgid="7023180794008631780">"Ekki var hægt að nota mynd sem veggfóður"</string>
<plurals name="number_of_items_selected">
<item quantity="zero" msgid="9015111147509924344">"%1$d valin"</item>
<item quantity="one" msgid="8409622005831789373">"%1$d valið"</item>
diff --git a/WallpaperPicker/res/values-it/strings.xml b/WallpaperPicker/res/values-it/strings.xml
index f4d38d1..fdb0ce8 100644
--- a/WallpaperPicker/res/values-it/strings.xml
+++ b/WallpaperPicker/res/values-it/strings.xml
@@ -22,6 +22,7 @@
<string name="wallpaper_instructions" msgid="3524143401182707094">"Imposta sfondo"</string>
<string name="image_load_fail" msgid="7538534580694411837">"Impossibile caricare l\'immagine"</string>
<string name="wallpaper_load_fail" msgid="4800700444605404650">"Impossibile caricare l\'immagine come sfondo"</string>
+ <string name="wallpaper_set_fail" msgid="7023180794008631780">"Impossibile impostare l\'immagine come sfondo"</string>
<plurals name="number_of_items_selected">
<item quantity="zero" msgid="9015111147509924344">"%1$d selezionati"</item>
<item quantity="one" msgid="8409622005831789373">"%1$d selezionato"</item>
diff --git a/WallpaperPicker/res/values-iw/strings.xml b/WallpaperPicker/res/values-iw/strings.xml
index e29f237..c6a583d 100644
--- a/WallpaperPicker/res/values-iw/strings.xml
+++ b/WallpaperPicker/res/values-iw/strings.xml
@@ -22,6 +22,7 @@
<string name="wallpaper_instructions" msgid="3524143401182707094">"הגדר טפט"</string>
<string name="image_load_fail" msgid="7538534580694411837">"לא ניתן היה לטעון את התמונה"</string>
<string name="wallpaper_load_fail" msgid="4800700444605404650">"לא ניתן היה לטעון את התמונה כטפט"</string>
+ <string name="wallpaper_set_fail" msgid="7023180794008631780">"לא ניתן היה להגדיר את התמונה כטפט"</string>
<plurals name="number_of_items_selected">
<item quantity="zero" msgid="9015111147509924344">"%1$d נבחרו"</item>
<item quantity="one" msgid="8409622005831789373">"%1$d נבחרו"</item>
diff --git a/WallpaperPicker/res/values-ja/strings.xml b/WallpaperPicker/res/values-ja/strings.xml
index e86026b..f18da5d 100644
--- a/WallpaperPicker/res/values-ja/strings.xml
+++ b/WallpaperPicker/res/values-ja/strings.xml
@@ -22,6 +22,7 @@
<string name="wallpaper_instructions" msgid="3524143401182707094">"壁紙を設定"</string>
<string name="image_load_fail" msgid="7538534580694411837">"画像を読み込めませんでした"</string>
<string name="wallpaper_load_fail" msgid="4800700444605404650">"画像を壁紙として読み込めませんでした"</string>
+ <string name="wallpaper_set_fail" msgid="7023180794008631780">"画像を壁紙として設定できませんでした"</string>
<plurals name="number_of_items_selected">
<item quantity="zero" msgid="9015111147509924344">"%1$d個選択済み"</item>
<item quantity="one" msgid="8409622005831789373">"%1$d個選択済み"</item>
diff --git a/WallpaperPicker/res/values-ka-rGE/strings.xml b/WallpaperPicker/res/values-ka-rGE/strings.xml
index 1ae1021..1f65282 100644
--- a/WallpaperPicker/res/values-ka-rGE/strings.xml
+++ b/WallpaperPicker/res/values-ka-rGE/strings.xml
@@ -22,6 +22,7 @@
<string name="wallpaper_instructions" msgid="3524143401182707094">"ფონის დაყენება"</string>
<string name="image_load_fail" msgid="7538534580694411837">"სურათი ვერ ჩაიტვირთა."</string>
<string name="wallpaper_load_fail" msgid="4800700444605404650">"სურათი ფონად ვერ ჩაიტვირთა."</string>
+ <string name="wallpaper_set_fail" msgid="7023180794008631780">"სურათი ფონად ვერ დაყენდა"</string>
<plurals name="number_of_items_selected">
<item quantity="zero" msgid="9015111147509924344">"არჩეულია %1$d"</item>
<item quantity="one" msgid="8409622005831789373">"არჩეულია %1$d"</item>
diff --git a/WallpaperPicker/res/values-kk-rKZ/strings.xml b/WallpaperPicker/res/values-kk-rKZ/strings.xml
index a10e273..6f4ee7c 100644
--- a/WallpaperPicker/res/values-kk-rKZ/strings.xml
+++ b/WallpaperPicker/res/values-kk-rKZ/strings.xml
@@ -22,6 +22,7 @@
<string name="wallpaper_instructions" msgid="3524143401182707094">"Тұсқағаз орнату"</string>
<string name="image_load_fail" msgid="7538534580694411837">"Суретті жүктей алмады"</string>
<string name="wallpaper_load_fail" msgid="4800700444605404650">"Суретті артқы фон ретінде жүктей алмады"</string>
+ <string name="wallpaper_set_fail" msgid="7023180794008631780">"Кескінді тұсқағаз ретінде орнату мүмкін болмады"</string>
<plurals name="number_of_items_selected">
<item quantity="zero" msgid="9015111147509924344">"%1$d таңдалған"</item>
<item quantity="one" msgid="8409622005831789373">"%1$d таңдалған"</item>
diff --git a/WallpaperPicker/res/values-km-rKH/strings.xml b/WallpaperPicker/res/values-km-rKH/strings.xml
index 2a605e8..801260d 100644
--- a/WallpaperPicker/res/values-km-rKH/strings.xml
+++ b/WallpaperPicker/res/values-km-rKH/strings.xml
@@ -22,6 +22,7 @@
<string name="wallpaper_instructions" msgid="3524143401182707094">"កំណត់ផ្ទាំងរូបភាព"</string>
<string name="image_load_fail" msgid="7538534580694411837">"មិនអាចផ្ទុករូបភាព"</string>
<string name="wallpaper_load_fail" msgid="4800700444605404650">"មិនអាចផ្ទុករូបភាពជាផ្ទាំងរូបភាព"</string>
+ <string name="wallpaper_set_fail" msgid="7023180794008631780">"មិនអាចកំណត់រូបភាពជាផ្ទាំងរូបភាពទេ"</string>
<plurals name="number_of_items_selected">
<item quantity="zero" msgid="9015111147509924344">"បានជ្រើស %1$d"</item>
<item quantity="one" msgid="8409622005831789373">"បានជ្រើស %1$d"</item>
diff --git a/WallpaperPicker/res/values-kn-rIN/strings.xml b/WallpaperPicker/res/values-kn-rIN/strings.xml
index b69bda5..7d4d7e7 100644
--- a/WallpaperPicker/res/values-kn-rIN/strings.xml
+++ b/WallpaperPicker/res/values-kn-rIN/strings.xml
@@ -22,6 +22,7 @@
<string name="wallpaper_instructions" msgid="3524143401182707094">"ವಾಲ್ಪೇಪರ್ ಹೊಂದಿಸಿ"</string>
<string name="image_load_fail" msgid="7538534580694411837">"ಚಿತ್ರವನ್ನು ಲೋಡ್ ಮಾಡಲು ಸಾಧ್ಯವಾಗಲಿಲ್ಲ"</string>
<string name="wallpaper_load_fail" msgid="4800700444605404650">"ಚಿತ್ರವನ್ನು ವಾಲ್ಪೇಪರ್ ರೂಪದಲ್ಲಿ ಲೋಡ್ ಮಾಡಲು ಸಾಧ್ಯವಾಗಲಿಲ್ಲ"</string>
+ <string name="wallpaper_set_fail" msgid="7023180794008631780">"ಚಿತ್ರವನ್ನು ವಾಲ್ಪೇಪರ್ ರೂಪದಲ್ಲಿ ಹೊಂದಿಸಲಾಗಲಿಲ್ಲ"</string>
<plurals name="number_of_items_selected">
<item quantity="zero" msgid="9015111147509924344">"%1$d ಅನ್ನು ಆಯ್ಕೆ ಮಾಡಲಾಗಿದೆ"</item>
<item quantity="one" msgid="8409622005831789373">"%1$d ಅನ್ನು ಆಯ್ಕೆ ಮಾಡಲಾಗಿದೆ"</item>
diff --git a/WallpaperPicker/res/values-ko/strings.xml b/WallpaperPicker/res/values-ko/strings.xml
index 30e7cfa..f407294 100644
--- a/WallpaperPicker/res/values-ko/strings.xml
+++ b/WallpaperPicker/res/values-ko/strings.xml
@@ -22,6 +22,7 @@
<string name="wallpaper_instructions" msgid="3524143401182707094">"배경화면 설정"</string>
<string name="image_load_fail" msgid="7538534580694411837">"이미지를 로드할 수 없습니다."</string>
<string name="wallpaper_load_fail" msgid="4800700444605404650">"이미지를 배경화면으로 로드할 수 없습니다."</string>
+ <string name="wallpaper_set_fail" msgid="7023180794008631780">"이미지를 배경화면으로 설정할 수 없습니다."</string>
<plurals name="number_of_items_selected">
<item quantity="zero" msgid="9015111147509924344">"%1$d개 선택됨"</item>
<item quantity="one" msgid="8409622005831789373">"%1$d개 선택됨"</item>
diff --git a/WallpaperPicker/res/values-ky-rKG/strings.xml b/WallpaperPicker/res/values-ky-rKG/strings.xml
index f1ebf09..f53f52b 100644
--- a/WallpaperPicker/res/values-ky-rKG/strings.xml
+++ b/WallpaperPicker/res/values-ky-rKG/strings.xml
@@ -22,6 +22,7 @@
<string name="wallpaper_instructions" msgid="3524143401182707094">"Тушкагаз орнотуу"</string>
<string name="image_load_fail" msgid="7538534580694411837">"Сүрөт жүктөө мүмкүн болбоду"</string>
<string name="wallpaper_load_fail" msgid="4800700444605404650">"Сүрөттү тушкагаз катары жүктөө кыйрады"</string>
+ <string name="wallpaper_set_fail" msgid="7023180794008631780">"Сүрөт тушкагаз катары коюлбай койду"</string>
<plurals name="number_of_items_selected">
<item quantity="zero" msgid="9015111147509924344">"%1$d тандалды"</item>
<item quantity="one" msgid="8409622005831789373">"%1$d тандалды"</item>
diff --git a/WallpaperPicker/res/values-lo-rLA/strings.xml b/WallpaperPicker/res/values-lo-rLA/strings.xml
index e32cafb..1da6d29 100644
--- a/WallpaperPicker/res/values-lo-rLA/strings.xml
+++ b/WallpaperPicker/res/values-lo-rLA/strings.xml
@@ -22,6 +22,7 @@
<string name="wallpaper_instructions" msgid="3524143401182707094">"ຕັ້ງເປັນພາບພື້ນຫຼັງ"</string>
<string name="image_load_fail" msgid="7538534580694411837">"ບໍ່ສາມາດໂຫຼດຮູບໄດ້"</string>
<string name="wallpaper_load_fail" msgid="4800700444605404650">"ບໍ່ສາມາດໂຫຼດຮູບເປັນພາບພື້ນຫຼັງໄດ້"</string>
+ <string name="wallpaper_set_fail" msgid="7023180794008631780">"ບໍ່ສາມາດໂຫຼດຮູບເປັນພາບພື້ນຫຼັງໄດ້"</string>
<plurals name="number_of_items_selected">
<item quantity="zero" msgid="9015111147509924344">"ເລືອກ %1$d"</item>
<item quantity="one" msgid="8409622005831789373">"ເລືອກ %1$d"</item>
diff --git a/WallpaperPicker/res/values-lt/strings.xml b/WallpaperPicker/res/values-lt/strings.xml
index c442e3a..98c9a36 100644
--- a/WallpaperPicker/res/values-lt/strings.xml
+++ b/WallpaperPicker/res/values-lt/strings.xml
@@ -22,6 +22,7 @@
<string name="wallpaper_instructions" msgid="3524143401182707094">"Nustatyti ekrano foną"</string>
<string name="image_load_fail" msgid="7538534580694411837">"Nepavyko įkelti vaizdo"</string>
<string name="wallpaper_load_fail" msgid="4800700444605404650">"Nepavyko įkelti vaizdo kaip ekrano fono"</string>
+ <string name="wallpaper_set_fail" msgid="7023180794008631780">"Nepavyko nustatyti vaizdo kaip ekrano fono"</string>
<plurals name="number_of_items_selected">
<item quantity="zero" msgid="9015111147509924344">"Pasirinkta: %1$d"</item>
<item quantity="one" msgid="8409622005831789373">"Pasirinkta: %1$d"</item>
diff --git a/WallpaperPicker/res/values-lv/strings.xml b/WallpaperPicker/res/values-lv/strings.xml
index d05a175..ff7876c 100644
--- a/WallpaperPicker/res/values-lv/strings.xml
+++ b/WallpaperPicker/res/values-lv/strings.xml
@@ -22,6 +22,7 @@
<string name="wallpaper_instructions" msgid="3524143401182707094">"Iestatīt fona tapeti"</string>
<string name="image_load_fail" msgid="7538534580694411837">"Nevarēja ielādēt attēlu."</string>
<string name="wallpaper_load_fail" msgid="4800700444605404650">"Nevarēja ielādēt attēlu kā fona tapeti."</string>
+ <string name="wallpaper_set_fail" msgid="7023180794008631780">"Nevarēja iestatīt attēlu kā fona tapeti."</string>
<plurals name="number_of_items_selected">
<item quantity="zero" msgid="9015111147509924344">"Atlasīts: %1$d"</item>
<item quantity="one" msgid="8409622005831789373">"Atlasīta: %1$d"</item>
diff --git a/WallpaperPicker/res/values-mk-rMK/strings.xml b/WallpaperPicker/res/values-mk-rMK/strings.xml
index f9e0963..13b38cd 100644
--- a/WallpaperPicker/res/values-mk-rMK/strings.xml
+++ b/WallpaperPicker/res/values-mk-rMK/strings.xml
@@ -22,6 +22,7 @@
<string name="wallpaper_instructions" msgid="3524143401182707094">"Подеси тапет"</string>
<string name="image_load_fail" msgid="7538534580694411837">"Сликата не можеше да се вчита"</string>
<string name="wallpaper_load_fail" msgid="4800700444605404650">"Сликата не можеше да се вчита како тапет"</string>
+ <string name="wallpaper_set_fail" msgid="7023180794008631780">"Сликата не може да се постави како тапет"</string>
<plurals name="number_of_items_selected">
<item quantity="zero" msgid="9015111147509924344">"Избрано %1$d"</item>
<item quantity="one" msgid="8409622005831789373">"Избрано %1$d"</item>
diff --git a/WallpaperPicker/res/values-ml-rIN/strings.xml b/WallpaperPicker/res/values-ml-rIN/strings.xml
index 6be771c..5831b36 100644
--- a/WallpaperPicker/res/values-ml-rIN/strings.xml
+++ b/WallpaperPicker/res/values-ml-rIN/strings.xml
@@ -22,6 +22,7 @@
<string name="wallpaper_instructions" msgid="3524143401182707094">"വാൾപേപ്പർ സജ്ജീകരിക്കുക"</string>
<string name="image_load_fail" msgid="7538534580694411837">"ചിത്രം ലോഡുചെയ്യാനായില്ല"</string>
<string name="wallpaper_load_fail" msgid="4800700444605404650">"വാൾപേപ്പറായി ചിത്രം ലോഡുചെയ്യാനായില്ല"</string>
+ <string name="wallpaper_set_fail" msgid="7023180794008631780">"വാൾപേപ്പറായി ചിത്രം ലോഡുചെയ്യാനായില്ല"</string>
<plurals name="number_of_items_selected">
<item quantity="zero" msgid="9015111147509924344">"%1$d തിരഞ്ഞെടുത്തു"</item>
<item quantity="one" msgid="8409622005831789373">"%1$d തിരഞ്ഞെടുത്തു"</item>
diff --git a/WallpaperPicker/res/values-mn-rMN/strings.xml b/WallpaperPicker/res/values-mn-rMN/strings.xml
index b88da5a..9995547 100644
--- a/WallpaperPicker/res/values-mn-rMN/strings.xml
+++ b/WallpaperPicker/res/values-mn-rMN/strings.xml
@@ -22,6 +22,7 @@
<string name="wallpaper_instructions" msgid="3524143401182707094">"Ханын зургийг тохируулах"</string>
<string name="image_load_fail" msgid="7538534580694411837">"Зургийг ачаалж чадсангүй"</string>
<string name="wallpaper_load_fail" msgid="4800700444605404650">"Зургийг ханын зураг болгож ачаалж чадсангүй"</string>
+ <string name="wallpaper_set_fail" msgid="7023180794008631780">"Зургийг ханын зураг болгож чадсангүй"</string>
<plurals name="number_of_items_selected">
<item quantity="zero" msgid="9015111147509924344">"%1$d сонгогдсон"</item>
<item quantity="one" msgid="8409622005831789373">"%1$d сонгогдсон"</item>
diff --git a/WallpaperPicker/res/values-mr-rIN/strings.xml b/WallpaperPicker/res/values-mr-rIN/strings.xml
index 128b21c..d740fd2 100644
--- a/WallpaperPicker/res/values-mr-rIN/strings.xml
+++ b/WallpaperPicker/res/values-mr-rIN/strings.xml
@@ -22,6 +22,7 @@
<string name="wallpaper_instructions" msgid="3524143401182707094">"वॉलपेपर सेट करा"</string>
<string name="image_load_fail" msgid="7538534580694411837">"प्रतिमा लोड करू शकलो नाही"</string>
<string name="wallpaper_load_fail" msgid="4800700444605404650">"वॉलपेपर म्हणून प्रतिमा लोड करू शकलो नाही"</string>
+ <string name="wallpaper_set_fail" msgid="7023180794008631780">"प्रतिमा वॉलपेपर म्हणून सेट करू शकलो नाही"</string>
<plurals name="number_of_items_selected">
<item quantity="zero" msgid="9015111147509924344">"%1$d निवडले"</item>
<item quantity="one" msgid="8409622005831789373">"%1$d निवडले"</item>
diff --git a/WallpaperPicker/res/values-ms-rMY/strings.xml b/WallpaperPicker/res/values-ms-rMY/strings.xml
index 9d824e4..759e48c 100644
--- a/WallpaperPicker/res/values-ms-rMY/strings.xml
+++ b/WallpaperPicker/res/values-ms-rMY/strings.xml
@@ -22,6 +22,7 @@
<string name="wallpaper_instructions" msgid="3524143401182707094">"Tetapkan kertas dinding"</string>
<string name="image_load_fail" msgid="7538534580694411837">"Tidak dapat memuatkan imej"</string>
<string name="wallpaper_load_fail" msgid="4800700444605404650">"Tidak dapat memuatkan imej sebagai kertas dinding"</string>
+ <string name="wallpaper_set_fail" msgid="7023180794008631780">"Tidak dapat menetapkan imej sebagai kertas dinding"</string>
<plurals name="number_of_items_selected">
<item quantity="zero" msgid="9015111147509924344">"%1$d dipilih"</item>
<item quantity="one" msgid="8409622005831789373">"%1$d dipilih"</item>
diff --git a/WallpaperPicker/res/values-my-rMM/strings.xml b/WallpaperPicker/res/values-my-rMM/strings.xml
index 2336114..5197b98 100644
--- a/WallpaperPicker/res/values-my-rMM/strings.xml
+++ b/WallpaperPicker/res/values-my-rMM/strings.xml
@@ -22,6 +22,7 @@
<string name="wallpaper_instructions" msgid="3524143401182707094">"နောက်ခံအား သတ်မှတ်ရန်"</string>
<string name="image_load_fail" msgid="7538534580694411837">"ပုံရိပ် တင် မရပါ"</string>
<string name="wallpaper_load_fail" msgid="4800700444605404650">"ပုံရိပ်အား နောက်ခံအဖြစ် တင် မရပါ"</string>
+ <string name="wallpaper_set_fail" msgid="7023180794008631780">"ပုံရိပ်အား နောက်ခံအဖြစ် တင်၍မရပါ"</string>
<plurals name="number_of_items_selected">
<item quantity="zero" msgid="9015111147509924344">"%1$d ရွေးချယ်ပြီး"</item>
<item quantity="one" msgid="8409622005831789373">"%1$d ရွေးချယ်ပြီး"</item>
diff --git a/WallpaperPicker/res/values-nb/strings.xml b/WallpaperPicker/res/values-nb/strings.xml
index 9ae0b98..8125b53 100644
--- a/WallpaperPicker/res/values-nb/strings.xml
+++ b/WallpaperPicker/res/values-nb/strings.xml
@@ -22,6 +22,7 @@
<string name="wallpaper_instructions" msgid="3524143401182707094">"Angi bakgrunn"</string>
<string name="image_load_fail" msgid="7538534580694411837">"Kunne ikke laste inn bildet"</string>
<string name="wallpaper_load_fail" msgid="4800700444605404650">"Kunne ikke laste inn bildet som bakgrunn"</string>
+ <string name="wallpaper_set_fail" msgid="7023180794008631780">"Kunne ikke angi bildet som bakgrunn"</string>
<plurals name="number_of_items_selected">
<item quantity="zero" msgid="9015111147509924344">"%1$d valgt"</item>
<item quantity="one" msgid="8409622005831789373">"%1$d valgt"</item>
diff --git a/WallpaperPicker/res/values-ne-rNP/strings.xml b/WallpaperPicker/res/values-ne-rNP/strings.xml
index 5bca8d8..b77a1c5 100644
--- a/WallpaperPicker/res/values-ne-rNP/strings.xml
+++ b/WallpaperPicker/res/values-ne-rNP/strings.xml
@@ -22,6 +22,7 @@
<string name="wallpaper_instructions" msgid="3524143401182707094">"वालपेपर मिलाउनुहोस्"</string>
<string name="image_load_fail" msgid="7538534580694411837">"तस्बिर लोड गर्न सकिएन"</string>
<string name="wallpaper_load_fail" msgid="4800700444605404650">"तस्बिरलाई वालपेपरका रूपमा लोड गर्न सकिएन"</string>
+ <string name="wallpaper_set_fail" msgid="7023180794008631780">"छविलाई वालपेपरको रूपमा सेट गर्न सकिएन"</string>
<plurals name="number_of_items_selected">
<item quantity="zero" msgid="9015111147509924344">"%1$d चयन भयो"</item>
<item quantity="one" msgid="8409622005831789373">"%1$d चयन भयो"</item>
diff --git a/WallpaperPicker/res/values-nl/strings.xml b/WallpaperPicker/res/values-nl/strings.xml
index a86f0f6..dc78305 100644
--- a/WallpaperPicker/res/values-nl/strings.xml
+++ b/WallpaperPicker/res/values-nl/strings.xml
@@ -22,6 +22,7 @@
<string name="wallpaper_instructions" msgid="3524143401182707094">"Achtergrond instellen"</string>
<string name="image_load_fail" msgid="7538534580694411837">"Kan afbeelding niet laden"</string>
<string name="wallpaper_load_fail" msgid="4800700444605404650">"Kan afbeelding niet laden als achtergrond"</string>
+ <string name="wallpaper_set_fail" msgid="7023180794008631780">"Kan afbeelding niet instellen als achtergrond"</string>
<plurals name="number_of_items_selected">
<item quantity="zero" msgid="9015111147509924344">"%1$d geselecteerd"</item>
<item quantity="one" msgid="8409622005831789373">"%1$d geselecteerd"</item>
diff --git a/WallpaperPicker/res/values-pl/strings.xml b/WallpaperPicker/res/values-pl/strings.xml
index cd52082..9693de4 100644
--- a/WallpaperPicker/res/values-pl/strings.xml
+++ b/WallpaperPicker/res/values-pl/strings.xml
@@ -22,6 +22,7 @@
<string name="wallpaper_instructions" msgid="3524143401182707094">"Ustaw tapetę"</string>
<string name="image_load_fail" msgid="7538534580694411837">"Nie udało się załadować obrazu"</string>
<string name="wallpaper_load_fail" msgid="4800700444605404650">"Nie udało się załadować obrazu jako tapety"</string>
+ <string name="wallpaper_set_fail" msgid="7023180794008631780">"Nie udało się ustawić obrazu jako tapety"</string>
<plurals name="number_of_items_selected">
<item quantity="zero" msgid="9015111147509924344">"Wybranych %1$d"</item>
<item quantity="one" msgid="8409622005831789373">"Wybrana %1$d"</item>
diff --git a/WallpaperPicker/res/values-pt-rPT/strings.xml b/WallpaperPicker/res/values-pt-rPT/strings.xml
index 82aa469..3c4fa9b 100644
--- a/WallpaperPicker/res/values-pt-rPT/strings.xml
+++ b/WallpaperPicker/res/values-pt-rPT/strings.xml
@@ -22,6 +22,7 @@
<string name="wallpaper_instructions" msgid="3524143401182707094">"Definir imagem fundo"</string>
<string name="image_load_fail" msgid="7538534580694411837">"Não foi possível carregar a imagem"</string>
<string name="wallpaper_load_fail" msgid="4800700444605404650">"Não foi possível carregar a imagem como imagem de fundo"</string>
+ <string name="wallpaper_set_fail" msgid="7023180794008631780">"Não foi possível definir a imagem como imagem de fundo"</string>
<plurals name="number_of_items_selected">
<item quantity="zero" msgid="9015111147509924344">"%1$d selecionadas"</item>
<item quantity="one" msgid="8409622005831789373">"%1$d selecionada"</item>
diff --git a/WallpaperPicker/res/values-pt/strings.xml b/WallpaperPicker/res/values-pt/strings.xml
index 74ff310..2520eed 100644
--- a/WallpaperPicker/res/values-pt/strings.xml
+++ b/WallpaperPicker/res/values-pt/strings.xml
@@ -22,6 +22,7 @@
<string name="wallpaper_instructions" msgid="3524143401182707094">"Definir plano de fundo"</string>
<string name="image_load_fail" msgid="7538534580694411837">"Não foi possível carregar a imagem"</string>
<string name="wallpaper_load_fail" msgid="4800700444605404650">"Não foi possível carregar a imagem como plano de fundo"</string>
+ <string name="wallpaper_set_fail" msgid="7023180794008631780">"Não foi possível definir a imagem como plano de fundo"</string>
<plurals name="number_of_items_selected">
<item quantity="zero" msgid="9015111147509924344">"%1$d selecionados"</item>
<item quantity="one" msgid="8409622005831789373">"%1$d selecionado"</item>
diff --git a/WallpaperPicker/res/values-ro/strings.xml b/WallpaperPicker/res/values-ro/strings.xml
index 6281b80..f5df3ee 100644
--- a/WallpaperPicker/res/values-ro/strings.xml
+++ b/WallpaperPicker/res/values-ro/strings.xml
@@ -22,6 +22,7 @@
<string name="wallpaper_instructions" msgid="3524143401182707094">"Setați imaginea de fundal"</string>
<string name="image_load_fail" msgid="7538534580694411837">"Nu s-a putut încărca imaginea"</string>
<string name="wallpaper_load_fail" msgid="4800700444605404650">"Nu s-a putut încărca imaginea ca fundal"</string>
+ <string name="wallpaper_set_fail" msgid="7023180794008631780">"Nu s-a putut seta ca imagine de fundal"</string>
<plurals name="number_of_items_selected">
<item quantity="zero" msgid="9015111147509924344">"%1$d selectate"</item>
<item quantity="one" msgid="8409622005831789373">"%1$d selectată"</item>
diff --git a/WallpaperPicker/res/values-ru/strings.xml b/WallpaperPicker/res/values-ru/strings.xml
index 959205a..f8c350a 100644
--- a/WallpaperPicker/res/values-ru/strings.xml
+++ b/WallpaperPicker/res/values-ru/strings.xml
@@ -22,6 +22,7 @@
<string name="wallpaper_instructions" msgid="3524143401182707094">"Установить как обои"</string>
<string name="image_load_fail" msgid="7538534580694411837">"Не удалось загрузить изображение"</string>
<string name="wallpaper_load_fail" msgid="4800700444605404650">"Не удалось загрузить изображение"</string>
+ <string name="wallpaper_set_fail" msgid="7023180794008631780">"Не удалось сменить обои"</string>
<plurals name="number_of_items_selected">
<item quantity="zero" msgid="9015111147509924344">"Выбрано: %1$d"</item>
<item quantity="one" msgid="8409622005831789373">"Выбрано: %1$d"</item>
diff --git a/WallpaperPicker/res/values-si-rLK/strings.xml b/WallpaperPicker/res/values-si-rLK/strings.xml
index 37ce1fc..3945bdf 100644
--- a/WallpaperPicker/res/values-si-rLK/strings.xml
+++ b/WallpaperPicker/res/values-si-rLK/strings.xml
@@ -22,6 +22,7 @@
<string name="wallpaper_instructions" msgid="3524143401182707094">"වෝල්පේපරය සකසන්න"</string>
<string name="image_load_fail" msgid="7538534580694411837">"පින්තූරය පූරණය කිරීමට නොහැකි විය"</string>
<string name="wallpaper_load_fail" msgid="4800700444605404650">"පින්තූරය වෝල්පේපරයක් ලෙස පූරණය කිරීමට නොහැකි විය"</string>
+ <string name="wallpaper_set_fail" msgid="7023180794008631780">"පින්තූරය බිතුපතක් ලෙස සැකසීමට නොහැකි විය"</string>
<plurals name="number_of_items_selected">
<item quantity="zero" msgid="9015111147509924344">"%1$d තෝරා ගන්නා ලදි"</item>
<item quantity="one" msgid="8409622005831789373">"%1$d තෝරා ගන්නා ලදි"</item>
diff --git a/WallpaperPicker/res/values-sk/strings.xml b/WallpaperPicker/res/values-sk/strings.xml
index 9d38de4..fb2c819 100644
--- a/WallpaperPicker/res/values-sk/strings.xml
+++ b/WallpaperPicker/res/values-sk/strings.xml
@@ -22,6 +22,7 @@
<string name="wallpaper_instructions" msgid="3524143401182707094">"Nastaviť tapetu"</string>
<string name="image_load_fail" msgid="7538534580694411837">"Obrázok nie je možné načítať"</string>
<string name="wallpaper_load_fail" msgid="4800700444605404650">"Obrázok nie je možné načítať ako tapetu"</string>
+ <string name="wallpaper_set_fail" msgid="7023180794008631780">"Obrázok nie je možné nastaviť ako tapetu"</string>
<plurals name="number_of_items_selected">
<item quantity="zero" msgid="9015111147509924344">"Počet vybratých položiek: %1$d"</item>
<item quantity="one" msgid="8409622005831789373">"Počet vybratých položiek: %1$d"</item>
diff --git a/WallpaperPicker/res/values-sl/strings.xml b/WallpaperPicker/res/values-sl/strings.xml
index e776cc7..a7ff089 100644
--- a/WallpaperPicker/res/values-sl/strings.xml
+++ b/WallpaperPicker/res/values-sl/strings.xml
@@ -22,6 +22,7 @@
<string name="wallpaper_instructions" msgid="3524143401182707094">"Nastavi ozadje"</string>
<string name="image_load_fail" msgid="7538534580694411837">"Slike ni bilo mogoče naložiti"</string>
<string name="wallpaper_load_fail" msgid="4800700444605404650">"Slike ni bilo mogoče naložiti kot ozadje"</string>
+ <string name="wallpaper_set_fail" msgid="7023180794008631780">"Slike ni bilo mogoče nastaviti kot ozadje"</string>
<plurals name="number_of_items_selected">
<item quantity="zero" msgid="9015111147509924344">"Št. izbranih: %1$d"</item>
<item quantity="one" msgid="8409622005831789373">"Št. izbranih: %1$d"</item>
diff --git a/WallpaperPicker/res/values-sr/strings.xml b/WallpaperPicker/res/values-sr/strings.xml
index c37bc06..6154526 100644
--- a/WallpaperPicker/res/values-sr/strings.xml
+++ b/WallpaperPicker/res/values-sr/strings.xml
@@ -22,6 +22,7 @@
<string name="wallpaper_instructions" msgid="3524143401182707094">"Подеси позадину"</string>
<string name="image_load_fail" msgid="7538534580694411837">"Није могуће учитати слику"</string>
<string name="wallpaper_load_fail" msgid="4800700444605404650">"Није могуће учитати слику као позадину"</string>
+ <string name="wallpaper_set_fail" msgid="7023180794008631780">"Учитавање слике као позадине није успело"</string>
<plurals name="number_of_items_selected">
<item quantity="zero" msgid="9015111147509924344">"Изабрано је %1$d"</item>
<item quantity="one" msgid="8409622005831789373">"Изабрана је %1$d"</item>
diff --git a/WallpaperPicker/res/values-sv/strings.xml b/WallpaperPicker/res/values-sv/strings.xml
index 044508b..38062b9 100644
--- a/WallpaperPicker/res/values-sv/strings.xml
+++ b/WallpaperPicker/res/values-sv/strings.xml
@@ -22,6 +22,7 @@
<string name="wallpaper_instructions" msgid="3524143401182707094">"Ange bakgrund"</string>
<string name="image_load_fail" msgid="7538534580694411837">"Det gick inte att läsa in bilden"</string>
<string name="wallpaper_load_fail" msgid="4800700444605404650">"Det gick inte att läsa in bilden som bakgrund"</string>
+ <string name="wallpaper_set_fail" msgid="7023180794008631780">"Det gick inte att ange bilden som bakgrund"</string>
<plurals name="number_of_items_selected">
<item quantity="zero" msgid="9015111147509924344">"%1$d har valts"</item>
<item quantity="one" msgid="8409622005831789373">"%1$d har valts"</item>
diff --git a/WallpaperPicker/res/values-sw/strings.xml b/WallpaperPicker/res/values-sw/strings.xml
index 367912a..729a79a 100644
--- a/WallpaperPicker/res/values-sw/strings.xml
+++ b/WallpaperPicker/res/values-sw/strings.xml
@@ -22,6 +22,7 @@
<string name="wallpaper_instructions" msgid="3524143401182707094">"Weka mandhari"</string>
<string name="image_load_fail" msgid="7538534580694411837">"Haikuweza kupakia picha"</string>
<string name="wallpaper_load_fail" msgid="4800700444605404650">"Haikuweza kupakia picha iwe mandhari"</string>
+ <string name="wallpaper_set_fail" msgid="7023180794008631780">"Haikuweza kuweka picha kuwa mandhari"</string>
<plurals name="number_of_items_selected">
<item quantity="zero" msgid="9015111147509924344">"%1$d zimechaguliwa"</item>
<item quantity="one" msgid="8409622005831789373">"%1$d zimechaguliwa"</item>
diff --git a/WallpaperPicker/res/values-sw720dp-v19/styles.xml b/WallpaperPicker/res/values-sw720dp-v19/styles.xml
deleted file mode 100644
index d8dab22..0000000
--- a/WallpaperPicker/res/values-sw720dp-v19/styles.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-* Copyright (C) 2013 The Android Open Source Project
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*/
--->
-
-<resources>
- <style name="Theme" parent="@android:style/Theme.DeviceDefault.Wallpaper.NoTitleBar">
- <item name="android:windowActionModeOverlay">true</item>
- <item name="android:windowTranslucentStatus">true</item>
- <item name="android:windowTranslucentNavigation">true</item>
- </style>
-</resources>
diff --git a/WallpaperPicker/res/values-sw720dp/styles.xml b/WallpaperPicker/res/values-sw720dp/styles.xml
index 12f8884..0058f7e 100644
--- a/WallpaperPicker/res/values-sw720dp/styles.xml
+++ b/WallpaperPicker/res/values-sw720dp/styles.xml
@@ -18,7 +18,11 @@
-->
<resources>
- <style name="Theme" parent="@android:style/Theme.DeviceDefault.Wallpaper.NoTitleBar">
+ <style name="BaseWallpaperTheme" parent="@android:style/Theme.DeviceDefault.Light.NoActionBar">
+ <item name="android:windowBackground">@android:color/transparent</item>
+ <item name="android:colorBackgroundCacheHint">@null</item>
+ <item name="android:windowShowWallpaper">true</item>
+ <item name="android:windowNoTitle">true</item>
<item name="android:windowActionModeOverlay">true</item>
</style>
</resources>
diff --git a/WallpaperPicker/res/values-ta-rIN/strings.xml b/WallpaperPicker/res/values-ta-rIN/strings.xml
index 7284da8..69a9d38 100644
--- a/WallpaperPicker/res/values-ta-rIN/strings.xml
+++ b/WallpaperPicker/res/values-ta-rIN/strings.xml
@@ -22,6 +22,7 @@
<string name="wallpaper_instructions" msgid="3524143401182707094">"வால்பேப்பரை அமை"</string>
<string name="image_load_fail" msgid="7538534580694411837">"படத்தை ஏற்ற முடியவில்லை"</string>
<string name="wallpaper_load_fail" msgid="4800700444605404650">"படத்தை வால்பேப்பராக ஏற்ற முடியவில்லை"</string>
+ <string name="wallpaper_set_fail" msgid="7023180794008631780">"படத்தை வால்பேப்பராக அமைக்க முடியவில்லை"</string>
<plurals name="number_of_items_selected">
<item quantity="zero" msgid="9015111147509924344">"%1$d தேர்ந்தெடுக்கப்பட்டன"</item>
<item quantity="one" msgid="8409622005831789373">"%1$d தேர்ந்தெடுக்கப்பட்டது"</item>
diff --git a/WallpaperPicker/res/values-te-rIN/strings.xml b/WallpaperPicker/res/values-te-rIN/strings.xml
index 4c5ad2f..6fb5fa2 100644
--- a/WallpaperPicker/res/values-te-rIN/strings.xml
+++ b/WallpaperPicker/res/values-te-rIN/strings.xml
@@ -22,6 +22,7 @@
<string name="wallpaper_instructions" msgid="3524143401182707094">"వాల్పేపర్ను సెట్ చేయి"</string>
<string name="image_load_fail" msgid="7538534580694411837">"చిత్రాన్ని లోడ్ చేయడం సాధ్యపడలేదు"</string>
<string name="wallpaper_load_fail" msgid="4800700444605404650">"చిత్రాన్ని వాల్పేపర్గా లోడ్ చేయడం సాధ్యపడలేదు"</string>
+ <string name="wallpaper_set_fail" msgid="7023180794008631780">"చిత్రాన్ని వాల్పేపర్గా సెట్ చేయడం సాధ్యపడలేదు"</string>
<plurals name="number_of_items_selected">
<item quantity="zero" msgid="9015111147509924344">"%1$d ఎంచుకోబడింది"</item>
<item quantity="one" msgid="8409622005831789373">"%1$d ఎంచుకోబడింది"</item>
diff --git a/WallpaperPicker/res/values-th/strings.xml b/WallpaperPicker/res/values-th/strings.xml
index b3d7a8b..c689436 100644
--- a/WallpaperPicker/res/values-th/strings.xml
+++ b/WallpaperPicker/res/values-th/strings.xml
@@ -22,6 +22,7 @@
<string name="wallpaper_instructions" msgid="3524143401182707094">"ตั้งวอลเปเปอร์"</string>
<string name="image_load_fail" msgid="7538534580694411837">"ไม่สามารถโหลดรูปภาพ"</string>
<string name="wallpaper_load_fail" msgid="4800700444605404650">"ไม่สามารถโหลดรูปภาพเป็นวอลเปเปอร์"</string>
+ <string name="wallpaper_set_fail" msgid="7023180794008631780">"ไม่สามารถตั้งรูปภาพเป็นวอลเปเปอร์"</string>
<plurals name="number_of_items_selected">
<item quantity="zero" msgid="9015111147509924344">"เลือกไว้ %1$d"</item>
<item quantity="one" msgid="8409622005831789373">"เลือกไว้ %1$d"</item>
diff --git a/WallpaperPicker/res/values-tl/strings.xml b/WallpaperPicker/res/values-tl/strings.xml
index db8f4d5..c760d7f 100644
--- a/WallpaperPicker/res/values-tl/strings.xml
+++ b/WallpaperPicker/res/values-tl/strings.xml
@@ -22,6 +22,7 @@
<string name="wallpaper_instructions" msgid="3524143401182707094">"Itakda ang wallpaper"</string>
<string name="image_load_fail" msgid="7538534580694411837">"Hindi ma-load ang larawan"</string>
<string name="wallpaper_load_fail" msgid="4800700444605404650">"Hindi ma-load ang larawan bilang wallpaper"</string>
+ <string name="wallpaper_set_fail" msgid="7023180794008631780">"Hindi maitakda ang larawan bilang wallpaper"</string>
<plurals name="number_of_items_selected">
<item quantity="zero" msgid="9015111147509924344">"%1$d ang napili"</item>
<item quantity="one" msgid="8409622005831789373">"%1$d ang napili"</item>
diff --git a/WallpaperPicker/res/values-tr/strings.xml b/WallpaperPicker/res/values-tr/strings.xml
index d1e57ed..e9dc1d2 100644
--- a/WallpaperPicker/res/values-tr/strings.xml
+++ b/WallpaperPicker/res/values-tr/strings.xml
@@ -22,6 +22,7 @@
<string name="wallpaper_instructions" msgid="3524143401182707094">"Duvar kağıdını ayarla"</string>
<string name="image_load_fail" msgid="7538534580694411837">"Resim yüklenemedi"</string>
<string name="wallpaper_load_fail" msgid="4800700444605404650">"Resim duvar kağıdı olarak yüklenemedi"</string>
+ <string name="wallpaper_set_fail" msgid="7023180794008631780">"Resim, duvar kağıdı olarak ayarlanamadı"</string>
<plurals name="number_of_items_selected">
<item quantity="zero" msgid="9015111147509924344">"%1$d tane seçildi"</item>
<item quantity="one" msgid="8409622005831789373">"%1$d tane seçildi"</item>
diff --git a/WallpaperPicker/res/values-uk/strings.xml b/WallpaperPicker/res/values-uk/strings.xml
index 756e7cf..c6669c0 100644
--- a/WallpaperPicker/res/values-uk/strings.xml
+++ b/WallpaperPicker/res/values-uk/strings.xml
@@ -22,6 +22,7 @@
<string name="wallpaper_instructions" msgid="3524143401182707094">"Установити фон"</string>
<string name="image_load_fail" msgid="7538534580694411837">"Не вдалося завантажити зображення"</string>
<string name="wallpaper_load_fail" msgid="4800700444605404650">"Не вдалося завантажити зображення як фоновий малюнок"</string>
+ <string name="wallpaper_set_fail" msgid="7023180794008631780">"Не вдалося зробити зображення фоновим малюнком"</string>
<plurals name="number_of_items_selected">
<item quantity="zero" msgid="9015111147509924344">"Вибрано %1$d"</item>
<item quantity="one" msgid="8409622005831789373">"Вибрано %1$d"</item>
diff --git a/WallpaperPicker/res/values-ur-rPK/strings.xml b/WallpaperPicker/res/values-ur-rPK/strings.xml
index 86d8163..e240e1a 100644
--- a/WallpaperPicker/res/values-ur-rPK/strings.xml
+++ b/WallpaperPicker/res/values-ur-rPK/strings.xml
@@ -22,6 +22,7 @@
<string name="wallpaper_instructions" msgid="3524143401182707094">"وال پیپر سیٹ کریں"</string>
<string name="image_load_fail" msgid="7538534580694411837">"تصویر کو لوڈ نہیں کیا جا سکا"</string>
<string name="wallpaper_load_fail" msgid="4800700444605404650">"تصویر کو وال پیپر کے بطور لوڈ نہیں کیا جا سکا"</string>
+ <string name="wallpaper_set_fail" msgid="7023180794008631780">"تصویر کو بطور وال پیپر سیٹ نہیں کیا جا سکا"</string>
<plurals name="number_of_items_selected">
<item quantity="zero" msgid="9015111147509924344">"%1$d کو منتخب کیا گیا"</item>
<item quantity="one" msgid="8409622005831789373">"%1$d کو منتخب کیا گیا"</item>
diff --git a/WallpaperPicker/res/values-uz-rUZ/strings.xml b/WallpaperPicker/res/values-uz-rUZ/strings.xml
index 97d3938..5a79981 100644
--- a/WallpaperPicker/res/values-uz-rUZ/strings.xml
+++ b/WallpaperPicker/res/values-uz-rUZ/strings.xml
@@ -22,6 +22,7 @@
<string name="wallpaper_instructions" msgid="3524143401182707094">"Fonga rasm o‘rnatish"</string>
<string name="image_load_fail" msgid="7538534580694411837">"Rasm yuklanmadi"</string>
<string name="wallpaper_load_fail" msgid="4800700444605404650">"Fon rasmi sifatida rasm yuklanmadi"</string>
+ <string name="wallpaper_set_fail" msgid="7023180794008631780">"Rasmni fon rasmi sifatida o‘rnatib bo‘lmadi"</string>
<plurals name="number_of_items_selected">
<item quantity="zero" msgid="9015111147509924344">"%1$d ta tanlandi"</item>
<item quantity="one" msgid="8409622005831789373">"%1$d ta tanlandi"</item>
diff --git a/WallpaperPicker/res/values-v21/styles.xml b/WallpaperPicker/res/values-v21/styles.xml
index 70220ed..de4b2f2 100644
--- a/WallpaperPicker/res/values-v21/styles.xml
+++ b/WallpaperPicker/res/values-v21/styles.xml
@@ -34,8 +34,8 @@
</style>
<style name="Theme" parent="@style/BaseWallpaperTheme">
- <item name="android:windowTranslucentStatus">true</item>
- <item name="android:windowTranslucentNavigation">true</item>
+ <item name="android:statusBarColor">#00000000</item>
+ <item name="android:navigationBarColor">#00000000</item>
<item name="android:colorControlActivated">@color/launcher_accent_color</item>
<item name="android:colorAccent">@color/launcher_accent_color</item>
<item name="android:colorPrimary">@color/launcher_accent_color</item>
diff --git a/WallpaperPicker/res/values-vi/strings.xml b/WallpaperPicker/res/values-vi/strings.xml
index ae00d58..a7c636d 100644
--- a/WallpaperPicker/res/values-vi/strings.xml
+++ b/WallpaperPicker/res/values-vi/strings.xml
@@ -22,6 +22,7 @@
<string name="wallpaper_instructions" msgid="3524143401182707094">"Đặt hình nền"</string>
<string name="image_load_fail" msgid="7538534580694411837">"Không thể tải hình ảnh"</string>
<string name="wallpaper_load_fail" msgid="4800700444605404650">"Không thể tải hình ảnh làm hình nền"</string>
+ <string name="wallpaper_set_fail" msgid="7023180794008631780">"Không thể đặt hình ảnh làm hình nền"</string>
<plurals name="number_of_items_selected">
<item quantity="zero" msgid="9015111147509924344">"Đã chọn %1$d"</item>
<item quantity="one" msgid="8409622005831789373">"Đã chọn %1$d"</item>
diff --git a/WallpaperPicker/res/values-zh-rCN/strings.xml b/WallpaperPicker/res/values-zh-rCN/strings.xml
index 8bd5342..4656ec6 100644
--- a/WallpaperPicker/res/values-zh-rCN/strings.xml
+++ b/WallpaperPicker/res/values-zh-rCN/strings.xml
@@ -22,6 +22,7 @@
<string name="wallpaper_instructions" msgid="3524143401182707094">"设置壁纸"</string>
<string name="image_load_fail" msgid="7538534580694411837">"无法加载图片"</string>
<string name="wallpaper_load_fail" msgid="4800700444605404650">"无法加载要设为壁纸的图片"</string>
+ <string name="wallpaper_set_fail" msgid="7023180794008631780">"无法将图片设为壁纸"</string>
<plurals name="number_of_items_selected">
<item quantity="zero" msgid="9015111147509924344">"已选择%1$d项"</item>
<item quantity="one" msgid="8409622005831789373">"已选择%1$d项"</item>
diff --git a/WallpaperPicker/res/values-zh-rHK/strings.xml b/WallpaperPicker/res/values-zh-rHK/strings.xml
index e51d60a..eb9c327 100644
--- a/WallpaperPicker/res/values-zh-rHK/strings.xml
+++ b/WallpaperPicker/res/values-zh-rHK/strings.xml
@@ -22,6 +22,7 @@
<string name="wallpaper_instructions" msgid="3524143401182707094">"設定桌布"</string>
<string name="image_load_fail" msgid="7538534580694411837">"無法載入圖片"</string>
<string name="wallpaper_load_fail" msgid="4800700444605404650">"無法載入圖片設為桌布"</string>
+ <string name="wallpaper_set_fail" msgid="7023180794008631780">"無法將圖片設為桌布"</string>
<plurals name="number_of_items_selected">
<item quantity="zero" msgid="9015111147509924344">"已選取 %1$d 張"</item>
<item quantity="one" msgid="8409622005831789373">"已選取 %1$d 張"</item>
diff --git a/WallpaperPicker/res/values-zh-rTW/strings.xml b/WallpaperPicker/res/values-zh-rTW/strings.xml
index c12350a..fda123c 100644
--- a/WallpaperPicker/res/values-zh-rTW/strings.xml
+++ b/WallpaperPicker/res/values-zh-rTW/strings.xml
@@ -22,6 +22,7 @@
<string name="wallpaper_instructions" msgid="3524143401182707094">"設定桌布"</string>
<string name="image_load_fail" msgid="7538534580694411837">"無法載入圖片"</string>
<string name="wallpaper_load_fail" msgid="4800700444605404650">"無法載入您要設為桌布的圖片"</string>
+ <string name="wallpaper_set_fail" msgid="7023180794008631780">"無法將圖片設為桌布"</string>
<plurals name="number_of_items_selected">
<item quantity="zero" msgid="9015111147509924344">"已選取 %1$d 個"</item>
<item quantity="one" msgid="8409622005831789373">"已選取 %1$d 個"</item>
diff --git a/WallpaperPicker/res/values-zu/strings.xml b/WallpaperPicker/res/values-zu/strings.xml
index 537b2f3..1a5b95e 100644
--- a/WallpaperPicker/res/values-zu/strings.xml
+++ b/WallpaperPicker/res/values-zu/strings.xml
@@ -22,6 +22,7 @@
<string name="wallpaper_instructions" msgid="3524143401182707094">"Setha isithombe sangemuva"</string>
<string name="image_load_fail" msgid="7538534580694411837">"Ayikwazanga ukulayisha isithombe"</string>
<string name="wallpaper_load_fail" msgid="4800700444605404650">"Ayikwazanga ukulayisha isithombe njengesithombe sangemuva"</string>
+ <string name="wallpaper_set_fail" msgid="7023180794008631780">"Ayikwazanga ukusetha isithombe njengesithombe sangemuva"</string>
<plurals name="number_of_items_selected">
<item quantity="zero" msgid="9015111147509924344">"%1$d khethiwe"</item>
<item quantity="one" msgid="8409622005831789373">"%1$d khethiwe"</item>
diff --git a/WallpaperPicker/res/values/strings.xml b/WallpaperPicker/res/values/strings.xml
index 72b1e15..2bfd476 100644
--- a/WallpaperPicker/res/values/strings.xml
+++ b/WallpaperPicker/res/values/strings.xml
@@ -28,6 +28,9 @@
usually see this when using another app and trying to set
an image as the wallpaper -->
<string name="wallpaper_load_fail">Couldn\'t load image as wallpaper</string>
+ <!-- Error message when an image is selected as a wallpaper,
+ but something goes wrong when the user clicks "Set wallpaper" -->
+ <string name="wallpaper_set_fail">Couldn\'t set image as wallpaper</string>
<!-- Shown when wallpapers are selected in Wallpaper picker -->
<!-- String indicating how many media item(s) is(are) selected
eg. 1 selected [CHAR LIMIT=30] -->
diff --git a/WallpaperPicker/src/com/android/gallery3d/common/BitmapCropTask.java b/WallpaperPicker/src/com/android/gallery3d/common/BitmapCropTask.java
index cb7090f..8b51447 100644
--- a/WallpaperPicker/src/com/android/gallery3d/common/BitmapCropTask.java
+++ b/WallpaperPicker/src/com/android/gallery3d/common/BitmapCropTask.java
@@ -31,6 +31,9 @@
import android.net.Uri;
import android.os.AsyncTask;
import android.util.Log;
+import android.widget.Toast;
+
+import com.android.launcher3.R;
import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
@@ -293,22 +296,16 @@
roundedTrueCrop.right = roundedTrueCrop.left + fullSize.getWidth();
}
if (roundedTrueCrop.right > fullSize.getWidth()) {
- // Adjust the left value
- int adjustment = roundedTrueCrop.left -
- Math.max(0, roundedTrueCrop.right - roundedTrueCrop.width());
- roundedTrueCrop.left -= adjustment;
- roundedTrueCrop.right -= adjustment;
+ // Adjust the left and right values.
+ roundedTrueCrop.offset(-(roundedTrueCrop.right - fullSize.getWidth()), 0);
}
if (roundedTrueCrop.height() > fullSize.getHeight()) {
// Adjust the height
roundedTrueCrop.bottom = roundedTrueCrop.top + fullSize.getHeight();
}
if (roundedTrueCrop.bottom > fullSize.getHeight()) {
- // Adjust the top value
- int adjustment = roundedTrueCrop.top -
- Math.max(0, roundedTrueCrop.bottom - roundedTrueCrop.height());
- roundedTrueCrop.top -= adjustment;
- roundedTrueCrop.bottom -= adjustment;
+ // Adjust the top and bottom values.
+ roundedTrueCrop.offset(0, -(roundedTrueCrop.bottom - fullSize.getHeight()));
}
crop = Bitmap.createBitmap(fullSize, roundedTrueCrop.left,
@@ -401,9 +398,12 @@
}
@Override
- protected void onPostExecute(Boolean result) {
+ protected void onPostExecute(Boolean cropSucceeded) {
+ if (!cropSucceeded) {
+ Toast.makeText(mContext, R.string.wallpaper_set_fail, Toast.LENGTH_SHORT).show();
+ }
if (mOnEndCropHandler != null) {
- mOnEndCropHandler.run(result);
+ mOnEndCropHandler.run(cropSucceeded);
}
}
}
\ No newline at end of file
diff --git a/WallpaperPicker/src/com/android/launcher3/WallpaperCropActivity.java b/WallpaperPicker/src/com/android/launcher3/WallpaperCropActivity.java
index 0dbd357..75bdb8a 100644
--- a/WallpaperPicker/src/com/android/launcher3/WallpaperCropActivity.java
+++ b/WallpaperPicker/src/com/android/launcher3/WallpaperCropActivity.java
@@ -123,6 +123,7 @@
new View.OnClickListener() {
@Override
public void onClick(View v) {
+ actionBar.hide();
boolean finishActivityWhenDone = true;
// Never fade on finish because we return to the app that started us (e.g.
// Photos), not the home screen.
@@ -361,6 +362,9 @@
protected void cropImageAndSetWallpaper(Uri uri,
BitmapCropTask.OnBitmapCroppedHandler onBitmapCroppedHandler,
final boolean finishActivityWhenDone, final boolean shouldFadeOutOnFinish) {
+ // Give some feedback so user knows something is happening.
+ mProgressView.setVisibility(View.VISIBLE);
+
boolean centerCrop = getResources().getBoolean(R.bool.center_crop);
// Get the crop
boolean ltr = mCropView.getLayoutDirection() == View.LAYOUT_DIRECTION_LTR;
@@ -467,7 +471,7 @@
editor.remove(WALLPAPER_WIDTH_KEY);
editor.remove(WALLPAPER_HEIGHT_KEY);
}
- editor.commit();
+ editor.apply();
WallpaperUtils.suggestWallpaperDimension(getResources(),
sp, getWindowManager(), WallpaperManager.getInstance(getContext()), true);
}
diff --git a/WallpaperPicker/src/com/android/launcher3/WallpaperPickerActivity.java b/WallpaperPicker/src/com/android/launcher3/WallpaperPickerActivity.java
index 041e4aa..5d41238 100644
--- a/WallpaperPicker/src/com/android/launcher3/WallpaperPickerActivity.java
+++ b/WallpaperPicker/src/com/android/launcher3/WallpaperPickerActivity.java
@@ -309,7 +309,7 @@
@Override
public float getParallaxOffset() {
- return 0;
+ return 0.5f;
}
};
req.result = new DrawableTileSource(a.getContext(),
@@ -857,12 +857,31 @@
}
private void addTemporaryWallpaperTile(final Uri uri, boolean fromRestore) {
- mTempWallpaperTiles.add(uri);
- // Add a tile for the image picked from Gallery
- final FrameLayout pickedImageThumbnail = (FrameLayout) getLayoutInflater().
- inflate(R.layout.wallpaper_picker_item, mWallpapersView, false);
- pickedImageThumbnail.setVisibility(View.GONE);
- mWallpapersView.addView(pickedImageThumbnail, 0);
+ // Add a tile for the image picked from Gallery, reusing the existing tile if there is one.
+ FrameLayout existingImageThumbnail = null;
+ int indexOfExistingTile = 0;
+ for (; indexOfExistingTile < mWallpapersView.getChildCount(); indexOfExistingTile++) {
+ FrameLayout thumbnail = (FrameLayout) mWallpapersView.getChildAt(indexOfExistingTile);
+ Object tag = thumbnail.getTag();
+ if (tag instanceof UriWallpaperInfo && ((UriWallpaperInfo) tag).mUri.equals(uri)) {
+ existingImageThumbnail = thumbnail;
+ break;
+ }
+ }
+ final FrameLayout pickedImageThumbnail;
+ if (existingImageThumbnail != null) {
+ pickedImageThumbnail = existingImageThumbnail;
+ // Always move the existing wallpaper to the front so user can see it without scrolling.
+ mWallpapersView.removeViewAt(indexOfExistingTile);
+ mWallpapersView.addView(existingImageThumbnail, 0);
+ } else {
+ // This is the first time this temporary wallpaper has been added
+ pickedImageThumbnail = (FrameLayout) getLayoutInflater()
+ .inflate(R.layout.wallpaper_picker_item, mWallpapersView, false);
+ pickedImageThumbnail.setVisibility(View.GONE);
+ mWallpapersView.addView(pickedImageThumbnail, 0);
+ mTempWallpaperTiles.add(uri);
+ }
// Load the thumbnail
final ImageView image = (ImageView) pickedImageThumbnail.findViewById(R.id.wallpaper_image);
@@ -872,7 +891,8 @@
protected Bitmap doInBackground(Void...args) {
try {
int rotation = BitmapUtils.getRotationFromExif(context, uri);
- return createThumbnail(defaultSize, context, uri, null, null, 0, rotation, false);
+ return createThumbnail(defaultSize, context, uri, null, null, 0, rotation,
+ false);
} catch (SecurityException securityException) {
if (isActivityDestroyed()) {
// Temporarily granted permissions are revoked when the activity
diff --git a/WallpaperPicker/src/com/android/photos/BitmapRegionTileSource.java b/WallpaperPicker/src/com/android/photos/BitmapRegionTileSource.java
index 2d496a5..6baac6a 100644
--- a/WallpaperPicker/src/com/android/photos/BitmapRegionTileSource.java
+++ b/WallpaperPicker/src/com/android/photos/BitmapRegionTileSource.java
@@ -159,6 +159,7 @@
public enum State { NOT_LOADED, LOADED, ERROR_LOADING };
private State mState = State.NOT_LOADED;
+ /** Returns whether loading was successful. */
public boolean loadInBackground(InBitmapProvider bitmapProvider) {
ExifInterface ei = new ExifInterface();
if (readExif(ei)) {
@@ -193,7 +194,7 @@
try {
mPreview = loadPreviewBitmap(opts);
} catch (IllegalArgumentException e) {
- Log.d(TAG, "Unable to reusage bitmap", e);
+ Log.d(TAG, "Unable to reuse bitmap", e);
opts.inBitmap = null;
mPreview = null;
}
@@ -202,6 +203,10 @@
if (mPreview == null) {
mPreview = loadPreviewBitmap(opts);
}
+ if (mPreview == null) {
+ mState = State.ERROR_LOADING;
+ return false;
+ }
// Verify that the bitmap can be used on GL surface
try {
@@ -212,7 +217,7 @@
Log.d(TAG, "Image cannot be rendered on a GL surface", e);
mState = State.ERROR_LOADING;
}
- return true;
+ return mState == State.LOADED;
}
}
@@ -310,7 +315,7 @@
Bitmap b = BitmapFactory.decodeStream(is, null, options);
Utils.closeSilently(is);
return b;
- } catch (FileNotFoundException e) {
+ } catch (FileNotFoundException | OutOfMemoryError e) {
Log.e("BitmapRegionTileSource", "Failed to load URI " + mUri, e);
return null;
}
@@ -412,7 +417,8 @@
"Failed to create preview of apropriate size! "
+ " in: %dx%d, out: %dx%d",
mWidth, mHeight,
- preview.getWidth(), preview.getHeight()));
+ preview == null ? -1 : preview.getWidth(),
+ preview == null ? -1 : preview.getHeight()));
}
}
}
diff --git a/build.gradle b/build.gradle
index d971755..44f5b7c 100644
--- a/build.gradle
+++ b/build.gradle
@@ -3,7 +3,7 @@
mavenCentral()
}
dependencies {
- classpath 'com.android.tools.build:gradle:1.3.0'
+ classpath 'com.android.tools.build:gradle:+'
classpath 'com.google.protobuf:protobuf-gradle-plugin:0.7.0'
}
}
@@ -21,6 +21,9 @@
targetSdkVersion 23
versionCode 1
versionName "1.0"
+
+ testApplicationId "com.android.launcher3.tests"
+ testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
debug {
@@ -30,10 +33,16 @@
sourceSets {
main {
res.srcDirs = ['res', 'WallpaperPicker/res']
- main.java.srcDirs = ['src', 'WallpaperPicker/src']
+ java.srcDirs = ['src', 'WallpaperPicker/src']
manifest.srcFile 'AndroidManifest.xml'
proto.srcDirs 'protos/'
}
+
+ androidTest {
+ java.srcDirs = ['tests/src']
+ res.srcDirs = ['tests/res']
+ manifest.srcFile "tests/AndroidManifest.xml"
+ }
}
}
@@ -42,9 +51,13 @@
}
dependencies {
- compile 'com.android.support:support-v4:+'
- compile 'com.android.support:recyclerview-v7:+'
+ compile 'com.android.support:support-v4:23.0.1'
+ compile 'com.android.support:recyclerview-v7:23.0.1'
compile 'com.google.protobuf.nano:protobuf-javanano:3.0.0-alpha-2'
+
+ testCompile 'junit:junit:4.12'
+ androidTestCompile 'com.android.support.test:runner:+'
+ androidTestCompile 'com.android.support.test.uiautomator:uiautomator-v18:+'
}
protobuf {
diff --git a/print_db.py b/print_db.py
index 05237d0..7257a12 100755
--- a/print_db.py
+++ b/print_db.py
@@ -4,6 +4,7 @@
import codecs
import os
import pprint
+import re
import shutil
import sys
import sqlite3
@@ -22,9 +23,10 @@
INDEX_FILE = DIR + "/index.html"
def usage():
- print "usage: print_db.py launcher.db <sw600|sw720> -- prints a launcher.db"
- print "usage: print_db.py <sw600|sw720> -- adb pulls a launcher.db from a device"
- print " and prints it"
+ print "usage: print_db.py launcher.db <4x4|5x5|5x6|...> -- prints a launcher.db with"
+ print " the specified grid size (rows x cols)"
+ print "usage: print_db.py <4x4|5x5|5x6|...> -- adb pulls a launcher.db from a device"
+ print " and prints it with the specified grid size (rows x cols)"
print
print "The dump will be created in a directory called db_files in cwd."
print "This script will delete any db_files directory you have now"
@@ -41,7 +43,7 @@
def pull_file(fn):
print "pull_file: " + fn
rv = os.system("adb pull"
- + " /data/data/com.google.android.googlequicksearchbox/databases/launcher.db"
+ + " /data/data/com.android.launcher3/databases/launcher.db"
+ " " + fn);
if rv != 0:
print "adb pull failed"
@@ -287,16 +289,11 @@
def updateDeviceClassConstants(str):
global SCREENS, COLUMNS, ROWS, HOTSEAT_SIZE
- devClass = str.lower()
- if devClass == "sw600":
- COLUMNS = 6
- ROWS = 6
- HOTSEAT_SIZE = 6
- return True
- elif devClass == "sw720":
- COLUMNS = 8
- ROWS = 6
- HOTSEAT_SIZE = 8
+ match = re.search(r"(\d+)x(\d+)", str)
+ if match:
+ COLUMNS = int(match.group(1))
+ ROWS = int(match.group(2))
+ HOTSEAT_SIZE = 2 * int(COLUMNS / 2)
return True
return False
diff --git a/proguard.flags b/proguard.flags
index 5a3dfd1..7725800 100644
--- a/proguard.flags
+++ b/proguard.flags
@@ -19,11 +19,6 @@
public float getAlpha();
}
--keep class com.android.launcher3.BubbleTextView {
- public void setFastScrollFocus(float);
- public float getFastScrollFocus();
-}
-
-keep class com.android.launcher3.ButtonDropTarget {
public int getTextColor();
}
@@ -56,8 +51,10 @@
}
-keep class com.android.launcher3.FastBitmapDrawable {
- public int getBrightness();
- public void setBrightness(int);
+ public void setDesaturation(float);
+ public float getDesaturation();
+ public void setBrightness(float);
+ public float getBrightness();
}
-keep class com.android.launcher3.MemoryDumpActivity {
diff --git a/protos/backup.proto b/protos/backup.proto
index 6704e08..c3f27e1 100644
--- a/protos/backup.proto
+++ b/protos/backup.proto
@@ -18,7 +18,7 @@
package launcher_backup;
-option java_package = "com.android.launcher3.backup";
+option java_package = "com.android.launcher3.backup.nano";
option java_outer_classname = "BackupProtos";
message Key {
diff --git a/res/drawable-hdpi/cling_bg.9.png b/res/drawable-hdpi/cling_bg.9.png
index e173ba5..fb101f4 100644
--- a/res/drawable-hdpi/cling_bg.9.png
+++ b/res/drawable-hdpi/cling_bg.9.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_all_apps_bg_hand.png b/res/drawable-hdpi/ic_all_apps_bg_hand.png
index 64f50df..43b1bed 100644
--- a/res/drawable-hdpi/ic_all_apps_bg_hand.png
+++ b/res/drawable-hdpi/ic_all_apps_bg_hand.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_all_apps_bg_icon_1.png b/res/drawable-hdpi/ic_all_apps_bg_icon_1.png
index df3e2de..d2c4cc1 100644
--- a/res/drawable-hdpi/ic_all_apps_bg_icon_1.png
+++ b/res/drawable-hdpi/ic_all_apps_bg_icon_1.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_all_apps_bg_icon_2.png b/res/drawable-hdpi/ic_all_apps_bg_icon_2.png
index 7138ee8..57b7456 100644
--- a/res/drawable-hdpi/ic_all_apps_bg_icon_2.png
+++ b/res/drawable-hdpi/ic_all_apps_bg_icon_2.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_all_apps_bg_icon_3.png b/res/drawable-hdpi/ic_all_apps_bg_icon_3.png
index ed88199..54fe70b 100644
--- a/res/drawable-hdpi/ic_all_apps_bg_icon_3.png
+++ b/res/drawable-hdpi/ic_all_apps_bg_icon_3.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_all_apps_bg_icon_4.png b/res/drawable-hdpi/ic_all_apps_bg_icon_4.png
index 0ff9453..9c0f777 100644
--- a/res/drawable-hdpi/ic_all_apps_bg_icon_4.png
+++ b/res/drawable-hdpi/ic_all_apps_bg_icon_4.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_allapps.png b/res/drawable-hdpi/ic_allapps.png
index b98e65f..253755f 100644
--- a/res/drawable-hdpi/ic_allapps.png
+++ b/res/drawable-hdpi/ic_allapps.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_allapps_pressed.png b/res/drawable-hdpi/ic_allapps_pressed.png
index b7eaa67..1e644c5 100644
--- a/res/drawable-hdpi/ic_allapps_pressed.png
+++ b/res/drawable-hdpi/ic_allapps_pressed.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_arrow_back_grey.png b/res/drawable-hdpi/ic_arrow_back_grey.png
index c7c0088..7d7bfb1 100755
--- a/res/drawable-hdpi/ic_arrow_back_grey.png
+++ b/res/drawable-hdpi/ic_arrow_back_grey.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_info_launcher.png b/res/drawable-hdpi/ic_info_launcher.png
index ec0cdd1..11162e1 100644
--- a/res/drawable-hdpi/ic_info_launcher.png
+++ b/res/drawable-hdpi/ic_info_launcher.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_pageindicator_add.png b/res/drawable-hdpi/ic_pageindicator_add.png
index ab0e5db..6e3f5af 100644
--- a/res/drawable-hdpi/ic_pageindicator_add.png
+++ b/res/drawable-hdpi/ic_pageindicator_add.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_pageindicator_current.png b/res/drawable-hdpi/ic_pageindicator_current.png
index 423ca2b..6dbc4f9 100644
--- a/res/drawable-hdpi/ic_pageindicator_current.png
+++ b/res/drawable-hdpi/ic_pageindicator_current.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_pageindicator_current_folder.png b/res/drawable-hdpi/ic_pageindicator_current_folder.png
index 43fbb0e..c6c4228 100644
--- a/res/drawable-hdpi/ic_pageindicator_current_folder.png
+++ b/res/drawable-hdpi/ic_pageindicator_current_folder.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_pageindicator_default.png b/res/drawable-hdpi/ic_pageindicator_default.png
index 83fa73f..19945a5 100644
--- a/res/drawable-hdpi/ic_pageindicator_default.png
+++ b/res/drawable-hdpi/ic_pageindicator_default.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_pageindicator_default_folder.png b/res/drawable-hdpi/ic_pageindicator_default_folder.png
index 55cab1c..4710374 100644
--- a/res/drawable-hdpi/ic_pageindicator_default_folder.png
+++ b/res/drawable-hdpi/ic_pageindicator_default_folder.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_remove_launcher.png b/res/drawable-hdpi/ic_remove_launcher.png
index c081457..ad2b9af 100644
--- a/res/drawable-hdpi/ic_remove_launcher.png
+++ b/res/drawable-hdpi/ic_remove_launcher.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_search_grey.png b/res/drawable-hdpi/ic_search_grey.png
index bd20ba0..bc50a47 100755
--- a/res/drawable-hdpi/ic_search_grey.png
+++ b/res/drawable-hdpi/ic_search_grey.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_setting.png b/res/drawable-hdpi/ic_setting.png
index 1c12a5b..72a9745 100644
--- a/res/drawable-hdpi/ic_setting.png
+++ b/res/drawable-hdpi/ic_setting.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_setting_pressed.png b/res/drawable-hdpi/ic_setting_pressed.png
index d5b5ca2..b86fce1 100644
--- a/res/drawable-hdpi/ic_setting_pressed.png
+++ b/res/drawable-hdpi/ic_setting_pressed.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_uninstall_launcher.png b/res/drawable-hdpi/ic_uninstall_launcher.png
index 3d8f726..426683c 100644
--- a/res/drawable-hdpi/ic_uninstall_launcher.png
+++ b/res/drawable-hdpi/ic_uninstall_launcher.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_wallpaper.png b/res/drawable-hdpi/ic_wallpaper.png
index 34d5943..5936059 100644
--- a/res/drawable-hdpi/ic_wallpaper.png
+++ b/res/drawable-hdpi/ic_wallpaper.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_wallpaper_pressed.png b/res/drawable-hdpi/ic_wallpaper_pressed.png
index 1588ce7..4bb1958 100644
--- a/res/drawable-hdpi/ic_wallpaper_pressed.png
+++ b/res/drawable-hdpi/ic_wallpaper_pressed.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_widget.png b/res/drawable-hdpi/ic_widget.png
index ed7e1ca..172664b 100644
--- a/res/drawable-hdpi/ic_widget.png
+++ b/res/drawable-hdpi/ic_widget.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_widget_pressed.png b/res/drawable-hdpi/ic_widget_pressed.png
index 19d6fed..7f31ab3 100644
--- a/res/drawable-hdpi/ic_widget_pressed.png
+++ b/res/drawable-hdpi/ic_widget_pressed.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_widget_resize_handle.png b/res/drawable-hdpi/ic_widget_resize_handle.png
index 844f3cf..b243aec 100644
--- a/res/drawable-hdpi/ic_widget_resize_handle.png
+++ b/res/drawable-hdpi/ic_widget_resize_handle.png
Binary files differ
diff --git a/res/drawable-hdpi/page_hover_left.9.png b/res/drawable-hdpi/page_hover_left.9.png
index cc029d8..3f11d0b 100644
--- a/res/drawable-hdpi/page_hover_left.9.png
+++ b/res/drawable-hdpi/page_hover_left.9.png
Binary files differ
diff --git a/res/drawable-hdpi/page_hover_left_active.9.png b/res/drawable-hdpi/page_hover_left_active.9.png
index 20c91a0..abe4c31 100644
--- a/res/drawable-hdpi/page_hover_left_active.9.png
+++ b/res/drawable-hdpi/page_hover_left_active.9.png
Binary files differ
diff --git a/res/drawable-hdpi/page_hover_right.9.png b/res/drawable-hdpi/page_hover_right.9.png
index a42822a..3bcf191 100644
--- a/res/drawable-hdpi/page_hover_right.9.png
+++ b/res/drawable-hdpi/page_hover_right.9.png
Binary files differ
diff --git a/res/drawable-hdpi/page_hover_right_active.9.png b/res/drawable-hdpi/page_hover_right_active.9.png
index 523fafd..101e4dc 100644
--- a/res/drawable-hdpi/page_hover_right_active.9.png
+++ b/res/drawable-hdpi/page_hover_right_active.9.png
Binary files differ
diff --git a/res/drawable-hdpi/portal_ring_inner.png b/res/drawable-hdpi/portal_ring_inner.png
index c29b4aa..65f5af2 100644
--- a/res/drawable-hdpi/portal_ring_inner.png
+++ b/res/drawable-hdpi/portal_ring_inner.png
Binary files differ
diff --git a/res/drawable-hdpi/portal_ring_inner_nolip.png b/res/drawable-hdpi/portal_ring_inner_nolip.png
index e2f06fe..5be25fc 100644
--- a/res/drawable-hdpi/portal_ring_inner_nolip.png
+++ b/res/drawable-hdpi/portal_ring_inner_nolip.png
Binary files differ
diff --git a/res/drawable-hdpi/portal_ring_outer.png b/res/drawable-hdpi/portal_ring_outer.png
index e7b436b..712eeb2 100644
--- a/res/drawable-hdpi/portal_ring_outer.png
+++ b/res/drawable-hdpi/portal_ring_outer.png
Binary files differ
diff --git a/res/drawable-hdpi/portal_ring_rest.png b/res/drawable-hdpi/portal_ring_rest.png
index e3b1339..33cec32 100644
--- a/res/drawable-hdpi/portal_ring_rest.png
+++ b/res/drawable-hdpi/portal_ring_rest.png
Binary files differ
diff --git a/res/drawable-hdpi/quantum_panel_bitmap.9.png b/res/drawable-hdpi/quantum_panel_bitmap.9.png
index c331929..d2aee73 100644
--- a/res/drawable-hdpi/quantum_panel_bitmap.9.png
+++ b/res/drawable-hdpi/quantum_panel_bitmap.9.png
Binary files differ
diff --git a/res/drawable-hdpi/quantum_panel_dark_bitmap.9.png b/res/drawable-hdpi/quantum_panel_dark_bitmap.9.png
index 0145d36..78345b8 100644
--- a/res/drawable-hdpi/quantum_panel_dark_bitmap.9.png
+++ b/res/drawable-hdpi/quantum_panel_dark_bitmap.9.png
Binary files differ
diff --git a/res/drawable-hdpi/screenpanel.9.png b/res/drawable-hdpi/screenpanel.9.png
index f7ae011..5bccd33 100644
--- a/res/drawable-hdpi/screenpanel.9.png
+++ b/res/drawable-hdpi/screenpanel.9.png
Binary files differ
diff --git a/res/drawable-hdpi/screenpanel_hover.9.png b/res/drawable-hdpi/screenpanel_hover.9.png
index ac8e83d..f6b8c62 100644
--- a/res/drawable-hdpi/screenpanel_hover.9.png
+++ b/res/drawable-hdpi/screenpanel_hover.9.png
Binary files differ
diff --git a/res/drawable-hdpi/virtual_preload.9.png b/res/drawable-hdpi/virtual_preload.9.png
index 71e5326..670088f 100644
--- a/res/drawable-hdpi/virtual_preload.9.png
+++ b/res/drawable-hdpi/virtual_preload.9.png
Binary files differ
diff --git a/res/drawable-hdpi/virtual_preload_folder.9.png b/res/drawable-hdpi/virtual_preload_folder.9.png
index ece3226..68e2afe 100644
--- a/res/drawable-hdpi/virtual_preload_folder.9.png
+++ b/res/drawable-hdpi/virtual_preload_folder.9.png
Binary files differ
diff --git a/res/drawable-hdpi/widget_resize_frame.9.png b/res/drawable-hdpi/widget_resize_frame.9.png
index b0a7403..a710932 100644
--- a/res/drawable-hdpi/widget_resize_frame.9.png
+++ b/res/drawable-hdpi/widget_resize_frame.9.png
Binary files differ
diff --git a/res/drawable-hdpi/widget_resize_shadow.9.png b/res/drawable-hdpi/widget_resize_shadow.9.png
index 6e2932d..7cb5214 100644
--- a/res/drawable-hdpi/widget_resize_shadow.9.png
+++ b/res/drawable-hdpi/widget_resize_shadow.9.png
Binary files differ
diff --git a/res/drawable-hdpi/widget_tile.png b/res/drawable-hdpi/widget_tile.png
index 310ff8b..572bf6f 100644
--- a/res/drawable-hdpi/widget_tile.png
+++ b/res/drawable-hdpi/widget_tile.png
Binary files differ
diff --git a/res/drawable-hdpi/workspace_bg.9.png b/res/drawable-hdpi/workspace_bg.9.png
index 5bbfa4f..ff75186 100644
--- a/res/drawable-hdpi/workspace_bg.9.png
+++ b/res/drawable-hdpi/workspace_bg.9.png
Binary files differ
diff --git a/res/drawable-land-hdpi/workspace_bg.9.png b/res/drawable-land-hdpi/workspace_bg.9.png
index 1a58144..eecd6de 100644
--- a/res/drawable-land-hdpi/workspace_bg.9.png
+++ b/res/drawable-land-hdpi/workspace_bg.9.png
Binary files differ
diff --git a/res/drawable-land-mdpi/workspace_bg.9.png b/res/drawable-land-mdpi/workspace_bg.9.png
index a12519e..626f4a4 100644
--- a/res/drawable-land-mdpi/workspace_bg.9.png
+++ b/res/drawable-land-mdpi/workspace_bg.9.png
Binary files differ
diff --git a/res/drawable-land-xhdpi/workspace_bg.9.png b/res/drawable-land-xhdpi/workspace_bg.9.png
index ce41454..60f7d73 100644
--- a/res/drawable-land-xhdpi/workspace_bg.9.png
+++ b/res/drawable-land-xhdpi/workspace_bg.9.png
Binary files differ
diff --git a/res/drawable-land-xxhdpi/workspace_bg.9.png b/res/drawable-land-xxhdpi/workspace_bg.9.png
index b0b4561..fc71a0f 100644
--- a/res/drawable-land-xxhdpi/workspace_bg.9.png
+++ b/res/drawable-land-xxhdpi/workspace_bg.9.png
Binary files differ
diff --git a/res/drawable-mdpi/cling_bg.9.png b/res/drawable-mdpi/cling_bg.9.png
index fc49c89..6384f29 100644
--- a/res/drawable-mdpi/cling_bg.9.png
+++ b/res/drawable-mdpi/cling_bg.9.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_all_apps_bg_hand.png b/res/drawable-mdpi/ic_all_apps_bg_hand.png
index d94bb7a..8868d6b 100644
--- a/res/drawable-mdpi/ic_all_apps_bg_hand.png
+++ b/res/drawable-mdpi/ic_all_apps_bg_hand.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_all_apps_bg_icon_1.png b/res/drawable-mdpi/ic_all_apps_bg_icon_1.png
index 76d973f..4c78288 100644
--- a/res/drawable-mdpi/ic_all_apps_bg_icon_1.png
+++ b/res/drawable-mdpi/ic_all_apps_bg_icon_1.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_all_apps_bg_icon_2.png b/res/drawable-mdpi/ic_all_apps_bg_icon_2.png
index 0257f8c..0ed311b 100644
--- a/res/drawable-mdpi/ic_all_apps_bg_icon_2.png
+++ b/res/drawable-mdpi/ic_all_apps_bg_icon_2.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_all_apps_bg_icon_3.png b/res/drawable-mdpi/ic_all_apps_bg_icon_3.png
index 67545f5..2aa3d4e 100644
--- a/res/drawable-mdpi/ic_all_apps_bg_icon_3.png
+++ b/res/drawable-mdpi/ic_all_apps_bg_icon_3.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_all_apps_bg_icon_4.png b/res/drawable-mdpi/ic_all_apps_bg_icon_4.png
index 3e36e27b..2cdea9c 100644
--- a/res/drawable-mdpi/ic_all_apps_bg_icon_4.png
+++ b/res/drawable-mdpi/ic_all_apps_bg_icon_4.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_allapps.png b/res/drawable-mdpi/ic_allapps.png
index f410673..6936b20 100644
--- a/res/drawable-mdpi/ic_allapps.png
+++ b/res/drawable-mdpi/ic_allapps.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_allapps_pressed.png b/res/drawable-mdpi/ic_allapps_pressed.png
index aa4f913..850ded6 100644
--- a/res/drawable-mdpi/ic_allapps_pressed.png
+++ b/res/drawable-mdpi/ic_allapps_pressed.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_arrow_back_grey.png b/res/drawable-mdpi/ic_arrow_back_grey.png
index 5892c77..97999af 100755
--- a/res/drawable-mdpi/ic_arrow_back_grey.png
+++ b/res/drawable-mdpi/ic_arrow_back_grey.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_info_launcher.png b/res/drawable-mdpi/ic_info_launcher.png
index c72d0c2..6fbe5e3 100644
--- a/res/drawable-mdpi/ic_info_launcher.png
+++ b/res/drawable-mdpi/ic_info_launcher.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_pageindicator_add.png b/res/drawable-mdpi/ic_pageindicator_add.png
index 11659a3..d9939b4 100644
--- a/res/drawable-mdpi/ic_pageindicator_add.png
+++ b/res/drawable-mdpi/ic_pageindicator_add.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_pageindicator_current.png b/res/drawable-mdpi/ic_pageindicator_current.png
index ca889c4..832f8ef 100644
--- a/res/drawable-mdpi/ic_pageindicator_current.png
+++ b/res/drawable-mdpi/ic_pageindicator_current.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_pageindicator_current_folder.png b/res/drawable-mdpi/ic_pageindicator_current_folder.png
index 5bbba91..b6c4d7f 100644
--- a/res/drawable-mdpi/ic_pageindicator_current_folder.png
+++ b/res/drawable-mdpi/ic_pageindicator_current_folder.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_pageindicator_default.png b/res/drawable-mdpi/ic_pageindicator_default.png
index 34493b1..9c44afc 100644
--- a/res/drawable-mdpi/ic_pageindicator_default.png
+++ b/res/drawable-mdpi/ic_pageindicator_default.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_pageindicator_default_folder.png b/res/drawable-mdpi/ic_pageindicator_default_folder.png
index 0a987a4..f462558 100644
--- a/res/drawable-mdpi/ic_pageindicator_default_folder.png
+++ b/res/drawable-mdpi/ic_pageindicator_default_folder.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_remove_launcher.png b/res/drawable-mdpi/ic_remove_launcher.png
index 4a2c319..2bb281d 100644
--- a/res/drawable-mdpi/ic_remove_launcher.png
+++ b/res/drawable-mdpi/ic_remove_launcher.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_setting.png b/res/drawable-mdpi/ic_setting.png
index c614e91..60c4fa5 100644
--- a/res/drawable-mdpi/ic_setting.png
+++ b/res/drawable-mdpi/ic_setting.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_setting_pressed.png b/res/drawable-mdpi/ic_setting_pressed.png
index 61e574a..018bea3 100644
--- a/res/drawable-mdpi/ic_setting_pressed.png
+++ b/res/drawable-mdpi/ic_setting_pressed.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_uninstall_launcher.png b/res/drawable-mdpi/ic_uninstall_launcher.png
index af45669..bfcbc6df 100644
--- a/res/drawable-mdpi/ic_uninstall_launcher.png
+++ b/res/drawable-mdpi/ic_uninstall_launcher.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_wallpaper.png b/res/drawable-mdpi/ic_wallpaper.png
index 8f2a00a..a934783 100644
--- a/res/drawable-mdpi/ic_wallpaper.png
+++ b/res/drawable-mdpi/ic_wallpaper.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_wallpaper_pressed.png b/res/drawable-mdpi/ic_wallpaper_pressed.png
index aa598c3..08794d9 100644
--- a/res/drawable-mdpi/ic_wallpaper_pressed.png
+++ b/res/drawable-mdpi/ic_wallpaper_pressed.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_widget.png b/res/drawable-mdpi/ic_widget.png
index 1bd3935..5545350 100644
--- a/res/drawable-mdpi/ic_widget.png
+++ b/res/drawable-mdpi/ic_widget.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_widget_pressed.png b/res/drawable-mdpi/ic_widget_pressed.png
index 9b690d9..634b415 100644
--- a/res/drawable-mdpi/ic_widget_pressed.png
+++ b/res/drawable-mdpi/ic_widget_pressed.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_widget_resize_handle.png b/res/drawable-mdpi/ic_widget_resize_handle.png
index c3b287f..656e96c 100644
--- a/res/drawable-mdpi/ic_widget_resize_handle.png
+++ b/res/drawable-mdpi/ic_widget_resize_handle.png
Binary files differ
diff --git a/res/drawable-mdpi/page_hover_left.9.png b/res/drawable-mdpi/page_hover_left.9.png
index 2bbf428..2b6094c 100644
--- a/res/drawable-mdpi/page_hover_left.9.png
+++ b/res/drawable-mdpi/page_hover_left.9.png
Binary files differ
diff --git a/res/drawable-mdpi/page_hover_left_active.9.png b/res/drawable-mdpi/page_hover_left_active.9.png
index bf70f36..9eb00a2 100644
--- a/res/drawable-mdpi/page_hover_left_active.9.png
+++ b/res/drawable-mdpi/page_hover_left_active.9.png
Binary files differ
diff --git a/res/drawable-mdpi/page_hover_right.9.png b/res/drawable-mdpi/page_hover_right.9.png
index 4bafd0f..c2e59835 100644
--- a/res/drawable-mdpi/page_hover_right.9.png
+++ b/res/drawable-mdpi/page_hover_right.9.png
Binary files differ
diff --git a/res/drawable-mdpi/page_hover_right_active.9.png b/res/drawable-mdpi/page_hover_right_active.9.png
index 4aaa014..d2771a1 100644
--- a/res/drawable-mdpi/page_hover_right_active.9.png
+++ b/res/drawable-mdpi/page_hover_right_active.9.png
Binary files differ
diff --git a/res/drawable-mdpi/portal_ring_inner.png b/res/drawable-mdpi/portal_ring_inner.png
index 99aaa60..7c5e2b7 100644
--- a/res/drawable-mdpi/portal_ring_inner.png
+++ b/res/drawable-mdpi/portal_ring_inner.png
Binary files differ
diff --git a/res/drawable-mdpi/portal_ring_inner_nolip.png b/res/drawable-mdpi/portal_ring_inner_nolip.png
index f981778..6ccdebb 100644
--- a/res/drawable-mdpi/portal_ring_inner_nolip.png
+++ b/res/drawable-mdpi/portal_ring_inner_nolip.png
Binary files differ
diff --git a/res/drawable-mdpi/portal_ring_outer.png b/res/drawable-mdpi/portal_ring_outer.png
index c98f64b..40a73ab 100644
--- a/res/drawable-mdpi/portal_ring_outer.png
+++ b/res/drawable-mdpi/portal_ring_outer.png
Binary files differ
diff --git a/res/drawable-mdpi/portal_ring_rest.png b/res/drawable-mdpi/portal_ring_rest.png
index 5c33b42..b2c733b 100644
--- a/res/drawable-mdpi/portal_ring_rest.png
+++ b/res/drawable-mdpi/portal_ring_rest.png
Binary files differ
diff --git a/res/drawable-mdpi/quantum_panel_bitmap.9.png b/res/drawable-mdpi/quantum_panel_bitmap.9.png
index 86be568..9325d49 100644
--- a/res/drawable-mdpi/quantum_panel_bitmap.9.png
+++ b/res/drawable-mdpi/quantum_panel_bitmap.9.png
Binary files differ
diff --git a/res/drawable-mdpi/quantum_panel_dark_bitmap.9.png b/res/drawable-mdpi/quantum_panel_dark_bitmap.9.png
index 70429b9..bf74fa0 100644
--- a/res/drawable-mdpi/quantum_panel_dark_bitmap.9.png
+++ b/res/drawable-mdpi/quantum_panel_dark_bitmap.9.png
Binary files differ
diff --git a/res/drawable-mdpi/screenpanel.9.png b/res/drawable-mdpi/screenpanel.9.png
index c2779fc..9603c12 100644
--- a/res/drawable-mdpi/screenpanel.9.png
+++ b/res/drawable-mdpi/screenpanel.9.png
Binary files differ
diff --git a/res/drawable-mdpi/screenpanel_hover.9.png b/res/drawable-mdpi/screenpanel_hover.9.png
index 70b3078..7f28ce0 100644
--- a/res/drawable-mdpi/screenpanel_hover.9.png
+++ b/res/drawable-mdpi/screenpanel_hover.9.png
Binary files differ
diff --git a/res/drawable-mdpi/virtual_preload.9.png b/res/drawable-mdpi/virtual_preload.9.png
index a3c7519..c4a01fe 100644
--- a/res/drawable-mdpi/virtual_preload.9.png
+++ b/res/drawable-mdpi/virtual_preload.9.png
Binary files differ
diff --git a/res/drawable-mdpi/virtual_preload_folder.9.png b/res/drawable-mdpi/virtual_preload_folder.9.png
index fa2f131..2f3e420 100644
--- a/res/drawable-mdpi/virtual_preload_folder.9.png
+++ b/res/drawable-mdpi/virtual_preload_folder.9.png
Binary files differ
diff --git a/res/drawable-mdpi/widget_resize_frame.9.png b/res/drawable-mdpi/widget_resize_frame.9.png
index 856cec6..252482f 100644
--- a/res/drawable-mdpi/widget_resize_frame.9.png
+++ b/res/drawable-mdpi/widget_resize_frame.9.png
Binary files differ
diff --git a/res/drawable-mdpi/widget_resize_shadow.9.png b/res/drawable-mdpi/widget_resize_shadow.9.png
index 02522f3..a2010e2 100644
--- a/res/drawable-mdpi/widget_resize_shadow.9.png
+++ b/res/drawable-mdpi/widget_resize_shadow.9.png
Binary files differ
diff --git a/res/drawable-mdpi/widget_tile.png b/res/drawable-mdpi/widget_tile.png
index 1ba559d..9652ace 100644
--- a/res/drawable-mdpi/widget_tile.png
+++ b/res/drawable-mdpi/widget_tile.png
Binary files differ
diff --git a/res/drawable-mdpi/workspace_bg.9.png b/res/drawable-mdpi/workspace_bg.9.png
index 2856e09..c67c432 100644
--- a/res/drawable-mdpi/workspace_bg.9.png
+++ b/res/drawable-mdpi/workspace_bg.9.png
Binary files differ
diff --git a/res/drawable-nodpi/ic_migration.png b/res/drawable-nodpi/ic_migration.png
index c282cd2..14f8721 100644
--- a/res/drawable-nodpi/ic_migration.png
+++ b/res/drawable-nodpi/ic_migration.png
Binary files differ
diff --git a/res/drawable-sw720dp-hdpi/workspace_bg.9.png b/res/drawable-sw720dp-hdpi/workspace_bg.9.png
index 5bbfa4f..ff75186 100644
--- a/res/drawable-sw720dp-hdpi/workspace_bg.9.png
+++ b/res/drawable-sw720dp-hdpi/workspace_bg.9.png
Binary files differ
diff --git a/res/drawable-sw720dp-mdpi/workspace_bg.9.png b/res/drawable-sw720dp-mdpi/workspace_bg.9.png
index 2856e09..c67c432 100644
--- a/res/drawable-sw720dp-mdpi/workspace_bg.9.png
+++ b/res/drawable-sw720dp-mdpi/workspace_bg.9.png
Binary files differ
diff --git a/res/drawable-sw720dp-xhdpi/workspace_bg.9.png b/res/drawable-sw720dp-xhdpi/workspace_bg.9.png
index 72269f2..0b80cbf 100644
--- a/res/drawable-sw720dp-xhdpi/workspace_bg.9.png
+++ b/res/drawable-sw720dp-xhdpi/workspace_bg.9.png
Binary files differ
diff --git a/res/drawable-sw720dp-xxhdpi/workspace_bg.9.png b/res/drawable-sw720dp-xxhdpi/workspace_bg.9.png
index efc9b04..0d180c2 100644
--- a/res/drawable-sw720dp-xxhdpi/workspace_bg.9.png
+++ b/res/drawable-sw720dp-xxhdpi/workspace_bg.9.png
Binary files differ
diff --git a/res/drawable-xhdpi/cling_bg.9.png b/res/drawable-xhdpi/cling_bg.9.png
index 4db356f..7d8b1f0 100644
--- a/res/drawable-xhdpi/cling_bg.9.png
+++ b/res/drawable-xhdpi/cling_bg.9.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_all_apps_bg_hand.png b/res/drawable-xhdpi/ic_all_apps_bg_hand.png
index 5dde7f3..8a67245 100644
--- a/res/drawable-xhdpi/ic_all_apps_bg_hand.png
+++ b/res/drawable-xhdpi/ic_all_apps_bg_hand.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_all_apps_bg_icon_1.png b/res/drawable-xhdpi/ic_all_apps_bg_icon_1.png
index f5bd32a..c0ebaed 100644
--- a/res/drawable-xhdpi/ic_all_apps_bg_icon_1.png
+++ b/res/drawable-xhdpi/ic_all_apps_bg_icon_1.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_all_apps_bg_icon_2.png b/res/drawable-xhdpi/ic_all_apps_bg_icon_2.png
index fb07956..71cf250 100644
--- a/res/drawable-xhdpi/ic_all_apps_bg_icon_2.png
+++ b/res/drawable-xhdpi/ic_all_apps_bg_icon_2.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_all_apps_bg_icon_3.png b/res/drawable-xhdpi/ic_all_apps_bg_icon_3.png
index c7d687e..3c69fc5 100644
--- a/res/drawable-xhdpi/ic_all_apps_bg_icon_3.png
+++ b/res/drawable-xhdpi/ic_all_apps_bg_icon_3.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_all_apps_bg_icon_4.png b/res/drawable-xhdpi/ic_all_apps_bg_icon_4.png
index e22b962..5f6ca38 100644
--- a/res/drawable-xhdpi/ic_all_apps_bg_icon_4.png
+++ b/res/drawable-xhdpi/ic_all_apps_bg_icon_4.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_allapps.png b/res/drawable-xhdpi/ic_allapps.png
index ff3d823..c11c103 100644
--- a/res/drawable-xhdpi/ic_allapps.png
+++ b/res/drawable-xhdpi/ic_allapps.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_allapps_pressed.png b/res/drawable-xhdpi/ic_allapps_pressed.png
index 5f188f6..f319bf1 100644
--- a/res/drawable-xhdpi/ic_allapps_pressed.png
+++ b/res/drawable-xhdpi/ic_allapps_pressed.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_arrow_back_grey.png b/res/drawable-xhdpi/ic_arrow_back_grey.png
index 11996ef..22854bf 100755
--- a/res/drawable-xhdpi/ic_arrow_back_grey.png
+++ b/res/drawable-xhdpi/ic_arrow_back_grey.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_info_launcher.png b/res/drawable-xhdpi/ic_info_launcher.png
index 076b59b..041f2b3 100644
--- a/res/drawable-xhdpi/ic_info_launcher.png
+++ b/res/drawable-xhdpi/ic_info_launcher.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_pageindicator_add.png b/res/drawable-xhdpi/ic_pageindicator_add.png
index af1da2d..7e18c05 100644
--- a/res/drawable-xhdpi/ic_pageindicator_add.png
+++ b/res/drawable-xhdpi/ic_pageindicator_add.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_pageindicator_current.png b/res/drawable-xhdpi/ic_pageindicator_current.png
index 3054f2f..866725f 100644
--- a/res/drawable-xhdpi/ic_pageindicator_current.png
+++ b/res/drawable-xhdpi/ic_pageindicator_current.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_pageindicator_current_folder.png b/res/drawable-xhdpi/ic_pageindicator_current_folder.png
index cd92e9f..ec19b7c 100644
--- a/res/drawable-xhdpi/ic_pageindicator_current_folder.png
+++ b/res/drawable-xhdpi/ic_pageindicator_current_folder.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_pageindicator_default.png b/res/drawable-xhdpi/ic_pageindicator_default.png
index 38538dc..0cde8f4 100644
--- a/res/drawable-xhdpi/ic_pageindicator_default.png
+++ b/res/drawable-xhdpi/ic_pageindicator_default.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_pageindicator_default_folder.png b/res/drawable-xhdpi/ic_pageindicator_default_folder.png
index e7c46e3..7c22d41 100644
--- a/res/drawable-xhdpi/ic_pageindicator_default_folder.png
+++ b/res/drawable-xhdpi/ic_pageindicator_default_folder.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_remove_launcher.png b/res/drawable-xhdpi/ic_remove_launcher.png
index de05889..ff94eb8 100644
--- a/res/drawable-xhdpi/ic_remove_launcher.png
+++ b/res/drawable-xhdpi/ic_remove_launcher.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_search_grey.png b/res/drawable-xhdpi/ic_search_grey.png
index e83891c..e63182d 100755
--- a/res/drawable-xhdpi/ic_search_grey.png
+++ b/res/drawable-xhdpi/ic_search_grey.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_setting.png b/res/drawable-xhdpi/ic_setting.png
index 3a7310b..bb90789 100644
--- a/res/drawable-xhdpi/ic_setting.png
+++ b/res/drawable-xhdpi/ic_setting.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_setting_pressed.png b/res/drawable-xhdpi/ic_setting_pressed.png
index 005d49c..949373f 100644
--- a/res/drawable-xhdpi/ic_setting_pressed.png
+++ b/res/drawable-xhdpi/ic_setting_pressed.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_uninstall_launcher.png b/res/drawable-xhdpi/ic_uninstall_launcher.png
index dd50e88..2c7ab56 100644
--- a/res/drawable-xhdpi/ic_uninstall_launcher.png
+++ b/res/drawable-xhdpi/ic_uninstall_launcher.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_wallpaper.png b/res/drawable-xhdpi/ic_wallpaper.png
index d2bf246..0acf773 100644
--- a/res/drawable-xhdpi/ic_wallpaper.png
+++ b/res/drawable-xhdpi/ic_wallpaper.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_wallpaper_pressed.png b/res/drawable-xhdpi/ic_wallpaper_pressed.png
index 5a9b84d..e1e291d 100644
--- a/res/drawable-xhdpi/ic_wallpaper_pressed.png
+++ b/res/drawable-xhdpi/ic_wallpaper_pressed.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_widget.png b/res/drawable-xhdpi/ic_widget.png
index cf6be81..94bb79f 100644
--- a/res/drawable-xhdpi/ic_widget.png
+++ b/res/drawable-xhdpi/ic_widget.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_widget_pressed.png b/res/drawable-xhdpi/ic_widget_pressed.png
index 633c9c6..1dcaf37 100644
--- a/res/drawable-xhdpi/ic_widget_pressed.png
+++ b/res/drawable-xhdpi/ic_widget_pressed.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_widget_resize_handle.png b/res/drawable-xhdpi/ic_widget_resize_handle.png
index f445a1c..0e8dd68 100644
--- a/res/drawable-xhdpi/ic_widget_resize_handle.png
+++ b/res/drawable-xhdpi/ic_widget_resize_handle.png
Binary files differ
diff --git a/res/drawable-xhdpi/page_hover_left.9.png b/res/drawable-xhdpi/page_hover_left.9.png
index a2b9b65..dbcc0ab 100644
--- a/res/drawable-xhdpi/page_hover_left.9.png
+++ b/res/drawable-xhdpi/page_hover_left.9.png
Binary files differ
diff --git a/res/drawable-xhdpi/page_hover_left_active.9.png b/res/drawable-xhdpi/page_hover_left_active.9.png
index ba9478e..3233efe 100644
--- a/res/drawable-xhdpi/page_hover_left_active.9.png
+++ b/res/drawable-xhdpi/page_hover_left_active.9.png
Binary files differ
diff --git a/res/drawable-xhdpi/page_hover_right.9.png b/res/drawable-xhdpi/page_hover_right.9.png
index 1243ea9..d82f809 100644
--- a/res/drawable-xhdpi/page_hover_right.9.png
+++ b/res/drawable-xhdpi/page_hover_right.9.png
Binary files differ
diff --git a/res/drawable-xhdpi/page_hover_right_active.9.png b/res/drawable-xhdpi/page_hover_right_active.9.png
index 582261c..819ea19 100644
--- a/res/drawable-xhdpi/page_hover_right_active.9.png
+++ b/res/drawable-xhdpi/page_hover_right_active.9.png
Binary files differ
diff --git a/res/drawable-xhdpi/portal_ring_inner.png b/res/drawable-xhdpi/portal_ring_inner.png
index 7b6a8a0..b088042 100644
--- a/res/drawable-xhdpi/portal_ring_inner.png
+++ b/res/drawable-xhdpi/portal_ring_inner.png
Binary files differ
diff --git a/res/drawable-xhdpi/portal_ring_inner_nolip.png b/res/drawable-xhdpi/portal_ring_inner_nolip.png
index 4b84436..decf766 100644
--- a/res/drawable-xhdpi/portal_ring_inner_nolip.png
+++ b/res/drawable-xhdpi/portal_ring_inner_nolip.png
Binary files differ
diff --git a/res/drawable-xhdpi/portal_ring_outer.png b/res/drawable-xhdpi/portal_ring_outer.png
index 79c1888..5ab9a21 100644
--- a/res/drawable-xhdpi/portal_ring_outer.png
+++ b/res/drawable-xhdpi/portal_ring_outer.png
Binary files differ
diff --git a/res/drawable-xhdpi/portal_ring_rest.png b/res/drawable-xhdpi/portal_ring_rest.png
index 544a74f..7d1c842 100644
--- a/res/drawable-xhdpi/portal_ring_rest.png
+++ b/res/drawable-xhdpi/portal_ring_rest.png
Binary files differ
diff --git a/res/drawable-xhdpi/quantum_panel_bitmap.9.png b/res/drawable-xhdpi/quantum_panel_bitmap.9.png
index 13bdf09..b89e8b4 100644
--- a/res/drawable-xhdpi/quantum_panel_bitmap.9.png
+++ b/res/drawable-xhdpi/quantum_panel_bitmap.9.png
Binary files differ
diff --git a/res/drawable-xhdpi/quantum_panel_dark_bitmap.9.png b/res/drawable-xhdpi/quantum_panel_dark_bitmap.9.png
index ac2e423..1d17136 100644
--- a/res/drawable-xhdpi/quantum_panel_dark_bitmap.9.png
+++ b/res/drawable-xhdpi/quantum_panel_dark_bitmap.9.png
Binary files differ
diff --git a/res/drawable-xhdpi/screenpanel.9.png b/res/drawable-xhdpi/screenpanel.9.png
index 53a7812..75343f7 100644
--- a/res/drawable-xhdpi/screenpanel.9.png
+++ b/res/drawable-xhdpi/screenpanel.9.png
Binary files differ
diff --git a/res/drawable-xhdpi/screenpanel_hover.9.png b/res/drawable-xhdpi/screenpanel_hover.9.png
index a2e200f..55b4d6e 100644
--- a/res/drawable-xhdpi/screenpanel_hover.9.png
+++ b/res/drawable-xhdpi/screenpanel_hover.9.png
Binary files differ
diff --git a/res/drawable-xhdpi/virtual_preload.9.png b/res/drawable-xhdpi/virtual_preload.9.png
index d2c3fea..2afade1 100644
--- a/res/drawable-xhdpi/virtual_preload.9.png
+++ b/res/drawable-xhdpi/virtual_preload.9.png
Binary files differ
diff --git a/res/drawable-xhdpi/virtual_preload_folder.9.png b/res/drawable-xhdpi/virtual_preload_folder.9.png
index 1f9202b..cb3fdca 100644
--- a/res/drawable-xhdpi/virtual_preload_folder.9.png
+++ b/res/drawable-xhdpi/virtual_preload_folder.9.png
Binary files differ
diff --git a/res/drawable-xhdpi/widget_resize_frame.9.png b/res/drawable-xhdpi/widget_resize_frame.9.png
index bf7cc6b..563c75d 100644
--- a/res/drawable-xhdpi/widget_resize_frame.9.png
+++ b/res/drawable-xhdpi/widget_resize_frame.9.png
Binary files differ
diff --git a/res/drawable-xhdpi/widget_resize_shadow.9.png b/res/drawable-xhdpi/widget_resize_shadow.9.png
index 96dee7f..2b1ac05 100644
--- a/res/drawable-xhdpi/widget_resize_shadow.9.png
+++ b/res/drawable-xhdpi/widget_resize_shadow.9.png
Binary files differ
diff --git a/res/drawable-xhdpi/widget_tile.png b/res/drawable-xhdpi/widget_tile.png
index 9730f35..be1748d 100644
--- a/res/drawable-xhdpi/widget_tile.png
+++ b/res/drawable-xhdpi/widget_tile.png
Binary files differ
diff --git a/res/drawable-xhdpi/workspace_bg.9.png b/res/drawable-xhdpi/workspace_bg.9.png
index 72269f2..0b80cbf 100644
--- a/res/drawable-xhdpi/workspace_bg.9.png
+++ b/res/drawable-xhdpi/workspace_bg.9.png
Binary files differ
diff --git a/res/drawable-xxhdpi/cling_bg.9.png b/res/drawable-xxhdpi/cling_bg.9.png
index dc9f69a..d31ea70 100644
--- a/res/drawable-xxhdpi/cling_bg.9.png
+++ b/res/drawable-xxhdpi/cling_bg.9.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_all_apps_bg_hand.png b/res/drawable-xxhdpi/ic_all_apps_bg_hand.png
index e107c2e..ed694f8 100644
--- a/res/drawable-xxhdpi/ic_all_apps_bg_hand.png
+++ b/res/drawable-xxhdpi/ic_all_apps_bg_hand.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_all_apps_bg_icon_1.png b/res/drawable-xxhdpi/ic_all_apps_bg_icon_1.png
index 7482830..5cb0427 100644
--- a/res/drawable-xxhdpi/ic_all_apps_bg_icon_1.png
+++ b/res/drawable-xxhdpi/ic_all_apps_bg_icon_1.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_all_apps_bg_icon_2.png b/res/drawable-xxhdpi/ic_all_apps_bg_icon_2.png
index 028c7f4..cd0322b 100644
--- a/res/drawable-xxhdpi/ic_all_apps_bg_icon_2.png
+++ b/res/drawable-xxhdpi/ic_all_apps_bg_icon_2.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_all_apps_bg_icon_3.png b/res/drawable-xxhdpi/ic_all_apps_bg_icon_3.png
index dce7b67..19ffc2d 100644
--- a/res/drawable-xxhdpi/ic_all_apps_bg_icon_3.png
+++ b/res/drawable-xxhdpi/ic_all_apps_bg_icon_3.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_all_apps_bg_icon_4.png b/res/drawable-xxhdpi/ic_all_apps_bg_icon_4.png
index 811a6b3..311c3df 100644
--- a/res/drawable-xxhdpi/ic_all_apps_bg_icon_4.png
+++ b/res/drawable-xxhdpi/ic_all_apps_bg_icon_4.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_allapps.png b/res/drawable-xxhdpi/ic_allapps.png
index 5dbfe4c..cf6a2cb 100644
--- a/res/drawable-xxhdpi/ic_allapps.png
+++ b/res/drawable-xxhdpi/ic_allapps.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_allapps_pressed.png b/res/drawable-xxhdpi/ic_allapps_pressed.png
index e761723..379389a 100644
--- a/res/drawable-xxhdpi/ic_allapps_pressed.png
+++ b/res/drawable-xxhdpi/ic_allapps_pressed.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_arrow_back_grey.png b/res/drawable-xxhdpi/ic_arrow_back_grey.png
index ccd3900..a3ed052 100755
--- a/res/drawable-xxhdpi/ic_arrow_back_grey.png
+++ b/res/drawable-xxhdpi/ic_arrow_back_grey.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_info_launcher.png b/res/drawable-xxhdpi/ic_info_launcher.png
index 386d091..8e602da 100644
--- a/res/drawable-xxhdpi/ic_info_launcher.png
+++ b/res/drawable-xxhdpi/ic_info_launcher.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_pageindicator_add.png b/res/drawable-xxhdpi/ic_pageindicator_add.png
index c288952..d790e86 100644
--- a/res/drawable-xxhdpi/ic_pageindicator_add.png
+++ b/res/drawable-xxhdpi/ic_pageindicator_add.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_pageindicator_current.png b/res/drawable-xxhdpi/ic_pageindicator_current.png
index 5941c8e..9550c61 100644
--- a/res/drawable-xxhdpi/ic_pageindicator_current.png
+++ b/res/drawable-xxhdpi/ic_pageindicator_current.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_pageindicator_current_folder.png b/res/drawable-xxhdpi/ic_pageindicator_current_folder.png
index 602b89a..987c882 100644
--- a/res/drawable-xxhdpi/ic_pageindicator_current_folder.png
+++ b/res/drawable-xxhdpi/ic_pageindicator_current_folder.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_pageindicator_default.png b/res/drawable-xxhdpi/ic_pageindicator_default.png
index 3fa9e5f..3bee96f 100644
--- a/res/drawable-xxhdpi/ic_pageindicator_default.png
+++ b/res/drawable-xxhdpi/ic_pageindicator_default.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_pageindicator_default_folder.png b/res/drawable-xxhdpi/ic_pageindicator_default_folder.png
index bbcd7f9..46ff473 100644
--- a/res/drawable-xxhdpi/ic_pageindicator_default_folder.png
+++ b/res/drawable-xxhdpi/ic_pageindicator_default_folder.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_remove_launcher.png b/res/drawable-xxhdpi/ic_remove_launcher.png
index 7c28bb0..78ca080 100644
--- a/res/drawable-xxhdpi/ic_remove_launcher.png
+++ b/res/drawable-xxhdpi/ic_remove_launcher.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_search_grey.png b/res/drawable-xxhdpi/ic_search_grey.png
index f4c5e27..33b4ea9 100755
--- a/res/drawable-xxhdpi/ic_search_grey.png
+++ b/res/drawable-xxhdpi/ic_search_grey.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_setting.png b/res/drawable-xxhdpi/ic_setting.png
index 01bdcd5..3effb50 100644
--- a/res/drawable-xxhdpi/ic_setting.png
+++ b/res/drawable-xxhdpi/ic_setting.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_setting_pressed.png b/res/drawable-xxhdpi/ic_setting_pressed.png
index d0cad5e..d78cad6 100644
--- a/res/drawable-xxhdpi/ic_setting_pressed.png
+++ b/res/drawable-xxhdpi/ic_setting_pressed.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_uninstall_launcher.png b/res/drawable-xxhdpi/ic_uninstall_launcher.png
index 872e829..43aba6e 100644
--- a/res/drawable-xxhdpi/ic_uninstall_launcher.png
+++ b/res/drawable-xxhdpi/ic_uninstall_launcher.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_wallpaper.png b/res/drawable-xxhdpi/ic_wallpaper.png
index 490c45a..218fd1d 100644
--- a/res/drawable-xxhdpi/ic_wallpaper.png
+++ b/res/drawable-xxhdpi/ic_wallpaper.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_wallpaper_pressed.png b/res/drawable-xxhdpi/ic_wallpaper_pressed.png
index e5d200b..52c92cb 100644
--- a/res/drawable-xxhdpi/ic_wallpaper_pressed.png
+++ b/res/drawable-xxhdpi/ic_wallpaper_pressed.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_widget.png b/res/drawable-xxhdpi/ic_widget.png
index d4b8324..cc5002e 100644
--- a/res/drawable-xxhdpi/ic_widget.png
+++ b/res/drawable-xxhdpi/ic_widget.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_widget_pressed.png b/res/drawable-xxhdpi/ic_widget_pressed.png
index b8dd35d..0c9b02a 100644
--- a/res/drawable-xxhdpi/ic_widget_pressed.png
+++ b/res/drawable-xxhdpi/ic_widget_pressed.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_widget_resize_handle.png b/res/drawable-xxhdpi/ic_widget_resize_handle.png
index 144cac9..736a157 100644
--- a/res/drawable-xxhdpi/ic_widget_resize_handle.png
+++ b/res/drawable-xxhdpi/ic_widget_resize_handle.png
Binary files differ
diff --git a/res/drawable-xxhdpi/page_hover_left.9.png b/res/drawable-xxhdpi/page_hover_left.9.png
index 63869dd..c81f86c 100644
--- a/res/drawable-xxhdpi/page_hover_left.9.png
+++ b/res/drawable-xxhdpi/page_hover_left.9.png
Binary files differ
diff --git a/res/drawable-xxhdpi/page_hover_left_active.9.png b/res/drawable-xxhdpi/page_hover_left_active.9.png
index 9a418ce..858a3b2 100644
--- a/res/drawable-xxhdpi/page_hover_left_active.9.png
+++ b/res/drawable-xxhdpi/page_hover_left_active.9.png
Binary files differ
diff --git a/res/drawable-xxhdpi/page_hover_right.9.png b/res/drawable-xxhdpi/page_hover_right.9.png
index c6fd398..c529770 100644
--- a/res/drawable-xxhdpi/page_hover_right.9.png
+++ b/res/drawable-xxhdpi/page_hover_right.9.png
Binary files differ
diff --git a/res/drawable-xxhdpi/page_hover_right_active.9.png b/res/drawable-xxhdpi/page_hover_right_active.9.png
index 7aef373..9900553 100644
--- a/res/drawable-xxhdpi/page_hover_right_active.9.png
+++ b/res/drawable-xxhdpi/page_hover_right_active.9.png
Binary files differ
diff --git a/res/drawable-xxhdpi/portal_ring_inner.png b/res/drawable-xxhdpi/portal_ring_inner.png
index d088a17..cd23cf7 100644
--- a/res/drawable-xxhdpi/portal_ring_inner.png
+++ b/res/drawable-xxhdpi/portal_ring_inner.png
Binary files differ
diff --git a/res/drawable-xxhdpi/portal_ring_inner_nolip.png b/res/drawable-xxhdpi/portal_ring_inner_nolip.png
index 0fad656..d82b910 100644
--- a/res/drawable-xxhdpi/portal_ring_inner_nolip.png
+++ b/res/drawable-xxhdpi/portal_ring_inner_nolip.png
Binary files differ
diff --git a/res/drawable-xxhdpi/portal_ring_outer.png b/res/drawable-xxhdpi/portal_ring_outer.png
index 45ac040..e5d33b2 100644
--- a/res/drawable-xxhdpi/portal_ring_outer.png
+++ b/res/drawable-xxhdpi/portal_ring_outer.png
Binary files differ
diff --git a/res/drawable-xxhdpi/portal_ring_rest.png b/res/drawable-xxhdpi/portal_ring_rest.png
index 6fa6a53..d52825c 100644
--- a/res/drawable-xxhdpi/portal_ring_rest.png
+++ b/res/drawable-xxhdpi/portal_ring_rest.png
Binary files differ
diff --git a/res/drawable-xxhdpi/quantum_panel_bitmap.9.png b/res/drawable-xxhdpi/quantum_panel_bitmap.9.png
index b44269e..1dd1f6d 100644
--- a/res/drawable-xxhdpi/quantum_panel_bitmap.9.png
+++ b/res/drawable-xxhdpi/quantum_panel_bitmap.9.png
Binary files differ
diff --git a/res/drawable-xxhdpi/quantum_panel_dark_bitmap.9.png b/res/drawable-xxhdpi/quantum_panel_dark_bitmap.9.png
index 7979cf7..48d584b 100644
--- a/res/drawable-xxhdpi/quantum_panel_dark_bitmap.9.png
+++ b/res/drawable-xxhdpi/quantum_panel_dark_bitmap.9.png
Binary files differ
diff --git a/res/drawable-xxhdpi/screenpanel.9.png b/res/drawable-xxhdpi/screenpanel.9.png
index 2d13954..b221b37 100644
--- a/res/drawable-xxhdpi/screenpanel.9.png
+++ b/res/drawable-xxhdpi/screenpanel.9.png
Binary files differ
diff --git a/res/drawable-xxhdpi/screenpanel_hover.9.png b/res/drawable-xxhdpi/screenpanel_hover.9.png
index 369fc44..418cf0a 100644
--- a/res/drawable-xxhdpi/screenpanel_hover.9.png
+++ b/res/drawable-xxhdpi/screenpanel_hover.9.png
Binary files differ
diff --git a/res/drawable-xxhdpi/virtual_preload.9.png b/res/drawable-xxhdpi/virtual_preload.9.png
index 93e3b33..03c6e7f 100644
--- a/res/drawable-xxhdpi/virtual_preload.9.png
+++ b/res/drawable-xxhdpi/virtual_preload.9.png
Binary files differ
diff --git a/res/drawable-xxhdpi/virtual_preload_folder.9.png b/res/drawable-xxhdpi/virtual_preload_folder.9.png
index fae19b3..052a72e 100644
--- a/res/drawable-xxhdpi/virtual_preload_folder.9.png
+++ b/res/drawable-xxhdpi/virtual_preload_folder.9.png
Binary files differ
diff --git a/res/drawable-xxhdpi/widget_resize_frame.9.png b/res/drawable-xxhdpi/widget_resize_frame.9.png
index 7e189d4..ea527f4 100644
--- a/res/drawable-xxhdpi/widget_resize_frame.9.png
+++ b/res/drawable-xxhdpi/widget_resize_frame.9.png
Binary files differ
diff --git a/res/drawable-xxhdpi/widget_resize_shadow.9.png b/res/drawable-xxhdpi/widget_resize_shadow.9.png
index 41c448b..5412168 100644
--- a/res/drawable-xxhdpi/widget_resize_shadow.9.png
+++ b/res/drawable-xxhdpi/widget_resize_shadow.9.png
Binary files differ
diff --git a/res/drawable-xxhdpi/widget_tile.png b/res/drawable-xxhdpi/widget_tile.png
index 3a3790d..c6237db 100644
--- a/res/drawable-xxhdpi/widget_tile.png
+++ b/res/drawable-xxhdpi/widget_tile.png
Binary files differ
diff --git a/res/drawable-xxhdpi/workspace_bg.9.png b/res/drawable-xxhdpi/workspace_bg.9.png
index efc9b04..0d180c2 100644
--- a/res/drawable-xxhdpi/workspace_bg.9.png
+++ b/res/drawable-xxhdpi/workspace_bg.9.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/ic_all_apps_bg_hand.png b/res/drawable-xxxhdpi/ic_all_apps_bg_hand.png
index c638456..615374a 100644
--- a/res/drawable-xxxhdpi/ic_all_apps_bg_hand.png
+++ b/res/drawable-xxxhdpi/ic_all_apps_bg_hand.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/ic_all_apps_bg_icon_1.png b/res/drawable-xxxhdpi/ic_all_apps_bg_icon_1.png
index 511a02a..10f8c41 100644
--- a/res/drawable-xxxhdpi/ic_all_apps_bg_icon_1.png
+++ b/res/drawable-xxxhdpi/ic_all_apps_bg_icon_1.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/ic_all_apps_bg_icon_2.png b/res/drawable-xxxhdpi/ic_all_apps_bg_icon_2.png
index 2cc18f8..102d925 100644
--- a/res/drawable-xxxhdpi/ic_all_apps_bg_icon_2.png
+++ b/res/drawable-xxxhdpi/ic_all_apps_bg_icon_2.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/ic_all_apps_bg_icon_3.png b/res/drawable-xxxhdpi/ic_all_apps_bg_icon_3.png
index c32f8ff..9be5b7a 100644
--- a/res/drawable-xxxhdpi/ic_all_apps_bg_icon_3.png
+++ b/res/drawable-xxxhdpi/ic_all_apps_bg_icon_3.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/ic_all_apps_bg_icon_4.png b/res/drawable-xxxhdpi/ic_all_apps_bg_icon_4.png
index 7bead8a..d7fb29b 100644
--- a/res/drawable-xxxhdpi/ic_all_apps_bg_icon_4.png
+++ b/res/drawable-xxxhdpi/ic_all_apps_bg_icon_4.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/ic_arrow_back_grey.png b/res/drawable-xxxhdpi/ic_arrow_back_grey.png
index 79b9b48..6b42051 100755
--- a/res/drawable-xxxhdpi/ic_arrow_back_grey.png
+++ b/res/drawable-xxxhdpi/ic_arrow_back_grey.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/ic_info_launcher.png b/res/drawable-xxxhdpi/ic_info_launcher.png
index bf39e5b..3540de1 100644
--- a/res/drawable-xxxhdpi/ic_info_launcher.png
+++ b/res/drawable-xxxhdpi/ic_info_launcher.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/ic_remove_launcher.png b/res/drawable-xxxhdpi/ic_remove_launcher.png
index 7043be0..418d81a 100644
--- a/res/drawable-xxxhdpi/ic_remove_launcher.png
+++ b/res/drawable-xxxhdpi/ic_remove_launcher.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/ic_search_grey.png b/res/drawable-xxxhdpi/ic_search_grey.png
index bd5fdf4..d957186 100755
--- a/res/drawable-xxxhdpi/ic_search_grey.png
+++ b/res/drawable-xxxhdpi/ic_search_grey.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/ic_uninstall_launcher.png b/res/drawable-xxxhdpi/ic_uninstall_launcher.png
index 77a3302..724437a 100644
--- a/res/drawable-xxxhdpi/ic_uninstall_launcher.png
+++ b/res/drawable-xxxhdpi/ic_uninstall_launcher.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/ic_widget_resize_handle.png b/res/drawable-xxxhdpi/ic_widget_resize_handle.png
index 4bde6b9..e3c45ad 100644
--- a/res/drawable-xxxhdpi/ic_widget_resize_handle.png
+++ b/res/drawable-xxxhdpi/ic_widget_resize_handle.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/portal_ring_inner.png b/res/drawable-xxxhdpi/portal_ring_inner.png
index 34a3599..59e811d 100644
--- a/res/drawable-xxxhdpi/portal_ring_inner.png
+++ b/res/drawable-xxxhdpi/portal_ring_inner.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/portal_ring_inner_nolip.png b/res/drawable-xxxhdpi/portal_ring_inner_nolip.png
index 8cebb35..c1e7585 100644
--- a/res/drawable-xxxhdpi/portal_ring_inner_nolip.png
+++ b/res/drawable-xxxhdpi/portal_ring_inner_nolip.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/portal_ring_outer.png b/res/drawable-xxxhdpi/portal_ring_outer.png
index d2df322..f2f818b 100644
--- a/res/drawable-xxxhdpi/portal_ring_outer.png
+++ b/res/drawable-xxxhdpi/portal_ring_outer.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/portal_ring_rest.png b/res/drawable-xxxhdpi/portal_ring_rest.png
index 11e92ee..2af67b8 100644
--- a/res/drawable-xxxhdpi/portal_ring_rest.png
+++ b/res/drawable-xxxhdpi/portal_ring_rest.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/quantum_panel_bitmap.9.png b/res/drawable-xxxhdpi/quantum_panel_bitmap.9.png
index bc887fe..915177d 100644
--- a/res/drawable-xxxhdpi/quantum_panel_bitmap.9.png
+++ b/res/drawable-xxxhdpi/quantum_panel_bitmap.9.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/quantum_panel_dark_bitmap.9.png b/res/drawable-xxxhdpi/quantum_panel_dark_bitmap.9.png
index 7cfd6e4..27b8466 100644
--- a/res/drawable-xxxhdpi/quantum_panel_dark_bitmap.9.png
+++ b/res/drawable-xxxhdpi/quantum_panel_dark_bitmap.9.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/widget_resize_frame.9.png b/res/drawable-xxxhdpi/widget_resize_frame.9.png
index cb609ce..4644e9a 100644
--- a/res/drawable-xxxhdpi/widget_resize_frame.9.png
+++ b/res/drawable-xxxhdpi/widget_resize_frame.9.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/widget_resize_shadow.9.png b/res/drawable-xxxhdpi/widget_resize_shadow.9.png
index 82c8b9c..63cea84 100644
--- a/res/drawable-xxxhdpi/widget_resize_shadow.9.png
+++ b/res/drawable-xxxhdpi/widget_resize_shadow.9.png
Binary files differ
diff --git a/res/layout/all_apps_search_market.xml b/res/layout/all_apps_search_market.xml
index 1ed5088..a2bb2e7 100644
--- a/res/layout/all_apps_search_market.xml
+++ b/res/layout/all_apps_search_market.xml
@@ -25,5 +25,5 @@
android:textSize="14sp"
android:textColor="@color/launcher_accent_color"
android:textAllCaps="true"
- android:focusable="false"
+ android:focusable="true"
android:background="@drawable/all_apps_search_market_bg" />
diff --git a/res/layout/overview_panel.xml b/res/layout/overview_panel.xml
index 1f02dce..4f54f1d 100644
--- a/res/layout/overview_panel.xml
+++ b/res/layout/overview_panel.xml
@@ -33,7 +33,8 @@
android:text="@string/wallpaper_button_text"
android:textAllCaps="true"
android:textColor="@android:color/white"
- android:textSize="12sp" />
+ android:textSize="12sp"
+ android:focusable="true" />
<TextView
android:id="@+id/widget_button"
@@ -47,7 +48,8 @@
android:text="@string/widget_button_text"
android:textAllCaps="true"
android:textColor="@android:color/white"
- android:textSize="12sp" />
+ android:textSize="12sp"
+ android:focusable="true" />
<TextView
android:id="@+id/settings_button"
@@ -61,6 +63,7 @@
android:text="@string/settings_button_text"
android:textAllCaps="true"
android:textColor="@android:color/white"
- android:textSize="12sp" />
+ android:textSize="12sp"
+ android:focusable="true" />
</LinearLayout>
\ No newline at end of file
diff --git a/res/layout/dummy_widget.xml b/res/layout/zzz_dummy_widget.xml
similarity index 100%
rename from res/layout/dummy_widget.xml
rename to res/layout/zzz_dummy_widget.xml
diff --git a/res/layout/zzz_weight_watcher.xml b/res/layout/zzz_weight_watcher.xml
new file mode 100644
index 0000000..07fd39e
--- /dev/null
+++ b/res/layout/zzz_weight_watcher.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<com.android.launcher3.testing.WeightWatcher xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" />
diff --git a/res/mipmap-hdpi/ic_launcher_home.png b/res/mipmap-hdpi/ic_launcher_home.png
index b556d7a..d068d92 100644
--- a/res/mipmap-hdpi/ic_launcher_home.png
+++ b/res/mipmap-hdpi/ic_launcher_home.png
Binary files differ
diff --git a/res/mipmap-mdpi/ic_launcher_home.png b/res/mipmap-mdpi/ic_launcher_home.png
index 961bb7d..16c8ec2 100644
--- a/res/mipmap-mdpi/ic_launcher_home.png
+++ b/res/mipmap-mdpi/ic_launcher_home.png
Binary files differ
diff --git a/res/mipmap-xhdpi/ic_launcher_home.png b/res/mipmap-xhdpi/ic_launcher_home.png
index 46ec2b7..8b2671b 100644
--- a/res/mipmap-xhdpi/ic_launcher_home.png
+++ b/res/mipmap-xhdpi/ic_launcher_home.png
Binary files differ
diff --git a/res/mipmap-xxhdpi/ic_launcher_home.png b/res/mipmap-xxhdpi/ic_launcher_home.png
index d2975a3..43d8b7d 100644
--- a/res/mipmap-xxhdpi/ic_launcher_home.png
+++ b/res/mipmap-xxhdpi/ic_launcher_home.png
Binary files differ
diff --git a/res/values-af/strings.xml b/res/values-af/strings.xml
index b94ddab..e426e50 100644
--- a/res/values-af/strings.xml
+++ b/res/values-af/strings.xml
@@ -26,8 +26,8 @@
<string name="activity_not_available" msgid="7456344436509528827">"Program is nie beskikbaar nie"</string>
<string name="safemode_shortcut_error" msgid="9160126848219158407">"Afgelaaide program in veiligmodus gedeaktiveer"</string>
<string name="safemode_widget_error" msgid="4863470563535682004">"Legstukke gedeaktiveer in Veiligmodus"</string>
- <string name="toggle_weight_watcher" msgid="5645299835184636119">"Wys Mem"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"Raak en hou om \'n legstuk op te tel."</string>
+ <string name="long_accessible_way_to_add" msgid="4289502106628154155">"Dubbeltik en hou om \'n legstuk op te tel of gebruik gepasmaakte handelinge."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="all_apps_search_bar_hint" msgid="7084713969757597256">"Deursoek programme"</string>
<string name="all_apps_loading_message" msgid="7557140873644765180">"Laai tans programme …"</string>
@@ -53,6 +53,7 @@
<string name="folder_hint_text" msgid="6617836969016293992">"Naamlose vouer"</string>
<string name="default_scroll_format" msgid="7475544710230993317">"Bladsy %1$d van %2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"Tuisskerm %1$d van %2$d"</string>
+ <string name="workspace_new_page" msgid="257366611030256142">"Nuwe tuisskermbladsy"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"Welkom"</string>
<string name="migration_cling_title" msgid="9181776667882933767">"Kopieer jou program-ikone"</string>
<string name="migration_cling_description" msgid="2752413805582227644">"Voer ikone en vouers vanaf jou ou tuisskerms in?"</string>
@@ -76,6 +77,8 @@
<string name="abandoned_search" msgid="891119232568284442">"Soek"</string>
<string name="abandoned_promises_title" msgid="7096178467971716750">"Hierdie program is nie geïnstalleer nie"</string>
<string name="abandoned_promise_explanation" msgid="3990027586878167529">"Die program vir hierdie ikoon is nie geïnstalleer nie. Jy kan dit verwyder of die program soek en dit self installeer."</string>
+ <string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> laai tans af, <xliff:g id="PROGRESS">%2$s</xliff:g> voltooid"</string>
+ <string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> wag tans om te installeer"</string>
<string name="action_add_to_workspace" msgid="8902165848117513641">"Voeg by tuisskerm"</string>
<string name="action_move_here" msgid="2170188780612570250">"Skuif item hierheen"</string>
<string name="item_added_to_workspace" msgid="4211073925752213539">"Item is by tuisskerm gevoeg"</string>
diff --git a/res/values-am/strings.xml b/res/values-am/strings.xml
index fc404ff..2d1fb3d 100644
--- a/res/values-am/strings.xml
+++ b/res/values-am/strings.xml
@@ -26,8 +26,8 @@
<string name="activity_not_available" msgid="7456344436509528827">"መተግበሪያ አይገኝም"</string>
<string name="safemode_shortcut_error" msgid="9160126848219158407">"የወረደው መተግበሪያ ደህንነቱ በተጠበቀ ሁኔታ ውስጥ ተሰናክሏል"</string>
<string name="safemode_widget_error" msgid="4863470563535682004">"ምግብሮች በደህንነቱ የተጠበቀ ሁኔታ ተሰናክለዋል"</string>
- <string name="toggle_weight_watcher" msgid="5645299835184636119">"ማህደረ ማስታወሻ አሳይ"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"ፍርግም ለማንሳት ይንኩ እና ይያዙት"</string>
+ <string name="long_accessible_way_to_add" msgid="4289502106628154155">"አንድ ንዑስ ፕሮግራም ለመምረጥ ወይም ብጁ እርምጃዎችን ለመጠቀም ሁለቴ መታ አድርገው ይያዙ።"</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="all_apps_search_bar_hint" msgid="7084713969757597256">"መተግበሪያዎችን ይፈልጉ"</string>
<string name="all_apps_loading_message" msgid="7557140873644765180">"መተግበሪያዎችን በመጫን ላይ..."</string>
@@ -53,6 +53,7 @@
<string name="folder_hint_text" msgid="6617836969016293992">"ስም-አልባ አቃፊ"</string>
<string name="default_scroll_format" msgid="7475544710230993317">"ገጽ %1$d ከ%2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"መነሻ ማያ ገጽ %1$d ከ%2$d"</string>
+ <string name="workspace_new_page" msgid="257366611030256142">"አዲስ የመነሻ ማያ ገጽ"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"እንኳን በደህና መጡ"</string>
<string name="migration_cling_title" msgid="9181776667882933767">"የመተግበሪያ አዶዎችዎን ይቅዱ"</string>
<string name="migration_cling_description" msgid="2752413805582227644">"አዶዎች እና አቃፊዎች ከድሮው የመነሻ ማያ ገጾችዎ ይምጡ?"</string>
@@ -76,6 +77,8 @@
<string name="abandoned_search" msgid="891119232568284442">"ፈልግ"</string>
<string name="abandoned_promises_title" msgid="7096178467971716750">"ይህ መተግበሪያ አልተጫነም"</string>
<string name="abandoned_promise_explanation" msgid="3990027586878167529">"የዚህ አዶ መተግበሪያ አልተጫነም። ማስወገድ ወይም መተግበሪያውን መፈለግና ራስዎ መጫን ይችላሉ።"</string>
+ <string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> በመውረድ ላይ፣ <xliff:g id="PROGRESS">%2$s</xliff:g> ተጠናቋል"</string>
+ <string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> ለመጫን በመጠበቅ ላይ"</string>
<string name="action_add_to_workspace" msgid="8902165848117513641">"ወደ መነሻ ማያ ገጽ ያክሉ"</string>
<string name="action_move_here" msgid="2170188780612570250">"ንጥልን ወደዚህ ውሰድ"</string>
<string name="item_added_to_workspace" msgid="4211073925752213539">"ወደ መነሻ ማያ ገጽ ንጥል ታክሏል"</string>
diff --git a/res/values-ar/strings.xml b/res/values-ar/strings.xml
index 1bea20c..67400d4 100644
--- a/res/values-ar/strings.xml
+++ b/res/values-ar/strings.xml
@@ -26,8 +26,8 @@
<string name="activity_not_available" msgid="7456344436509528827">"التطبيق ليس متاحًا"</string>
<string name="safemode_shortcut_error" msgid="9160126848219158407">"تم تعطيل التطبيق الذي تم تنزيله في الوضع الآمن"</string>
<string name="safemode_widget_error" msgid="4863470563535682004">"الأدوات معطلة في الوضع الآمن"</string>
- <string name="toggle_weight_watcher" msgid="5645299835184636119">"عرض الذاكرة"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"المس مع الاستمرار لاختيار إحدى الأدوات."</string>
+ <string name="long_accessible_way_to_add" msgid="4289502106628154155">"انقر نقرًا مزدوجًا مع الاستمرار لاختيار أداة أو استخدم الإجراءات المخصصة."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="all_apps_search_bar_hint" msgid="7084713969757597256">"البحث في التطبيقات"</string>
<string name="all_apps_loading_message" msgid="7557140873644765180">"جارٍ تحميل التطبيقات…"</string>
@@ -53,6 +53,7 @@
<string name="folder_hint_text" msgid="6617836969016293992">"مجلد بدون اسم"</string>
<string name="default_scroll_format" msgid="7475544710230993317">"الصفحة %1$d من %2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"الشاشة الرئيسية %1$d من %2$d"</string>
+ <string name="workspace_new_page" msgid="257366611030256142">"صفحة الشاشة الرئيسية الجديدة"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"مرحبًا"</string>
<string name="migration_cling_title" msgid="9181776667882933767">"نسخ رموز التطبيقات"</string>
<string name="migration_cling_description" msgid="2752413805582227644">"هل تريد استيراد رموز ومجلدات من الشاشات الرئيسية القديمة؟"</string>
@@ -76,6 +77,8 @@
<string name="abandoned_search" msgid="891119232568284442">"بحث"</string>
<string name="abandoned_promises_title" msgid="7096178467971716750">"لم يتم تثبيت هذا التطبيق"</string>
<string name="abandoned_promise_explanation" msgid="3990027586878167529">"لم يتم تثبيت تطبيق لهذا الرمز. يمكنك إزالته أو البحث عن التطبيق وتثبيته يدويًا."</string>
+ <string name="app_downloading_title" msgid="8336702962104482644">"جارٍ تنزيل <xliff:g id="NAME">%1$s</xliff:g>، اكتمل <xliff:g id="PROGRESS">%2$s</xliff:g>"</string>
+ <string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> في انتظار التثبيت"</string>
<string name="action_add_to_workspace" msgid="8902165848117513641">"إضافة إلى الشاشة الرئيسية"</string>
<string name="action_move_here" msgid="2170188780612570250">"نقل العنصر إلى هنا"</string>
<string name="item_added_to_workspace" msgid="4211073925752213539">"تمت إضافة العنصر إلى الشاشة الرئيسية"</string>
diff --git a/res/values-az-rAZ/strings.xml b/res/values-az-rAZ/strings.xml
index 6a2bbbb..b9ea83f 100644
--- a/res/values-az-rAZ/strings.xml
+++ b/res/values-az-rAZ/strings.xml
@@ -19,7 +19,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_name" msgid="649227358658669779">"Launcher3"</string>
+ <string name="application_name" msgid="5181331383435256801">"Launcher3"</string>
<string name="folder_name" msgid="7371454440695724752"></string>
<string name="work_folder_name" msgid="3753320833950115786">"İş"</string>
<string name="activity_not_found" msgid="8071924732094499514">"Tətbiq quraşdırılmayıb."</string>
@@ -46,7 +46,6 @@
<string name="permdesc_read_settings" msgid="5833423719057558387">"Tətbiqə Əsas Səhifədə parametrləri və qısayolları oxumağa icazə verir."</string>
<string name="permlab_write_settings" msgid="3574213698004620587">"Əsas Səhifə ayarlarını və qısayolları yazın"</string>
<string name="permdesc_write_settings" msgid="5440712911516509985">"Tətbiqə Əsas Səhifədə ayarları və qısayolları dəyişməyə icazə verir."</string>
- <string name="msg_no_phone_permission" msgid="9208659281529857371">"<xliff:g id="APP_NAME">%1$s</xliff:g> tətbiqinə telefon zəngləri etmək üçün icazə verilmir"</string>
<string name="gadget_error_text" msgid="6081085226050792095">"Vidcet yükləmə problemi"</string>
<string name="gadget_setup_text" msgid="8274003207686040488">"Quraşdırma"</string>
<string name="uninstall_system_app_text" msgid="4172046090762920660">"Bu sistem tətbiqi olduğu üçün sistemdən silinə bilməz."</string>
diff --git a/res/values-bg/strings.xml b/res/values-bg/strings.xml
index 92bc153..0ba7525 100644
--- a/res/values-bg/strings.xml
+++ b/res/values-bg/strings.xml
@@ -26,8 +26,8 @@
<string name="activity_not_available" msgid="7456344436509528827">"Приложението не е налично"</string>
<string name="safemode_shortcut_error" msgid="9160126848219158407">"Изтегленото приложение е деактивирано в безопасния режим"</string>
<string name="safemode_widget_error" msgid="4863470563535682004">"Приспособленията са деактивирани в безопасния режим"</string>
- <string name="toggle_weight_watcher" msgid="5645299835184636119">"Показване на паметта"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"Докоснете и задръжте за избор на приспособление."</string>
+ <string name="long_accessible_way_to_add" msgid="4289502106628154155">"Докоснете двукратно и задръжте за избор на приспособление или използвайте персонализирани действия."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="all_apps_search_bar_hint" msgid="7084713969757597256">"Търсене в приложенията"</string>
<string name="all_apps_loading_message" msgid="7557140873644765180">"Приложенията се зареждат…"</string>
@@ -53,6 +53,7 @@
<string name="folder_hint_text" msgid="6617836969016293992">"Папка без име"</string>
<string name="default_scroll_format" msgid="7475544710230993317">"Страница %1$d от %2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"Начален екран %1$d от %2$d"</string>
+ <string name="workspace_new_page" msgid="257366611030256142">"Нова страница на началния екран"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"Добре дошли"</string>
<string name="migration_cling_title" msgid="9181776667882933767">"Икони на прилож. ви: Копиране"</string>
<string name="migration_cling_description" msgid="2752413805582227644">"Да се импортират ли иконите и папките от старите ви начални екрани?"</string>
@@ -76,6 +77,8 @@
<string name="abandoned_search" msgid="891119232568284442">"Търсене"</string>
<string name="abandoned_promises_title" msgid="7096178467971716750">"Това приложение не е инсталирано"</string>
<string name="abandoned_promise_explanation" msgid="3990027586878167529">"Приложението за тази икона не е инсталирано. Можете да я премахнете или да потърсите приложението и да го инсталирате ръчно."</string>
+ <string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> се изтегля. Завършено: <xliff:g id="PROGRESS">%2$s</xliff:g>"</string>
+ <string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> изчаква инсталиране"</string>
<string name="action_add_to_workspace" msgid="8902165848117513641">"Добавяне към началния екран"</string>
<string name="action_move_here" msgid="2170188780612570250">"Преместване на елемента тук"</string>
<string name="item_added_to_workspace" msgid="4211073925752213539">"Елементът е добавен към началния екран"</string>
diff --git a/res/values-bn-rBD/strings.xml b/res/values-bn-rBD/strings.xml
index fd9b711..8f0c922 100644
--- a/res/values-bn-rBD/strings.xml
+++ b/res/values-bn-rBD/strings.xml
@@ -26,8 +26,8 @@
<string name="activity_not_available" msgid="7456344436509528827">"অ্যাপ্লিকেশান অনুপলব্ধ"</string>
<string name="safemode_shortcut_error" msgid="9160126848219158407">"ডাউনলোড করা অ্যাপ্লিকেশান নিরাপদ মোডে অক্ষম রয়েছে"</string>
<string name="safemode_widget_error" msgid="4863470563535682004">"সুরক্ষিত মোডে উইজেট নিষ্ক্রিয় থাকে"</string>
- <string name="toggle_weight_watcher" msgid="5645299835184636119">"মেম দেখান"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"একটি উইজেট তুলতে তা স্পর্শ করে ধরে রাখুন৷"</string>
+ <string name="long_accessible_way_to_add" msgid="4289502106628154155">"কোনো উইজেট বেছে নিতে দুবার-আলতো চেপে ধরে থাকুন অথবা কাস্টম ক্রিয়াগুলি ব্যবহার করুন৷"</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="all_apps_search_bar_hint" msgid="7084713969757597256">"অ্যাপ্লিকেশানগুলি অনুসন্ধান করুন"</string>
<string name="all_apps_loading_message" msgid="7557140873644765180">"অ্যাপ্লিকেশানগুলি লোড হচ্ছে..."</string>
@@ -53,6 +53,7 @@
<string name="folder_hint_text" msgid="6617836969016293992">"নামবিহীন ফোল্ডার"</string>
<string name="default_scroll_format" msgid="7475544710230993317">"%2$dটির মধ্যে %1$dটি পৃষ্ঠা"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"%2$dটির %1$d নম্বর হোম স্ক্রীন"</string>
+ <string name="workspace_new_page" msgid="257366611030256142">"নতুন হোম স্ক্রীনের পৃষ্ঠা"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"স্বাগতম"</string>
<string name="migration_cling_title" msgid="9181776667882933767">"আপনার অ্যাপ্লিকেশান আইকনগুলি অনুলিপি করুন"</string>
<string name="migration_cling_description" msgid="2752413805582227644">"আপনার পুরানো হোম স্ক্রীন থেকে আইকন এবং ফোল্ডারগুলি আমদানি করবেন?"</string>
@@ -76,6 +77,8 @@
<string name="abandoned_search" msgid="891119232568284442">"অনুসন্ধান"</string>
<string name="abandoned_promises_title" msgid="7096178467971716750">"এই অ্যাপ্লিকেশানটি ইন্সটল করা নাই"</string>
<string name="abandoned_promise_explanation" msgid="3990027586878167529">"এই আইকনের অ্যাপ্লিকেশানটি ইন্সটল করা নাই। আপনি এটি সরাতে পারেন বা অ্যাপ্লিকেশানটি অনুসন্ধান করে এটি নিজে ইন্সটল করতে পারেন।"</string>
+ <string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> ডাউনলোড হচ্ছে <xliff:g id="PROGRESS">%2$s</xliff:g> সম্পন্ন হয়েছে"</string>
+ <string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> ইনস্টলের অপেক্ষায় রয়েছে"</string>
<string name="action_add_to_workspace" msgid="8902165848117513641">"হোম স্ক্রীনে যোগ করুন"</string>
<string name="action_move_here" msgid="2170188780612570250">"এখানে আইটেম সরান"</string>
<string name="item_added_to_workspace" msgid="4211073925752213539">"হোম স্ক্রীনে আইটেম যোগ করা হয়েছে"</string>
diff --git a/res/values-ca/strings.xml b/res/values-ca/strings.xml
index 61ae743..2d3f9ed 100644
--- a/res/values-ca/strings.xml
+++ b/res/values-ca/strings.xml
@@ -26,8 +26,8 @@
<string name="activity_not_available" msgid="7456344436509528827">"L\'aplicació no està disponible."</string>
<string name="safemode_shortcut_error" msgid="9160126848219158407">"L\'aplicació que has baixat està desactivada al mode segur."</string>
<string name="safemode_widget_error" msgid="4863470563535682004">"En Mode segur, els widgets estan desactivats."</string>
- <string name="toggle_weight_watcher" msgid="5645299835184636119">"Mostra la memòria"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"Mantén premut un widget per triar-lo."</string>
+ <string name="long_accessible_way_to_add" msgid="4289502106628154155">"Fes doble toc i mantén premut per seleccionar un widget o per utilitzar les accions personalitzades."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="all_apps_search_bar_hint" msgid="7084713969757597256">"Cerca a les aplicacions"</string>
<string name="all_apps_loading_message" msgid="7557140873644765180">"S\'estan carregant les aplicacions..."</string>
@@ -53,6 +53,7 @@
<string name="folder_hint_text" msgid="6617836969016293992">"Carpeta sense nom"</string>
<string name="default_scroll_format" msgid="7475544710230993317">"Pàgina %1$d de %2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"Pantalla d\'inici %1$d de %2$d"</string>
+ <string name="workspace_new_page" msgid="257366611030256142">"Pàgina de la pantalla d\'inici nova"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"Us donem la benvinguda"</string>
<string name="migration_cling_title" msgid="9181776667882933767">"Copiar les icones d\'aplicació"</string>
<string name="migration_cling_description" msgid="2752413805582227644">"Importar icones i carpetes de pantalles d\'inici anteriors?"</string>
@@ -76,6 +77,8 @@
<string name="abandoned_search" msgid="891119232568284442">"Cerca"</string>
<string name="abandoned_promises_title" msgid="7096178467971716750">"Aquesta aplicació no està instal·lada"</string>
<string name="abandoned_promise_explanation" msgid="3990027586878167529">"L\'aplicació d\'aquesta icona no està instal·lada. Pots suprimir-la o cercar l\'aplicació i instal·lar-la manualment."</string>
+ <string name="app_downloading_title" msgid="8336702962104482644">"S\'està baixant <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="PROGRESS">%2$s</xliff:g> completat"</string>
+ <string name="app_waiting_download_title" msgid="7053938513995617849">"S\'està esperant per instal·lar <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="action_add_to_workspace" msgid="8902165848117513641">"Afegeix a la pantalla d\'inici"</string>
<string name="action_move_here" msgid="2170188780612570250">"Mou l\'element aquí"</string>
<string name="item_added_to_workspace" msgid="4211073925752213539">"S\'ha afegit l\'element a la pantalla d\'inici"</string>
diff --git a/res/values-cs/strings.xml b/res/values-cs/strings.xml
index 6d0326b..ce3757a 100644
--- a/res/values-cs/strings.xml
+++ b/res/values-cs/strings.xml
@@ -26,8 +26,8 @@
<string name="activity_not_available" msgid="7456344436509528827">"Aplikace není k dispozici."</string>
<string name="safemode_shortcut_error" msgid="9160126848219158407">"Stažená aplikace je v nouzovém režimu zakázána"</string>
<string name="safemode_widget_error" msgid="4863470563535682004">"V nouzovém režimu jsou widgety zakázány."</string>
- <string name="toggle_weight_watcher" msgid="5645299835184636119">"Zobrazit Mem"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"Widget vyberete dotykem a podržením."</string>
+ <string name="long_accessible_way_to_add" msgid="4289502106628154155">"Dvojitým klepnutím a podržením vyberte widget, případně použijte vlastní akce."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="all_apps_search_bar_hint" msgid="7084713969757597256">"Hledat aplikace"</string>
<string name="all_apps_loading_message" msgid="7557140873644765180">"Načítání aplikací…"</string>
@@ -53,6 +53,7 @@
<string name="folder_hint_text" msgid="6617836969016293992">"Složka bez názvu"</string>
<string name="default_scroll_format" msgid="7475544710230993317">"Strana %1$d z %2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"Plocha %1$d z %2$d"</string>
+ <string name="workspace_new_page" msgid="257366611030256142">"Nová stránka plochy"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"Vítejte"</string>
<string name="migration_cling_title" msgid="9181776667882933767">"Zkopírování ikon aplikací"</string>
<string name="migration_cling_description" msgid="2752413805582227644">"Chcete importovat ikony a složky ze svých starých ploch?"</string>
@@ -76,6 +77,8 @@
<string name="abandoned_search" msgid="891119232568284442">"Hledat"</string>
<string name="abandoned_promises_title" msgid="7096178467971716750">"Tato aplikace není nainstalována"</string>
<string name="abandoned_promise_explanation" msgid="3990027586878167529">"Aplikace pro tuto ikonu není nainstalována. Můžete ikonu odstranit nebo zkusit aplikaci vyhledat a nainstalovat ručně."</string>
+ <string name="app_downloading_title" msgid="8336702962104482644">"Stahování aplikace <xliff:g id="NAME">%1$s</xliff:g> (dokončeno <xliff:g id="PROGRESS">%2$s</xliff:g>)"</string>
+ <string name="app_waiting_download_title" msgid="7053938513995617849">"Instalace aplikace <xliff:g id="NAME">%1$s</xliff:g> čeká na zahájení"</string>
<string name="action_add_to_workspace" msgid="8902165848117513641">"Přidat na plochu"</string>
<string name="action_move_here" msgid="2170188780612570250">"Přesunout položku sem"</string>
<string name="item_added_to_workspace" msgid="4211073925752213539">"Položka byla přidána na plochu"</string>
diff --git a/res/values-da/strings.xml b/res/values-da/strings.xml
index d536bc6..ffa168b 100644
--- a/res/values-da/strings.xml
+++ b/res/values-da/strings.xml
@@ -26,8 +26,8 @@
<string name="activity_not_available" msgid="7456344436509528827">"Appen er ikke tilgængelig"</string>
<string name="safemode_shortcut_error" msgid="9160126848219158407">"Downloadet app er deaktiveret i sikker tilstand"</string>
<string name="safemode_widget_error" msgid="4863470563535682004">"Widgets er deaktiveret i Beskyttet tilstand"</string>
- <string name="toggle_weight_watcher" msgid="5645299835184636119">"Vis Mem"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"Tryk på en widget, og hold den nede for at vælge."</string>
+ <string name="long_accessible_way_to_add" msgid="4289502106628154155">"Tryk to gange, og hold fingeren nede for at vælge en widget eller bruge tilpassede handlinger."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="all_apps_search_bar_hint" msgid="7084713969757597256">"Søg i Apps"</string>
<string name="all_apps_loading_message" msgid="7557140873644765180">"Indlæser apps…"</string>
@@ -53,6 +53,7 @@
<string name="folder_hint_text" msgid="6617836969016293992">"Unavngiven mappe"</string>
<string name="default_scroll_format" msgid="7475544710230993317">"Side %1$d ud af %2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"Startskærm %1$d ud af %2$d"</string>
+ <string name="workspace_new_page" msgid="257366611030256142">"Ny startskærm"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"Velkommen"</string>
<string name="migration_cling_title" msgid="9181776667882933767">"Kopiér dine appikoner"</string>
<string name="migration_cling_description" msgid="2752413805582227644">"Vil du importere ikoner og mapper fra gamle startskærme?"</string>
@@ -76,6 +77,8 @@
<string name="abandoned_search" msgid="891119232568284442">"Søg"</string>
<string name="abandoned_promises_title" msgid="7096178467971716750">"Denne app er ikke installeret"</string>
<string name="abandoned_promise_explanation" msgid="3990027586878167529">"Appen, der hører til dette ikon, er ikke installeret. Du kan fjerne den eller prøve at søge efter appen og installere den manuelt."</string>
+ <string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> downloades. <xliff:g id="PROGRESS">%2$s</xliff:g> er gennemført"</string>
+ <string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> venter på at installere"</string>
<string name="action_add_to_workspace" msgid="8902165848117513641">"Føj til startskærm"</string>
<string name="action_move_here" msgid="2170188780612570250">"Flyt elementet hertil"</string>
<string name="item_added_to_workspace" msgid="4211073925752213539">"Elementet er føjet til startskærmen"</string>
diff --git a/res/values-de/strings.xml b/res/values-de/strings.xml
index bf423cb..118e34a 100644
--- a/res/values-de/strings.xml
+++ b/res/values-de/strings.xml
@@ -26,8 +26,8 @@
<string name="activity_not_available" msgid="7456344436509528827">"App nicht verfügbar"</string>
<string name="safemode_shortcut_error" msgid="9160126848219158407">"Heruntergeladene App im abgesicherten Modus deaktiviert"</string>
<string name="safemode_widget_error" msgid="4863470563535682004">"Widgets im abgesicherten Modus deaktiviert"</string>
- <string name="toggle_weight_watcher" msgid="5645299835184636119">"Speicher anzeigen"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"Zum Hinzufügen Widget berühren und halten"</string>
+ <string name="long_accessible_way_to_add" msgid="4289502106628154155">"Zum Hinzufügen auf Widget doppeltippen und gedrückt halten oder benutzerdefinierte Aktionen verwenden."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="all_apps_search_bar_hint" msgid="7084713969757597256">"In Apps suchen"</string>
<string name="all_apps_loading_message" msgid="7557140873644765180">"Apps werden geladen..."</string>
@@ -53,6 +53,7 @@
<string name="folder_hint_text" msgid="6617836969016293992">"Unbenannter Ordner"</string>
<string name="default_scroll_format" msgid="7475544710230993317">"Seite %1$d von %2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"Startbildschirm %1$d von %2$d"</string>
+ <string name="workspace_new_page" msgid="257366611030256142">"Neue Startbildschirmseite"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"Hallo!"</string>
<string name="migration_cling_title" msgid="9181776667882933767">"App-Symbole kopieren"</string>
<string name="migration_cling_description" msgid="2752413805582227644">"Symbole und Ordner alter Startbildschirme importieren?"</string>
@@ -76,6 +77,8 @@
<string name="abandoned_search" msgid="891119232568284442">"Suchen"</string>
<string name="abandoned_promises_title" msgid="7096178467971716750">"Diese App ist nicht installiert"</string>
<string name="abandoned_promise_explanation" msgid="3990027586878167529">"Die App für dieses Symbol ist nicht installiert. Sie können das Symbol entfernen oder nach der App suchen und sie manuell installieren."</string>
+ <string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> wird heruntergeladen, <xliff:g id="PROGRESS">%2$s</xliff:g> abgeschlossen"</string>
+ <string name="app_waiting_download_title" msgid="7053938513995617849">"Warten auf Installation von <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="action_add_to_workspace" msgid="8902165848117513641">"Zum Startbildschirm hinzufügen"</string>
<string name="action_move_here" msgid="2170188780612570250">"Element hierhin verschieben"</string>
<string name="item_added_to_workspace" msgid="4211073925752213539">"Element zum Startbildschirm hinzugefügt"</string>
diff --git a/res/values-el/strings.xml b/res/values-el/strings.xml
index ba5562f..38ee326 100644
--- a/res/values-el/strings.xml
+++ b/res/values-el/strings.xml
@@ -26,8 +26,8 @@
<string name="activity_not_available" msgid="7456344436509528827">"Η εφαρμογή δεν είναι διαθέσιμη"</string>
<string name="safemode_shortcut_error" msgid="9160126848219158407">"Η λήψη εφαρμογών απενεργοποήθηκε στην Ασφαλή λειτουργία"</string>
<string name="safemode_widget_error" msgid="4863470563535682004">"Τα γραφικά στοιχεία απενεργοποιήθηκαν στην ασφαλή λειτουργία"</string>
- <string name="toggle_weight_watcher" msgid="5645299835184636119">"Εμφάνιση Mem"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"Αγγίξτε παρατεταμένα για να πάρετε ένα γραφ.στοιχ."</string>
+ <string name="long_accessible_way_to_add" msgid="4289502106628154155">"Πατήστε δύο φορές παρατεταμένα για επιλογή γραφικού στοιχείου ή χρήση προσαρμοσμένων ενεργειών."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="all_apps_search_bar_hint" msgid="7084713969757597256">"Αναζήτηση εφαρμογών"</string>
<string name="all_apps_loading_message" msgid="7557140873644765180">"Φόρτωση εφαρμογών…"</string>
@@ -53,6 +53,7 @@
<string name="folder_hint_text" msgid="6617836969016293992">"Φάκελος χωρίς όνομα"</string>
<string name="default_scroll_format" msgid="7475544710230993317">"Σελίδα %1$d από %2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"Αρχική οθόνη %1$d από %2$d"</string>
+ <string name="workspace_new_page" msgid="257366611030256142">"Νέα σελίδα αρχικής οθόνης"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"Καλώς ορίσατε"</string>
<string name="migration_cling_title" msgid="9181776667882933767">"Αντιγραφή εικονιδίων εφαρμογών"</string>
<string name="migration_cling_description" msgid="2752413805582227644">"Εισαγωγή εικονιδίων και φακέλων από παλιές αρχικές οθόνες;"</string>
@@ -76,6 +77,8 @@
<string name="abandoned_search" msgid="891119232568284442">"Αναζήτηση"</string>
<string name="abandoned_promises_title" msgid="7096178467971716750">"Αυτή η εφαρμογή δεν είναι εγκατεστημένη"</string>
<string name="abandoned_promise_explanation" msgid="3990027586878167529">"Η εφαρμογή γι\' αυτό το εικονίδιο δεν είναι εγκατεστημένη. Μπορείτε να το καταργήσετε ή να αναζητήσετε την εφαρμογή και να την εγκαταστήσετε με μη αυτόματο τρόπο."</string>
+ <string name="app_downloading_title" msgid="8336702962104482644">"Λήψη <xliff:g id="NAME">%1$s</xliff:g>, ολοκληρώθηκε <xliff:g id="PROGRESS">%2$s</xliff:g>"</string>
+ <string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> σε αναμονή για εγκατάσταση"</string>
<string name="action_add_to_workspace" msgid="8902165848117513641">"Προσθήκη στην αρχική οθόνη"</string>
<string name="action_move_here" msgid="2170188780612570250">"Μετακίνηση στοιχείου εδώ"</string>
<string name="item_added_to_workspace" msgid="4211073925752213539">"Το στοιχείο προστέθηκε στην αρχική οθόνη"</string>
diff --git a/res/values-en-rAU/strings.xml b/res/values-en-rAU/strings.xml
index 18cb59d..ee45af0 100644
--- a/res/values-en-rAU/strings.xml
+++ b/res/values-en-rAU/strings.xml
@@ -26,8 +26,8 @@
<string name="activity_not_available" msgid="7456344436509528827">"App isn\'t available"</string>
<string name="safemode_shortcut_error" msgid="9160126848219158407">"Downloaded app disabled in Safe mode"</string>
<string name="safemode_widget_error" msgid="4863470563535682004">"Widgets disabled in Safe mode"</string>
- <string name="toggle_weight_watcher" msgid="5645299835184636119">"Show Mem"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"Touch & hold to pick up a widget."</string>
+ <string name="long_accessible_way_to_add" msgid="4289502106628154155">"Double-tap & hold to pick up a widget or use customised actions."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="all_apps_search_bar_hint" msgid="7084713969757597256">"Search Apps"</string>
<string name="all_apps_loading_message" msgid="7557140873644765180">"Loading Apps…"</string>
@@ -53,6 +53,7 @@
<string name="folder_hint_text" msgid="6617836969016293992">"Unnamed Folder"</string>
<string name="default_scroll_format" msgid="7475544710230993317">"Page %1$d of %2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"Home screen %1$d of %2$d"</string>
+ <string name="workspace_new_page" msgid="257366611030256142">"New home screen page"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"Welcome"</string>
<string name="migration_cling_title" msgid="9181776667882933767">"Copy your app icons"</string>
<string name="migration_cling_description" msgid="2752413805582227644">"Import icons and folders from your old Home screens?"</string>
@@ -76,6 +77,8 @@
<string name="abandoned_search" msgid="891119232568284442">"Search"</string>
<string name="abandoned_promises_title" msgid="7096178467971716750">"This app is not installed"</string>
<string name="abandoned_promise_explanation" msgid="3990027586878167529">"The app for this icon isn\'t installed. You can remove it, or search for the app and install it manually."</string>
+ <string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> downloading, <xliff:g id="PROGRESS">%2$s</xliff:g> complete"</string>
+ <string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> waiting to install"</string>
<string name="action_add_to_workspace" msgid="8902165848117513641">"Add to Home screen"</string>
<string name="action_move_here" msgid="2170188780612570250">"Move item here"</string>
<string name="item_added_to_workspace" msgid="4211073925752213539">"Item added to home screen"</string>
diff --git a/res/values-en-rGB/strings.xml b/res/values-en-rGB/strings.xml
index 18cb59d..ee45af0 100644
--- a/res/values-en-rGB/strings.xml
+++ b/res/values-en-rGB/strings.xml
@@ -26,8 +26,8 @@
<string name="activity_not_available" msgid="7456344436509528827">"App isn\'t available"</string>
<string name="safemode_shortcut_error" msgid="9160126848219158407">"Downloaded app disabled in Safe mode"</string>
<string name="safemode_widget_error" msgid="4863470563535682004">"Widgets disabled in Safe mode"</string>
- <string name="toggle_weight_watcher" msgid="5645299835184636119">"Show Mem"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"Touch & hold to pick up a widget."</string>
+ <string name="long_accessible_way_to_add" msgid="4289502106628154155">"Double-tap & hold to pick up a widget or use customised actions."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="all_apps_search_bar_hint" msgid="7084713969757597256">"Search Apps"</string>
<string name="all_apps_loading_message" msgid="7557140873644765180">"Loading Apps…"</string>
@@ -53,6 +53,7 @@
<string name="folder_hint_text" msgid="6617836969016293992">"Unnamed Folder"</string>
<string name="default_scroll_format" msgid="7475544710230993317">"Page %1$d of %2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"Home screen %1$d of %2$d"</string>
+ <string name="workspace_new_page" msgid="257366611030256142">"New home screen page"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"Welcome"</string>
<string name="migration_cling_title" msgid="9181776667882933767">"Copy your app icons"</string>
<string name="migration_cling_description" msgid="2752413805582227644">"Import icons and folders from your old Home screens?"</string>
@@ -76,6 +77,8 @@
<string name="abandoned_search" msgid="891119232568284442">"Search"</string>
<string name="abandoned_promises_title" msgid="7096178467971716750">"This app is not installed"</string>
<string name="abandoned_promise_explanation" msgid="3990027586878167529">"The app for this icon isn\'t installed. You can remove it, or search for the app and install it manually."</string>
+ <string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> downloading, <xliff:g id="PROGRESS">%2$s</xliff:g> complete"</string>
+ <string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> waiting to install"</string>
<string name="action_add_to_workspace" msgid="8902165848117513641">"Add to Home screen"</string>
<string name="action_move_here" msgid="2170188780612570250">"Move item here"</string>
<string name="item_added_to_workspace" msgid="4211073925752213539">"Item added to home screen"</string>
diff --git a/res/values-en-rIN/strings.xml b/res/values-en-rIN/strings.xml
index 18cb59d..ee45af0 100644
--- a/res/values-en-rIN/strings.xml
+++ b/res/values-en-rIN/strings.xml
@@ -26,8 +26,8 @@
<string name="activity_not_available" msgid="7456344436509528827">"App isn\'t available"</string>
<string name="safemode_shortcut_error" msgid="9160126848219158407">"Downloaded app disabled in Safe mode"</string>
<string name="safemode_widget_error" msgid="4863470563535682004">"Widgets disabled in Safe mode"</string>
- <string name="toggle_weight_watcher" msgid="5645299835184636119">"Show Mem"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"Touch & hold to pick up a widget."</string>
+ <string name="long_accessible_way_to_add" msgid="4289502106628154155">"Double-tap & hold to pick up a widget or use customised actions."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="all_apps_search_bar_hint" msgid="7084713969757597256">"Search Apps"</string>
<string name="all_apps_loading_message" msgid="7557140873644765180">"Loading Apps…"</string>
@@ -53,6 +53,7 @@
<string name="folder_hint_text" msgid="6617836969016293992">"Unnamed Folder"</string>
<string name="default_scroll_format" msgid="7475544710230993317">"Page %1$d of %2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"Home screen %1$d of %2$d"</string>
+ <string name="workspace_new_page" msgid="257366611030256142">"New home screen page"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"Welcome"</string>
<string name="migration_cling_title" msgid="9181776667882933767">"Copy your app icons"</string>
<string name="migration_cling_description" msgid="2752413805582227644">"Import icons and folders from your old Home screens?"</string>
@@ -76,6 +77,8 @@
<string name="abandoned_search" msgid="891119232568284442">"Search"</string>
<string name="abandoned_promises_title" msgid="7096178467971716750">"This app is not installed"</string>
<string name="abandoned_promise_explanation" msgid="3990027586878167529">"The app for this icon isn\'t installed. You can remove it, or search for the app and install it manually."</string>
+ <string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> downloading, <xliff:g id="PROGRESS">%2$s</xliff:g> complete"</string>
+ <string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> waiting to install"</string>
<string name="action_add_to_workspace" msgid="8902165848117513641">"Add to Home screen"</string>
<string name="action_move_here" msgid="2170188780612570250">"Move item here"</string>
<string name="item_added_to_workspace" msgid="4211073925752213539">"Item added to home screen"</string>
diff --git a/res/values-es-rUS/strings.xml b/res/values-es-rUS/strings.xml
index 93bc0c2..6f6c9de 100644
--- a/res/values-es-rUS/strings.xml
+++ b/res/values-es-rUS/strings.xml
@@ -26,8 +26,8 @@
<string name="activity_not_available" msgid="7456344436509528827">"La aplicación no está disponible."</string>
<string name="safemode_shortcut_error" msgid="9160126848219158407">"Aplicación descargada inhabilitada en modo seguro"</string>
<string name="safemode_widget_error" msgid="4863470563535682004">"Widgets inhabilitados en modo seguro"</string>
- <string name="toggle_weight_watcher" msgid="5645299835184636119">"Mostrar memoria"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"Mantén presionado el widget que desees elegir."</string>
+ <string name="long_accessible_way_to_add" msgid="4289502106628154155">"Presiona dos veces y mantén presionado para elegir un widget o usa una acción personalizada."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="all_apps_search_bar_hint" msgid="7084713969757597256">"Buscar aplicaciones"</string>
<string name="all_apps_loading_message" msgid="7557140873644765180">"Cargando aplicaciones…"</string>
@@ -53,6 +53,7 @@
<string name="folder_hint_text" msgid="6617836969016293992">"Carpeta sin nombre"</string>
<string name="default_scroll_format" msgid="7475544710230993317">"Página %1$d de %2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"Pantalla principal %1$d de %2$d"</string>
+ <string name="workspace_new_page" msgid="257366611030256142">"Nueva página en la pantalla principal"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"Bienvenido"</string>
<string name="migration_cling_title" msgid="9181776667882933767">"Copiar íconos de aplicaciones"</string>
<string name="migration_cling_description" msgid="2752413805582227644">"¿Importar íconos y carpetas de pant. principales antiguas?"</string>
@@ -76,6 +77,8 @@
<string name="abandoned_search" msgid="891119232568284442">"Buscar"</string>
<string name="abandoned_promises_title" msgid="7096178467971716750">"Esta aplicación no está instalada"</string>
<string name="abandoned_promise_explanation" msgid="3990027586878167529">"La aplicación para este ícono no está instalada. Puedes eliminar el ícono o buscar la aplicación e instarla manualmente."</string>
+ <string name="app_downloading_title" msgid="8336702962104482644">"Se completó el <xliff:g id="PROGRESS">%2$s</xliff:g> de la descarga de <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="app_waiting_download_title" msgid="7053938513995617849">"Instalación de <xliff:g id="NAME">%1$s</xliff:g> en espera"</string>
<string name="action_add_to_workspace" msgid="8902165848117513641">"Agregar a la pantalla principal"</string>
<string name="action_move_here" msgid="2170188780612570250">"Mover elemento aquí"</string>
<string name="item_added_to_workspace" msgid="4211073925752213539">"Se agregó el elemento a la pantalla principal."</string>
diff --git a/res/values-es/strings.xml b/res/values-es/strings.xml
index 0487143..11ae8cb 100644
--- a/res/values-es/strings.xml
+++ b/res/values-es/strings.xml
@@ -26,8 +26,8 @@
<string name="activity_not_available" msgid="7456344436509528827">"La aplicación no está disponible"</string>
<string name="safemode_shortcut_error" msgid="9160126848219158407">"Aplicación descargada inhabilitada en modo seguro"</string>
<string name="safemode_widget_error" msgid="4863470563535682004">"Widgets inhabilitados en modo seguro"</string>
- <string name="toggle_weight_watcher" msgid="5645299835184636119">"Mostrar memoria"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"Mantén pulsado el widget que quieras seleccionar."</string>
+ <string name="long_accessible_way_to_add" msgid="4289502106628154155">"Toca dos veces y mantén pulsado el widget que quieras seleccionar o utiliza acciones personalizadas."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="all_apps_search_bar_hint" msgid="7084713969757597256">"Busca aplicaciones"</string>
<string name="all_apps_loading_message" msgid="7557140873644765180">"Cargando aplicaciones…"</string>
@@ -53,6 +53,7 @@
<string name="folder_hint_text" msgid="6617836969016293992">"Carpeta sin nombre"</string>
<string name="default_scroll_format" msgid="7475544710230993317">"Página %1$d de %2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"Pantalla de inicio %1$d de %2$d"</string>
+ <string name="workspace_new_page" msgid="257366611030256142">"Nueva página de pantalla de inicio"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"Te damos la bienvenida"</string>
<string name="migration_cling_title" msgid="9181776667882933767">"Copiar iconos de aplicaciones"</string>
<string name="migration_cling_description" msgid="2752413805582227644">"¿Importar iconos y carpetas de pantallas de inicio antiguas?"</string>
@@ -76,6 +77,8 @@
<string name="abandoned_search" msgid="891119232568284442">"Buscar"</string>
<string name="abandoned_promises_title" msgid="7096178467971716750">"Esta aplicación no está instalada"</string>
<string name="abandoned_promise_explanation" msgid="3990027586878167529">"La aplicación de este icono no está instalada. Puedes eliminar el icono o buscar la aplicación e instalarla manualmente."</string>
+ <string name="app_downloading_title" msgid="8336702962104482644">"Descargando <xliff:g id="NAME">%1$s</xliff:g> (<xliff:g id="PROGRESS">%2$s</xliff:g> completado)"</string>
+ <string name="app_waiting_download_title" msgid="7053938513995617849">"Esperando para instalar <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="action_add_to_workspace" msgid="8902165848117513641">"Añadir a la pantalla de inicio"</string>
<string name="action_move_here" msgid="2170188780612570250">"Mover elemento aquí"</string>
<string name="item_added_to_workspace" msgid="4211073925752213539">"Elemento añadido a la pantalla de inicio"</string>
diff --git a/res/values-et-rEE/strings.xml b/res/values-et-rEE/strings.xml
index a162d06..6f45387 100644
--- a/res/values-et-rEE/strings.xml
+++ b/res/values-et-rEE/strings.xml
@@ -26,8 +26,8 @@
<string name="activity_not_available" msgid="7456344436509528827">"Rakendus ei ole saadaval"</string>
<string name="safemode_shortcut_error" msgid="9160126848219158407">"Allalaetud rakendus on turvarežiimis keelatud"</string>
<string name="safemode_widget_error" msgid="4863470563535682004">"Turvarežiimis on vidinad keelatud"</string>
- <string name="toggle_weight_watcher" msgid="5645299835184636119">"Mälu kuvamine"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"Vidina valimiseks vajutage ja hoidke seda all."</string>
+ <string name="long_accessible_way_to_add" msgid="4289502106628154155">"Topeltpuudutage ja hoidke vidina valimiseks või kohandatud toimingute kasutamiseks."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="all_apps_search_bar_hint" msgid="7084713969757597256">"Otsige rakendustest"</string>
<string name="all_apps_loading_message" msgid="7557140873644765180">"Rakenduste laadimine ..."</string>
@@ -53,6 +53,7 @@
<string name="folder_hint_text" msgid="6617836969016293992">"Nimetu kaust"</string>
<string name="default_scroll_format" msgid="7475544710230993317">"Leht %1$d/%2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"Avaekraan %1$d/%2$d"</string>
+ <string name="workspace_new_page" msgid="257366611030256142">"Uus avaekraan"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"Tere tulemast"</string>
<string name="migration_cling_title" msgid="9181776667882933767">"Kopeerige rakenduste ikoonid"</string>
<string name="migration_cling_description" msgid="2752413805582227644">"Kas importida vanade avaekraanide ikoonid ja kaustad?"</string>
@@ -76,6 +77,8 @@
<string name="abandoned_search" msgid="891119232568284442">"Otsing"</string>
<string name="abandoned_promises_title" msgid="7096178467971716750">"See rakendus ei ole installitud"</string>
<string name="abandoned_promise_explanation" msgid="3990027586878167529">"Selle ikooni rakendust pole installitud. Saate selle eemaldada või rakendust otsida ja käsitsi installida."</string>
+ <string name="app_downloading_title" msgid="8336702962104482644">"Rakenduse <xliff:g id="NAME">%1$s</xliff:g> allalaadimine, <xliff:g id="PROGRESS">%2$s</xliff:g> on valmis"</string>
+ <string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> on installimise ootel"</string>
<string name="action_add_to_workspace" msgid="8902165848117513641">"Lisa avaekraanile"</string>
<string name="action_move_here" msgid="2170188780612570250">"Teisalda üksus siia"</string>
<string name="item_added_to_workspace" msgid="4211073925752213539">"Üksus lisati avaekraanile"</string>
diff --git a/res/values-eu-rES/strings.xml b/res/values-eu-rES/strings.xml
index 63a94cc..7a465b3 100644
--- a/res/values-eu-rES/strings.xml
+++ b/res/values-eu-rES/strings.xml
@@ -26,8 +26,8 @@
<string name="activity_not_available" msgid="7456344436509528827">"Ez dago erabilgarri aplikazioa"</string>
<string name="safemode_shortcut_error" msgid="9160126848219158407">"Deskargatutako aplikazioa modu seguruan desgaitu da"</string>
<string name="safemode_widget_error" msgid="4863470563535682004">"Widgetak desgaitu egin dira modu seguruan"</string>
- <string name="toggle_weight_watcher" msgid="5645299835184636119">"Erakutsi memoria"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"Eduki ukituta widgeta aukeratzeko."</string>
+ <string name="long_accessible_way_to_add" msgid="4289502106628154155">"Sakatu birritan eta eduki sakatuta widgeta aukeratzeko edo ekintza pertsonalizatuak erabiltzeko."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="all_apps_search_bar_hint" msgid="7084713969757597256">"Bilatu aplikazioetan"</string>
<string name="all_apps_loading_message" msgid="7557140873644765180">"Aplikazioak kargatzen…"</string>
@@ -53,6 +53,7 @@
<string name="folder_hint_text" msgid="6617836969016293992">"Izenik gabeko karpeta"</string>
<string name="default_scroll_format" msgid="7475544710230993317">"%1$d/%2$d orria"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"%1$d/%2$d hasierako pantaila"</string>
+ <string name="workspace_new_page" msgid="257366611030256142">"Hasierako pantailaren orri berria"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"Ongi etorri"</string>
<string name="migration_cling_title" msgid="9181776667882933767">"Kopiatu aplikazioen ikonoak"</string>
<string name="migration_cling_description" msgid="2752413805582227644">"Ikonoak eta karpetak aurreko hasierako pantailatik inportatu?"</string>
@@ -76,6 +77,8 @@
<string name="abandoned_search" msgid="891119232568284442">"Bilatu"</string>
<string name="abandoned_promises_title" msgid="7096178467971716750">"Aplikazio hau ez dago instalatuta"</string>
<string name="abandoned_promise_explanation" msgid="3990027586878167529">"Ikono honen aplikazioa ez dago instalatuta. Ikonoa ken dezakezu, edo aplikazioa bilatu eta eskuz instalatu."</string>
+ <string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> deskargatzen, <xliff:g id="PROGRESS">%2$s</xliff:g> osatuta"</string>
+ <string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> instalatzeko zain"</string>
<string name="action_add_to_workspace" msgid="8902165848117513641">"Gehitu hasierako pantailan"</string>
<string name="action_move_here" msgid="2170188780612570250">"Ekarri elementua hona"</string>
<string name="item_added_to_workspace" msgid="4211073925752213539">"Gehitu da elementua hasierako pantailan"</string>
diff --git a/res/values-fa/strings.xml b/res/values-fa/strings.xml
index 0aa9b7c..9f0bb44 100644
--- a/res/values-fa/strings.xml
+++ b/res/values-fa/strings.xml
@@ -26,8 +26,8 @@
<string name="activity_not_available" msgid="7456344436509528827">"برنامه در دسترس نیست"</string>
<string name="safemode_shortcut_error" msgid="9160126848219158407">"برنامه دانلود شده در حالت ایمن غیرفعال شد"</string>
<string name="safemode_widget_error" msgid="4863470563535682004">"ابزارکها در حالت ایمن غیرفعال هستند"</string>
- <string name="toggle_weight_watcher" msgid="5645299835184636119">"نمایش Mem"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"برای انتخاب ابزارک لمس کنید و نگه دارید."</string>
+ <string name="long_accessible_way_to_add" msgid="4289502106628154155">"برای انتخاب یک ابزارک، دو ضربه سریع بزنید و نگهدارید یا از اقدامات سفارشی استفاده کنید."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="all_apps_search_bar_hint" msgid="7084713969757597256">"جستجوی برنامهها"</string>
<string name="all_apps_loading_message" msgid="7557140873644765180">"در حال بارگیری برنامهها..."</string>
@@ -53,6 +53,7 @@
<string name="folder_hint_text" msgid="6617836969016293992">"پوشه بینام"</string>
<string name="default_scroll_format" msgid="7475544710230993317">"صفحه %1$d از %2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"صفحه اصلی %1$d از %2$d"</string>
+ <string name="workspace_new_page" msgid="257366611030256142">"صفحه اصلی جدید"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"خوش آمدید"</string>
<string name="migration_cling_title" msgid="9181776667882933767">"کپی کردن نمادهای برنامه شما"</string>
<string name="migration_cling_description" msgid="2752413805582227644">"نمادها و پوشهها از صفحههای اصلی قدیمی شما وارد شوند؟"</string>
@@ -76,6 +77,8 @@
<string name="abandoned_search" msgid="891119232568284442">"جستجو"</string>
<string name="abandoned_promises_title" msgid="7096178467971716750">"این برنامه نصب نشده است."</string>
<string name="abandoned_promise_explanation" msgid="3990027586878167529">"برنامه برای این نماد نصب نشده است. میتوانید آن را حذف کنید یا سعی کنید برنامه را جستجو کنید و آن را به صورت دستی نصب کنید."</string>
+ <string name="app_downloading_title" msgid="8336702962104482644">"درحال دانلود <xliff:g id="NAME">%1$s</xliff:g>، <xliff:g id="PROGRESS">%2$s</xliff:g> کامل شد"</string>
+ <string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> درانتظار نصب"</string>
<string name="action_add_to_workspace" msgid="8902165848117513641">"افزودن به صفحه اصلی"</string>
<string name="action_move_here" msgid="2170188780612570250">"انتقال مورد به اینجا"</string>
<string name="item_added_to_workspace" msgid="4211073925752213539">"مورد به صفحه اصلی اضافه شد"</string>
diff --git a/res/values-fi/strings.xml b/res/values-fi/strings.xml
index 82e4b03..2cbf127 100644
--- a/res/values-fi/strings.xml
+++ b/res/values-fi/strings.xml
@@ -26,8 +26,8 @@
<string name="activity_not_available" msgid="7456344436509528827">"Sovellus ei ole käytettävissä"</string>
<string name="safemode_shortcut_error" msgid="9160126848219158407">"Ladattu sovellus poistettiin käytöstä suojatussa tilassa"</string>
<string name="safemode_widget_error" msgid="4863470563535682004">"Widgetit poistettu käytöstä vikasietotilassa"</string>
- <string name="toggle_weight_watcher" msgid="5645299835184636119">"Näytä muisti"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"Valitse widget painamalla sitä pitkään."</string>
+ <string name="long_accessible_way_to_add" msgid="4289502106628154155">"Valitse widget tai käytä muokattuja toimintoja kaksoisnapauttamalla ja painamalla kohdetta pitkään."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="all_apps_search_bar_hint" msgid="7084713969757597256">"Sovellushaku"</string>
<string name="all_apps_loading_message" msgid="7557140873644765180">"Ladataan sovelluksia…"</string>
@@ -53,6 +53,7 @@
<string name="folder_hint_text" msgid="6617836969016293992">"Nimetön kansio"</string>
<string name="default_scroll_format" msgid="7475544710230993317">"Sivu %1$d / %2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"Aloitusruutu %1$d/%2$d"</string>
+ <string name="workspace_new_page" msgid="257366611030256142">"Uusi aloitusnäytön sivu"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"Tervetuloa"</string>
<string name="migration_cling_title" msgid="9181776667882933767">"Kopioi sovelluskuvakkeet"</string>
<string name="migration_cling_description" msgid="2752413805582227644">"Tuodaanko kuvakkeet ja kansiot vanhoista aloitusruuduista?"</string>
@@ -76,6 +77,8 @@
<string name="abandoned_search" msgid="891119232568284442">"Haku"</string>
<string name="abandoned_promises_title" msgid="7096178467971716750">"Sovellusta ei ole asennettu"</string>
<string name="abandoned_promise_explanation" msgid="3990027586878167529">"Kuvakkeen sovellusta ei ole asennettu. Voit poistaa kuvakkeen tai etsiä sovelluksen ja asentaa sen manuaalisesti."</string>
+ <string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> latautuu, valmiina <xliff:g id="PROGRESS">%2$s</xliff:g>"</string>
+ <string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> odottaa asennusta"</string>
<string name="action_add_to_workspace" msgid="8902165848117513641">"Lisää aloitusnäytölle"</string>
<string name="action_move_here" msgid="2170188780612570250">"Siirrä kohde tänne"</string>
<string name="item_added_to_workspace" msgid="4211073925752213539">"Kohde lisättiin aloitusnäytölle."</string>
diff --git a/res/values-fr-rCA/strings.xml b/res/values-fr-rCA/strings.xml
index c24a34c..2b05477 100644
--- a/res/values-fr-rCA/strings.xml
+++ b/res/values-fr-rCA/strings.xml
@@ -26,8 +26,8 @@
<string name="activity_not_available" msgid="7456344436509528827">"Application indisponible"</string>
<string name="safemode_shortcut_error" msgid="9160126848219158407">"L\'application téléchargée est désactivée en mode sécurisé."</string>
<string name="safemode_widget_error" msgid="4863470563535682004">"Widgets désactivés en mode sans échec"</string>
- <string name="toggle_weight_watcher" msgid="5645299835184636119">"Afficher la mémoire"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"Maintenez un doigt sur le widget pour l\'ajouter."</string>
+ <string name="long_accessible_way_to_add" msgid="4289502106628154155">"Touchez 2x un widget et maintenez doigt dessus pour l’ajouter ou utiliser des actions personnalisées"</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="all_apps_search_bar_hint" msgid="7084713969757597256">"Rechercher des applications"</string>
<string name="all_apps_loading_message" msgid="7557140873644765180">"Chargement des applications en cours..."</string>
@@ -53,6 +53,7 @@
<string name="folder_hint_text" msgid="6617836969016293992">"Dossier sans nom"</string>
<string name="default_scroll_format" msgid="7475544710230993317">"Page %1$d sur %2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"Écran d\'accueil %1$d sur %2$d"</string>
+ <string name="workspace_new_page" msgid="257366611030256142">"Nouvelle page d\'écran d\'accueil"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"Bienvenue"</string>
<string name="migration_cling_title" msgid="9181776667882933767">"Copier les icônes de vos applis"</string>
<string name="migration_cling_description" msgid="2752413805582227644">"Importer les icônes et dossiers des anciens écrans d\'accueil?"</string>
@@ -76,6 +77,8 @@
<string name="abandoned_search" msgid="891119232568284442">"Rechercher"</string>
<string name="abandoned_promises_title" msgid="7096178467971716750">"Cette application n\'est pas installée"</string>
<string name="abandoned_promise_explanation" msgid="3990027586878167529">"L\'application liée à cette icône n\'est pas installée. Vous pouvez la supprimer ou rechercher l\'application et l\'installer manuellement."</string>
+ <string name="app_downloading_title" msgid="8336702962104482644">"Téléchargement de <xliff:g id="NAME">%1$s</xliff:g> : <xliff:g id="PROGRESS">%2$s</xliff:g>"</string>
+ <string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> en attente d\'installation"</string>
<string name="action_add_to_workspace" msgid="8902165848117513641">"Ajouter à l\'écran d\'accueil"</string>
<string name="action_move_here" msgid="2170188780612570250">"Déplacer l\'élément ici"</string>
<string name="item_added_to_workspace" msgid="4211073925752213539">"Élément ajouté à l\'écran d\'accueil"</string>
diff --git a/res/values-fr/strings.xml b/res/values-fr/strings.xml
index 573a0e0..2d97d23 100644
--- a/res/values-fr/strings.xml
+++ b/res/values-fr/strings.xml
@@ -26,8 +26,8 @@
<string name="activity_not_available" msgid="7456344436509528827">"Application indisponible"</string>
<string name="safemode_shortcut_error" msgid="9160126848219158407">"L\'application téléchargée est désactivée en mode sécurisé."</string>
<string name="safemode_widget_error" msgid="4863470563535682004">"Les widgets sont désactivés en mode sécurisé."</string>
- <string name="toggle_weight_watcher" msgid="5645299835184636119">"Afficher la mémoire"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"App. de manière prolongée pour sélectionner widget."</string>
+ <string name="long_accessible_way_to_add" msgid="4289502106628154155">"Appuyez 2 fois et maintenez la pression pour sélectionner widget ou utilisez actions personnalisées."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d x %2$d"</string>
<string name="all_apps_search_bar_hint" msgid="7084713969757597256">"Rechercher dans les applications"</string>
<string name="all_apps_loading_message" msgid="7557140873644765180">"Chargement des applications en cours…"</string>
@@ -53,6 +53,7 @@
<string name="folder_hint_text" msgid="6617836969016293992">"Dossier sans nom"</string>
<string name="default_scroll_format" msgid="7475544710230993317">"Page %1$d sur %2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"Écran d\'accueil %1$d sur %2$d"</string>
+ <string name="workspace_new_page" msgid="257366611030256142">"Nouvelle page d\'écran d\'accueil"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"Bienvenue"</string>
<string name="migration_cling_title" msgid="9181776667882933767">"Copier les icônes de vos applis"</string>
<string name="migration_cling_description" msgid="2752413805582227644">"Importer les icônes et dossiers des anciens écrans d\'accueil ?"</string>
@@ -76,6 +77,8 @@
<string name="abandoned_search" msgid="891119232568284442">"Rechercher"</string>
<string name="abandoned_promises_title" msgid="7096178467971716750">"Cette application n\'est pas installée"</string>
<string name="abandoned_promise_explanation" msgid="3990027586878167529">"L\'application correspondant à cette icône n\'est pas installée. Vous pouvez supprimer cette dernière, ou essayer de rechercher l\'application et de l\'installer manuellement."</string>
+ <string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> en cours de téléchargement, <xliff:g id="PROGRESS">%2$s</xliff:g> effectué(s)"</string>
+ <string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> en attente d\'installation"</string>
<string name="action_add_to_workspace" msgid="8902165848117513641">"Ajouter à l\'écran d\'accueil"</string>
<string name="action_move_here" msgid="2170188780612570250">"Déplacer l\'élément ici"</string>
<string name="item_added_to_workspace" msgid="4211073925752213539">"L\'élément a bien été ajouté à l\'écran d\'accueil."</string>
diff --git a/res/values-gl-rES/strings.xml b/res/values-gl-rES/strings.xml
index f57a49c..0a1cbe1 100644
--- a/res/values-gl-rES/strings.xml
+++ b/res/values-gl-rES/strings.xml
@@ -26,8 +26,8 @@
<string name="activity_not_available" msgid="7456344436509528827">"A aplicación non está dispoñible"</string>
<string name="safemode_shortcut_error" msgid="9160126848219158407">"A aplicación que descargaches está desactivada no modo seguro"</string>
<string name="safemode_widget_error" msgid="4863470563535682004">"Os widgets están desactivados no modo seguro"</string>
- <string name="toggle_weight_watcher" msgid="5645299835184636119">"Mostrar memoria"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"Mantén premido un widget para seleccionalo."</string>
+ <string name="long_accessible_way_to_add" msgid="4289502106628154155">"Toca dúas veces e mantén premido para seleccionar un widget ou utiliza accións personalizadas."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="all_apps_search_bar_hint" msgid="7084713969757597256">"Aplicacións de busca"</string>
<string name="all_apps_loading_message" msgid="7557140873644765180">"Cargando aplicacións..."</string>
@@ -53,6 +53,7 @@
<string name="folder_hint_text" msgid="6617836969016293992">"Cartafol sen nome"</string>
<string name="default_scroll_format" msgid="7475544710230993317">"Páxina %1$d de %2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"Pantalla de inicio %1$d de %2$d"</string>
+ <string name="workspace_new_page" msgid="257366611030256142">"Nova páxina da pantalla de inicio"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"Dámosche a benvida"</string>
<string name="migration_cling_title" msgid="9181776667882933767">"Copiar iconas das aplicacións"</string>
<string name="migration_cling_description" msgid="2752413805582227644">"Queres importar as iconas e os cartafoles doutras pantallas de inicio?"</string>
@@ -76,6 +77,8 @@
<string name="abandoned_search" msgid="891119232568284442">"Buscar"</string>
<string name="abandoned_promises_title" msgid="7096178467971716750">"Esta aplicación non está instalada"</string>
<string name="abandoned_promise_explanation" msgid="3990027586878167529">"A aplicación para esta icona non está instalada. Podes eliminala ou buscar a aplicación e instalala manualmente."</string>
+ <string name="app_downloading_title" msgid="8336702962104482644">"Descargando <xliff:g id="NAME">%1$s</xliff:g> (<xliff:g id="PROGRESS">%2$s</xliff:g> completado)"</string>
+ <string name="app_waiting_download_title" msgid="7053938513995617849">"Esperando para instalar <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="action_add_to_workspace" msgid="8902165848117513641">"Engadir á pantalla de inicio"</string>
<string name="action_move_here" msgid="2170188780612570250">"Mover elemento aquí"</string>
<string name="item_added_to_workspace" msgid="4211073925752213539">"Engadiuse o elemento á pantalla de inicio"</string>
diff --git a/res/values-gu-rIN/strings.xml b/res/values-gu-rIN/strings.xml
index f2375ad..db056a0 100644
--- a/res/values-gu-rIN/strings.xml
+++ b/res/values-gu-rIN/strings.xml
@@ -19,7 +19,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_name" msgid="649227358658669779">"Launcher3"</string>
+ <string name="application_name" msgid="5181331383435256801">"Launcher3"</string>
<string name="folder_name" msgid="7371454440695724752"></string>
<string name="work_folder_name" msgid="3753320833950115786">"કાર્યાલય"</string>
<string name="activity_not_found" msgid="8071924732094499514">"એપ્લિકેશન ઇન્સ્ટોલ થઈ નથી."</string>
@@ -46,7 +46,6 @@
<string name="permdesc_read_settings" msgid="5833423719057558387">"એપ્લિકેશનને હોમમાં સેટિંગ્સ અને શોર્ટકટ્સ વાંચવાની મંજૂરી આપે છે."</string>
<string name="permlab_write_settings" msgid="3574213698004620587">"હોમ સેટિંગ્સ અને શોર્ટકટ્સ લખો"</string>
<string name="permdesc_write_settings" msgid="5440712911516509985">"એપ્લિકેશનને હોમમાં સેટિંગ્સ અને શોર્ટકટ્સ બદલવાની મંજૂરી આપે છે."</string>
- <string name="msg_no_phone_permission" msgid="9208659281529857371">"<xliff:g id="APP_NAME">%1$s</xliff:g> ને ફોન કૉલ્સ કરવાની મંજૂરી નથી"</string>
<string name="gadget_error_text" msgid="6081085226050792095">"વિજેટ લોડ કરવામાં સમસ્યા"</string>
<string name="gadget_setup_text" msgid="8274003207686040488">"સેટઅપ"</string>
<string name="uninstall_system_app_text" msgid="4172046090762920660">"આ એક સિસ્ટમ એપ્લિકેશન છે અને અનઇન્સ્ટોલ કરી શકાતી નથી."</string>
diff --git a/res/values-hi/strings.xml b/res/values-hi/strings.xml
index 9ae75ab..49531af 100644
--- a/res/values-hi/strings.xml
+++ b/res/values-hi/strings.xml
@@ -26,8 +26,8 @@
<string name="activity_not_available" msgid="7456344436509528827">"ऐप्स उपलब्ध नहीं है"</string>
<string name="safemode_shortcut_error" msgid="9160126848219158407">"डाउनलोड किए गए ऐप्स सुरक्षित मोड में अक्षम है"</string>
<string name="safemode_widget_error" msgid="4863470563535682004">"विजेट सुरक्षित मोड में अक्षम हैं"</string>
- <string name="toggle_weight_watcher" msgid="5645299835184636119">"मेमोरी दिखाएं"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"विजेट को चुनने के लिए स्पर्श करके रखें."</string>
+ <string name="long_accessible_way_to_add" msgid="4289502106628154155">"कोई विजेट चुनने के लिए डबल टैप करके रखें या कस्टम कार्रवाइयां चुनें."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="all_apps_search_bar_hint" msgid="7084713969757597256">"ऐप्स खोजें"</string>
<string name="all_apps_loading_message" msgid="7557140873644765180">"ऐप्स लोड हो रहे हैं..."</string>
@@ -53,6 +53,7 @@
<string name="folder_hint_text" msgid="6617836969016293992">"अनामित फ़ोल्डर"</string>
<string name="default_scroll_format" msgid="7475544710230993317">"पृष्ठ %2$d में से %1$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"होम स्क्रीन %2$d में से %1$d"</string>
+ <string name="workspace_new_page" msgid="257366611030256142">"नया होम स्क्रीन पृष्ठ"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"स्वागत है"</string>
<string name="migration_cling_title" msgid="9181776667882933767">"ऐप्स आइकन की प्रतिलिपि बनाएं"</string>
<string name="migration_cling_description" msgid="2752413805582227644">"अपनी पुरानी होम स्क्रीन से आइकन और फ़ोल्डर आयात करें?"</string>
@@ -76,6 +77,8 @@
<string name="abandoned_search" msgid="891119232568284442">"खोजें"</string>
<string name="abandoned_promises_title" msgid="7096178467971716750">"यह ऐप्स इंस्टॉल नहीं है"</string>
<string name="abandoned_promise_explanation" msgid="3990027586878167529">"इस आइकन का ऐप्स इंस्टॉल नहीं है. आप उसे निकाल सकते हैं या ऐप्स की खोज करके उसे मैन्युअल रूप से इंस्टॉल कर सकते हैं."</string>
+ <string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> डाउनलोड हो रहा है, <xliff:g id="PROGRESS">%2$s</xliff:g> पूर्ण"</string>
+ <string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> के इंस्टॉल होने की प्रतीक्षा की जा रही है"</string>
<string name="action_add_to_workspace" msgid="8902165848117513641">"होम स्क्रीन में जोड़ें"</string>
<string name="action_move_here" msgid="2170188780612570250">"आइटम यहां ले जाएं"</string>
<string name="item_added_to_workspace" msgid="4211073925752213539">"होम स्क्रीन में आइटम जोड़ा गया"</string>
diff --git a/res/values-hr/strings.xml b/res/values-hr/strings.xml
index 6b78c7e..0ec3789 100644
--- a/res/values-hr/strings.xml
+++ b/res/values-hr/strings.xml
@@ -26,8 +26,8 @@
<string name="activity_not_available" msgid="7456344436509528827">"Aplikacija nije dostupna"</string>
<string name="safemode_shortcut_error" msgid="9160126848219158407">"Preuzeta aplikacija onemogućena je u Sigurnom načinu rada"</string>
<string name="safemode_widget_error" msgid="4863470563535682004">"Widgeti su onemogućeni u Sigurnom načinu rada"</string>
- <string name="toggle_weight_watcher" msgid="5645299835184636119">"Prikaži mem"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"Dodirnite i držite kako biste podigli widget."</string>
+ <string name="long_accessible_way_to_add" msgid="4289502106628154155">"Dodirnite dvaput i držite kako biste podigli widget ili pokušajte prilagođenim radnjama."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="all_apps_search_bar_hint" msgid="7084713969757597256">"Pretraži aplikacije"</string>
<string name="all_apps_loading_message" msgid="7557140873644765180">"Učitavanje aplikacija…"</string>
@@ -53,6 +53,7 @@
<string name="folder_hint_text" msgid="6617836969016293992">"Neimenovana mapa"</string>
<string name="default_scroll_format" msgid="7475544710230993317">"Stranica %1$d od %2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"Početni zaslon %1$d od %2$d"</string>
+ <string name="workspace_new_page" msgid="257366611030256142">"Nova stranica početnog zaslona"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"Dobro došli"</string>
<string name="migration_cling_title" msgid="9181776667882933767">"Kopiranje ikona aplikacija"</string>
<string name="migration_cling_description" msgid="2752413805582227644">"Želite li uvesti ikone i mape sa starih početnih zaslona?"</string>
@@ -76,6 +77,8 @@
<string name="abandoned_search" msgid="891119232568284442">"Traži"</string>
<string name="abandoned_promises_title" msgid="7096178467971716750">"Ta aplikacija nije instalirana"</string>
<string name="abandoned_promise_explanation" msgid="3990027586878167529">"Aplikacija ove ikone nije instalirana. Možete je ukloniti ili potražiti aplikaciju i instalirati je ručno."</string>
+ <string name="app_downloading_title" msgid="8336702962104482644">"Preuzimanje aplikacije <xliff:g id="NAME">%1$s</xliff:g>, dovršeno <xliff:g id="PROGRESS">%2$s</xliff:g>"</string>
+ <string name="app_waiting_download_title" msgid="7053938513995617849">"Čekanje na instaliranje aplikacije <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="action_add_to_workspace" msgid="8902165848117513641">"Dodavanje na početni zaslon"</string>
<string name="action_move_here" msgid="2170188780612570250">"Premjesti stavku ovdje"</string>
<string name="item_added_to_workspace" msgid="4211073925752213539">"Stavka je dodana na početni zaslon"</string>
diff --git a/res/values-hu/strings.xml b/res/values-hu/strings.xml
index 506ac6e..8f93d97 100644
--- a/res/values-hu/strings.xml
+++ b/res/values-hu/strings.xml
@@ -26,8 +26,8 @@
<string name="activity_not_available" msgid="7456344436509528827">"Az alkalmazás nem érhető el"</string>
<string name="safemode_shortcut_error" msgid="9160126848219158407">"A letöltött alkalmazás Csökkentett módban ki van kapcsolva"</string>
<string name="safemode_widget_error" msgid="4863470563535682004">"A modulok ki vannak kapcsolva Csökkentett módban"</string>
- <string name="toggle_weight_watcher" msgid="5645299835184636119">"Mem. megjelenítése"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"Modul felvételéhez érintse meg, és tartsa lenyomva"</string>
+ <string name="long_accessible_way_to_add" msgid="4289502106628154155">"Modul mozgatásához koppintson rá duplán és tartsa lenyomva, vagy használjon egyéni műveleteket."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="all_apps_search_bar_hint" msgid="7084713969757597256">"Alkalmazások keresése"</string>
<string name="all_apps_loading_message" msgid="7557140873644765180">"Alkalmazások betöltése…"</string>
@@ -53,6 +53,7 @@
<string name="folder_hint_text" msgid="6617836969016293992">"Névtelen mappa"</string>
<string name="default_scroll_format" msgid="7475544710230993317">"%2$d/%1$d. oldal"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"%2$d/%1$d. kezdőképernyő"</string>
+ <string name="workspace_new_page" msgid="257366611030256142">"Új kezdőképernyő oldal"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"Üdvözöljük!"</string>
<string name="migration_cling_title" msgid="9181776667882933767">"Alkalmazásikonok másolása"</string>
<string name="migration_cling_description" msgid="2752413805582227644">"Importálja ikonjait és mappáit régi kezdőképernyőiről?"</string>
@@ -76,6 +77,8 @@
<string name="abandoned_search" msgid="891119232568284442">"Keresés"</string>
<string name="abandoned_promises_title" msgid="7096178467971716750">"Az alkalmazás nincs telepítve"</string>
<string name="abandoned_promise_explanation" msgid="3990027586878167529">"Az ikonhoz tartozó alkalmazás nincs telepítve. Törölheti az ikont, vagy az alkalmazás megkeresése után manuálisan telepítheti azt."</string>
+ <string name="app_downloading_title" msgid="8336702962104482644">"A(z) <xliff:g id="NAME">%1$s</xliff:g> letöltése, <xliff:g id="PROGRESS">%2$s</xliff:g> kész"</string>
+ <string name="app_waiting_download_title" msgid="7053938513995617849">"A(z) <xliff:g id="NAME">%1$s</xliff:g> telepítésre vár"</string>
<string name="action_add_to_workspace" msgid="8902165848117513641">"Hozzáadás a kezdőképernyőhöz"</string>
<string name="action_move_here" msgid="2170188780612570250">"Elem áthelyezése ide"</string>
<string name="item_added_to_workspace" msgid="4211073925752213539">"Elem hozzáadva a kezdőképernyőhöz"</string>
diff --git a/res/values-hy-rAM/strings.xml b/res/values-hy-rAM/strings.xml
index 01b8e4d..3f06f8c 100644
--- a/res/values-hy-rAM/strings.xml
+++ b/res/values-hy-rAM/strings.xml
@@ -26,8 +26,8 @@
<string name="activity_not_available" msgid="7456344436509528827">"Հավելվածը հասանելի չէ"</string>
<string name="safemode_shortcut_error" msgid="9160126848219158407">"Ներբեռնված ծրագիրն անջատված է Անվտանգ ռեժիմում"</string>
<string name="safemode_widget_error" msgid="4863470563535682004">"Վիջեթներն անջատված են անվտանգ ռեժիմում"</string>
- <string name="toggle_weight_watcher" msgid="5645299835184636119">"Ցուցադրել մեմը"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"Հպեք և պահեք՝ վիջեթն ընտրելու համար:"</string>
+ <string name="long_accessible_way_to_add" msgid="4289502106628154155">"Կրկնակի հպեք և պահեք՝ վիջեթ ավելացնելու համար կամ օգտվեք հարմարեցրած գործողություններից:"</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="all_apps_search_bar_hint" msgid="7084713969757597256">"Հավելվածների որոնում"</string>
<string name="all_apps_loading_message" msgid="7557140873644765180">"Հավելվածների բեռնում…"</string>
@@ -53,6 +53,7 @@
<string name="folder_hint_text" msgid="6617836969016293992">"Անանուն պանակ"</string>
<string name="default_scroll_format" msgid="7475544710230993317">"Էջ %1$d՝ %2$d-ից"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"Հիմնական էկրան %1$d` %2$d-ից"</string>
+ <string name="workspace_new_page" msgid="257366611030256142">"Հիմնական էկրանի նոր էջ"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"Բարի գալուստ"</string>
<string name="migration_cling_title" msgid="9181776667882933767">"Պատճենել ձեր ծրագրի պատկերակները"</string>
<string name="migration_cling_description" msgid="2752413805582227644">"Ներմուծե՞լ պատկերակները և պանակները ձեր նախկին Հիմնական էկրանից"</string>
@@ -76,6 +77,8 @@
<string name="abandoned_search" msgid="891119232568284442">"Գտնել"</string>
<string name="abandoned_promises_title" msgid="7096178467971716750">"Այս ծրագիրը տեղադրված չէ:"</string>
<string name="abandoned_promise_explanation" msgid="3990027586878167529">"Այս պատկերակի ծրագիրը տեղադրված չէ: Դուք կարող եք հեռացնել այն կամ գտնել ծրագիրը և տեղադրել այն ձեռքով:"</string>
+ <string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g>–ի ներբեռնում (<xliff:g id="PROGRESS">%2$s</xliff:g>)"</string>
+ <string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g>-ի տեղադրման սպասում"</string>
<string name="action_add_to_workspace" msgid="8902165848117513641">"Ավելացնել Հիմնական էկրանին"</string>
<string name="action_move_here" msgid="2170188780612570250">"Տեղափոխել տարրն այստեղ"</string>
<string name="item_added_to_workspace" msgid="4211073925752213539">"Տարրն ավելացվեց հիմնական էկրանին"</string>
diff --git a/res/values-in/strings.xml b/res/values-in/strings.xml
index 3c99ff1..2537255 100644
--- a/res/values-in/strings.xml
+++ b/res/values-in/strings.xml
@@ -26,8 +26,8 @@
<string name="activity_not_available" msgid="7456344436509528827">"Aplikasi tidak tersedia"</string>
<string name="safemode_shortcut_error" msgid="9160126848219158407">"Aplikasi yang diunduh dinonaktifkan dalam mode Aman"</string>
<string name="safemode_widget_error" msgid="4863470563535682004">"Widget dinonaktifkan dalam mode Aman"</string>
- <string name="toggle_weight_watcher" msgid="5645299835184636119">"Tampilkan Memori"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"Sentuh lama untuk memilih widget."</string>
+ <string name="long_accessible_way_to_add" msgid="4289502106628154155">"Ketuk dua kalip & tahan untuk mengambil widget atau menggunakan tindakan khusus."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="all_apps_search_bar_hint" msgid="7084713969757597256">"Telusuri Apps"</string>
<string name="all_apps_loading_message" msgid="7557140873644765180">"Memuat Aplikasi..."</string>
@@ -53,6 +53,7 @@
<string name="folder_hint_text" msgid="6617836969016293992">"Folder Tanpa Nama"</string>
<string name="default_scroll_format" msgid="7475544710230993317">"Laman %1$d dari %2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"Layar utama %1$d dari %2$d"</string>
+ <string name="workspace_new_page" msgid="257366611030256142">"Laman layar utama baru"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"Selamat Datang"</string>
<string name="migration_cling_title" msgid="9181776667882933767">"Salin ikon aplikasi Anda"</string>
<string name="migration_cling_description" msgid="2752413805582227644">"Impor ikon dan folder dari layar Utama lama Anda?"</string>
@@ -76,6 +77,8 @@
<string name="abandoned_search" msgid="891119232568284442">"Telusuri"</string>
<string name="abandoned_promises_title" msgid="7096178467971716750">"Aplikasi ini belum terpasang"</string>
<string name="abandoned_promise_explanation" msgid="3990027586878167529">"Aplikasi untuk ikon ini belum dipasang. Anda dapat membuangnya, atau menelusuri aplikasi dan memasangnya secara manual."</string>
+ <string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> sedang diunduh, <xliff:g id="PROGRESS">%2$s</xliff:g> selesai"</string>
+ <string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> menunggu dipasang"</string>
<string name="action_add_to_workspace" msgid="8902165848117513641">"Tambahkan ke layar Utama"</string>
<string name="action_move_here" msgid="2170188780612570250">"Pindahkan item ke sini"</string>
<string name="item_added_to_workspace" msgid="4211073925752213539">"Item ditambahkan ke layar utama"</string>
diff --git a/res/values-is-rIS/strings.xml b/res/values-is-rIS/strings.xml
index d8404c4..1bf3dbf 100644
--- a/res/values-is-rIS/strings.xml
+++ b/res/values-is-rIS/strings.xml
@@ -26,8 +26,8 @@
<string name="activity_not_available" msgid="7456344436509528827">"Forritið er ekki í boði"</string>
<string name="safemode_shortcut_error" msgid="9160126848219158407">"Sótt forrit er óvirkt í öryggisstillingu"</string>
<string name="safemode_widget_error" msgid="4863470563535682004">"Græjur eru óvirkar í öruggri stillingu"</string>
- <string name="toggle_weight_watcher" msgid="5645299835184636119">"Sýna minni"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"Haltu fingri á græju til að grípa hana."</string>
+ <string name="long_accessible_way_to_add" msgid="4289502106628154155">"Ýttu tvisvar og haltu fingri á græju til að grípa hana eða notaðu sérsniðnar aðgerðir."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="all_apps_search_bar_hint" msgid="7084713969757597256">"Leita í forritum"</string>
<string name="all_apps_loading_message" msgid="7557140873644765180">"Hleður forrit…"</string>
@@ -53,6 +53,7 @@
<string name="folder_hint_text" msgid="6617836969016293992">"Ónefnd mappa"</string>
<string name="default_scroll_format" msgid="7475544710230993317">"Síða %1$d af %2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"Heimaskjár %1$d af %2$d"</string>
+ <string name="workspace_new_page" msgid="257366611030256142">"Ný síða á heimaskjá"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"Komdu fagnandi"</string>
<string name="migration_cling_title" msgid="9181776667882933767">"Afritaðu forritatáknin þín"</string>
<string name="migration_cling_description" msgid="2752413805582227644">"Flytja inn tákn og möppur af eldri heimaskjáum?"</string>
@@ -76,6 +77,8 @@
<string name="abandoned_search" msgid="891119232568284442">"Leita"</string>
<string name="abandoned_promises_title" msgid="7096178467971716750">"Þetta forrit er ekki uppsett"</string>
<string name="abandoned_promise_explanation" msgid="3990027586878167529">"Forritið fyrir þetta tákn er ekki uppsett. Þú getur fjarlægt það eða leitað að forritinu og sett það upp handvirkt."</string>
+ <string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> í niðurhali, <xliff:g id="PROGRESS">%2$s</xliff:g> lokið"</string>
+ <string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> bíður uppsetningar"</string>
<string name="action_add_to_workspace" msgid="8902165848117513641">"Bæta á heimaskjá"</string>
<string name="action_move_here" msgid="2170188780612570250">"Færa atriði hingað"</string>
<string name="item_added_to_workspace" msgid="4211073925752213539">"Atriði bætt á heimaskjáinn"</string>
diff --git a/res/values-it/strings.xml b/res/values-it/strings.xml
index 3b7a957..e1631a4 100644
--- a/res/values-it/strings.xml
+++ b/res/values-it/strings.xml
@@ -26,8 +26,8 @@
<string name="activity_not_available" msgid="7456344436509528827">"App non disponibile"</string>
<string name="safemode_shortcut_error" msgid="9160126848219158407">"L\'app scaricata è stata disattivata in modalità provvisoria"</string>
<string name="safemode_widget_error" msgid="4863470563535682004">"Widget disabilitati in modalità provvisoria"</string>
- <string name="toggle_weight_watcher" msgid="5645299835184636119">"Mostra Mem"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"Tocca e tieni premuto per scegliere un widget."</string>
+ <string name="long_accessible_way_to_add" msgid="4289502106628154155">"Tocca due volte e tieni premuto per scegliere un widget o per utilizzare azioni personalizzate."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="all_apps_search_bar_hint" msgid="7084713969757597256">"Cerca app"</string>
<string name="all_apps_loading_message" msgid="7557140873644765180">"Caricamento di app…"</string>
@@ -53,6 +53,7 @@
<string name="folder_hint_text" msgid="6617836969016293992">"Cartella senza nome"</string>
<string name="default_scroll_format" msgid="7475544710230993317">"Pagina %1$d di %2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"Schermata Home %1$d di %2$d"</string>
+ <string name="workspace_new_page" msgid="257366611030256142">"Nuova pagina Schermata Home"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"Benvenuto"</string>
<string name="migration_cling_title" msgid="9181776667882933767">"Copia le icone delle tue app"</string>
<string name="migration_cling_description" msgid="2752413805582227644">"Importare icone e cartelle dalle schermate Home precedenti?"</string>
@@ -76,6 +77,8 @@
<string name="abandoned_search" msgid="891119232568284442">"Cerca"</string>
<string name="abandoned_promises_title" msgid="7096178467971716750">"L\'app non è installata"</string>
<string name="abandoned_promise_explanation" msgid="3990027586878167529">"L\'app per questa icona non è installata. Puoi rimuoverla o cercare l\'app e installarla manualmente."</string>
+ <string name="app_downloading_title" msgid="8336702962104482644">"Download di <xliff:g id="NAME">%1$s</xliff:g> in corso, <xliff:g id="PROGRESS">%2$s</xliff:g> completato"</string>
+ <string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> in attesa di installazione"</string>
<string name="action_add_to_workspace" msgid="8902165848117513641">"Aggiungi a schermata Home"</string>
<string name="action_move_here" msgid="2170188780612570250">"Sposta elemento qui"</string>
<string name="item_added_to_workspace" msgid="4211073925752213539">"Elemento aggiunto alla schermata Home"</string>
diff --git a/res/values-iw/strings.xml b/res/values-iw/strings.xml
index 333da35..db88fe2 100644
--- a/res/values-iw/strings.xml
+++ b/res/values-iw/strings.xml
@@ -26,8 +26,8 @@
<string name="activity_not_available" msgid="7456344436509528827">"האפליקציה אינה זמינה"</string>
<string name="safemode_shortcut_error" msgid="9160126848219158407">"אפליקציה שהורדת הושבתה במצב בטוח"</string>
<string name="safemode_widget_error" msgid="4863470563535682004">"ווידג\'טים מושבתים במצב בטוח"</string>
- <string name="toggle_weight_watcher" msgid="5645299835184636119">"הצג זכרון"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"גע נגיעה רציפה בווידג\'ט כדי לבחור בו."</string>
+ <string name="long_accessible_way_to_add" msgid="4289502106628154155">"הקש פעמיים וגע נגיעה רציפה בווידג\'ט כדי לבחור בו, או השתמש בפעולות מותאמות אישית."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="all_apps_search_bar_hint" msgid="7084713969757597256">"חפש אפליקציות"</string>
<string name="all_apps_loading_message" msgid="7557140873644765180">"טוען אפליקציות…"</string>
@@ -53,6 +53,7 @@
<string name="folder_hint_text" msgid="6617836969016293992">"תיקיה ללא שם"</string>
<string name="default_scroll_format" msgid="7475544710230993317">"דף %1$d מתוך %2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"מסך דף הבית %1$d מתוך %2$d"</string>
+ <string name="workspace_new_page" msgid="257366611030256142">"מסך דף הבית חדש"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"ברוכים הבאים"</string>
<string name="migration_cling_title" msgid="9181776667882933767">"העתקת סמלי האפליקציות שלך"</string>
<string name="migration_cling_description" msgid="2752413805582227644">"האם לייבא סמלים ותיקיות ממסכי דף הבית הישנים שלך?"</string>
@@ -76,6 +77,8 @@
<string name="abandoned_search" msgid="891119232568284442">"חפש"</string>
<string name="abandoned_promises_title" msgid="7096178467971716750">"אפליקציה זו אינה מותקנת"</string>
<string name="abandoned_promise_explanation" msgid="3990027586878167529">"האפליקציה של סמל זה אינה מותקנת. ניתן להסיר אותו, או לחפש את האפליקציה ולהתקין אותה ידנית."</string>
+ <string name="app_downloading_title" msgid="8336702962104482644">"מוריד את <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="PROGRESS">%2$s</xliff:g> הושלמו"</string>
+ <string name="app_waiting_download_title" msgid="7053938513995617849">"מחכה להתקנה של <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="action_add_to_workspace" msgid="8902165848117513641">"הוסף למסך דף הבית"</string>
<string name="action_move_here" msgid="2170188780612570250">"העבר את הפריט לכאן"</string>
<string name="item_added_to_workspace" msgid="4211073925752213539">"הפריט הועבר אל מסך דף הבית"</string>
diff --git a/res/values-ja/strings.xml b/res/values-ja/strings.xml
index 43411e8..b4873a0 100644
--- a/res/values-ja/strings.xml
+++ b/res/values-ja/strings.xml
@@ -26,8 +26,8 @@
<string name="activity_not_available" msgid="7456344436509528827">"このアプリは使用できません"</string>
<string name="safemode_shortcut_error" msgid="9160126848219158407">"ダウンロードしたアプリは、セーフモードでは無効です"</string>
<string name="safemode_widget_error" msgid="4863470563535682004">"セーフモードではウィジェットは無効です"</string>
- <string name="toggle_weight_watcher" msgid="5645299835184636119">"メモリーを表示"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"ウィジェットを追加するには押し続けます。"</string>
+ <string name="long_accessible_way_to_add" msgid="4289502106628154155">"ダブルタップ後に押し続けてウィジェットを選択するか、カスタム操作を使用してください。"</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$dx%2$d"</string>
<string name="all_apps_search_bar_hint" msgid="7084713969757597256">"アプリを検索"</string>
<string name="all_apps_loading_message" msgid="7557140873644765180">"アプリを読み込んでいます…"</string>
@@ -53,6 +53,7 @@
<string name="folder_hint_text" msgid="6617836969016293992">"名前のないフォルダ"</string>
<string name="default_scroll_format" msgid="7475544710230993317">"%1$d/%2$dページ"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"ホーム画面: %1$d/%2$d"</string>
+ <string name="workspace_new_page" msgid="257366611030256142">"新しいホーム画面ページ"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"ようこそ"</string>
<string name="migration_cling_title" msgid="9181776667882933767">"アプリのアイコンをコピー"</string>
<string name="migration_cling_description" msgid="2752413805582227644">"古いホーム画面からアイコンとフォルダをインポートしますか?"</string>
@@ -76,6 +77,8 @@
<string name="abandoned_search" msgid="891119232568284442">"検索"</string>
<string name="abandoned_promises_title" msgid="7096178467971716750">"このアプリはインストールされていません"</string>
<string name="abandoned_promise_explanation" msgid="3990027586878167529">"このアイコンのアプリはインストールされていません。このアイコンは削除できます。または、手動でアプリを検索してインストールしください。"</string>
+ <string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g>をダウンロード中、<xliff:g id="PROGRESS">%2$s</xliff:g>完了"</string>
+ <string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g>のインストール待ち"</string>
<string name="action_add_to_workspace" msgid="8902165848117513641">"ホーム画面に追加"</string>
<string name="action_move_here" msgid="2170188780612570250">"アイテムをここに移動"</string>
<string name="item_added_to_workspace" msgid="4211073925752213539">"アイテムをホーム画面に追加しました"</string>
diff --git a/res/values-ka-rGE/strings.xml b/res/values-ka-rGE/strings.xml
index 1280a54..44c17a2 100644
--- a/res/values-ka-rGE/strings.xml
+++ b/res/values-ka-rGE/strings.xml
@@ -26,8 +26,8 @@
<string name="activity_not_available" msgid="7456344436509528827">"აპი მიუწვდომელია"</string>
<string name="safemode_shortcut_error" msgid="9160126848219158407">"უსაფრთხო რეჟიმში ჩამოტვირთული აპი გაუქმებულია"</string>
<string name="safemode_widget_error" msgid="4863470563535682004">"უსაფრთხო რეჟიმში ვიჯეტი გამორთულია"</string>
- <string name="toggle_weight_watcher" msgid="5645299835184636119">"Mem-ის ჩვენება"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"შეეხეთ და დააყოვნეთ ვიჯეტის ასარჩევად."</string>
+ <string name="long_accessible_way_to_add" msgid="4289502106628154155">"ორმაგად შეეხეთ და გეჭიროთ ვიჯეტის ასარჩევად ან მორგებული მოქმედებების გამოსაყენებლად."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="all_apps_search_bar_hint" msgid="7084713969757597256">"აპების ძიება"</string>
<string name="all_apps_loading_message" msgid="7557140873644765180">"აპები იტვირთება..."</string>
@@ -53,6 +53,7 @@
<string name="folder_hint_text" msgid="6617836969016293992">"უსახელო საქაღალდე"</string>
<string name="default_scroll_format" msgid="7475544710230993317">"გვერდი %1$d %2$d-დან"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"მთავარი ეკრანი %1$d, %2$d-დან"</string>
+ <string name="workspace_new_page" msgid="257366611030256142">"მთავარი ეკრანის ახალი გვერდი"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"მოგესალმებით"</string>
<string name="migration_cling_title" msgid="9181776667882933767">"თქვენი აპის ხატულების კოპირება"</string>
<string name="migration_cling_description" msgid="2752413805582227644">"გსურთ, ძველი მთავარი ეკრანიდან ხატულების და საქაღ. იმპორტი?"</string>
@@ -76,6 +77,8 @@
<string name="abandoned_search" msgid="891119232568284442">"ძიება"</string>
<string name="abandoned_promises_title" msgid="7096178467971716750">"ეს აპი დაყენებული არ არის"</string>
<string name="abandoned_promise_explanation" msgid="3990027586878167529">"ამ ხატულის აპი დაყენებული არ არის. შეგიძლიათ ამოშალოთ, ან მოიძიოთ აპი და ხელით მოახდინოთ მისი ინსტალაცია."</string>
+ <string name="app_downloading_title" msgid="8336702962104482644">"მიმდინარეობს <xliff:g id="NAME">%1$s</xliff:g>-ის ჩამოტვირთვა, <xliff:g id="PROGRESS">%2$s</xliff:g> დასრულდა"</string>
+ <string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> ელოდება ინსტალაციას"</string>
<string name="action_add_to_workspace" msgid="8902165848117513641">"მთავარ ეკრანზე დამატება"</string>
<string name="action_move_here" msgid="2170188780612570250">"ერთეულის გადაადგილება აქ"</string>
<string name="item_added_to_workspace" msgid="4211073925752213539">"ერთეული დაემატა მთავარ ეკრანს"</string>
diff --git a/res/values-kk-rKZ/strings.xml b/res/values-kk-rKZ/strings.xml
index c6ab0e3..e30d9fe 100644
--- a/res/values-kk-rKZ/strings.xml
+++ b/res/values-kk-rKZ/strings.xml
@@ -26,8 +26,8 @@
<string name="activity_not_available" msgid="7456344436509528827">"Қолданба қол жетімді емес"</string>
<string name="safemode_shortcut_error" msgid="9160126848219158407">"Жүктелген қолданба қауіпсіз режимде өшірілген"</string>
<string name="safemode_widget_error" msgid="4863470563535682004">"Қауіпсіз режимде виджеттер өшіріледі"</string>
- <string name="toggle_weight_watcher" msgid="5645299835184636119">"Жадты көрсету"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"Виджетті таңдау үшін түртіп, мықтап ұстаңыз."</string>
+ <string name="long_accessible_way_to_add" msgid="4289502106628154155">"Виджетті таңдау немесе арнаулы әрекеттерді таңдау үшін екі рет түртіп, ұстап тұрыңыз."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="all_apps_search_bar_hint" msgid="7084713969757597256">"Қолданбаларды іздеу"</string>
<string name="all_apps_loading_message" msgid="7557140873644765180">"Қолданбалар жүктелуде…"</string>
@@ -53,6 +53,7 @@
<string name="folder_hint_text" msgid="6617836969016293992">"Атауы жоқ қалта"</string>
<string name="default_scroll_format" msgid="7475544710230993317">"%1$d бет, барлығы %2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"%1$d негізгі экран, барлығы %2$d"</string>
+ <string name="workspace_new_page" msgid="257366611030256142">"Жаңа негізгі экран беті"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"Қош келдіңіз"</string>
<string name="migration_cling_title" msgid="9181776667882933767">"Қолданба таңбаларын көшіру"</string>
<string name="migration_cling_description" msgid="2752413805582227644">"Бұрынғы негізгі экрандарыңыздағы таңбалар мен қалталар импортталсын ба?"</string>
@@ -76,6 +77,8 @@
<string name="abandoned_search" msgid="891119232568284442">"Іздеу"</string>
<string name="abandoned_promises_title" msgid="7096178467971716750">"Бұл қолданба орнатылмаған"</string>
<string name="abandoned_promise_explanation" msgid="3990027586878167529">"Осы белгіше үшін қолданба орнатылмаған. Оны жоюға болады немесе қолданбаны іздеп, қолмен орнатуға болады."</string>
+ <string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> жүктелуде, <xliff:g id="PROGRESS">%2$s</xliff:g> аяқталды"</string>
+ <string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> орнату күтілуде"</string>
<string name="action_add_to_workspace" msgid="8902165848117513641">"Негізгі экранға қосу"</string>
<string name="action_move_here" msgid="2170188780612570250">"Элементті мұнда жылжыту"</string>
<string name="item_added_to_workspace" msgid="4211073925752213539">"Элемент негізгі экранға қосылды"</string>
diff --git a/res/values-km-rKH/strings.xml b/res/values-km-rKH/strings.xml
index 6f4feeb..abe8a1c 100644
--- a/res/values-km-rKH/strings.xml
+++ b/res/values-km-rKH/strings.xml
@@ -26,8 +26,8 @@
<string name="activity_not_available" msgid="7456344436509528827">"មិនមានកម្មវិធី"</string>
<string name="safemode_shortcut_error" msgid="9160126848219158407">"បានបិទកម្មវិធីដែលបានទាញយកក្នុងរបៀបសុវត្ថិភាព"</string>
<string name="safemode_widget_error" msgid="4863470563535682004">"បានបិទធាតុក្រាហ្វិកក្នុងរបៀបសុវត្ថិភាព"</string>
- <string name="toggle_weight_watcher" msgid="5645299835184636119">"បង្ហាញ Mem"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"ប៉ះ & សង្កត់ ដើម្បីជ្រើសធាតុក្រាហ្វិក។"</string>
+ <string name="long_accessible_way_to_add" msgid="4289502106628154155">"ប៉ះពីរដង ហើយចុចឲ្យជាប់ដើម្បីជ្រើសយកធាតុក្រាហ្វិក ឬប្រើសកម្មភាពផ្ទាល់ខ្លួន។"</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="all_apps_search_bar_hint" msgid="7084713969757597256">"ស្វែងរកកម្មវិធី"</string>
<string name="all_apps_loading_message" msgid="7557140873644765180">"កំពុងដំណើរការកម្មវិធី..."</string>
@@ -53,6 +53,7 @@
<string name="folder_hint_text" msgid="6617836969016293992">"ថតគ្មានឈ្មោះ"</string>
<string name="default_scroll_format" msgid="7475544710230993317">"ទំព័រ %1$d នៃ %2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"អេក្រង់ដើម %1$d នៃ %2$d"</string>
+ <string name="workspace_new_page" msgid="257366611030256142">"ទំព័រអេក្រង់ដើមថ្មី"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"សូមស្វាគមន៍"</string>
<string name="migration_cling_title" msgid="9181776667882933767">"ចម្លងរូបតំណាងកម្មវិធីរបស់អ្នក"</string>
<string name="migration_cling_description" msgid="2752413805582227644">"នាំចូលរូបតំណាង និងថតពីអេក្រង់ដើមចាស់របស់អ្នក?"</string>
@@ -76,6 +77,8 @@
<string name="abandoned_search" msgid="891119232568284442">"ស្វែងរក"</string>
<string name="abandoned_promises_title" msgid="7096178467971716750">"មិនបានដំឡើងកម្មវិធីនេះ"</string>
<string name="abandoned_promise_explanation" msgid="3990027586878167529">"មិនបានដំឡើងកម្មវិធីសម្រាប់រូបតំណាងនេះ។ អ្នកអាចលុបវា ឬស្វែងរកកម្មវិធី និងដំឡើងវាដោយដៃ។"</string>
+ <string name="app_downloading_title" msgid="8336702962104482644">"កំពុងដោនឡូត <xliff:g id="NAME">%1$s</xliff:g> បានបញ្ចប់ <xliff:g id="PROGRESS">%2$s</xliff:g>"</string>
+ <string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> កំពុងរង់ចាំការដំឡើង"</string>
<string name="action_add_to_workspace" msgid="8902165848117513641">"បន្ថែមទៅអេក្រង់ដើម"</string>
<string name="action_move_here" msgid="2170188780612570250">"ផ្លាស់ធាតុមកទីនេះ"</string>
<string name="item_added_to_workspace" msgid="4211073925752213539">"ធាតុដែលត្រូវបានបន្ថែមទៅអេក្រង់ដើម"</string>
diff --git a/res/values-kn-rIN/strings.xml b/res/values-kn-rIN/strings.xml
index 14cfe55..9086d9b 100644
--- a/res/values-kn-rIN/strings.xml
+++ b/res/values-kn-rIN/strings.xml
@@ -26,8 +26,8 @@
<string name="activity_not_available" msgid="7456344436509528827">"ಅಪ್ಲಿಕೇಶನ್ ಲಭ್ಯವಿಲ್ಲ"</string>
<string name="safemode_shortcut_error" msgid="9160126848219158407">"ಡೌನ್ಲೋಡ್ ಮಾಡಲಾದ ಅಪ್ಲಿಕೇಶನ್ ಅನ್ನು ಸುರಕ್ಷಿತ ಮೋಡ್ನಲ್ಲಿ ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ"</string>
<string name="safemode_widget_error" msgid="4863470563535682004">"ಸುರಕ್ಷಿತ ಮೋಡ್ನಲ್ಲಿ ವಿಜೆಟ್ಗಳನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ"</string>
- <string name="toggle_weight_watcher" msgid="5645299835184636119">"ಸ್ಮರಣೆ ತೋರಿಸು"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"ವಿಜೆಟ್ ಅನ್ನು ಆರಿಸಿಕೊಳ್ಳಲು ಸ್ಪರ್ಶಿಸಿ & ಹಿಡಿದುಕೊಳ್ಳಿ."</string>
+ <string name="long_accessible_way_to_add" msgid="4289502106628154155">"ಡಬಲ್ ಟ್ಯಾಪ್ ಮಾಡಿ ಮತ್ತು ವಿಜೆಟ್ ಆರಿಸಿಕೊಳ್ಳಲು ಹೋಲ್ಡ್ ಮಾಡಿ ಅಥವಾ ಕಸ್ಟಮ್ ಕ್ರಿಯೆಗಳನ್ನು ಬಳಸಿ"</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="all_apps_search_bar_hint" msgid="7084713969757597256">"ಅಪ್ಲಿಕೇಷನ್ಗಳನ್ನು ಹುಡುಕಿ"</string>
<string name="all_apps_loading_message" msgid="7557140873644765180">"ಅಪ್ಲಿಕೇಶನ್ಗಳನ್ನು ಲೋಡ್ ಮಾಡಲಾಗುತ್ತಿದೆ..."</string>
@@ -53,6 +53,7 @@
<string name="folder_hint_text" msgid="6617836969016293992">"ಹೆಸರಿಲ್ಲದ ಫೋಲ್ಡರ್"</string>
<string name="default_scroll_format" msgid="7475544710230993317">"%2$d ರಲ್ಲಿ %1$d ಪುಟ"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"%2$d ರಲ್ಲಿ %1$d ಮುಖಪುಟದ ಪರದೆ"</string>
+ <string name="workspace_new_page" msgid="257366611030256142">"ಹೊಸ ಮುಖಪುಟ ಪರದೆ"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"ಸುಸ್ವಾಗತ"</string>
<string name="migration_cling_title" msgid="9181776667882933767">"ಅಪ್ಲಿಕೇಶನ್ ಐಕಾನ್ ನಕಲಿಸು"</string>
<string name="migration_cling_description" msgid="2752413805582227644">"ನಿಮ್ಮ ಹಳೆಯ ಮುಖಪುಟದ ಪರದೆಗಳಿಂದ ಐಕಾನ್ಗಳು ಮತ್ತು ಫೋಲ್ಡರ್ಗಳನ್ನು ಆಮದು ಮಾಡಿಕೊಳ್ಳುವುದೇ?"</string>
@@ -76,6 +77,8 @@
<string name="abandoned_search" msgid="891119232568284442">"ಹುಡುಕು"</string>
<string name="abandoned_promises_title" msgid="7096178467971716750">"ಈ ಅಪ್ಲಿಕೇಶನ್ ಸ್ಥಾಪನೆಗೊಂಡಿಲ್ಲ"</string>
<string name="abandoned_promise_explanation" msgid="3990027586878167529">"ಈ ಐಕಾನ್ ಅಪ್ಲಿಕೇಶನ್ ಸ್ಥಾಪನೆಗೊಂಡಿಲ್ಲ. ನೀವು ಅದನ್ನು ತೆಗೆದುಹಾಕಬಹುದು ಅಥವಾ ಅಪ್ಲಿಕೇಶನ್ ಹುಡುಕಬಹುದು ಮತ್ತು ಹಸ್ತಚಾಲಿತವಾಗಿ ಅದನ್ನು ಸ್ಥಾಪಿಸಬಹುದು."</string>
+ <string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> ಡೌನ್ಲೋಡ್ ಮಾಡಲಾಗುತ್ತಿದೆ, <xliff:g id="PROGRESS">%2$s</xliff:g> ಪೂರ್ಣಗೊಂಡಿದೆ"</string>
+ <string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> ಸ್ಥಾಪಿಸಲು ಕಾಯಲಾಗುತ್ತಿದೆ"</string>
<string name="action_add_to_workspace" msgid="8902165848117513641">"ಮುಖಪುಟಕ್ಕೆ ಸೇರಿಸು"</string>
<string name="action_move_here" msgid="2170188780612570250">"ಐಟಂ ಇಲ್ಲಿಗೆ ಸರಿಸಿ"</string>
<string name="item_added_to_workspace" msgid="4211073925752213539">"ಮುಖಪುಟ ಪರದೆಗೆ ಐಟಂ ಸೇರಿಸಲಾಗಿದೆ"</string>
diff --git a/res/values-ko/strings.xml b/res/values-ko/strings.xml
index 2eb75f9..cebf762 100644
--- a/res/values-ko/strings.xml
+++ b/res/values-ko/strings.xml
@@ -26,8 +26,8 @@
<string name="activity_not_available" msgid="7456344436509528827">"앱을 사용할 수 없음"</string>
<string name="safemode_shortcut_error" msgid="9160126848219158407">"다운로드한 앱은 안전 모드에서 사용할 수 없습니다."</string>
<string name="safemode_widget_error" msgid="4863470563535682004">"안전 모드에서 위젯 사용 중지됨"</string>
- <string name="toggle_weight_watcher" msgid="5645299835184636119">"메모리 표시"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"위젯을 선택하려면 길게 터치하세요."</string>
+ <string name="long_accessible_way_to_add" msgid="4289502106628154155">"위젯을 선택하려면 두 번 탭한 다음 길게 터치하거나 맞춤 액션을 사용합니다."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d×%2$d"</string>
<string name="all_apps_search_bar_hint" msgid="7084713969757597256">"앱 검색"</string>
<string name="all_apps_loading_message" msgid="7557140873644765180">"앱 로드 중..."</string>
@@ -53,6 +53,7 @@
<string name="folder_hint_text" msgid="6617836969016293992">"이름이 없는 폴더"</string>
<string name="default_scroll_format" msgid="7475544710230993317">"페이지 %1$d/%2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"홈 화면 %1$d/%2$d"</string>
+ <string name="workspace_new_page" msgid="257366611030256142">"새로운 메인 스크린 페이지"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"환영합니다."</string>
<string name="migration_cling_title" msgid="9181776667882933767">"앱 아이콘 복사"</string>
<string name="migration_cling_description" msgid="2752413805582227644">"이전 메인 스크린에서 아이콘과 폴더를 가져오시겠습니까?"</string>
@@ -76,6 +77,8 @@
<string name="abandoned_search" msgid="891119232568284442">"검색"</string>
<string name="abandoned_promises_title" msgid="7096178467971716750">"이 앱이 설치되어 있지 않음"</string>
<string name="abandoned_promise_explanation" msgid="3990027586878167529">"이 아이콘의 앱이 설치되어 있지 않습니다. 아이콘을 삭제하거나 앱을 검색하여 수동으로 설치하세요."</string>
+ <string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> 다운로드 중, <xliff:g id="PROGRESS">%2$s</xliff:g> 완료"</string>
+ <string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> 설치 대기 중"</string>
<string name="action_add_to_workspace" msgid="8902165848117513641">"메인 스크린에 추가"</string>
<string name="action_move_here" msgid="2170188780612570250">"여기에 항목을 이동"</string>
<string name="item_added_to_workspace" msgid="4211073925752213539">"메인 스크린에 항목 추가됨"</string>
diff --git a/res/values-ky-rKG/strings.xml b/res/values-ky-rKG/strings.xml
index 799a69e..89f97a4 100644
--- a/res/values-ky-rKG/strings.xml
+++ b/res/values-ky-rKG/strings.xml
@@ -26,8 +26,8 @@
<string name="activity_not_available" msgid="7456344436509528827">"Колдонмо жеткиликтүү эмес"</string>
<string name="safemode_shortcut_error" msgid="9160126848219158407">"Жүктөп алынган колдонмо Коопсуз режиминде иштен чыгарылды"</string>
<string name="safemode_widget_error" msgid="4863470563535682004">"Виджеттер Коопсуз режимде өчүрүлгөн"</string>
- <string name="toggle_weight_watcher" msgid="5645299835184636119">"Мемди көргөзүү"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"Виджетти тандаш үчүн, басып туруңуз"</string>
+ <string name="long_accessible_way_to_add" msgid="4289502106628154155">"Виджет тандоо үчүн эки жолу таптап, кармап туруңуз же ыңгайлаштырылган аракеттерди колдонуңуз."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="all_apps_search_bar_hint" msgid="7084713969757597256">"Колдонмолорду издөө"</string>
<string name="all_apps_loading_message" msgid="7557140873644765180">"Колдонмолор жүктөлүүдө…"</string>
@@ -53,6 +53,7 @@
<string name="folder_hint_text" msgid="6617836969016293992">"Аты жок фолдер"</string>
<string name="default_scroll_format" msgid="7475544710230993317">"%2$d ичинен %1$d барак"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"Үй экраны %2$d ичинен %1$d"</string>
+ <string name="workspace_new_page" msgid="257366611030256142">"Жаңы башкы экран барагы"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"Кош келиңиз"</string>
<string name="migration_cling_title" msgid="9181776667882933767">"Колдонмоңуздун сүрөтчөлөрүн көчүрүү"</string>
<string name="migration_cling_description" msgid="2752413805582227644">"Эски үй экрандарыңыздан сүрөтчөлөр жана фолдерлер импорттолсунбу?"</string>
@@ -76,6 +77,8 @@
<string name="abandoned_search" msgid="891119232568284442">"Издөө"</string>
<string name="abandoned_promises_title" msgid="7096178467971716750">"Бул колдонмо орнотулган эмес"</string>
<string name="abandoned_promise_explanation" msgid="3990027586878167529">"Бул сүрөтчөнүн колдонмосу орнотулган эмес. Аны алып салсаңыз же колдонмону издеп, кол менен орнотсоңуз болот."</string>
+ <string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> жүктөлүп алынууда, <xliff:g id="PROGRESS">%2$s</xliff:g> аяктады"</string>
+ <string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> орнотулушу күтүлүүдө"</string>
<string name="action_add_to_workspace" msgid="8902165848117513641">"Башкы экранга кошуу"</string>
<string name="action_move_here" msgid="2170188780612570250">"Бул нерсени бул жерге жылдыруу"</string>
<string name="item_added_to_workspace" msgid="4211073925752213539">"Башкы экранга кошулду"</string>
diff --git a/res/values-lo-rLA/strings.xml b/res/values-lo-rLA/strings.xml
index 4ae46ab..04fdd02 100644
--- a/res/values-lo-rLA/strings.xml
+++ b/res/values-lo-rLA/strings.xml
@@ -26,8 +26,8 @@
<string name="activity_not_available" msgid="7456344436509528827">"ແອັບຯໃຊ້ບໍ່ໄດ້"</string>
<string name="safemode_shortcut_error" msgid="9160126848219158407">"ແອັບຯທີ່ດາວໂຫລດແລ້ວຖືກປິດການນຳໃຊ້ໃນ Safe mode"</string>
<string name="safemode_widget_error" msgid="4863470563535682004">"ວິດເຈັດຖືກປິດໃນ Safe mode"</string>
- <string name="toggle_weight_watcher" msgid="5645299835184636119">"ສະແດງຄວາມຈຳ"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"ສຳພັດຄ້າງໄວ້ ເພື່ອຈັບວິດເຈັດ."</string>
+ <string name="long_accessible_way_to_add" msgid="4289502106628154155">"ແຕະຄ້າງໄວ້ ເພື່ອເລືອກວິດເຈັດ ຫຼື ໃຊ້ການດຳເນີນການກຳນົດເອງ."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="all_apps_search_bar_hint" msgid="7084713969757597256">"ຊອກຫາແອັບ"</string>
<string name="all_apps_loading_message" msgid="7557140873644765180">"ກຳລັງໂຫລດແອັບ..."</string>
@@ -53,6 +53,7 @@
<string name="folder_hint_text" msgid="6617836969016293992">"ໂຟນເດີຍັງບໍ່ຖືກຕັ້ງຊື່"</string>
<string name="default_scroll_format" msgid="7475544710230993317">"ໜ້າ %1$d ຈາກ %2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"ໜ້າຈໍຫຼັກ %1$d ໃນ %2$d"</string>
+ <string name="workspace_new_page" msgid="257366611030256142">"ໜ້າຂອງໜ້າຈໍຫຼັກໃໝ່"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"ຍິນດີຕ້ອນຮັບ"</string>
<string name="migration_cling_title" msgid="9181776667882933767">"ສຳເນົາໄອຄອນແອັບຯຂອງທ່ານ"</string>
<string name="migration_cling_description" msgid="2752413805582227644">"ນຳເຂົ້າໄອຄອນ ແລະ ໂຟນເດີຈາກໂຮມສະກຣີນອັນເກົ່າຂອງທ່ານບໍ່?"</string>
@@ -76,6 +77,8 @@
<string name="abandoned_search" msgid="891119232568284442">"ຊອກຫາ"</string>
<string name="abandoned_promises_title" msgid="7096178467971716750">"ແອັບຯນີ້ຍັງບໍ່ໄດ້ຕິດຕັ້ງເທື່ອ"</string>
<string name="abandoned_promise_explanation" msgid="3990027586878167529">"ແອັບຯສຳລັບໄອຄອນນີ້ຍັງບໍ່ໄດ້ຕິດຕັ້ງເທື່ອ. ທ່ານສາມາດລຶບມັນອອກ ຫຼືຊອກຫາແອັບຯ ແລ້ວຕິດຕັ້ງມັນໄດ້ດ້ວຍຕົນເອງ."</string>
+ <string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> ກຳລັງດາວໂຫຼດ, <xliff:g id="PROGRESS">%2$s</xliff:g> ສຳເລັດ"</string>
+ <string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> ກຳລັງລໍຖ້າຕິດຕັ້ງ"</string>
<string name="action_add_to_workspace" msgid="8902165848117513641">"ເພີ່ມໃສ່ໜ້າຈໍຫຼັກ"</string>
<string name="action_move_here" msgid="2170188780612570250">"Move item here"</string>
<string name="item_added_to_workspace" msgid="4211073925752213539">"ເພີ່ມລາຍການໃສ່ໜ້າຈໍຫຼັກແລ້ວ"</string>
diff --git a/res/values-lt/strings.xml b/res/values-lt/strings.xml
index 741ef12..34d1bba 100644
--- a/res/values-lt/strings.xml
+++ b/res/values-lt/strings.xml
@@ -26,8 +26,8 @@
<string name="activity_not_available" msgid="7456344436509528827">"Programa nepasiekiama"</string>
<string name="safemode_shortcut_error" msgid="9160126848219158407">"Atsisiųsta programa išjungta Saugos režimu"</string>
<string name="safemode_widget_error" msgid="4863470563535682004">"Valdikliai išjungti Saugiame režime"</string>
- <string name="toggle_weight_watcher" msgid="5645299835184636119">"Rodyti atmintinę"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"Palieskite ir laikykite, kad pasirinkt. valdiklį."</string>
+ <string name="long_accessible_way_to_add" msgid="4289502106628154155">"Dukart palieskite ir laikykite, kad pasirinktumėte valdiklį ar naudotumėte tinkintus veiksmus."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="all_apps_search_bar_hint" msgid="7084713969757597256">"Ieškoti programų"</string>
<string name="all_apps_loading_message" msgid="7557140873644765180">"Įkeliamos programos..."</string>
@@ -53,6 +53,7 @@
<string name="folder_hint_text" msgid="6617836969016293992">"Aplankas be pavadinimo"</string>
<string name="default_scroll_format" msgid="7475544710230993317">"%1$d psl. iš %2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"%1$d pagrindinis ekranas iš %2$d"</string>
+ <string name="workspace_new_page" msgid="257366611030256142">"Naujas pagrindinio ekrano puslapis"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"Sveiki"</string>
<string name="migration_cling_title" msgid="9181776667882933767">"Programų piktogramų kopij."</string>
<string name="migration_cling_description" msgid="2752413805582227644">"Importuoti piktogramas ir aplankus iš senų pagr. ekranų?"</string>
@@ -76,6 +77,8 @@
<string name="abandoned_search" msgid="891119232568284442">"Ieškoti"</string>
<string name="abandoned_promises_title" msgid="7096178467971716750">"Ši programa neįdiegta"</string>
<string name="abandoned_promise_explanation" msgid="3990027586878167529">"Šios piktogramos programa neįdiegta. Galite ją pašalinti arba bandyti ieškoti programos ir ją įdiegti patys."</string>
+ <string name="app_downloading_title" msgid="8336702962104482644">"Atsisiunčiama programa „<xliff:g id="NAME">%1$s</xliff:g>“, <xliff:g id="PROGRESS">%2$s</xliff:g> baigta"</string>
+ <string name="app_waiting_download_title" msgid="7053938513995617849">"Laukiama, kol bus įdiegta programa „<xliff:g id="NAME">%1$s</xliff:g>“"</string>
<string name="action_add_to_workspace" msgid="8902165848117513641">"Pridėti prie pagrind. ekrano"</string>
<string name="action_move_here" msgid="2170188780612570250">"Perkelti elementą čia"</string>
<string name="item_added_to_workspace" msgid="4211073925752213539">"Elementas pridėtas prie pagrindinio ekrano"</string>
diff --git a/res/values-lv/strings.xml b/res/values-lv/strings.xml
index 1cea519..cc157c5 100644
--- a/res/values-lv/strings.xml
+++ b/res/values-lv/strings.xml
@@ -26,8 +26,8 @@
<string name="activity_not_available" msgid="7456344436509528827">"Lietotne nav pieejama."</string>
<string name="safemode_shortcut_error" msgid="9160126848219158407">"Lejupielādētā lietotne ir atspējota drošajā režīmā."</string>
<string name="safemode_widget_error" msgid="4863470563535682004">"Logrīki atspējoti drošajā režīmā"</string>
- <string name="toggle_weight_watcher" msgid="5645299835184636119">"Rādīt atmiņu"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"Lai izvēlētos logrīku, pieskarieties un turiet to."</string>
+ <string name="long_accessible_way_to_add" msgid="4289502106628154155">"Lai atlasītu logrīku, veiciet dubultskārienu uz tā un turiet to vai arī veiciet pielāgotas darbības."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="all_apps_search_bar_hint" msgid="7084713969757597256">"Meklēt lietotnes"</string>
<string name="all_apps_loading_message" msgid="7557140873644765180">"Notiek lietotņu ielāde…"</string>
@@ -53,6 +53,7 @@
<string name="folder_hint_text" msgid="6617836969016293992">"Mape bez nosaukuma"</string>
<string name="default_scroll_format" msgid="7475544710230993317">"%1$d. lapa no %2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"Sākuma ekrāns: %1$d no %2$d"</string>
+ <string name="workspace_new_page" msgid="257366611030256142">"Jauna sākuma ekrāna lapa"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"Laipni lūdzam!"</string>
<string name="migration_cling_title" msgid="9181776667882933767">"Lietotņu ikonu kopēšana"</string>
<string name="migration_cling_description" msgid="2752413805582227644">"Vai importēt ikonas, mapes no iepriekšējiem sākuma ekrāniem?"</string>
@@ -76,6 +77,8 @@
<string name="abandoned_search" msgid="891119232568284442">"Meklēt"</string>
<string name="abandoned_promises_title" msgid="7096178467971716750">"Šī lietotne nav instalēta"</string>
<string name="abandoned_promise_explanation" msgid="3990027586878167529">"Šai ikonai paredzētā lietotne nav instalēta. Varat noņemt ikonu vai meklēt lietotni un instalēt to manuāli."</string>
+ <string name="app_downloading_title" msgid="8336702962104482644">"Lietotnes <xliff:g id="NAME">%1$s</xliff:g> lejupielāde (<xliff:g id="PROGRESS">%2$s</xliff:g> pabeigti)"</string>
+ <string name="app_waiting_download_title" msgid="7053938513995617849">"Notiek <xliff:g id="NAME">%1$s</xliff:g> instalēšana"</string>
<string name="action_add_to_workspace" msgid="8902165848117513641">"Pievienot sākuma ekrānam"</string>
<string name="action_move_here" msgid="2170188780612570250">"Pārvietot vienumu šeit"</string>
<string name="item_added_to_workspace" msgid="4211073925752213539">"Vienums pievienots sākuma ekrānam"</string>
diff --git a/res/values-mk-rMK/strings.xml b/res/values-mk-rMK/strings.xml
index e84a5cb..b6f89d1 100644
--- a/res/values-mk-rMK/strings.xml
+++ b/res/values-mk-rMK/strings.xml
@@ -26,8 +26,8 @@
<string name="activity_not_available" msgid="7456344436509528827">"Апликацијата не е достапна"</string>
<string name="safemode_shortcut_error" msgid="9160126848219158407">"Преземената апликација е оневозможена во безбеден режим"</string>
<string name="safemode_widget_error" msgid="4863470563535682004">"Додатоците се оневозможени во безбеден режим"</string>
- <string name="toggle_weight_watcher" msgid="5645299835184636119">"Прикажи „Мени“"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"Допри и задржи за да се избере виџетот."</string>
+ <string name="long_accessible_way_to_add" msgid="4289502106628154155">"Допрете двапати и задржете за да изберете додаток или да користите приспособени дејства."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="all_apps_search_bar_hint" msgid="7084713969757597256">"Пребарување апликации"</string>
<string name="all_apps_loading_message" msgid="7557140873644765180">"Се вчитуваат апликации…"</string>
@@ -53,6 +53,7 @@
<string name="folder_hint_text" msgid="6617836969016293992">"Неименувана папка"</string>
<string name="default_scroll_format" msgid="7475544710230993317">"Страница %1$d од %2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"Екран на почетна страница %1$d од %2$d"</string>
+ <string name="workspace_new_page" msgid="257366611030256142">"Нова страница на почетен екран"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"Добредојдовте"</string>
<string name="migration_cling_title" msgid="9181776667882933767">"Копирај икони за апликација"</string>
<string name="migration_cling_description" msgid="2752413805582227644">"Зачувај икони и папки од твоите стари почетни страни?"</string>
@@ -76,6 +77,8 @@
<string name="abandoned_search" msgid="891119232568284442">"Барај"</string>
<string name="abandoned_promises_title" msgid="7096178467971716750">"Апликацијата не е инсталирана"</string>
<string name="abandoned_promise_explanation" msgid="3990027586878167529">"Апликацијата за оваа икона не е инсталирана. Може да ја отстраните или да се обидете да ја најдете апликацијата и да ја инсталирате рачно."</string>
+ <string name="app_downloading_title" msgid="8336702962104482644">"Се презема <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="PROGRESS">%2$s</xliff:g> завршено"</string>
+ <string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> чека да се инсталира"</string>
<string name="action_add_to_workspace" msgid="8902165848117513641">"Додај на Почетен екран"</string>
<string name="action_move_here" msgid="2170188780612570250">"Премести ја ставката овде"</string>
<string name="item_added_to_workspace" msgid="4211073925752213539">"Ставката е додадена на почетниот екран"</string>
diff --git a/res/values-ml-rIN/strings.xml b/res/values-ml-rIN/strings.xml
index e82aa36..4a47956 100644
--- a/res/values-ml-rIN/strings.xml
+++ b/res/values-ml-rIN/strings.xml
@@ -26,8 +26,8 @@
<string name="activity_not_available" msgid="7456344436509528827">"അപ്ലിക്കേഷൻ ലഭ്യമല്ല"</string>
<string name="safemode_shortcut_error" msgid="9160126848219158407">"ഡൗൺലോഡുചെയ്ത അപ്ലിക്കേഷൻ സുരക്ഷാ മോഡിൽ പ്രവർത്തനരഹിതമാക്കി"</string>
<string name="safemode_widget_error" msgid="4863470563535682004">"സുരക്ഷിത മോഡിൽ വിജറ്റുകൾ പ്രവർത്തനരഹിതമാക്കി"</string>
- <string name="toggle_weight_watcher" msgid="5645299835184636119">"മെമ്മറി കാണിക്കുക"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"ഒരു വിജറ്റ് ചേർക്കുന്നതിന് അത് സ്പർശിച്ച് പിടിക്കുക."</string>
+ <string name="long_accessible_way_to_add" msgid="4289502106628154155">"വിജറ്റ് തിരഞ്ഞെടുക്കാനോ ഇഷ്ടാനുസൃത പ്രവർത്തനങ്ങൾ ഉപയോഗിക്കാനോ രണ്ടുതവണ ടാപ്പുചെയ്ത് പിടിക്കുക."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="all_apps_search_bar_hint" msgid="7084713969757597256">"ആപ്പ്സ് തിരയുക"</string>
<string name="all_apps_loading_message" msgid="7557140873644765180">"ആപ്പ്സ് ലോഡുചെയ്യുന്നു..."</string>
@@ -53,6 +53,7 @@
<string name="folder_hint_text" msgid="6617836969016293992">"പേരുനൽകാത്ത ഫോൾഡർ"</string>
<string name="default_scroll_format" msgid="7475544710230993317">"പേജ് %1$d / %2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"ഹോം സ്ക്രീൻ %1$d / %2$d"</string>
+ <string name="workspace_new_page" msgid="257366611030256142">"പുതിയ ഹോം സ്ക്രീൻ പേജ്"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"സ്വാഗതം"</string>
<string name="migration_cling_title" msgid="9181776667882933767">"നിങ്ങളുടെ അപ്ലിക്കേഷൻ ഐക്കണുകൾ പകർത്തുക"</string>
<string name="migration_cling_description" msgid="2752413805582227644">"നിങ്ങളുടെ പഴയ ഹോം സ്ക്രീനുകളിൽ നിന്ന് ഐക്കണുകളും ഫോൾഡറുകളും ഇമ്പോർട്ടുചെയ്യണോ?"</string>
@@ -76,6 +77,8 @@
<string name="abandoned_search" msgid="891119232568284442">"തിരയുക"</string>
<string name="abandoned_promises_title" msgid="7096178467971716750">"ഈ അപ്ലിക്കേഷൻ ഇൻസ്റ്റാളുചെയ്തിട്ടില്ല"</string>
<string name="abandoned_promise_explanation" msgid="3990027586878167529">"ഈ ഐക്കണുവേണ്ടി അപ്ലിക്കേഷൻ ഇൻസ്റ്റാളുചെയ്തിട്ടില്ല. നിങ്ങൾക്കത് നീക്കംചെയ്യാനാകും അല്ലെങ്കിൽ അപ്ലിക്കേഷനുവേണ്ടി തിരഞ്ഞുകൊണ്ട് അത് സ്വമേധയാ ഇൻസ്റ്റാളുചെയ്യുക."</string>
+ <string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> ഡൗൺലോഡ് ചെയ്യുന്നു, <xliff:g id="PROGRESS">%2$s</xliff:g> പൂർത്തിയായി"</string>
+ <string name="app_waiting_download_title" msgid="7053938513995617849">"ഇൻസ്റ്റാൾ ചെയ്യാൻ <xliff:g id="NAME">%1$s</xliff:g> കാക്കുന്നു"</string>
<string name="action_add_to_workspace" msgid="8902165848117513641">"ഹോം സ്ക്രീനിൽ ചേർക്കുക"</string>
<string name="action_move_here" msgid="2170188780612570250">"ഇനം ഇവിടേക്ക് നീക്കുക"</string>
<string name="item_added_to_workspace" msgid="4211073925752213539">"ഹോം സ്ക്രീനിൽ ഇനം ചേർത്തു"</string>
diff --git a/res/values-mn-rMN/strings.xml b/res/values-mn-rMN/strings.xml
index bdf9123..c59a206 100644
--- a/res/values-mn-rMN/strings.xml
+++ b/res/values-mn-rMN/strings.xml
@@ -26,8 +26,8 @@
<string name="activity_not_available" msgid="7456344436509528827">"Апп-г ашиглах боломжгүй"</string>
<string name="safemode_shortcut_error" msgid="9160126848219158407">"Татаж авсан апп-г Аюулгүй горим дотроос идэвхгүйжүүлсэн"</string>
<string name="safemode_widget_error" msgid="4863470563535682004">"Safe горимд виджетүүдийг идэвхгүйжүүлсэн"</string>
- <string name="toggle_weight_watcher" msgid="5645299835184636119">"Мем харуулах"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"Виджетийг авах бол хүрээд барина уу."</string>
+ <string name="long_accessible_way_to_add" msgid="4289502106628154155">"Жижиг хэрэгсэл авах болон тохируулсан үйлдлийг ашиглахын тулд 2 удаа товшоод барина уу."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="all_apps_search_bar_hint" msgid="7084713969757597256">"Апп хайх"</string>
<string name="all_apps_loading_message" msgid="7557140873644765180">"Аппликейшныг ачаалж байна..."</string>
@@ -53,6 +53,7 @@
<string name="folder_hint_text" msgid="6617836969016293992">"Нэргүй фолдер"</string>
<string name="default_scroll_format" msgid="7475544710230993317">"%2$d-н %1$d хуудас"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"%2$d-н Нүүр дэлгэц %1$d"</string>
+ <string name="workspace_new_page" msgid="257366611030256142">"Шинэ үндсэн нүүр хуудас"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"Тавтай морилно уу"</string>
<string name="migration_cling_title" msgid="9181776667882933767">"Таны апп дүрсүүдийг хуулах"</string>
<string name="migration_cling_description" msgid="2752413805582227644">"Таны хуучин Үндсэн дэлгэц дээрх дүрсүүдийг импорт хийх үү?"</string>
@@ -76,6 +77,8 @@
<string name="abandoned_search" msgid="891119232568284442">"Хайх"</string>
<string name="abandoned_promises_title" msgid="7096178467971716750">"Энэ апп-г суулгаагүй байна"</string>
<string name="abandoned_promise_explanation" msgid="3990027586878167529">"Энэ дүрсний апп-г суулгаагүй байна. Та үүнийг устгах буюу апп-г хайж суулгах боломжтой."</string>
+ <string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g>-г татаж байна, <xliff:g id="PROGRESS">%2$s</xliff:g> татсан"</string>
+ <string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> нь суулгахыг хүлээж байна"</string>
<string name="action_add_to_workspace" msgid="8902165848117513641">"Нүүр дэлгэц нэмэх"</string>
<string name="action_move_here" msgid="2170188780612570250">"Энд байршуулах"</string>
<string name="item_added_to_workspace" msgid="4211073925752213539">"Нүүр дэлгэцэнд нэмсэн зүйл"</string>
diff --git a/res/values-mr-rIN/strings.xml b/res/values-mr-rIN/strings.xml
index 820e8e8..373a7cd 100644
--- a/res/values-mr-rIN/strings.xml
+++ b/res/values-mr-rIN/strings.xml
@@ -26,8 +26,8 @@
<string name="activity_not_available" msgid="7456344436509528827">"अॅप उपलब्ध नाही"</string>
<string name="safemode_shortcut_error" msgid="9160126848219158407">"डाउनलोड केलेला अॅप सुरक्षित मोड मध्ये अक्षम केला"</string>
<string name="safemode_widget_error" msgid="4863470563535682004">"विजेट सुरक्षित मोडमध्ये अक्षम झाले"</string>
- <string name="toggle_weight_watcher" msgid="5645299835184636119">"Mem दर्शवा"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"विजेट निवडण्यासाठी स्पर्श करा आणि धरून ठेवा."</string>
+ <string name="long_accessible_way_to_add" msgid="4289502106628154155">"एक विजेट निवडण्यासाठी दोनदा टॅप करा आणि धरून ठेवा किंवा सानुकूल क्रिया वापरा."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="all_apps_search_bar_hint" msgid="7084713969757597256">"अॅप्स शोधा"</string>
<string name="all_apps_loading_message" msgid="7557140873644765180">"अॅप्स लोड करीत आहे..."</string>
@@ -53,6 +53,7 @@
<string name="folder_hint_text" msgid="6617836969016293992">"अनामित फोल्डर"</string>
<string name="default_scroll_format" msgid="7475544710230993317">"%2$d पैकी %1$d पृष्ठ"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"%2$d पैकी %1$d मुख्य स्क्रीन"</string>
+ <string name="workspace_new_page" msgid="257366611030256142">"नवीन मुख्य स्क्रीन पृष्ठ"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"सुस्वागतम"</string>
<string name="migration_cling_title" msgid="9181776667882933767">"आपली अॅप चिन्हे कॉपी करा"</string>
<string name="migration_cling_description" msgid="2752413805582227644">"आपल्या जुन्या मुख्य स्क्रीनवरून चिन्हे आणि फोल्डर आयात करायची?"</string>
@@ -76,6 +77,8 @@
<string name="abandoned_search" msgid="891119232568284442">"शोधा"</string>
<string name="abandoned_promises_title" msgid="7096178467971716750">"हा अॅप स्थापित केलेला नाही"</string>
<string name="abandoned_promise_explanation" msgid="3990027586878167529">"या चिन्हासाठी अॅप स्थापित केलेला नाही. आपण ते काढू शकता किंवा अॅपचा शोध घेऊ शकता आणि त्यास व्यक्तिचलितपणे स्थापित करू शकता."</string>
+ <string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> डाउनलोड होत आहे , <xliff:g id="PROGRESS">%2$s</xliff:g> पूर्ण झाले"</string>
+ <string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> स्थापित करण्याची प्रतिक्षा करीत आहे"</string>
<string name="action_add_to_workspace" msgid="8902165848117513641">"मुख्य स्क्रीनवर जोडा"</string>
<string name="action_move_here" msgid="2170188780612570250">"आयटम येथे हलवा"</string>
<string name="item_added_to_workspace" msgid="4211073925752213539">"आयटम मुख्य स्क्रीनवर जोडला"</string>
diff --git a/res/values-ms-rMY/strings.xml b/res/values-ms-rMY/strings.xml
index aebc5bf..0ff456c 100644
--- a/res/values-ms-rMY/strings.xml
+++ b/res/values-ms-rMY/strings.xml
@@ -26,8 +26,8 @@
<string name="activity_not_available" msgid="7456344436509528827">"Apl tidak tersedia"</string>
<string name="safemode_shortcut_error" msgid="9160126848219158407">"Apl yang dimuat turun dilumpuhkan dalam mod Selamat"</string>
<string name="safemode_widget_error" msgid="4863470563535682004">"Widget dilumpuhkan dalam mod Selamat"</string>
- <string name="toggle_weight_watcher" msgid="5645299835184636119">"Papar Mem"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"Sentuh & tahan untuk mengambil widget."</string>
+ <string name="long_accessible_way_to_add" msgid="4289502106628154155">"Ketik dua kali & tahan untuk mengambil widget atau menggunakan tindakan tersuai"</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="all_apps_search_bar_hint" msgid="7084713969757597256">"Cari Apl"</string>
<string name="all_apps_loading_message" msgid="7557140873644765180">"Memuatkan Apl…"</string>
@@ -53,6 +53,7 @@
<string name="folder_hint_text" msgid="6617836969016293992">"Folder Tanpa Nama"</string>
<string name="default_scroll_format" msgid="7475544710230993317">"Halaman %1$d daripada %2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"Skrin Laman Utama %1$d daripada %2$d"</string>
+ <string name="workspace_new_page" msgid="257366611030256142">"Halaman skrin utama baharu"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"Selamat datang"</string>
<string name="migration_cling_title" msgid="9181776667882933767">"Salin ikon apl anda"</string>
<string name="migration_cling_description" msgid="2752413805582227644">"Import ikon dan folder dari skrin Laman Utama lama anda?"</string>
@@ -76,6 +77,8 @@
<string name="abandoned_search" msgid="891119232568284442">"Carian"</string>
<string name="abandoned_promises_title" msgid="7096178467971716750">"Apl ini tidak dipasang"</string>
<string name="abandoned_promise_explanation" msgid="3990027586878167529">"Apl untuk ikon ini tidak dipasang. Anda boleh mengalih keluar atau mencari dan memasang apl itu secara manual."</string>
+ <string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> memuat turun, <xliff:g id="PROGRESS">%2$s</xliff:g> selesai"</string>
+ <string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> menunggu untuk dipasang"</string>
<string name="action_add_to_workspace" msgid="8902165848117513641">"Tambahkan pada Skrin Utama"</string>
<string name="action_move_here" msgid="2170188780612570250">"Alihkan item ke sini"</string>
<string name="item_added_to_workspace" msgid="4211073925752213539">"Item ditambahkan pada skrin utama"</string>
diff --git a/res/values-my-rMM/strings.xml b/res/values-my-rMM/strings.xml
index e12b84a..ceef91c 100644
--- a/res/values-my-rMM/strings.xml
+++ b/res/values-my-rMM/strings.xml
@@ -26,8 +26,8 @@
<string name="activity_not_available" msgid="7456344436509528827">"App လက်လှမ်း မမှီပါ"</string>
<string name="safemode_shortcut_error" msgid="9160126848219158407">"ဒေါင်းလုဒ် appကို လုံခြုံရေး မုဒ်ထဲမှာ ပိတ်ထား"</string>
<string name="safemode_widget_error" msgid="4863470563535682004">"လုံခြုံရေး မုဒ်ထဲမှာ ဝီဂျက်များကို ပိတ်ထား"</string>
- <string name="toggle_weight_watcher" msgid="5645299835184636119">"Mem ကိုပြရန်"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"ဝဒ်ဂျက်တစ်ခုကို ကောက်ယူရန် ဖိနှိပ်ထားပါ"</string>
+ <string name="long_accessible_way_to_add" msgid="4289502106628154155">"ဝစ်ဂျက်တစ်ခုကိုရယူရန် သို့မဟုတ် စိတ်ကြိုက်လုပ်ဆောင်မှုများကို အသုံးပြုရန် နှစ်ချက်တို့ပြီး ကိုင်ထားပါ။"</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="all_apps_search_bar_hint" msgid="7084713969757597256">"ရှာဖွေမှု Appများ"</string>
<string name="all_apps_loading_message" msgid="7557140873644765180">"App များ ရယူနေစဉ်..."</string>
@@ -53,6 +53,7 @@
<string name="folder_hint_text" msgid="6617836969016293992">"အမည်မရှိအကန့်"</string>
<string name="default_scroll_format" msgid="7475544710230993317">"စာမျက်နှာ %1$d မှ %2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"ပင်မစာမျက်နှာ %1$d မှ %2$d"</string>
+ <string name="workspace_new_page" msgid="257366611030256142">"ပင်မမျက်နှာပြင် စာမျက်နှာသစ်"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"မင်္ဂလာပါ"</string>
<string name="migration_cling_title" msgid="9181776667882933767">"အပ်ပလီကေးရှင်းပုံညွှန်းများကို ကူးယူပါ"</string>
<string name="migration_cling_description" msgid="2752413805582227644">"ပင်မစာမျက်နှာအဟောင်းမှ ပုံညွှန်းများ နှင့် အကန့်များကို ယူလာပါမလား"</string>
@@ -76,6 +77,8 @@
<string name="abandoned_search" msgid="891119232568284442">"ရှာဖွေရန်"</string>
<string name="abandoned_promises_title" msgid="7096178467971716750">"App မတပ်ဆင်ရသေးပါ"</string>
<string name="abandoned_promise_explanation" msgid="3990027586878167529">"ဤအိုင်ကွန်အတွက် app အားမထည့်သွင်းထားပါ။ You can remove it, or search for the app and install it manually."</string>
+ <string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> ဒေါင်းလုဒ်လုပ်နေသည်၊ <xliff:g id="PROGRESS">%2$s</xliff:g> ပြီးပါပြီ"</string>
+ <string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> ကိုထည့်သွင်းရန်စောင့်နေသည်"</string>
<string name="action_add_to_workspace" msgid="8902165848117513641">"ပင်မမျက်နှာစာသို့ ထည့်ပါ"</string>
<string name="action_move_here" msgid="2170188780612570250">"၎င်းအား ဤသို့ ရွှေ့ပါ"</string>
<string name="item_added_to_workspace" msgid="4211073925752213539">"ပင်မ ဖန်မျက်နှာပြင်သို့ ထည့်ပြီး၏"</string>
diff --git a/res/values-nb/strings.xml b/res/values-nb/strings.xml
index 81aabd8..981b21e 100644
--- a/res/values-nb/strings.xml
+++ b/res/values-nb/strings.xml
@@ -26,8 +26,8 @@
<string name="activity_not_available" msgid="7456344436509528827">"Appen er ikke tilgjengelig"</string>
<string name="safemode_shortcut_error" msgid="9160126848219158407">"En nedlastet app er deaktivert i sikker modus"</string>
<string name="safemode_widget_error" msgid="4863470563535682004">"Moduler er deaktivert i sikker modus"</string>
- <string name="toggle_weight_watcher" msgid="5645299835184636119">"Vis minne"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"Trykk og hold inne for å plukke opp en modul."</string>
+ <string name="long_accessible_way_to_add" msgid="4289502106628154155">"Dobbelttrykk og hold inne for å velge en modul eller bruke tilpassede handlinger."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="all_apps_search_bar_hint" msgid="7084713969757597256">"Søk i apper"</string>
<string name="all_apps_loading_message" msgid="7557140873644765180">"Laster inn apper …"</string>
@@ -53,6 +53,7 @@
<string name="folder_hint_text" msgid="6617836969016293992">"Mappe uten navn"</string>
<string name="default_scroll_format" msgid="7475544710230993317">"Side %1$d av %2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"Startside %1$d av %2$d"</string>
+ <string name="workspace_new_page" msgid="257366611030256142">"Ny side på startskjermen"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"Velkommen"</string>
<string name="migration_cling_title" msgid="9181776667882933767">"Kopiér appikonene dine"</string>
<string name="migration_cling_description" msgid="2752413805582227644">"Vil du importere ikoner og mapper fra dine gamle startsider?"</string>
@@ -76,6 +77,8 @@
<string name="abandoned_search" msgid="891119232568284442">"Søk"</string>
<string name="abandoned_promises_title" msgid="7096178467971716750">"Denne appen er ikke installert"</string>
<string name="abandoned_promise_explanation" msgid="3990027586878167529">"Appen for dette ikonet er ikke installert. Du kan fjerne det, eller prøve å søke etter appen og installere den manuelt."</string>
+ <string name="app_downloading_title" msgid="8336702962104482644">"Laster ned <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="PROGRESS">%2$s</xliff:g> er fullført"</string>
+ <string name="app_waiting_download_title" msgid="7053938513995617849">"Venter på å installere <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="action_add_to_workspace" msgid="8902165848117513641">"Legg til på startskjermen"</string>
<string name="action_move_here" msgid="2170188780612570250">"Flytt elementet hit"</string>
<string name="item_added_to_workspace" msgid="4211073925752213539">"Elementet er lagt til på startskjermen"</string>
diff --git a/res/values-ne-rNP/strings.xml b/res/values-ne-rNP/strings.xml
index 847350a..b480826 100644
--- a/res/values-ne-rNP/strings.xml
+++ b/res/values-ne-rNP/strings.xml
@@ -26,8 +26,8 @@
<string name="activity_not_available" msgid="7456344436509528827">"अनुप्रयोग उपलब्ध छैन"</string>
<string name="safemode_shortcut_error" msgid="9160126848219158407">"सुरक्षित मोडमा डाउनलोड गरेको अनुप्रयोग अक्षम गरिएको छ"</string>
<string name="safemode_widget_error" msgid="4863470563535682004">"सुरक्षित मोडमा विगेटहरू अक्षम गरियो"</string>
- <string name="toggle_weight_watcher" msgid="5645299835184636119">"Mem देखाउनुहोस्"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"एउटा विजेटलाई टिप्नको लागि टच गरेर होल्ड गर्नुहोस्।"</string>
+ <string name="long_accessible_way_to_add" msgid="4289502106628154155">"विजेटलाई छान्न वा अनुकूलन कार्यहरू प्रयोग गर्न डबल ट्याप गरी होल्ड गर्नुहोस्।"</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="all_apps_search_bar_hint" msgid="7084713969757597256">"अनुप्रयोगहरू खोज्नुहोस्"</string>
<string name="all_apps_loading_message" msgid="7557140873644765180">"अनुप्रयोगहरू लोड गरिँदै..."</string>
@@ -53,6 +53,7 @@
<string name="folder_hint_text" msgid="6617836969016293992">"बेनाम फोल्डर"</string>
<string name="default_scroll_format" msgid="7475544710230993317">"पृष्ठ %2$d को %1$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"गृह स्क्रिन %1$d को %2$d"</string>
+ <string name="workspace_new_page" msgid="257366611030256142">"नयाँ गृह स्क्रिन पृष्ठ"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"स्वागतम"</string>
<string name="migration_cling_title" msgid="9181776667882933767">"तपाईँको अनुप्रयोग आईकनको प्रतिलिप गर्नुहोस्"</string>
<string name="migration_cling_description" msgid="2752413805582227644">"आफ्नो पुरानो गृह स्क्रीनबाट अाईकन र फोल्डरहरू आयात गर्नुहोस्?"</string>
@@ -76,6 +77,8 @@
<string name="abandoned_search" msgid="891119232568284442">"खोजी गर्नुहोस्"</string>
<string name="abandoned_promises_title" msgid="7096178467971716750">"यो अनुप्रयोग स्थापित छैन"</string>
<string name="abandoned_promise_explanation" msgid="3990027586878167529">"यो प्रतिमाका लागि अनुप्रयोगलाई स्थापना गरिएको छैन। तपाईँ यसलाई हटाउन, वा अनुप्रयोग खोजी र स्वयं यो स्थापित गर्न सक्नुहुन्छ।"</string>
+ <string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> डाउनलोड गर्दै, <xliff:g id="PROGRESS">%2$s</xliff:g> सम्पन्न"</string>
+ <string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> स्थापना गर्न प्रतीक्षा गर्दै"</string>
<string name="action_add_to_workspace" msgid="8902165848117513641">"गृह स्क्रिनमा थप्नुहोस्"</string>
<string name="action_move_here" msgid="2170188780612570250">"वस्तु यहाँ सार्नुहोस्"</string>
<string name="item_added_to_workspace" msgid="4211073925752213539">"वस्तु गृह स्क्रिनमा थपियो"</string>
diff --git a/res/values-nl/strings.xml b/res/values-nl/strings.xml
index edb012b..45c5e45 100644
--- a/res/values-nl/strings.xml
+++ b/res/values-nl/strings.xml
@@ -26,8 +26,8 @@
<string name="activity_not_available" msgid="7456344436509528827">"App is niet beschikbaar"</string>
<string name="safemode_shortcut_error" msgid="9160126848219158407">"Gedownloade app uitgeschakeld in veilige modus"</string>
<string name="safemode_widget_error" msgid="4863470563535682004">"Widgets uitgeschakeld in Veilige modus"</string>
- <string name="toggle_weight_watcher" msgid="5645299835184636119">"Geheugen weergeven"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"Blijf aanraken om een widget toe te voegen."</string>
+ <string name="long_accessible_way_to_add" msgid="4289502106628154155">"Dubbeltik en blijf aanraken om een widget toe te voegen of aangepaste acties te gebruiken."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="all_apps_search_bar_hint" msgid="7084713969757597256">"Apps zoeken"</string>
<string name="all_apps_loading_message" msgid="7557140873644765180">"Apps laden…"</string>
@@ -53,6 +53,7 @@
<string name="folder_hint_text" msgid="6617836969016293992">"Naamloze map"</string>
<string name="default_scroll_format" msgid="7475544710230993317">"Pagina %1$d van %2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"Startscherm %1$d van %2$d"</string>
+ <string name="workspace_new_page" msgid="257366611030256142">"Nieuwe startschermpagina"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"Welkom"</string>
<string name="migration_cling_title" msgid="9181776667882933767">"Je app-pictogrammen kopiëren"</string>
<string name="migration_cling_description" msgid="2752413805582227644">"Pictogrammen en mappen importeren uit je oude startschermen?"</string>
@@ -76,6 +77,8 @@
<string name="abandoned_search" msgid="891119232568284442">"Zoeken"</string>
<string name="abandoned_promises_title" msgid="7096178467971716750">"Deze app is niet geïnstalleerd"</string>
<string name="abandoned_promise_explanation" msgid="3990027586878167529">"De app voor dit pictogram is niet geïnstalleerd. Je kunt het pictogram verwijderen of de app zoeken en handmatig installeren."</string>
+ <string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> wordt gedownload, <xliff:g id="PROGRESS">%2$s</xliff:g> voltooid"</string>
+ <string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> wacht op installatie"</string>
<string name="action_add_to_workspace" msgid="8902165848117513641">"Toevoegen aan startpagina"</string>
<string name="action_move_here" msgid="2170188780612570250">"Item hier naartoe verplaatsen"</string>
<string name="item_added_to_workspace" msgid="4211073925752213539">"Item toegevoegd aan startscherm"</string>
diff --git a/res/values-pa-rIN/strings.xml b/res/values-pa-rIN/strings.xml
index 7352248..30c4428 100644
--- a/res/values-pa-rIN/strings.xml
+++ b/res/values-pa-rIN/strings.xml
@@ -19,7 +19,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_name" msgid="649227358658669779">"Launcher3"</string>
+ <string name="application_name" msgid="5181331383435256801">"ਲਾਂਚਰ3"</string>
<string name="folder_name" msgid="7371454440695724752"></string>
<string name="work_folder_name" msgid="3753320833950115786">"ਦਫ਼ਤਰ"</string>
<string name="activity_not_found" msgid="8071924732094499514">"ਐਪ ਇੰਸਟੌਲ ਨਹੀਂ ਕੀਤਾ ਹੋਇਆ ਹੈ।"</string>
@@ -46,7 +46,6 @@
<string name="permdesc_read_settings" msgid="5833423719057558387">"ਐਪ ਨੂੰ ਹੋਮ ਵਿੱਚ ਸੈਟਿੰਗਾਂ ਅਤੇ ਸ਼ੌਰਟਕਟ ਪੜ੍ਹਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।"</string>
<string name="permlab_write_settings" msgid="3574213698004620587">"ਹੋਮ ਸੈਟਿੰਗਾਂ ਅਤੇ ਸ਼ੌਰਟਕਟ ਲਿਖੋ"</string>
<string name="permdesc_write_settings" msgid="5440712911516509985">"ਐਪ ਨੂੰ ਹੋਮ ਵਿੱਚ ਸੈਟਿੰਗਾਂ ਅਤੇ ਸ਼ੌਰਟਕਟ ਬਦਲਣ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।"</string>
- <string name="msg_no_phone_permission" msgid="9208659281529857371">"<xliff:g id="APP_NAME">%1$s</xliff:g> ਨੂੰ ਫੋਨ ਕਾਲਾਂ ਕਰਨ ਦੀ ਆਗਿਆ ਨਹੀਂ ਹੈ"</string>
<string name="gadget_error_text" msgid="6081085226050792095">"ਵਿਜੇਟ ਲੋਡ ਕਰਨ ਵਿੱਚ ਸਮੱਸਿਆ"</string>
<string name="gadget_setup_text" msgid="8274003207686040488">"ਸੈਟਅਪ"</string>
<string name="uninstall_system_app_text" msgid="4172046090762920660">"ਇਹ ਇੱਕ ਸਿਸਟਮ ਐਪ ਹੈ ਅਤੇ ਇਸਨੂੰ ਅਣਇੰਸਟੌਲ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਦਾ।"</string>
diff --git a/res/values-pl/strings.xml b/res/values-pl/strings.xml
index 26f86cf..bbed949 100644
--- a/res/values-pl/strings.xml
+++ b/res/values-pl/strings.xml
@@ -26,8 +26,8 @@
<string name="activity_not_available" msgid="7456344436509528827">"Aplikacja niedostępna"</string>
<string name="safemode_shortcut_error" msgid="9160126848219158407">"Pobrana aplikacja została wyłączona w trybie awaryjnym"</string>
<string name="safemode_widget_error" msgid="4863470563535682004">"Widżety są wyłączone w trybie bezpiecznym"</string>
- <string name="toggle_weight_watcher" msgid="5645299835184636119">"Pokaż pamięć"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"Aby dodać widżet, kliknij go i przytrzymaj."</string>
+ <string name="long_accessible_way_to_add" msgid="4289502106628154155">"Kliknij dwukrotnie i przytrzymaj, by wybrać widżet lub użyć działań niestandardowych."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="all_apps_search_bar_hint" msgid="7084713969757597256">"Szukaj w aplikacjach"</string>
<string name="all_apps_loading_message" msgid="7557140873644765180">"Wczytuję aplikacje…"</string>
@@ -53,6 +53,7 @@
<string name="folder_hint_text" msgid="6617836969016293992">"Folder bez nazwy"</string>
<string name="default_scroll_format" msgid="7475544710230993317">"Strona %1$d z %2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"Ekran główny %1$d z %2$d"</string>
+ <string name="workspace_new_page" msgid="257366611030256142">"Nowa strona ekranu głównego"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"Witamy"</string>
<string name="migration_cling_title" msgid="9181776667882933767">"Kopiuj ikony aplikacji"</string>
<string name="migration_cling_description" msgid="2752413805582227644">"Zaimportować ikony i foldery ze starych ekranów głównych?"</string>
@@ -76,6 +77,8 @@
<string name="abandoned_search" msgid="891119232568284442">"Szukaj"</string>
<string name="abandoned_promises_title" msgid="7096178467971716750">"Ta aplikacja nie jest zainstalowana"</string>
<string name="abandoned_promise_explanation" msgid="3990027586878167529">"Aplikacja, której odpowiada ta ikona, nie jest zainstalowana. Możesz usunąć ikonę lub wyszukać aplikację i zainstalować ją ręcznie."</string>
+ <string name="app_downloading_title" msgid="8336702962104482644">"Pobieranie elementu <xliff:g id="NAME">%1$s</xliff:g>, ukończono: <xliff:g id="PROGRESS">%2$s</xliff:g>"</string>
+ <string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> oczekuje na instalację"</string>
<string name="action_add_to_workspace" msgid="8902165848117513641">"Dodaj do strony głównej"</string>
<string name="action_move_here" msgid="2170188780612570250">"Przenieś element tutaj"</string>
<string name="item_added_to_workspace" msgid="4211073925752213539">"Element został dodany do ekranu głównego"</string>
diff --git a/res/values-pt-rPT/strings.xml b/res/values-pt-rPT/strings.xml
index ed6c56c..a8c9b5e 100644
--- a/res/values-pt-rPT/strings.xml
+++ b/res/values-pt-rPT/strings.xml
@@ -26,8 +26,8 @@
<string name="activity_not_available" msgid="7456344436509528827">"A aplicação não está disponível"</string>
<string name="safemode_shortcut_error" msgid="9160126848219158407">"Aplicação transferida desativada no Modo de segurança"</string>
<string name="safemode_widget_error" msgid="4863470563535682004">"Widgets desativados no Modo de segurança"</string>
- <string name="toggle_weight_watcher" msgid="5645299835184636119">"Mostrar mem"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"Prima sem soltar para escolher um widget."</string>
+ <string name="long_accessible_way_to_add" msgid="4289502106628154155">"Toque duas vezes sem soltar para escolher um widget ou utilize ações personalizadas."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="all_apps_search_bar_hint" msgid="7084713969757597256">"Pesquisar aplicações"</string>
<string name="all_apps_loading_message" msgid="7557140873644765180">"A carregar aplicações..."</string>
@@ -53,6 +53,7 @@
<string name="folder_hint_text" msgid="6617836969016293992">"Pasta sem nome"</string>
<string name="default_scroll_format" msgid="7475544710230993317">"Página %1$d de %2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"Ecrã principal %1$d de %2$d"</string>
+ <string name="workspace_new_page" msgid="257366611030256142">"Nova página do ecrã principal"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"Bem-vindo(a)"</string>
<string name="migration_cling_title" msgid="9181776667882933767">"Copiar ícones das aplicações"</string>
<string name="migration_cling_description" msgid="2752413805582227644">"Importar ícones e pastas dos ecrãs principais antigos?"</string>
@@ -76,6 +77,8 @@
<string name="abandoned_search" msgid="891119232568284442">"Pesquisar"</string>
<string name="abandoned_promises_title" msgid="7096178467971716750">"Esta aplicação não está instalada"</string>
<string name="abandoned_promise_explanation" msgid="3990027586878167529">"A aplicação deste ícone não está instalada. Pode removê-lo ou pesquisar a aplicação e instalá-la manualmente."</string>
+ <string name="app_downloading_title" msgid="8336702962104482644">"A transferir o <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="PROGRESS">%2$s</xliff:g> concluído"</string>
+ <string name="app_waiting_download_title" msgid="7053938513995617849">"A aguardar a instalação do <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="action_add_to_workspace" msgid="8902165848117513641">"Adicionar ao Ecrã principal"</string>
<string name="action_move_here" msgid="2170188780612570250">"Mover o item para aqui"</string>
<string name="item_added_to_workspace" msgid="4211073925752213539">"Item adicionado ao ecrã principal"</string>
diff --git a/res/values-pt/strings.xml b/res/values-pt/strings.xml
index 50da2e8..f46dca1 100644
--- a/res/values-pt/strings.xml
+++ b/res/values-pt/strings.xml
@@ -26,8 +26,8 @@
<string name="activity_not_available" msgid="7456344436509528827">"O app não está disponível"</string>
<string name="safemode_shortcut_error" msgid="9160126848219158407">"App transferido por download desativado no modo de segurança"</string>
<string name="safemode_widget_error" msgid="4863470563535682004">"Widgets desativados no modo de segurança"</string>
- <string name="toggle_weight_watcher" msgid="5645299835184636119">"Mostrar memória"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"Toque e pressione para selecionar um widget."</string>
+ <string name="long_accessible_way_to_add" msgid="4289502106628154155">"Toque duas vezes e segure para selecionar um widget ou usar ações personalizadas."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="all_apps_search_bar_hint" msgid="7084713969757597256">"Pesquisar apps"</string>
<string name="all_apps_loading_message" msgid="7557140873644765180">"Carregando apps…"</string>
@@ -53,6 +53,7 @@
<string name="folder_hint_text" msgid="6617836969016293992">"Pasta sem nome"</string>
<string name="default_scroll_format" msgid="7475544710230993317">"Página %1$d de %2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"Tela inicial %1$d de %2$d"</string>
+ <string name="workspace_new_page" msgid="257366611030256142">"Nova página na tela inicial"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"Bem-vindo"</string>
<string name="migration_cling_title" msgid="9181776667882933767">"Copiar ícones de apps"</string>
<string name="migration_cling_description" msgid="2752413805582227644">"Importar ícones e pastas de suas telas iniciais antigas?"</string>
@@ -76,6 +77,8 @@
<string name="abandoned_search" msgid="891119232568284442">"Pesquisar"</string>
<string name="abandoned_promises_title" msgid="7096178467971716750">"Este app não está instalado"</string>
<string name="abandoned_promise_explanation" msgid="3990027586878167529">"O app deste ícone não está instalado. Você pode remover o ícone, ou procurar o app e instalá-lo manualmente."</string>
+ <string name="app_downloading_title" msgid="8336702962104482644">"Fazendo download de <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="PROGRESS">%2$s</xliff:g> concluído"</string>
+ <string name="app_waiting_download_title" msgid="7053938513995617849">"Aguardando instalação de <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="action_add_to_workspace" msgid="8902165848117513641">"Adicionar à tela inicial"</string>
<string name="action_move_here" msgid="2170188780612570250">"Mover item para cá"</string>
<string name="item_added_to_workspace" msgid="4211073925752213539">"Item adicionado à tela inicial"</string>
diff --git a/res/values-ro/strings.xml b/res/values-ro/strings.xml
index 8443769..512e5cf 100644
--- a/res/values-ro/strings.xml
+++ b/res/values-ro/strings.xml
@@ -26,8 +26,8 @@
<string name="activity_not_available" msgid="7456344436509528827">"Aplicația nu este disponibilă"</string>
<string name="safemode_shortcut_error" msgid="9160126848219158407">"Aplicația descărcată este dezactivată în modul de siguranță"</string>
<string name="safemode_widget_error" msgid="4863470563535682004">"Widgeturile sunt dezactivate în modul de siguranță"</string>
- <string name="toggle_weight_watcher" msgid="5645299835184636119">"Afișați memoria"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"Atingeți lung un widget pentru a-l alege."</string>
+ <string name="long_accessible_way_to_add" msgid="4289502106628154155">"Atingeți de două ori și mențineți apăsat ca să alegeți un widget sau folosiți acțiuni personalizate."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="all_apps_search_bar_hint" msgid="7084713969757597256">"Căutați aplicații"</string>
<string name="all_apps_loading_message" msgid="7557140873644765180">"Se încarcă aplicațiile..."</string>
@@ -53,6 +53,7 @@
<string name="folder_hint_text" msgid="6617836969016293992">"Dosar fără nume"</string>
<string name="default_scroll_format" msgid="7475544710230993317">"Pagina %1$d din %2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"Ecranul de pornire %1$d din %2$d"</string>
+ <string name="workspace_new_page" msgid="257366611030256142">"Pagină nouă pe ecranul de pornire"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"Bun venit"</string>
<string name="migration_cling_title" msgid="9181776667882933767">"Copiați pictogr. aplicațiilor"</string>
<string name="migration_cling_description" msgid="2752413805582227644">"Import. pictogr. și dosare de pe ecranele de pornire anter.?"</string>
@@ -76,6 +77,8 @@
<string name="abandoned_search" msgid="891119232568284442">"Căutați"</string>
<string name="abandoned_promises_title" msgid="7096178467971716750">"Aplicația nu este instalată"</string>
<string name="abandoned_promise_explanation" msgid="3990027586878167529">"Aplicația pentru această pictogramă nu este instalată. Puteți să ștergeți pictograma sau să căutați aplicația și s-o instalați manual."</string>
+ <string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> se descarcă (finalizat <xliff:g id="PROGRESS">%2$s</xliff:g>)"</string>
+ <string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> așteaptă instalarea"</string>
<string name="action_add_to_workspace" msgid="8902165848117513641">"Adăugați pe ecranul de pornire"</string>
<string name="action_move_here" msgid="2170188780612570250">"Mutați elementul aici"</string>
<string name="item_added_to_workspace" msgid="4211073925752213539">"Element adăugat pe ecranul de pornire"</string>
diff --git a/res/values-ru/strings.xml b/res/values-ru/strings.xml
index d2c7786..963c895 100644
--- a/res/values-ru/strings.xml
+++ b/res/values-ru/strings.xml
@@ -26,8 +26,8 @@
<string name="activity_not_available" msgid="7456344436509528827">"Приложение недоступно"</string>
<string name="safemode_shortcut_error" msgid="9160126848219158407">"Скачанное приложение отключено в безопасном режиме"</string>
<string name="safemode_widget_error" msgid="4863470563535682004">"Виджеты отключены в безопасном режиме"</string>
- <string name="toggle_weight_watcher" msgid="5645299835184636119">"Сведения о памяти"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"Чтобы выбрать виджет, нажмите на значок и удерживайте его."</string>
+ <string name="long_accessible_way_to_add" msgid="4289502106628154155">"Чтобы выбрать виджет, нажмите на него дважды и не отпускайте или выполните предложенные действия."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d x %2$d"</string>
<string name="all_apps_search_bar_hint" msgid="7084713969757597256">"Поиск приложений"</string>
<string name="all_apps_loading_message" msgid="7557140873644765180">"Загрузка…"</string>
@@ -53,6 +53,7 @@
<string name="folder_hint_text" msgid="6617836969016293992">"Папка без названия"</string>
<string name="default_scroll_format" msgid="7475544710230993317">"Стр. %1$d из %2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"Главные экран %1$d из %2$d"</string>
+ <string name="workspace_new_page" msgid="257366611030256142">"Новый экран"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"Добро пожаловать!"</string>
<string name="migration_cling_title" msgid="9181776667882933767">"Копировать значки приложений"</string>
<string name="migration_cling_description" msgid="2752413805582227644">"Импортировать значки и папки со старого главного экрана?"</string>
@@ -76,6 +77,8 @@
<string name="abandoned_search" msgid="891119232568284442">"Найти"</string>
<string name="abandoned_promises_title" msgid="7096178467971716750">"Приложение не установлено"</string>
<string name="abandoned_promise_explanation" msgid="3990027586878167529">"Приложение не установлено. Вы можете удалить значок или найти приложение и установить его вручную."</string>
+ <string name="app_downloading_title" msgid="8336702962104482644">"Скачивается \"<xliff:g id="NAME">%1$s</xliff:g>\" (<xliff:g id="PROGRESS">%2$s</xliff:g>)"</string>
+ <string name="app_waiting_download_title" msgid="7053938513995617849">"Ожидание установки \"<xliff:g id="NAME">%1$s</xliff:g>\""</string>
<string name="action_add_to_workspace" msgid="8902165848117513641">"Добавить на главный экран"</string>
<string name="action_move_here" msgid="2170188780612570250">"Переместить элемент сюда"</string>
<string name="item_added_to_workspace" msgid="4211073925752213539">"Элемент добавлен на главный экран"</string>
diff --git a/res/values-si-rLK/strings.xml b/res/values-si-rLK/strings.xml
index 29e06d2..84304f6 100644
--- a/res/values-si-rLK/strings.xml
+++ b/res/values-si-rLK/strings.xml
@@ -26,8 +26,8 @@
<string name="activity_not_available" msgid="7456344436509528827">"යෙදුම නොතිබේ"</string>
<string name="safemode_shortcut_error" msgid="9160126848219158407">"ආරක්ෂිත ආකාරය තුළ බාගන්න ලද යෙදුම් අබල කරන්න"</string>
<string name="safemode_widget_error" msgid="4863470563535682004">"සුරක්ෂිත ආකාරය තුළ විජටය අබල කරන ලදි"</string>
- <string name="toggle_weight_watcher" msgid="5645299835184636119">"Mem පෙන්වන්න"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"විජට් එක ස්පර්ශ කර අහුලා ගැනීමට අල්ලාගෙන සිටින්න."</string>
+ <string name="long_accessible_way_to_add" msgid="4289502106628154155">"විජට් එකක් අහුලා ගැනීමට හෝ අභිරුචි ක්රියා කිරීමට ඩබල් ටැප් කර අල්ලා ගෙන සිටින්න."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="all_apps_search_bar_hint" msgid="7084713969757597256">"යෙදුම් සෙවීම"</string>
<string name="all_apps_loading_message" msgid="7557140873644765180">"යෙදුම් පූරණය වෙමින්…"</string>
@@ -53,6 +53,7 @@
<string name="folder_hint_text" msgid="6617836969016293992">"නම් නොකළ ෆෝල්ඩරය"</string>
<string name="default_scroll_format" msgid="7475544710230993317">"%2$d හි %1$d පිටුව"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"මුල් පිටු තිරය %2$d හි %1$d"</string>
+ <string name="workspace_new_page" msgid="257366611030256142">"නව මුල් පිටුව"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"සාදරයෙන් පිළිගනිමු"</string>
<string name="migration_cling_title" msgid="9181776667882933767">"ඔබේ යෙදුම් නිරූපක පිටපත් කිරීම"</string>
<string name="migration_cling_description" msgid="2752413805582227644">"ඔබගේ පැරණි මුල් තිර වල නිරූපක සහ ෆෝල්ඩර ආයාත කරන්නද?"</string>
@@ -76,6 +77,8 @@
<string name="abandoned_search" msgid="891119232568284442">"සොයන්න"</string>
<string name="abandoned_promises_title" msgid="7096178467971716750">"මෙම යෙදුම ස්ථාපනය කර නොමැත"</string>
<string name="abandoned_promise_explanation" msgid="3990027586878167529">"මෙම නිරුපකයට යෙදුම ස්ථාපනය කර නොමැත. ඔබට එය ඉවත් කළ හැක, හෝ යෙදුම් සඳහා සොයන්න සහ අතින් ස්ථාපනය කරන්න."</string>
+ <string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> බාගත කරමින්, <xliff:g id="PROGRESS">%2$s</xliff:g> සම්පූර්ණයි"</string>
+ <string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> ස්ථාපනය කිරීමට බලා සිටිමින්"</string>
<string name="action_add_to_workspace" msgid="8902165848117513641">"මුල් තිරය වෙත එක් කරන්න"</string>
<string name="action_move_here" msgid="2170188780612570250">"මෙතනට අයිතමය ගෙන එන්න"</string>
<string name="item_added_to_workspace" msgid="4211073925752213539">"අයිතමය මුල් තිරය වෙත එකතු කරන ලදි"</string>
diff --git a/res/values-sk/strings.xml b/res/values-sk/strings.xml
index 2e80716..2875e96 100644
--- a/res/values-sk/strings.xml
+++ b/res/values-sk/strings.xml
@@ -26,8 +26,8 @@
<string name="activity_not_available" msgid="7456344436509528827">"Aplikácia nie je k dispozícii"</string>
<string name="safemode_shortcut_error" msgid="9160126848219158407">"Stiahnutá aplikácia je v núdzovom režime zakázaná"</string>
<string name="safemode_widget_error" msgid="4863470563535682004">"Miniaplikácie sú v núdzovom režime zakázané"</string>
- <string name="toggle_weight_watcher" msgid="5645299835184636119">"Zobraziť pamäť"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"Miniaplikáciu pridáte stlačením a podržaním."</string>
+ <string name="long_accessible_way_to_add" msgid="4289502106628154155">"Miniaplikáciu pridáte dvojitým klepnutím a pridržaním alebo pomocou vlastných akcií."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="all_apps_search_bar_hint" msgid="7084713969757597256">"Vyhľadávanie v aplikáciách"</string>
<string name="all_apps_loading_message" msgid="7557140873644765180">"Načítavajú sa aplikácie..."</string>
@@ -53,6 +53,7 @@
<string name="folder_hint_text" msgid="6617836969016293992">"Nepomenovaný priečinok"</string>
<string name="default_scroll_format" msgid="7475544710230993317">"Stránka %1$d z %2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"Plocha %1$d z %2$d"</string>
+ <string name="workspace_new_page" msgid="257366611030256142">"Nová stránka plochy"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"Vitajte!"</string>
<string name="migration_cling_title" msgid="9181776667882933767">"Kopírovanie ikon aplikácií"</string>
<string name="migration_cling_description" msgid="2752413805582227644">"Chcete importovať ikony a priečinky zo starých plôch?"</string>
@@ -76,6 +77,8 @@
<string name="abandoned_search" msgid="891119232568284442">"Vyhľadať"</string>
<string name="abandoned_promises_title" msgid="7096178467971716750">"Táto aplikácia nie je nainštalovaná"</string>
<string name="abandoned_promise_explanation" msgid="3990027586878167529">"Aplikácia, ktorú zastupuje táto ikona, nie je nainštalovaná. Ikonu môžete odstrániť alebo vyhľadajte aplikáciu a ručne ju nainštalujte."</string>
+ <string name="app_downloading_title" msgid="8336702962104482644">"Sťahuje sa aplikácia <xliff:g id="NAME">%1$s</xliff:g>. Stiahnuté: <xliff:g id="PROGRESS">%2$s</xliff:g>"</string>
+ <string name="app_waiting_download_title" msgid="7053938513995617849">"Aplikácia <xliff:g id="NAME">%1$s</xliff:g> čaká na inštaláciu"</string>
<string name="action_add_to_workspace" msgid="8902165848117513641">"Pridať na plochu"</string>
<string name="action_move_here" msgid="2170188780612570250">"Presunúť položku sem"</string>
<string name="item_added_to_workspace" msgid="4211073925752213539">"Položka bola pridaná na plochu"</string>
diff --git a/res/values-sl/strings.xml b/res/values-sl/strings.xml
index 3d090e7..2eea38a 100644
--- a/res/values-sl/strings.xml
+++ b/res/values-sl/strings.xml
@@ -26,8 +26,8 @@
<string name="activity_not_available" msgid="7456344436509528827">"Aplikacija ni na voljo"</string>
<string name="safemode_shortcut_error" msgid="9160126848219158407">"Prenesena aplikacija je onemogočena v Varnem načinu"</string>
<string name="safemode_widget_error" msgid="4863470563535682004">"Pripomočki so onemogočeni v varnem načinu"</string>
- <string name="toggle_weight_watcher" msgid="5645299835184636119">"Pokaži pomnilnik"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"Za izbiro pripomočka se ga dotaknite in pridržite."</string>
+ <string name="long_accessible_way_to_add" msgid="4289502106628154155">"Če želite izbrati pripomoček ali uporabiti dejanja po meri, se ga dvakrat dotaknite in ga pridržite."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="all_apps_search_bar_hint" msgid="7084713969757597256">"Iskanje po aplikacijah"</string>
<string name="all_apps_loading_message" msgid="7557140873644765180">"Nalaganje aplikacij …"</string>
@@ -53,6 +53,7 @@
<string name="folder_hint_text" msgid="6617836969016293992">"Neimenovana mapa"</string>
<string name="default_scroll_format" msgid="7475544710230993317">"Stran %1$d od %2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"Začetni zaslon %1$d od %2$d"</string>
+ <string name="workspace_new_page" msgid="257366611030256142">"Nova stran na začetnem zaslonu"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"Pozdravljeni"</string>
<string name="migration_cling_title" msgid="9181776667882933767">"Kopiranje ikon aplikacij"</string>
<string name="migration_cling_description" msgid="2752413805582227644">"Želite uvoziti ikone in mape iz starih začetnih zaslonov?"</string>
@@ -76,6 +77,8 @@
<string name="abandoned_search" msgid="891119232568284442">"Iskanje"</string>
<string name="abandoned_promises_title" msgid="7096178467971716750">"Ta aplikacija ni nameščena."</string>
<string name="abandoned_promise_explanation" msgid="3990027586878167529">"Aplikacija za to ikono ni nameščena. Lahko jo odstranite ali poiščete aplikacijo in to namestite ročno."</string>
+ <string name="app_downloading_title" msgid="8336702962104482644">"Prenašanje aplikacije <xliff:g id="NAME">%1$s</xliff:g>; preneseno <xliff:g id="PROGRESS">%2$s</xliff:g>"</string>
+ <string name="app_waiting_download_title" msgid="7053938513995617849">"Aplikacija <xliff:g id="NAME">%1$s</xliff:g> čaka na namestitev"</string>
<string name="action_add_to_workspace" msgid="8902165848117513641">"Dodajanje na začetni zaslon"</string>
<string name="action_move_here" msgid="2170188780612570250">"Premik elementa sem"</string>
<string name="item_added_to_workspace" msgid="4211073925752213539">"Element je bil dodan na začetni zaslon"</string>
diff --git a/res/values-sq-rAL/strings.xml b/res/values-sq-rAL/strings.xml
index b8430c6..2b535a3 100644
--- a/res/values-sq-rAL/strings.xml
+++ b/res/values-sq-rAL/strings.xml
@@ -19,7 +19,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_name" msgid="649227358658669779">"Nisësi3"</string>
+ <string name="application_name" msgid="5181331383435256801">"Nisësi3"</string>
<string name="folder_name" msgid="7371454440695724752"></string>
<string name="work_folder_name" msgid="3753320833950115786">"Puna"</string>
<string name="activity_not_found" msgid="8071924732094499514">"Aplikacioni nuk është i instaluar."</string>
@@ -46,7 +46,6 @@
<string name="permdesc_read_settings" msgid="5833423719057558387">"Lejon aplikacionin të lexojë cilësimet dhe shkurtoret në ekranin bazë."</string>
<string name="permlab_write_settings" msgid="3574213698004620587">"shkruaj cilësimet dhe shkurtoret e ekranit bazë"</string>
<string name="permdesc_write_settings" msgid="5440712911516509985">"Lejon aplikacionin të ndryshojë cilësimet dhe shkurtoret në ekranin bazë."</string>
- <string name="msg_no_phone_permission" msgid="9208659281529857371">"<xliff:g id="APP_NAME">%1$s</xliff:g> nuk lejohet të kryejë telefonata"</string>
<string name="gadget_error_text" msgid="6081085226050792095">"Problem në ngarkimin e miniaplikacionit"</string>
<string name="gadget_setup_text" msgid="8274003207686040488">"Konfiguro"</string>
<string name="uninstall_system_app_text" msgid="4172046090762920660">"Ky është aplikacion sistemi dhe nuk mund të çinstalohet."</string>
diff --git a/res/values-sr/strings.xml b/res/values-sr/strings.xml
index 55d848f..9fdf574 100644
--- a/res/values-sr/strings.xml
+++ b/res/values-sr/strings.xml
@@ -26,8 +26,8 @@
<string name="activity_not_available" msgid="7456344436509528827">"Апликација није доступна"</string>
<string name="safemode_shortcut_error" msgid="9160126848219158407">"Преузета апликација је онемогућена у Безбедном режиму"</string>
<string name="safemode_widget_error" msgid="4863470563535682004">"Виџети су онемогућени у Безбедном режиму"</string>
- <string name="toggle_weight_watcher" msgid="5645299835184636119">"Прикажи меморију"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"Додирните и задржите да бисте изабрали виџет."</string>
+ <string name="long_accessible_way_to_add" msgid="4289502106628154155">"Двапут додирните и задржите да бисте изабрали виџет или користите прилагођене радње."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d×%2$d"</string>
<string name="all_apps_search_bar_hint" msgid="7084713969757597256">"Претражите апликације"</string>
<string name="all_apps_loading_message" msgid="7557140873644765180">"Апликације се учитавају..."</string>
@@ -53,6 +53,7 @@
<string name="folder_hint_text" msgid="6617836969016293992">"Неименовани директоријум"</string>
<string name="default_scroll_format" msgid="7475544710230993317">"%1$d. страница од %2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"%1$d. почетни екран од %2$d"</string>
+ <string name="workspace_new_page" msgid="257366611030256142">"Нова страница почетног екрана"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"Добро дошли"</string>
<string name="migration_cling_title" msgid="9181776667882933767">"Копирајте иконе апликација"</string>
<string name="migration_cling_description" msgid="2752413805582227644">"Увести иконе и директоријуме са старих почетних екрана?"</string>
@@ -76,6 +77,8 @@
<string name="abandoned_search" msgid="891119232568284442">"Претражи"</string>
<string name="abandoned_promises_title" msgid="7096178467971716750">"Ова апликација није инсталирана"</string>
<string name="abandoned_promise_explanation" msgid="3990027586878167529">"Апликација за ову икону није инсталирана. Можете да је уклоните или да потражите апликацију и инсталирате је ручно."</string>
+ <string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> се преузима, завршено је <xliff:g id="PROGRESS">%2$s</xliff:g>"</string>
+ <string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> чека на инсталирање"</string>
<string name="action_add_to_workspace" msgid="8902165848117513641">"Додај на почетни екран"</string>
<string name="action_move_here" msgid="2170188780612570250">"Премести ставку овде"</string>
<string name="item_added_to_workspace" msgid="4211073925752213539">"Ставка је додата на почетни екран"</string>
diff --git a/res/values-sv/strings.xml b/res/values-sv/strings.xml
index fb49f32..4d9589e 100644
--- a/res/values-sv/strings.xml
+++ b/res/values-sv/strings.xml
@@ -26,8 +26,8 @@
<string name="activity_not_available" msgid="7456344436509528827">"Appen är inte tillgänglig"</string>
<string name="safemode_shortcut_error" msgid="9160126848219158407">"Den hämtade appen inaktiverades i säkert läge"</string>
<string name="safemode_widget_error" msgid="4863470563535682004">"Widgets är inaktiverade i felsäkert läge"</string>
- <string name="toggle_weight_watcher" msgid="5645299835184636119">"Visa Mem"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"Tryck länge om du vill flytta en widget."</string>
+ <string name="long_accessible_way_to_add" msgid="4289502106628154155">"Tryck två gånger och håll kvar om du vill ta upp en widget eller använda anpassade åtgärder."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="all_apps_search_bar_hint" msgid="7084713969757597256">"Sök efter appar"</string>
<string name="all_apps_loading_message" msgid="7557140873644765180">"Läser in appar …"</string>
@@ -53,6 +53,7 @@
<string name="folder_hint_text" msgid="6617836969016293992">"Namnlös mapp"</string>
<string name="default_scroll_format" msgid="7475544710230993317">"Sidan %1$d av %2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"Startskärmen %1$d av %2$d"</string>
+ <string name="workspace_new_page" msgid="257366611030256142">"Ny sida på startskärmen"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"Välkommen"</string>
<string name="migration_cling_title" msgid="9181776667882933767">"Kopiera appikoner"</string>
<string name="migration_cling_description" msgid="2752413805582227644">"Vill du importera ikoner och mappar från gamla startskärmar?"</string>
@@ -76,6 +77,8 @@
<string name="abandoned_search" msgid="891119232568284442">"Sök"</string>
<string name="abandoned_promises_title" msgid="7096178467971716750">"Appen är inte installerad"</string>
<string name="abandoned_promise_explanation" msgid="3990027586878167529">"Appen för den här ikonen har inte installerats. Du kan ta bort den eller söka efter appen och installera den manuellt."</string>
+ <string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> laddas ned, <xliff:g id="PROGRESS">%2$s</xliff:g> klart"</string>
+ <string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> väntar på installation"</string>
<string name="action_add_to_workspace" msgid="8902165848117513641">"Lägg till på startskärmen"</string>
<string name="action_move_here" msgid="2170188780612570250">"Flytta objekt hit"</string>
<string name="item_added_to_workspace" msgid="4211073925752213539">"Objektet har lagts till på startskärmen"</string>
diff --git a/res/values-sw/strings.xml b/res/values-sw/strings.xml
index 1e6c80a..bcd5082 100644
--- a/res/values-sw/strings.xml
+++ b/res/values-sw/strings.xml
@@ -26,8 +26,8 @@
<string name="activity_not_available" msgid="7456344436509528827">"Programu haipatikani"</string>
<string name="safemode_shortcut_error" msgid="9160126848219158407">"Programu iliyopakuliwa imezimwa katika Hali Salama"</string>
<string name="safemode_widget_error" msgid="4863470563535682004">"Wijeti zimezimwa katika hali ya Usalama"</string>
- <string name="toggle_weight_watcher" msgid="5645299835184636119">"Onyesha Kumbukumbu"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"Gusa na ushikilie ili kuteua wijeti."</string>
+ <string name="long_accessible_way_to_add" msgid="4289502106628154155">"Gonga mara mbili na ushikilie ile uchague wijeti au utumie vitendo maalum."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="all_apps_search_bar_hint" msgid="7084713969757597256">"Tafuta Programu"</string>
<string name="all_apps_loading_message" msgid="7557140873644765180">"Inapakia Programu..."</string>
@@ -55,6 +55,7 @@
<!-- String.format failed for translation -->
<!-- no translation found for workspace_scroll_format (8458889198184077399) -->
<skip />
+ <string name="workspace_new_page" msgid="257366611030256142">"Ukurasa mpya wa skrini ya kwanza"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"Karibu"</string>
<string name="migration_cling_title" msgid="9181776667882933767">"Nakili ikoni za programu yako"</string>
<string name="migration_cling_description" msgid="2752413805582227644">"Je, ungependa kuingiza ikoni na folda kutoka kwenye skrini zako za Mwanzo za zamani?"</string>
@@ -78,6 +79,8 @@
<string name="abandoned_search" msgid="891119232568284442">"Tafuta"</string>
<string name="abandoned_promises_title" msgid="7096178467971716750">"Programu hii haijasakinishwa"</string>
<string name="abandoned_promise_explanation" msgid="3990027586878167529">"Programu ya ikoni hii haijasakinishwa. Unaweza kuiondoa, au utafute programu na uisakinishe wewe mwenyewe."</string>
+ <string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> inapakuliwa, <xliff:g id="PROGRESS">%2$s</xliff:g> imekamilika"</string>
+ <string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> inasubiri kusakinisha"</string>
<string name="action_add_to_workspace" msgid="8902165848117513641">"Ongeza kwenye skrini ya Kwanza"</string>
<string name="action_move_here" msgid="2170188780612570250">"Hamishia kipengee hapa"</string>
<string name="item_added_to_workspace" msgid="4211073925752213539">"Kipengee kimeongezwa kwenye skrini ya kwanza"</string>
diff --git a/res/values-sw600dp/dimens.xml b/res/values-sw600dp/dimens.xml
index fb54f12..feb1a00 100644
--- a/res/values-sw600dp/dimens.xml
+++ b/res/values-sw600dp/dimens.xml
@@ -21,6 +21,7 @@
<dimen name="all_apps_icon_top_bottom_padding">12dp</dimen>
<dimen name="all_apps_background_canvas_width">850dp</dimen>
<dimen name="all_apps_background_canvas_height">525dp</dimen>
+ <dimen name="all_apps_icon_width_gap">36dp</dimen>
<!-- Cling -->
<dimen name="cling_migration_logo_height">400dp</dimen>
diff --git a/res/values-ta-rIN/strings.xml b/res/values-ta-rIN/strings.xml
index 180c2e9..a080bce8 100644
--- a/res/values-ta-rIN/strings.xml
+++ b/res/values-ta-rIN/strings.xml
@@ -26,8 +26,8 @@
<string name="activity_not_available" msgid="7456344436509528827">"பயன்பாடு இல்லை"</string>
<string name="safemode_shortcut_error" msgid="9160126848219158407">"இறக்கிய பயன்பாடு பாதுகாப்பு முறையில் முடக்கப்பட்டது"</string>
<string name="safemode_widget_error" msgid="4863470563535682004">"பாதுகாப்புப் பயன்முறையில் விட்ஜெட்கள் முடக்கப்பட்டுள்ளன"</string>
- <string name="toggle_weight_watcher" msgid="5645299835184636119">"நினைவகத்தைக் காட்டு"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"விட்ஜெட்டைத் தேர்வுசெய்ய தொட்டுப் பிடிக்கவும்."</string>
+ <string name="long_accessible_way_to_add" msgid="4289502106628154155">"விட்ஜெட்டைத் தேர்ந்தெடுக்க இருமுறை தட்டிப் பிடிக்கவும் அல்லது தனிப்பயன் செயல்களைப் பயன்படுத்தவும்."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="all_apps_search_bar_hint" msgid="7084713969757597256">"பயன்பாடுகளில் தேடுக"</string>
<string name="all_apps_loading_message" msgid="7557140873644765180">"பயன்பாடுகளை ஏற்றுகிறது..."</string>
@@ -53,6 +53,7 @@
<string name="folder_hint_text" msgid="6617836969016293992">"பெயரிடப்படாத கோப்புறை"</string>
<string name="default_scroll_format" msgid="7475544710230993317">"பக்கம் %1$d / %2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"முகப்புத் திரை %1$d of %2$d"</string>
+ <string name="workspace_new_page" msgid="257366611030256142">"புதிய முகப்புத் திரை பக்கம்"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"நல்வரவு"</string>
<string name="migration_cling_title" msgid="9181776667882933767">"பயன்பாட்டின் ஐகான்களை நகலெடுக்கவும்"</string>
<string name="migration_cling_description" msgid="2752413805582227644">"பழைய முகப்புத் திரைகளிலிருந்து ஐகான்களையும் கோப்புறைகளையும் இறக்குமதி செய்யவா?"</string>
@@ -76,6 +77,8 @@
<string name="abandoned_search" msgid="891119232568284442">"தேடு"</string>
<string name="abandoned_promises_title" msgid="7096178467971716750">"பயன்பாடு நிறுவப்படவில்லை"</string>
<string name="abandoned_promise_explanation" msgid="3990027586878167529">"ஐகானுக்கான பயன்பாடு நிறுவப்படவில்லை. இதை அகற்றலாம் அல்லது பயன்பாட்டைத் தேடி கைமுறையாக நிறுவலாம்."</string>
+ <string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g>ஐப் பதிவிறக்குகிறது, <xliff:g id="PROGRESS">%2$s</xliff:g> முடிந்தது"</string>
+ <string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g>ஐ நிறுவுவதற்காகக் காத்திருக்கிறது"</string>
<string name="action_add_to_workspace" msgid="8902165848117513641">"முகப்புத் திரையில் சேர்"</string>
<string name="action_move_here" msgid="2170188780612570250">"இங்கு நகர்த்து"</string>
<string name="item_added_to_workspace" msgid="4211073925752213539">"முகப்புத் திரையில் சேர்க்கப்பட்டது"</string>
diff --git a/res/values-te-rIN/strings.xml b/res/values-te-rIN/strings.xml
index b3f6ec0..65d9df8 100644
--- a/res/values-te-rIN/strings.xml
+++ b/res/values-te-rIN/strings.xml
@@ -26,8 +26,8 @@
<string name="activity_not_available" msgid="7456344436509528827">"అనువర్తనం అందుబాటులో లేదు"</string>
<string name="safemode_shortcut_error" msgid="9160126848219158407">"డౌన్లోడ్ చేసిన అనువర్తనం సురక్షిత మోడ్లో నిలిపివేయబడింది"</string>
<string name="safemode_widget_error" msgid="4863470563535682004">"సురక్షిత మోడ్లో విడ్జెట్లు నిలిపివేయబడ్డాయి"</string>
- <string name="toggle_weight_watcher" msgid="5645299835184636119">"మెమరీ చూపు"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"విడ్జెట్ను ఎంచుకోవడానికి తాకి & నొక్కి పెట్టండి."</string>
+ <string name="long_accessible_way_to_add" msgid="4289502106628154155">"విడ్జెట్ను ఎంచుకోవడానికి లేదా అనుకూల చర్యలను ఉపయోగించడానికి రెండుసార్లు నొక్కి, ఉంచండి."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="all_apps_search_bar_hint" msgid="7084713969757597256">"అనువర్తనాలను శోధించండి"</string>
<string name="all_apps_loading_message" msgid="7557140873644765180">"అనువర్తనాలను లోడ్ చేస్తోంది…"</string>
@@ -53,6 +53,7 @@
<string name="folder_hint_text" msgid="6617836969016293992">"పేరు లేని ఫోల్డర్"</string>
<string name="default_scroll_format" msgid="7475544710230993317">"%2$dలో %1$dవ పేజీ"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"%2$dలో %1$dవ హోమ్ స్క్రీన్"</string>
+ <string name="workspace_new_page" msgid="257366611030256142">"కొత్త హోమ్ స్క్రీన్ పేజీ"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"స్వాగతం"</string>
<string name="migration_cling_title" msgid="9181776667882933767">"మీ అనువర్తన చిహ్నాలను కాపీ చేయండి"</string>
<string name="migration_cling_description" msgid="2752413805582227644">"మీ పాత హోమ్ స్క్రీన్ల నుండి చిహ్నాలు మరియు ఫోల్డర్లను దిగుమతి చేయాలా?"</string>
@@ -76,6 +77,8 @@
<string name="abandoned_search" msgid="891119232568284442">"శోధించు"</string>
<string name="abandoned_promises_title" msgid="7096178467971716750">"ఈ అనువర్తనం ఇన్స్టాల్ చేయబడలేదు"</string>
<string name="abandoned_promise_explanation" msgid="3990027586878167529">"ఈ చిహ్నం యొక్క అనువర్తనం ఇన్స్టాల్ చేయబడలేదు. మీరు దీన్ని తీసివేయవచ్చు లేదా ఆ అనువర్తనం కోసం శోధించి దాన్ని మాన్యువల్గా ఇన్స్టాల్ చేయవచ్చు."</string>
+ <string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> డౌన్లోడ్ అవుతోంది, <xliff:g id="PROGRESS">%2$s</xliff:g> పూర్తయింది"</string>
+ <string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> ఇన్స్టాల్ కావడానికి వేచి ఉంది"</string>
<string name="action_add_to_workspace" msgid="8902165848117513641">"హోమ్ స్క్రీన్కు జోడించు"</string>
<string name="action_move_here" msgid="2170188780612570250">"అంశాన్ని ఇక్కడికి తరలించు"</string>
<string name="item_added_to_workspace" msgid="4211073925752213539">"అంశం హోమ్స్క్రీన్కి జోడించబడింది"</string>
diff --git a/res/values-th/strings.xml b/res/values-th/strings.xml
index 0c7d6aa..2813a1f 100644
--- a/res/values-th/strings.xml
+++ b/res/values-th/strings.xml
@@ -26,8 +26,8 @@
<string name="activity_not_available" msgid="7456344436509528827">"แอปไม่พร้อมใช้งาน"</string>
<string name="safemode_shortcut_error" msgid="9160126848219158407">"แอปที่ดาวน์โหลดถูกปิดในโหมดปลอดภัย"</string>
<string name="safemode_widget_error" msgid="4863470563535682004">"มีการปิดใช้งานวิดเจ็ตในเซฟโหมด"</string>
- <string name="toggle_weight_watcher" msgid="5645299835184636119">"แสดง Mem"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"แตะค้างเพื่อรับวิดเจ็ต"</string>
+ <string name="long_accessible_way_to_add" msgid="4289502106628154155">"แตะ 2 ครั้งค้างไว้เพื่อเลือกวิดเจ็ตหรือใช้การกระทำที่กำหนดเอง"</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="all_apps_search_bar_hint" msgid="7084713969757597256">"ค้นหาแอป"</string>
<string name="all_apps_loading_message" msgid="7557140873644765180">"กำลังโหลดแอป…"</string>
@@ -53,6 +53,7 @@
<string name="folder_hint_text" msgid="6617836969016293992">"โฟลเดอร์ที่ไม่มีชื่อ"</string>
<string name="default_scroll_format" msgid="7475544710230993317">"หน้า %1$d จาก %2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"หน้าจอหลัก %1$d จาก %2$d"</string>
+ <string name="workspace_new_page" msgid="257366611030256142">"หน้าใหม่ในหน้าจอหลัก"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"ยินดีต้อนรับ"</string>
<string name="migration_cling_title" msgid="9181776667882933767">"คัดลอกไอคอนแอปของคุณ"</string>
<string name="migration_cling_description" msgid="2752413805582227644">"นำเข้าไอคอนและโฟลเดอร์จากหน้าจอหลักเก่าของคุณ"</string>
@@ -76,6 +77,8 @@
<string name="abandoned_search" msgid="891119232568284442">"ค้นหา"</string>
<string name="abandoned_promises_title" msgid="7096178467971716750">"ไม่ได้ติดตั้งแอปนี้"</string>
<string name="abandoned_promise_explanation" msgid="3990027586878167529">"ยังไม่ได้ติดตั้งแอปสำหรับไอคอนนี้ คุณสามารถนำไอคอนออก หรือค้นหาแอปดังกล่าวแล้วติดตั้งด้วยตนเอง"</string>
+ <string name="app_downloading_title" msgid="8336702962104482644">"กำลังดาวน์โหลด <xliff:g id="NAME">%1$s</xliff:g> เสร็จแล้ว <xliff:g id="PROGRESS">%2$s</xliff:g>"</string>
+ <string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> กำลังรอติดตั้ง"</string>
<string name="action_add_to_workspace" msgid="8902165848117513641">"เพิ่มลงในหน้าแรก"</string>
<string name="action_move_here" msgid="2170188780612570250">"ย้ายรายการมาที่นี่"</string>
<string name="item_added_to_workspace" msgid="4211073925752213539">"เพิ่มรายการไปยังหน้าจอหลักแล้ว"</string>
diff --git a/res/values-tl/strings.xml b/res/values-tl/strings.xml
index 4b5115b..23e70ea 100644
--- a/res/values-tl/strings.xml
+++ b/res/values-tl/strings.xml
@@ -26,8 +26,8 @@
<string name="activity_not_available" msgid="7456344436509528827">"Hindi available ang app"</string>
<string name="safemode_shortcut_error" msgid="9160126848219158407">"Naka-disable ang na-download na app sa Safe mode"</string>
<string name="safemode_widget_error" msgid="4863470563535682004">"Naka-disable ang mga widget sa Safe mode"</string>
- <string name="toggle_weight_watcher" msgid="5645299835184636119">"Ipakita ang Mem"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"Pindutin nang matagal upang kumuha ng widget."</string>
+ <string name="long_accessible_way_to_add" msgid="4289502106628154155">"I-double tap nang matagal upang pumili ng widget o gumamit ng mga custom na pagkilos."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="all_apps_search_bar_hint" msgid="7084713969757597256">"Mga App sa Paghahanap"</string>
<string name="all_apps_loading_message" msgid="7557140873644765180">"Nilo-load ang Mga App…"</string>
@@ -53,6 +53,7 @@
<string name="folder_hint_text" msgid="6617836969016293992">"Walang Pangalang Folder"</string>
<string name="default_scroll_format" msgid="7475544710230993317">"Pahina %1$d ng %2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"Home screen %1$d ng %2$d"</string>
+ <string name="workspace_new_page" msgid="257366611030256142">"Bagong page ng home screen"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"Maligayang Pagdating"</string>
<string name="migration_cling_title" msgid="9181776667882933767">"Kopyahin ang mga icon ng app"</string>
<string name="migration_cling_description" msgid="2752413805582227644">"I-import ang icon at folder mula sa luma mong Home screen?"</string>
@@ -76,6 +77,8 @@
<string name="abandoned_search" msgid="891119232568284442">"Maghanap"</string>
<string name="abandoned_promises_title" msgid="7096178467971716750">"Hindi naka-install ang app na ito"</string>
<string name="abandoned_promise_explanation" msgid="3990027586878167529">"Hindi naka-install ang app para sa icon na ito. Maaari mo itong alisin, o maaari mong hanapin ang app at i-install ito nang manu-mano."</string>
+ <string name="app_downloading_title" msgid="8336702962104482644">"Dina-download na ang <xliff:g id="NAME">%1$s</xliff:g>, tapos na ang <xliff:g id="PROGRESS">%2$s</xliff:g>"</string>
+ <string name="app_waiting_download_title" msgid="7053938513995617849">"Hinihintay nang mag-install ang <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="action_add_to_workspace" msgid="8902165848117513641">"Idagdag sa Home screen"</string>
<string name="action_move_here" msgid="2170188780612570250">"Ilipat ang item dito"</string>
<string name="item_added_to_workspace" msgid="4211073925752213539">"Naidagdag sa home screen ang item"</string>
diff --git a/res/values-tr/strings.xml b/res/values-tr/strings.xml
index 1f47067..4149e9d 100644
--- a/res/values-tr/strings.xml
+++ b/res/values-tr/strings.xml
@@ -26,8 +26,8 @@
<string name="activity_not_available" msgid="7456344436509528827">"Uygulama kullanılamıyor"</string>
<string name="safemode_shortcut_error" msgid="9160126848219158407">"İndirilen uygulama Güvenli modda devre dışı bırakıldı"</string>
<string name="safemode_widget_error" msgid="4863470563535682004">"Güvenli modda widget\'lar devre dışı"</string>
- <string name="toggle_weight_watcher" msgid="5645299835184636119">"Belleği Göster"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"Widget seçmek için dokunun ve basılı tutun."</string>
+ <string name="long_accessible_way_to_add" msgid="4289502106628154155">"Bir widget\'ı seçmek veya özel işlemleri kullanmak için iki kez hafifçe dokunun ve basılı tutun."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="all_apps_search_bar_hint" msgid="7084713969757597256">"Uygulamalarda Ara"</string>
<string name="all_apps_loading_message" msgid="7557140873644765180">"Uygulamalar Yükleniyor…"</string>
@@ -53,6 +53,7 @@
<string name="folder_hint_text" msgid="6617836969016293992">"Adsız Klasör"</string>
<string name="default_scroll_format" msgid="7475544710230993317">"Sayfa %1$d / %2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"Ana ekran %1$d / %2$d"</string>
+ <string name="workspace_new_page" msgid="257366611030256142">"Yeni ana ekran sayfası"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"Hoş geldiniz"</string>
<string name="migration_cling_title" msgid="9181776667882933767">"Uygulama simgelerini kopyala"</string>
<string name="migration_cling_description" msgid="2752413805582227644">"Eski Ana ekranlarınızdaki simgeler ve klasörler içe aktarılsın mı?"</string>
@@ -76,6 +77,8 @@
<string name="abandoned_search" msgid="891119232568284442">"Ara"</string>
<string name="abandoned_promises_title" msgid="7096178467971716750">"Bu uygulama yüklü değil"</string>
<string name="abandoned_promise_explanation" msgid="3990027586878167529">"Bu simgenin uygulaması yüklü değil. Uygulamayı kaldırabilir veya arayıp manuel olarak yükleyebilirsiniz."</string>
+ <string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> indiriliyor, <xliff:g id="PROGRESS">%2$s</xliff:g> tamamlandı"</string>
+ <string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> uygulaması yüklenmek için bekliyor"</string>
<string name="action_add_to_workspace" msgid="8902165848117513641">"Ana ekrana ekle"</string>
<string name="action_move_here" msgid="2170188780612570250">"Öğeyi buraya taşı"</string>
<string name="item_added_to_workspace" msgid="4211073925752213539">"Öğe ana ekrana eklendi"</string>
diff --git a/res/values-uk/strings.xml b/res/values-uk/strings.xml
index 1015ebd..804f66f 100644
--- a/res/values-uk/strings.xml
+++ b/res/values-uk/strings.xml
@@ -26,8 +26,8 @@
<string name="activity_not_available" msgid="7456344436509528827">"Додаток недоступний"</string>
<string name="safemode_shortcut_error" msgid="9160126848219158407">"Завантажений додаток вимкнено в безпечному режимі"</string>
<string name="safemode_widget_error" msgid="4863470563535682004">"У безпечному режимі віджети вимкнено"</string>
- <string name="toggle_weight_watcher" msgid="5645299835184636119">"Показати пам’ять"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"Натисніть і утримуйте, щоб вибрати віджет."</string>
+ <string name="long_accessible_way_to_add" msgid="4289502106628154155">"Двічі натисніть і утримуйте, щоб вибрати віджет, або виконайте іншу дію."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="all_apps_search_bar_hint" msgid="7084713969757597256">"Пошук додатків"</string>
<string name="all_apps_loading_message" msgid="7557140873644765180">"Завантаження додатків…"</string>
@@ -53,6 +53,7 @@
<string name="folder_hint_text" msgid="6617836969016293992">"Папка без назви"</string>
<string name="default_scroll_format" msgid="7475544710230993317">"Сторінка %1$d з %2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"Головний екран %1$d з %2$d"</string>
+ <string name="workspace_new_page" msgid="257366611030256142">"Нова сторінка головного екрана"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"Вітаємо"</string>
<string name="migration_cling_title" msgid="9181776667882933767">"Копіювати значки програм"</string>
<string name="migration_cling_description" msgid="2752413805582227644">"Імпортувати значки та папки зі старих головних екранів?"</string>
@@ -76,6 +77,8 @@
<string name="abandoned_search" msgid="891119232568284442">"Шукати"</string>
<string name="abandoned_promises_title" msgid="7096178467971716750">"Цей додаток не встановлено"</string>
<string name="abandoned_promise_explanation" msgid="3990027586878167529">"Додаток для цього значка не встановлено. Можна видалити значок або знайти додаток і встановити його вручну."</string>
+ <string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> завантажується, <xliff:g id="PROGRESS">%2$s</xliff:g>"</string>
+ <string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> очікує на завантаження"</string>
<string name="action_add_to_workspace" msgid="8902165848117513641">"Додати на головний екран"</string>
<string name="action_move_here" msgid="2170188780612570250">"Перемістити елемент сюди"</string>
<string name="item_added_to_workspace" msgid="4211073925752213539">"Елемент додано на головний екран"</string>
diff --git a/res/values-ur-rPK/strings.xml b/res/values-ur-rPK/strings.xml
index 1560b8a..6bfe9b8 100644
--- a/res/values-ur-rPK/strings.xml
+++ b/res/values-ur-rPK/strings.xml
@@ -26,8 +26,8 @@
<string name="activity_not_available" msgid="7456344436509528827">"ایپ دستیاب نہیں ہے"</string>
<string name="safemode_shortcut_error" msgid="9160126848219158407">"ڈاؤن لوڈ کردہ ایپ کو محفوظ وضع میں غیر فعال کر دیا گیا"</string>
<string name="safemode_widget_error" msgid="4863470563535682004">"ویجیٹس کو محفوظ وضع میں غیر فعال کر دیا گیا"</string>
- <string name="toggle_weight_watcher" msgid="5645299835184636119">"Mem دکھائیں"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"کوئی ویجیٹ منتخب کرنے کیلئے ٹچ کریں اور پکڑے رہیں۔"</string>
+ <string name="long_accessible_way_to_add" msgid="4289502106628154155">"کوئی ویجٹ منتخب کرنے یا حسب ضرورت کاروائیاں استعمال کرنے کیلئے دو بار تھپتھپائیں اور پکڑے رکھیں۔"</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="all_apps_search_bar_hint" msgid="7084713969757597256">"ایپس تلاش کریں"</string>
<string name="all_apps_loading_message" msgid="7557140873644765180">"ایپس لوڈ ہو رہی ہیں…"</string>
@@ -53,6 +53,7 @@
<string name="folder_hint_text" msgid="6617836969016293992">"بلا نام فولڈر"</string>
<string name="default_scroll_format" msgid="7475544710230993317">"صفحہ %1$d از %2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"ہوم اسکرین %1$d از %2$d"</string>
+ <string name="workspace_new_page" msgid="257366611030256142">"نیا ہوم اسکرین صفحہ"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"خوش آمدید"</string>
<string name="migration_cling_title" msgid="9181776667882933767">"اپنے ایپ آئیکنز کو کاپی کریں"</string>
<string name="migration_cling_description" msgid="2752413805582227644">"اپنی پرانی ہوم اسکرینوں سے آئیکنز اور فولڈرز درآمد کریں؟"</string>
@@ -76,6 +77,8 @@
<string name="abandoned_search" msgid="891119232568284442">"تلاش کریں"</string>
<string name="abandoned_promises_title" msgid="7096178467971716750">"یہ ایپ انسٹال کردہ نہیں ہے"</string>
<string name="abandoned_promise_explanation" msgid="3990027586878167529">"اس آئیکن کیلئے ایپ انسٹال کردہ نہیں ہے۔ آپ اسے ہٹا سکتے ہیں یا ایپ کو تلاش کر سکتے اور دستی طور پر اسے انسٹال کر سکتے ہیں۔"</string>
+ <string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> ڈاؤن لوڈ ہو رہا ہے، <xliff:g id="PROGRESS">%2$s</xliff:g> مکمل ہو گیا"</string>
+ <string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> انسٹال ہونے کا انتظار کر رہی ہے"</string>
<string name="action_add_to_workspace" msgid="8902165848117513641">"ہوم اسکرین میں شامل کریں"</string>
<string name="action_move_here" msgid="2170188780612570250">"آئٹم یہاں منتقل کریں"</string>
<string name="item_added_to_workspace" msgid="4211073925752213539">"آئٹم کو ہوم اسکرین میں شامل کر دیا گیا"</string>
diff --git a/res/values-uz-rUZ/strings.xml b/res/values-uz-rUZ/strings.xml
index 58d8eb5..34ed118 100644
--- a/res/values-uz-rUZ/strings.xml
+++ b/res/values-uz-rUZ/strings.xml
@@ -26,8 +26,8 @@
<string name="activity_not_available" msgid="7456344436509528827">"Ilova mavjud emas"</string>
<string name="safemode_shortcut_error" msgid="9160126848219158407">"Yuklab olingan ilova xavfsiz rejimda o‘chirib qo‘yildi"</string>
<string name="safemode_widget_error" msgid="4863470563535682004">"Xavfsiz rejimda vidjetlar o‘chirib qo‘yilgan"</string>
- <string name="toggle_weight_watcher" msgid="5645299835184636119">"Xotirani ko‘rsatish"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"Vidjetni tanlash uchun bosib turing."</string>
+ <string name="long_accessible_way_to_add" msgid="4289502106628154155">"Ikki marta bosib va bosib turgan holatda vidjetni tanlang yoki maxsus amaldan foydalaning."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="all_apps_search_bar_hint" msgid="7084713969757597256">"Ilovalarni qidirish"</string>
<string name="all_apps_loading_message" msgid="7557140873644765180">"Ilovalar yuklanmoqda…"</string>
@@ -53,6 +53,7 @@
<string name="folder_hint_text" msgid="6617836969016293992">"Nomsiz jild"</string>
<string name="default_scroll_format" msgid="7475544710230993317">"%2$ddan %1$d ta sahifa"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"Uy ekrani %2$ddan %1$d"</string>
+ <string name="workspace_new_page" msgid="257366611030256142">"Yangi bosh ekran sahifasi"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"Xush kelibsiz"</string>
<string name="migration_cling_title" msgid="9181776667882933767">"Ilovangiz nishonchalaridan nusxa olish"</string>
<string name="migration_cling_description" msgid="2752413805582227644">"Eski \"Uy\" ekranlaringizdan jildlar va nishonchalar import qilinsinmi?"</string>
@@ -76,6 +77,8 @@
<string name="abandoned_search" msgid="891119232568284442">"Qidirish"</string>
<string name="abandoned_promises_title" msgid="7096178467971716750">"Ushbu ilova o‘rnatilmagan"</string>
<string name="abandoned_promise_explanation" msgid="3990027586878167529">"Ilova o‘rnatilmagan. Belgini o‘chirib tashlashingiz yoki ilovani topib, uni qo‘lda o‘rnatishingiz mumkin."</string>
+ <string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> yuklab olinmoqda, <xliff:g id="PROGRESS">%2$s</xliff:g> bajarildi"</string>
+ <string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> ilovasi o‘rnatilishi kutilmoqda"</string>
<string name="action_add_to_workspace" msgid="8902165848117513641">"Bosh ekranga qo‘shish"</string>
<string name="action_move_here" msgid="2170188780612570250">"Obyektni bu yerga ko‘chirish"</string>
<string name="item_added_to_workspace" msgid="4211073925752213539">"Obyekt bosh ekranga qo‘shildi"</string>
diff --git a/res/values-vi/strings.xml b/res/values-vi/strings.xml
index b1851d5..7b4b241 100644
--- a/res/values-vi/strings.xml
+++ b/res/values-vi/strings.xml
@@ -26,8 +26,8 @@
<string name="activity_not_available" msgid="7456344436509528827">"Ứng dụng không có sẵn"</string>
<string name="safemode_shortcut_error" msgid="9160126848219158407">"Ứng dụng đã tải xuống bị tắt ở chế độ An toàn"</string>
<string name="safemode_widget_error" msgid="4863470563535682004">"Tiện ích con bị vô hiệu hóa ở chế độ an toàn"</string>
- <string name="toggle_weight_watcher" msgid="5645299835184636119">"Hiển thị bộ nhớ"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"Chạm và giữ để chọn tiện ích con."</string>
+ <string name="long_accessible_way_to_add" msgid="4289502106628154155">"Nhấn đúp và giữ để chọn tiện ích hoặc sử dụng tác vụ tùy chỉnh."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="all_apps_search_bar_hint" msgid="7084713969757597256">"Tìm kiếm ứng dụng"</string>
<string name="all_apps_loading_message" msgid="7557140873644765180">"Đang tải ứng dụng..."</string>
@@ -53,6 +53,7 @@
<string name="folder_hint_text" msgid="6617836969016293992">"Thư mục chưa đặt tên"</string>
<string name="default_scroll_format" msgid="7475544710230993317">"Trang %1$d / %2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"Màn hình chính %1$d / %2$d"</string>
+ <string name="workspace_new_page" msgid="257366611030256142">"Trang màn hình chính mới"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"Chào mừng"</string>
<string name="migration_cling_title" msgid="9181776667882933767">"Sao chép biểu tượng ứng dụng của bạn"</string>
<string name="migration_cling_description" msgid="2752413805582227644">"Nhập biểu tượng và thư mục từ Màn hình chính cũ của bạn?"</string>
@@ -76,6 +77,8 @@
<string name="abandoned_search" msgid="891119232568284442">"Tìm kiếm"</string>
<string name="abandoned_promises_title" msgid="7096178467971716750">"Ứng dụng này chưa được cài đặt"</string>
<string name="abandoned_promise_explanation" msgid="3990027586878167529">"Ứng dụng cho biểu tượng này chưa được cài đặt. Bạn có thể xóa ứng dụng hoặc tìm kiếm và cài đặt ứng dụng theo cách thủ công."</string>
+ <string name="app_downloading_title" msgid="8336702962104482644">"Đang tải xuống <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="PROGRESS">%2$s</xliff:g> hoàn tất"</string>
+ <string name="app_waiting_download_title" msgid="7053938513995617849">"Đang chờ cài đặt <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="action_add_to_workspace" msgid="8902165848117513641">"Thêm vào màn hình chính"</string>
<string name="action_move_here" msgid="2170188780612570250">"Di chuyển mục vào đây"</string>
<string name="item_added_to_workspace" msgid="4211073925752213539">"Đã thêm mục vào màn hình chính"</string>
diff --git a/res/values-zh-rCN/strings.xml b/res/values-zh-rCN/strings.xml
index d4f7755..b42e021 100644
--- a/res/values-zh-rCN/strings.xml
+++ b/res/values-zh-rCN/strings.xml
@@ -26,8 +26,8 @@
<string name="activity_not_available" msgid="7456344436509528827">"应用不可用"</string>
<string name="safemode_shortcut_error" msgid="9160126848219158407">"安全模式下不允许使用下载的此应用"</string>
<string name="safemode_widget_error" msgid="4863470563535682004">"安全模式下不允许使用小部件"</string>
- <string name="toggle_weight_watcher" msgid="5645299835184636119">"显示内存空间"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"触摸并按住小部件即可选择。"</string>
+ <string name="long_accessible_way_to_add" msgid="4289502106628154155">"点按两次并按住小部件即可选择小部件,您也可以使用自定义操作。"</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="all_apps_search_bar_hint" msgid="7084713969757597256">"搜索应用"</string>
<string name="all_apps_loading_message" msgid="7557140873644765180">"正在加载应用…"</string>
@@ -53,6 +53,7 @@
<string name="folder_hint_text" msgid="6617836969016293992">"未命名文件夹"</string>
<string name="default_scroll_format" msgid="7475544710230993317">"第%1$d页,共%2$d页"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"主屏幕:第%1$d屏,共%2$d屏"</string>
+ <string name="workspace_new_page" msgid="257366611030256142">"主屏幕新页面"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"欢迎使用"</string>
<string name="migration_cling_title" msgid="9181776667882933767">"复制应用图标"</string>
<string name="migration_cling_description" msgid="2752413805582227644">"要导入旧的主屏幕中的图标和文件夹吗?"</string>
@@ -76,6 +77,8 @@
<string name="abandoned_search" msgid="891119232568284442">"搜索"</string>
<string name="abandoned_promises_title" msgid="7096178467971716750">"未安装此应用"</string>
<string name="abandoned_promise_explanation" msgid="3990027586878167529">"未安装此图标对应的应用。您可以移除此图标,也可以尝试搜索相应的应用并手动安装。"</string>
+ <string name="app_downloading_title" msgid="8336702962104482644">"正在下载<xliff:g id="NAME">%1$s</xliff:g>,已完成 <xliff:g id="PROGRESS">%2$s</xliff:g>"</string>
+ <string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g>正在等待安装"</string>
<string name="action_add_to_workspace" msgid="8902165848117513641">"添加到主屏幕"</string>
<string name="action_move_here" msgid="2170188780612570250">"将项目移至此处"</string>
<string name="item_added_to_workspace" msgid="4211073925752213539">"已将项目添加到主屏幕"</string>
diff --git a/res/values-zh-rHK/strings.xml b/res/values-zh-rHK/strings.xml
index ec8388f..beb3be1 100644
--- a/res/values-zh-rHK/strings.xml
+++ b/res/values-zh-rHK/strings.xml
@@ -26,8 +26,8 @@
<string name="activity_not_available" msgid="7456344436509528827">"目前無法使用這個應用程式"</string>
<string name="safemode_shortcut_error" msgid="9160126848219158407">"在安全模式中無法使用「已下載的應用程式」功能"</string>
<string name="safemode_widget_error" msgid="4863470563535682004">"在安全模式中無法使用小工具"</string>
- <string name="toggle_weight_watcher" msgid="5645299835184636119">"顯示記憶體"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"輕觸並按住小工具即可選取。"</string>
+ <string name="long_accessible_way_to_add" msgid="4289502106628154155">"連扲兩下,然後扲住,就可以新增小工具,或者執行自訂操作。"</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="all_apps_search_bar_hint" msgid="7084713969757597256">"搜尋應用程式"</string>
<string name="all_apps_loading_message" msgid="7557140873644765180">"正在載入應用程式…"</string>
@@ -53,6 +53,7 @@
<string name="folder_hint_text" msgid="6617836969016293992">"未命名的資料夾"</string>
<string name="default_scroll_format" msgid="7475544710230993317">"第 %1$d 頁,共 %2$d 頁"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"主畫面 %1$d,共 %2$d 個"</string>
+ <string name="workspace_new_page" msgid="257366611030256142">"新主畫面頁面"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"歡迎"</string>
<string name="migration_cling_title" msgid="9181776667882933767">"複製您的應用程式圖示"</string>
<string name="migration_cling_description" msgid="2752413805582227644">"要從舊主畫面匯入圖示和資料夾嗎?"</string>
@@ -76,6 +77,8 @@
<string name="abandoned_search" msgid="891119232568284442">"搜尋"</string>
<string name="abandoned_promises_title" msgid="7096178467971716750">"尚未安裝這個應用程式"</string>
<string name="abandoned_promise_explanation" msgid="3990027586878167529">"您尚未安裝這個圖示代表的應用程式。您可以移除這個圖示,也可以搜尋該應用程式並手動安裝。"</string>
+ <string name="app_downloading_title" msgid="8336702962104482644">"正在下載 <xliff:g id="NAME">%1$s</xliff:g>,已完成 <xliff:g id="PROGRESS">%2$s</xliff:g>"</string>
+ <string name="app_waiting_download_title" msgid="7053938513995617849">"正在等待安裝 <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="action_add_to_workspace" msgid="8902165848117513641">"新增至主畫面"</string>
<string name="action_move_here" msgid="2170188780612570250">"移動項目至這裡"</string>
<string name="item_added_to_workspace" msgid="4211073925752213539">"已將項目加入至主畫面"</string>
diff --git a/res/values-zh-rTW/strings.xml b/res/values-zh-rTW/strings.xml
index de06342..611e708 100644
--- a/res/values-zh-rTW/strings.xml
+++ b/res/values-zh-rTW/strings.xml
@@ -26,8 +26,8 @@
<string name="activity_not_available" msgid="7456344436509528827">"應用程式目前無法使用"</string>
<string name="safemode_shortcut_error" msgid="9160126848219158407">"在安全模式中無法使用「已下載的應用程式」功能"</string>
<string name="safemode_widget_error" msgid="4863470563535682004">"在安全模式下無法使用小工具"</string>
- <string name="toggle_weight_watcher" msgid="5645299835184636119">"顯示記憶體"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"輕觸並按住小工具即可選取。"</string>
+ <string name="long_accessible_way_to_add" msgid="4289502106628154155">"輕按兩下並按住小工具即可選取,您也可以使用自訂動作。"</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="all_apps_search_bar_hint" msgid="7084713969757597256">"搜尋應用程式"</string>
<string name="all_apps_loading_message" msgid="7557140873644765180">"正在載入應用程式…"</string>
@@ -53,6 +53,7 @@
<string name="folder_hint_text" msgid="6617836969016293992">"未命名的資料夾"</string>
<string name="default_scroll_format" msgid="7475544710230993317">"第 %1$d 頁,共 %2$d 頁"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"主螢幕:第 %1$d 頁,共 %2$d 頁"</string>
+ <string name="workspace_new_page" msgid="257366611030256142">"新的主畫面頁面"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"歡迎使用"</string>
<string name="migration_cling_title" msgid="9181776667882933767">"複製您的應用程式圖示"</string>
<string name="migration_cling_description" msgid="2752413805582227644">"要從舊的主螢幕匯入圖示和資料夾嗎?"</string>
@@ -76,6 +77,8 @@
<string name="abandoned_search" msgid="891119232568284442">"搜尋"</string>
<string name="abandoned_promises_title" msgid="7096178467971716750">"尚未安裝這個應用程式"</string>
<string name="abandoned_promise_explanation" msgid="3990027586878167529">"您尚未安裝這個圖示代表的應用程式。您可以移除這個圖示,也可以搜尋該應用程式並手動安裝。"</string>
+ <string name="app_downloading_title" msgid="8336702962104482644">"正在下載「<xliff:g id="NAME">%1$s</xliff:g>」,已完成 <xliff:g id="PROGRESS">%2$s</xliff:g>"</string>
+ <string name="app_waiting_download_title" msgid="7053938513995617849">"正在等待安裝「<xliff:g id="NAME">%1$s</xliff:g>」"</string>
<string name="action_add_to_workspace" msgid="8902165848117513641">"新增至主畫面"</string>
<string name="action_move_here" msgid="2170188780612570250">"將項目移至這裡"</string>
<string name="item_added_to_workspace" msgid="4211073925752213539">"已將項目新增到主畫面"</string>
diff --git a/res/values-zu/strings.xml b/res/values-zu/strings.xml
index 854ace1..6b6fc8e 100644
--- a/res/values-zu/strings.xml
+++ b/res/values-zu/strings.xml
@@ -26,8 +26,8 @@
<string name="activity_not_available" msgid="7456344436509528827">"Uhlelo lokusebenza alutholakali"</string>
<string name="safemode_shortcut_error" msgid="9160126848219158407">"Uhlelo lokusebenza olulandiwe lukhutshaziwe kumodi ephephile"</string>
<string name="safemode_widget_error" msgid="4863470563535682004">"Amawijethi akhutshaziwe kwimodi yokuphepha"</string>
- <string name="toggle_weight_watcher" msgid="5645299835184636119">"Bonisa i-Mem"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"Thinta uphinde ubambe ukuze uphakamise iwijethi."</string>
+ <string name="long_accessible_way_to_add" msgid="4289502106628154155">"Thepha kabili bese uyabamba ukuze uthathe iwijethi noma sebenzisa izenzo ezingokwezifiso."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="all_apps_search_bar_hint" msgid="7084713969757597256">"Sesha Izinhlelo Zokusebenza"</string>
<string name="all_apps_loading_message" msgid="7557140873644765180">"Ilayisha izinhlelo zokusebenza..."</string>
@@ -53,6 +53,7 @@
<string name="folder_hint_text" msgid="6617836969016293992">"Ifolda engenagama"</string>
<string name="default_scroll_format" msgid="7475544710230993317">"Ikhasi elingu-%1$d kwangu-%2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"Isikrini sasekhaya esingu-%1$d se-%2$d"</string>
+ <string name="workspace_new_page" msgid="257366611030256142">"Ikhasi elisha lesikrini sasekhaya"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"Siyakwamukela"</string>
<string name="migration_cling_title" msgid="9181776667882933767">"Kopisha izithonjana zakho zohlelo lokusebenza"</string>
<string name="migration_cling_description" msgid="2752413805582227644">"Ngenisa izithonjana namafolda kusukela kuzikrini zakho ezindala zasekhaya?"</string>
@@ -76,6 +77,8 @@
<string name="abandoned_search" msgid="891119232568284442">"Sesha"</string>
<string name="abandoned_promises_title" msgid="7096178467971716750">"Lolu hlelo lokusebenza alifakiwe"</string>
<string name="abandoned_promise_explanation" msgid="3990027586878167529">"Uhlelo lokusebenza lalesi sithonjana alufakiwe. Ungalisusa, noma sesha uhlelo lokusebenza bese uzifakela lona ngokuzenzela."</string>
+ <string name="app_downloading_title" msgid="8336702962104482644">"I-<xliff:g id="NAME">%1$s</xliff:g> iyalandwa, <xliff:g id="PROGRESS">%2$s</xliff:g> kuqediwe"</string>
+ <string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> ilinde ukufakwa"</string>
<string name="action_add_to_workspace" msgid="8902165848117513641">"Faka kusikrini sasekhaya"</string>
<string name="action_move_here" msgid="2170188780612570250">"Hambisa into lapha"</string>
<string name="item_added_to_workspace" msgid="4211073925752213539">"Into ingezwe kusikrini sasekhaya"</string>
diff --git a/res/values/config.xml b/res/values/config.xml
index 93c6d14..8550088 100644
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -67,9 +67,6 @@
<!-- Hotseat -->
<bool name="hotseat_transpose_layout_with_orientation">true</bool>
- <!-- Memory debugging, including a memory dump icon -->
- <bool name="debug_memory_enabled">false</bool>
-
<!-- Name of a subclass of com.android.launcher3.AppFilter used to
filter the activities shown in the launcher. Can be empty. -->
<string name="app_filter_class" translatable="false"></string>
@@ -81,6 +78,9 @@
<!-- View ID to use for QSB widget -->
<item type="id" name="qsb_widget" />
+ <!-- View ID used by cell layout to jail its content -->
+ <item type="id" name="cell_layout_jail_id" />
+
<!-- Accessibility actions -->
<item type="id" name="action_remove" />
<item type="id" name="action_uninstall" />
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 5d69012..1025aba 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -19,11 +19,15 @@
<!-- Dynamic Grid -->
<dimen name="dynamic_grid_edge_margin">6dp</dimen>
- <dimen name="dynamic_grid_search_bar_max_width">500dp</dimen>
- <dimen name="dynamic_grid_search_bar_height">56dp</dimen>
- <!-- We want 32dp extra for the tall search bar, but 10dp comes from unwanted padding between
- the search bar and workspace. -->
- <dimen name="dynamic_grid_search_bar_height_tall">78dp</dimen>
+ <dimen name="dynamic_grid_search_bar_height">48dp</dimen>
+ <!-- We want 32dp extra for the tall search bar. -->
+ <dimen name="dynamic_grid_search_bar_height_tall">80dp</dimen>
+ <dimen name="qsb_internal_padding_top">8dp</dimen>
+ <dimen name="qsb_internal_padding_bottom">8dp</dimen>
+ <dimen name="dynamic_grid_search_bar_bottom_padding">4dp</dimen>
+ <!-- Reduce the padding between the search bar and workspace when the search bar is tall -->
+ <dimen name="dynamic_grid_search_bar_bottom_padding_short">-6dp</dimen>
+ <dimen name="dynamic_grid_search_bar_bottom_padding_tablet">16dp</dimen>
<dimen name="dynamic_grid_page_indicator_height">20dp</dimen>
<dimen name="dynamic_grid_icon_drawable_padding">4dp</dimen>
<dimen name="dynamic_grid_workspace_page_spacing">8dp</dimen>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index b544788..6daa452 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -45,11 +45,11 @@
<!-- SafeMode widget error string -->
<string name="safemode_widget_error">Widgets disabled in Safe mode</string>
- <string name="toggle_weight_watcher">Show Mem</string>
-
<!-- Widgets -->
<!-- Message to tell the user to press and hold on a widget to add it [CHAR_LIMIT=50] -->
<string name="long_press_widget_to_add">Touch & hold to pick up a widget.</string>
+ <!-- Accessibility spoken hint message in widget picker, which allows user to add a widget. Custom action is the label for additional accessibility actions available in this mode [CHAR_LIMIT=100] -->
+ <string name="long_accessible_way_to_add">Double-tap & hold to pick up a widget or use custom actions.</string>
<!-- The format string for the dimensions of a widget in the drawer -->
<!-- There is a special version of this format string for Farsi -->
<string name="widget_dims_format">%1$d \u00d7 %2$d</string>
@@ -128,6 +128,8 @@
<string name="default_scroll_format">Page %1$d of %2$d</string>
<!-- The format string for Workspace page scroll text [CHAR_LIMIT=none] -->
<string name="workspace_scroll_format">Home screen %1$d of %2$d</string>
+ <!-- Description for a new page on homescreen[CHAR_LIMIT=none] -->
+ <string name="workspace_new_page">New home screen page</string>
<!-- Clings -->
<!-- The title text for the workspace cling [CHAR_LIMIT=30] -->
@@ -161,9 +163,6 @@
<!-- Folder name format -->
<string name="folder_name_format">Folder: <xliff:g id="name" example="Games">%1$s</xliff:g></string>
- <!-- Debug-only activity name. [DO NOT TRANSLATE] -->
- <string name="debug_memory_activity">* HPROF</string>
-
<!-- Strings for the customization mode -->
<!-- Text for widget add button -->
<string name="widget_button_text">Widgets</string>
@@ -190,6 +189,10 @@
<string name="abandoned_promise_explanation">The app for this icon isn\'t installed.
You can remove it, or search for the app and install it manually.
</string>
+ <!-- Title for an app which is being downloaded. -->
+ <string name="app_downloading_title"><xliff:g id="name" example="Messenger">%1$s</xliff:g> downloading, <xliff:g id="progress" example="30%">%2$s</xliff:g> complete</string>
+ <!-- Title for an app whose download has been started. -->
+ <string name="app_waiting_download_title"><xliff:g id="name" example="Messenger">%1$s</xliff:g> waiting to install</string>
<!-- Strings for accessibility actions -->
<!-- Accessibility action to add an app to workspace. [CHAR_LIMIT=30] -->
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 7d60cbe..4eee130 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -44,6 +44,8 @@
<item name="android:textColor">@color/quantum_panel_text_color</item>
<item name="android:drawablePadding">@dimen/dynamic_grid_icon_drawable_padding</item>
<item name="android:shadowRadius">0</item>
+ <item name="android:paddingLeft">4dp</item>
+ <item name="android:paddingRight">4dp</item>
<item name="customShadows">false</item>
</style>
diff --git a/res/xml/default_workspace_3x3.xml b/res/xml/default_workspace_3x3.xml
new file mode 100644
index 0000000..8d99404
--- /dev/null
+++ b/res/xml/default_workspace_3x3.xml
@@ -0,0 +1,88 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2015 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.
+-->
+
+<favorites xmlns:launcher="http://schemas.android.com/apk/res-auto/com.android.launcher3">
+
+ <!-- Hotseat (We use the screen as the position of the item in the hotseat) -->
+ <!-- Messaging, [All Apps], Dialer -->
+
+ <resolve
+ launcher:container="-101"
+ launcher:screen="0"
+ launcher:x="0"
+ launcher:y="0" >
+ <favorite launcher:uri="#Intent;action=android.intent.action.MAIN;category=android.intent.category.APP_MESSAGING;end" />
+ <favorite launcher:uri="sms:" />
+ <favorite launcher:uri="smsto:" />
+ <favorite launcher:uri="mms:" />
+ <favorite launcher:uri="mmsto:" />
+ </resolve>
+
+ <!-- All Apps -->
+
+ <resolve
+ launcher:container="-101"
+ launcher:screen="2"
+ launcher:x="2"
+ launcher:y="0" >
+ <favorite launcher:uri="#Intent;action=android.intent.action.DIAL;end" />
+ <favorite launcher:uri="tel:123" />
+ <favorite launcher:uri="#Intent;action=android.intent.action.CALL_BUTTON;end" />
+ </resolve>
+
+ <!-- Bottom row -->
+ <resolve
+ launcher:screen="0"
+ launcher:x="0"
+ launcher:y="-1" >
+ <favorite launcher:uri="#Intent;action=android.intent.action.MAIN;category=android.intent.category.APP_EMAIL;end" />
+ <favorite launcher:uri="mailto:" />
+ </resolve>
+
+ <resolve
+ launcher:screen="0"
+ launcher:x="1"
+ launcher:y="-1" >
+ <favorite launcher:uri="#Intent;action=android.intent.action.MAIN;category=android.intent.category.APP_GALLERY;end" />
+ <favorite launcher:uri="#Intent;type=images/*;end" />
+ </resolve>
+
+ <resolve
+ launcher:screen="0"
+ launcher:x="2"
+ launcher:y="-1" >
+ <favorite launcher:uri="#Intent;action=android.intent.action.MAIN;category=android.intent.category.APP_MARKET;end" />
+ <favorite launcher:uri="market://details?id=com.android.launcher" />
+ </resolve>
+
+ <!-- Second last row -->
+ <resolve
+ launcher:screen="0"
+ launcher:x="0"
+ launcher:y="-2" >
+ <favorite launcher:uri="#Intent;action=android.intent.action.MAIN;category=android.intent.category.APP_BROWSER;end" />
+ <favorite launcher:uri="http://www.example.com/" />
+ </resolve>
+
+ <resolve
+ launcher:screen="0"
+ launcher:x="2"
+ launcher:y="-2" >
+ <favorite launcher:uri="#Intent;action=android.media.action.STILL_IMAGE_CAMERA;end" />
+ <favorite launcher:uri="#Intent;action=android.intent.action.CAMERA_BUTTON;end" />
+ </resolve>
+
+</favorites>
diff --git a/res/xml/default_workspace_4x4.xml b/res/xml/default_workspace_4x4.xml
index 060a1f8..979a1b4 100644
--- a/res/xml/default_workspace_4x4.xml
+++ b/res/xml/default_workspace_4x4.xml
@@ -23,7 +23,7 @@
<resolve
launcher:screen="0"
launcher:x="0"
- launcher:y="3" >
+ launcher:y="-1" >
<favorite launcher:uri="#Intent;action=android.intent.action.MAIN;category=android.intent.category.APP_EMAIL;end" />
<favorite launcher:uri="mailto:" />
</resolve>
@@ -31,7 +31,7 @@
<resolve
launcher:screen="0"
launcher:x="1"
- launcher:y="3" >
+ launcher:y="-1" >
<favorite launcher:uri="#Intent;action=android.intent.action.MAIN;category=android.intent.category.APP_GALLERY;end" />
<favorite launcher:uri="#Intent;type=images/*;end" />
</resolve>
@@ -39,7 +39,7 @@
<resolve
launcher:screen="0"
launcher:x="3"
- launcher:y="3" >
+ launcher:y="-1" >
<favorite launcher:uri="#Intent;action=android.intent.action.MAIN;category=android.intent.category.APP_MARKET;end" />
<favorite launcher:uri="market://details?id=com.android.launcher" />
</resolve>
diff --git a/res/xml/default_workspace_5x5.xml b/res/xml/default_workspace_5x5.xml
index 3226617..f9cc0e7 100644
--- a/res/xml/default_workspace_5x5.xml
+++ b/res/xml/default_workspace_5x5.xml
@@ -23,7 +23,7 @@
<resolve
launcher:screen="0"
launcher:x="0"
- launcher:y="4" >
+ launcher:y="-1" >
<favorite launcher:uri="#Intent;action=android.intent.action.MAIN;category=android.intent.category.APP_EMAIL;end" />
<favorite launcher:uri="mailto:" />
@@ -32,7 +32,7 @@
<resolve
launcher:screen="0"
launcher:x="1"
- launcher:y="4" >
+ launcher:y="-1" >
<favorite launcher:uri="#Intent;action=android.intent.action.MAIN;category=android.intent.category.APP_GALLERY;end" />
<favorite launcher:uri="#Intent;type=images/*;end" />
@@ -41,7 +41,7 @@
<resolve
launcher:screen="0"
launcher:x="4"
- launcher:y="4" >
+ launcher:y="-1" >
<favorite launcher:uri="#Intent;action=android.intent.action.MAIN;category=android.intent.category.APP_MARKET;end" />
<favorite launcher:uri="market://details?id=com.android.launcher" />
</resolve>
diff --git a/res/xml/default_workspace_5x6.xml b/res/xml/default_workspace_5x6.xml
index bc236fb..8493c26 100644
--- a/res/xml/default_workspace_5x6.xml
+++ b/res/xml/default_workspace_5x6.xml
@@ -23,13 +23,13 @@
<favorite
launcher:screen="0"
launcher:x="0"
- launcher:y="4"
+ launcher:y="-1"
launcher:uri="#Intent;action=android.intent.action.MAIN;category=android.intent.category.APP_CONTACTS;end" />
<resolve
launcher:screen="0"
- launcher:x="5"
- launcher:y="4" >
+ launcher:x="-1"
+ launcher:y="-1" >
<favorite launcher:uri="#Intent;action=android.intent.action.MAIN;category=android.intent.category.APP_MARKET;end" />
<favorite launcher:uri="market://details?id=com.android.launcher" />
</resolve>
diff --git a/src/com/android/launcher3/AppInfo.java b/src/com/android/launcher3/AppInfo.java
index c95d558..ede6c71 100644
--- a/src/com/android/launcher3/AppInfo.java
+++ b/src/com/android/launcher3/AppInfo.java
@@ -51,11 +51,6 @@
*/
boolean usingLowResIcon;
- /**
- * The time at which the app was first installed.
- */
- long firstInstallTime;
-
public ComponentName componentName;
static final int DOWNLOADED_FLAG = 1;
@@ -84,7 +79,6 @@
this.container = ItemInfo.NO_ID;
flags = initFlags(info);
- firstInstallTime = info.getFirstInstallTime();
iconCache.getTitleAndIcon(this, info, true /* useLowResIcon */);
intent = makeLaunchIntent(context, info, user);
this.user = user;
@@ -109,7 +103,6 @@
title = Utilities.trim(info.title);
intent = new Intent(info.intent);
flags = info.flags;
- firstInstallTime = info.firstInstallTime;
iconBitmap = info.iconBitmap;
}
@@ -129,7 +122,6 @@
Log.d(tag, label + " size=" + list.size());
for (AppInfo info: list) {
Log.d(tag, " title=\"" + info.title + "\" iconBitmap=" + info.iconBitmap
- + " firstInstallTime=" + info.firstInstallTime
+ " componentName=" + info.componentName.getPackageName());
}
}
diff --git a/src/com/android/launcher3/AppWidgetResizeFrame.java b/src/com/android/launcher3/AppWidgetResizeFrame.java
index e6bf525..d868536 100644
--- a/src/com/android/launcher3/AppWidgetResizeFrame.java
+++ b/src/com/android/launcher3/AppWidgetResizeFrame.java
@@ -14,6 +14,8 @@
import android.widget.FrameLayout;
import android.widget.ImageView;
+import com.android.launcher3.accessibility.DragViewStateAnnouncer;
+
public class AppWidgetResizeFrame extends FrameLayout {
private static final int SNAP_DURATION = 150;
private static final float DIMMED_HANDLE_ALPHA = 0f;
@@ -40,6 +42,8 @@
private final int[] mLastDirectionVector = new int[2];
private final int[] mTmpPt = new int[2];
+ private final DragViewStateAnnouncer mStateAnnouncer;
+
private boolean mLeftBorderActive;
private boolean mRightBorderActive;
private boolean mTopBorderActive;
@@ -78,6 +82,8 @@
mMinHSpan = info.minSpanX;
mMinVSpan = info.minSpanY;
+ mStateAnnouncer = DragViewStateAnnouncer.createFor(this);
+
setBackgroundResource(R.drawable.widget_resize_shadow);
setForeground(getResources().getDrawable(R.drawable.widget_resize_frame));
setPadding(0, 0, 0, 0);
@@ -320,12 +326,18 @@
if (mCellLayout.createAreaForResize(cellX, cellY, spanX, spanY, mWidgetView,
mDirectionVector, onDismiss)) {
+ if (mStateAnnouncer != null && (lp.cellHSpan != spanX || lp.cellVSpan != spanY) ) {
+ mStateAnnouncer.announce(
+ mLauncher.getString(R.string.widget_resized, spanX, spanY));
+ }
+
lp.tmpCellX = cellX;
lp.tmpCellY = cellY;
lp.cellHSpan = spanX;
lp.cellVSpan = spanY;
mRunningVInc += vSpanDelta;
mRunningHInc += hSpanDelta;
+
if (!onDismiss) {
updateWidgetSizeRanges(mWidgetView, mLauncher, spanX, spanY);
}
diff --git a/src/com/android/launcher3/AutoInstallsLayout.java b/src/com/android/launcher3/AutoInstallsLayout.java
index 440e4e7..151048c 100644
--- a/src/com/android/launcher3/AutoInstallsLayout.java
+++ b/src/com/android/launcher3/AutoInstallsLayout.java
@@ -125,8 +125,12 @@
private static final String ATTR_CLASS_NAME = "className";
private static final String ATTR_TITLE = "title";
private static final String ATTR_SCREEN = "screen";
+
+ // x and y can be specified as negative integers, in which case -1 represents the
+ // last row / column, -2 represents the second last, and so on.
private static final String ATTR_X = "x";
private static final String ATTR_Y = "y";
+
private static final String ATTR_SPAN_X = "spanX";
private static final String ATTR_SPAN_Y = "spanY";
private static final String ATTR_ICON = "icon";
@@ -154,6 +158,8 @@
protected final int mLayoutId;
private final int mHotseatAllAppsRank;
+ private final int mRowCount;
+ private final int mColumnCount;
private final long[] mTemp = new long[2];
@Thunk final ContentValues mValues;
@@ -164,13 +170,6 @@
public AutoInstallsLayout(Context context, AppWidgetHost appWidgetHost,
LayoutParserCallback callback, Resources res,
int layoutId, String rootTag) {
- this(context, appWidgetHost, callback, res, layoutId, rootTag,
- LauncherAppState.getInstance().getInvariantDeviceProfile().hotseatAllAppsRank);
- }
-
- public AutoInstallsLayout(Context context, AppWidgetHost appWidgetHost,
- LayoutParserCallback callback, Resources res,
- int layoutId, String rootTag, int hotseatAllAppsRank) {
mContext = context;
mAppWidgetHost = appWidgetHost;
mCallback = callback;
@@ -181,7 +180,11 @@
mSourceRes = res;
mLayoutId = layoutId;
- mHotseatAllAppsRank = hotseatAllAppsRank;
+
+ InvariantDeviceProfile idp = LauncherAppState.getInstance().getInvariantDeviceProfile();
+ mHotseatAllAppsRank = idp.hotseatAllAppsRank;
+ mRowCount = idp.numRows;
+ mColumnCount = idp.numColumns;
}
/**
@@ -261,8 +264,11 @@
mValues.put(Favorites.CONTAINER, container);
mValues.put(Favorites.SCREEN, screenId);
- mValues.put(Favorites.CELLX, getAttributeValue(parser, ATTR_X));
- mValues.put(Favorites.CELLY, getAttributeValue(parser, ATTR_Y));
+
+ mValues.put(Favorites.CELLX,
+ convertToDistanceFromEnd(getAttributeValue(parser, ATTR_X), mColumnCount);
+ mValues.put(Favorites.CELLY,
+ convertToDistanceFromEnd(getAttributeValue(parser, ATTR_Y), mRowCount);
TagParser tagParser = tagParserMap.get(parser.getName());
if (tagParser == null) {
@@ -648,6 +654,16 @@
}
}
+ private static String convertToDistanceFromEnd(String value, int endValue) {
+ if (!TextUtils.isEmpty(value)) {
+ int x = Integer.parseInt(value);
+ if (x < 0) {
+ return Integer.toString(endValue + x);
+ }
+ }
+ return value;
+ }
+
/**
* Return attribute value, attempting launcher-specific namespace first
* before falling back to anonymous attribute.
diff --git a/src/com/android/launcher3/BaseRecyclerView.java b/src/com/android/launcher3/BaseRecyclerView.java
index f0d8b3b..f8ef1e1 100644
--- a/src/com/android/launcher3/BaseRecyclerView.java
+++ b/src/com/android/launcher3/BaseRecyclerView.java
@@ -52,8 +52,8 @@
public int rowIndex;
// The offset of the first visible row
public int rowTopOffset;
- // The height of a given row (they are currently all the same height)
- public int rowHeight;
+ // The adapter position of the first visible item
+ public int itemPos;
}
protected BaseRecyclerViewFastScrollBar mScrollbar;
@@ -187,15 +187,21 @@
}
/**
+ * Returns the visible height of the recycler view:
+ * VisibleHeight = View height - top padding - bottom padding
+ */
+ protected int getVisibleHeight() {
+ int visibleHeight = getHeight() - mBackgroundPadding.top - mBackgroundPadding.bottom;
+ return visibleHeight;
+ }
+
+ /**
* Returns the available scroll height:
* AvailableScrollHeight = Total height of the all items - last page height
- *
- * This assumes that all rows are the same height.
*/
- protected int getAvailableScrollHeight(int rowCount, int rowHeight) {
- int visibleHeight = getHeight() - mBackgroundPadding.top - mBackgroundPadding.bottom;
- int scrollHeight = getPaddingTop() + rowCount * rowHeight + getPaddingBottom();
- int availableScrollHeight = scrollHeight - visibleHeight;
+ protected int getAvailableScrollHeight(int rowCount) {
+ int totalHeight = getPaddingTop() + getTop(rowCount) + getPaddingBottom();
+ int availableScrollHeight = totalHeight - getVisibleHeight();
return availableScrollHeight;
}
@@ -204,8 +210,7 @@
* AvailableScrollBarHeight = Total height of the visible view - thumb height
*/
protected int getAvailableScrollBarHeight() {
- int visibleHeight = getHeight() - mBackgroundPadding.top - mBackgroundPadding.bottom;
- int availableScrollBarHeight = visibleHeight - mScrollbar.getThumbHeight();
+ int availableScrollBarHeight = getVisibleHeight() - mScrollbar.getThumbHeight();
return availableScrollBarHeight;
}
@@ -223,6 +228,13 @@
return defaultInactiveThumbColor;
}
+ /**
+ * Returns the scrollbar for this recycler view.
+ */
+ public BaseRecyclerViewFastScrollBar getScrollBar() {
+ return mScrollbar;
+ }
+
@Override
protected void dispatchDraw(Canvas canvas) {
super.dispatchDraw(canvas);
@@ -243,7 +255,7 @@
int rowCount) {
// Only show the scrollbar if there is height to be scrolled
int availableScrollBarHeight = getAvailableScrollBarHeight();
- int availableScrollHeight = getAvailableScrollHeight(rowCount, scrollPosState.rowHeight);
+ int availableScrollHeight = getAvailableScrollHeight(rowCount);
if (availableScrollHeight <= 0) {
mScrollbar.setThumbOffset(-1, -1);
return;
@@ -252,8 +264,7 @@
// Calculate the current scroll position, the scrollY of the recycler view accounts for the
// view padding, while the scrollBarY is drawn right up to the background padding (ignoring
// padding)
- int scrollY = getPaddingTop() +
- (scrollPosState.rowIndex * scrollPosState.rowHeight) - scrollPosState.rowTopOffset;
+ int scrollY = getScrollTop(scrollPosState);
int scrollBarY = mBackgroundPadding.top +
(int) (((float) scrollY / availableScrollHeight) * availableScrollBarHeight);
@@ -268,24 +279,47 @@
}
/**
+ * @return whether fast scrolling is supported in the current state.
+ */
+ protected boolean supportsFastScrolling() {
+ return true;
+ }
+
+ /**
+ * Maps the touch (from 0..1) to the adapter position that should be visible.
+ * <p>Override in each subclass of this base class.
+ *
+ * @return the scroll top of this recycler view.
+ */
+ protected int getScrollTop(ScrollPositionState scrollPosState) {
+ return getPaddingTop() + getTop(scrollPosState.rowIndex) -
+ scrollPosState.rowTopOffset;
+ }
+
+ /**
+ * Returns information about the item that the recycler view is currently scrolled to.
+ */
+ protected abstract void getCurScrollState(ScrollPositionState stateOut, int viewTypeMask);
+
+ /**
+ * Returns the top (or y position) of the row at the specified index.
+ */
+ protected abstract int getTop(int rowIndex);
+
+ /**
* Maps the touch (from 0..1) to the adapter position that should be visible.
* <p>Override in each subclass of this base class.
*/
- public abstract String scrollToPositionAtProgress(float touchFraction);
+ protected abstract String scrollToPositionAtProgress(float touchFraction);
/**
* Updates the bounds for the scrollbar.
* <p>Override in each subclass of this base class.
*/
- public abstract void onUpdateScrollbar(int dy);
+ protected abstract void onUpdateScrollbar(int dy);
/**
* <p>Override in each subclass of this base class.
*/
- public void onFastScrollCompleted() {}
-
- /**
- * Returns information about the item that the recycler view is currently scrolled to.
- */
- protected abstract void getCurScrollState(ScrollPositionState stateOut);
+ protected void onFastScrollCompleted() {}
}
\ No newline at end of file
diff --git a/src/com/android/launcher3/BaseRecyclerViewFastScrollBar.java b/src/com/android/launcher3/BaseRecyclerViewFastScrollBar.java
index fcee7e8..a680169 100644
--- a/src/com/android/launcher3/BaseRecyclerViewFastScrollBar.java
+++ b/src/com/android/launcher3/BaseRecyclerViewFastScrollBar.java
@@ -27,6 +27,7 @@
import android.graphics.Point;
import android.graphics.Rect;
import android.view.MotionEvent;
+import android.view.VelocityTracker;
import android.view.ViewConfiguration;
import com.android.launcher3.util.Thunk;
@@ -37,7 +38,7 @@
public class BaseRecyclerViewFastScrollBar {
public interface FastScrollFocusableView {
- void setFastScrollFocused(boolean focused, boolean animated);
+ void setFastScrollFocusState(final FastBitmapDrawable.State focusState, boolean animated);
}
private final static int MAX_TRACK_ALPHA = 30;
@@ -189,7 +190,8 @@
// Check if we should start scrolling, but ignore this fastscroll gesture if we have
// exceeded some fixed movement
mIgnoreDragGesture |= Math.abs(y - downY) > config.getScaledPagingTouchSlop();
- if (!mIsDragging && !mIgnoreDragGesture && isNearThumb(downX, lastY) &&
+ if (!mIsDragging && !mIgnoreDragGesture && mRv.supportsFastScrolling() &&
+ isNearThumb(downX, lastY) &&
Math.abs(y - downY) > config.getScaledTouchSlop()) {
mRv.getParent().requestDisallowInterceptTouchEvent(true);
mIsDragging = true;
@@ -198,7 +200,7 @@
}
mTouchOffset += (lastY - downY);
mPopup.animateVisibility(true);
- animateScrollbar(true);
+ showActiveScrollbar(true);
}
if (mIsDragging) {
// Update the fastscroller section name at this touch position
@@ -209,7 +211,7 @@
(bottom - top));
mPopup.setSectionName(sectionName);
mPopup.animateVisibility(!sectionName.isEmpty());
- mRv.invalidate(mPopup.updateFastScrollerBounds(mRv, lastY));
+ mRv.invalidate(mPopup.updateFastScrollerBounds(lastY));
mLastTouchY = boundedY;
}
break;
@@ -221,7 +223,7 @@
if (mIsDragging) {
mIsDragging = false;
mPopup.animateVisibility(false);
- animateScrollbar(false);
+ showActiveScrollbar(false);
}
break;
}
@@ -245,7 +247,7 @@
/**
* Animates the width and color of the scrollbar.
*/
- private void animateScrollbar(boolean isScrolling) {
+ private void showActiveScrollbar(boolean isScrolling) {
if (mScrollbarAnimator != null) {
mScrollbarAnimator.cancel();
}
diff --git a/src/com/android/launcher3/BaseRecyclerViewFastScrollPopup.java b/src/com/android/launcher3/BaseRecyclerViewFastScrollPopup.java
index aeeb515..ebaba18 100644
--- a/src/com/android/launcher3/BaseRecyclerViewFastScrollPopup.java
+++ b/src/com/android/launcher3/BaseRecyclerViewFastScrollPopup.java
@@ -77,26 +77,26 @@
* Updates the bounds for the fast scroller.
* @return the invalidation rect for this update.
*/
- public Rect updateFastScrollerBounds(BaseRecyclerView rv, int lastTouchY) {
+ public Rect updateFastScrollerBounds(int lastTouchY) {
mInvalidateRect.set(mBgBounds);
if (isVisible()) {
// Calculate the dimensions and position of the fast scroller popup
- int edgePadding = rv.getMaxScrollbarWidth();
+ int edgePadding = mRv.getMaxScrollbarWidth();
int bgPadding = (mBgOriginalSize - mTextBounds.height()) / 2;
int bgHeight = mBgOriginalSize;
int bgWidth = Math.max(mBgOriginalSize, mTextBounds.width() + (2 * bgPadding));
if (Utilities.isRtl(mRes)) {
- mBgBounds.left = rv.getBackgroundPadding().left + (2 * rv.getMaxScrollbarWidth());
+ mBgBounds.left = mRv.getBackgroundPadding().left + (2 * mRv.getMaxScrollbarWidth());
mBgBounds.right = mBgBounds.left + bgWidth;
} else {
- mBgBounds.right = rv.getWidth() - rv.getBackgroundPadding().right -
- (2 * rv.getMaxScrollbarWidth());
+ mBgBounds.right = mRv.getWidth() - mRv.getBackgroundPadding().right -
+ (2 * mRv.getMaxScrollbarWidth());
mBgBounds.left = mBgBounds.right - bgWidth;
}
mBgBounds.top = lastTouchY - (int) (FAST_SCROLL_OVERLAY_Y_OFFSET_FACTOR * bgHeight);
mBgBounds.top = Math.max(edgePadding,
- Math.min(mBgBounds.top, rv.getHeight() - edgePadding - bgHeight));
+ Math.min(mBgBounds.top, mRv.getHeight() - edgePadding - bgHeight));
mBgBounds.bottom = mBgBounds.top + bgHeight;
} else {
mBgBounds.setEmpty();
diff --git a/src/com/android/launcher3/BubbleTextView.java b/src/com/android/launcher3/BubbleTextView.java
index 5070878..f6c9e3c 100644
--- a/src/com/android/launcher3/BubbleTextView.java
+++ b/src/com/android/launcher3/BubbleTextView.java
@@ -16,7 +16,6 @@
package com.android.launcher3;
-import android.animation.ObjectAnimator;
import android.annotation.TargetApi;
import android.content.Context;
import android.content.res.ColorStateList;
@@ -25,8 +24,9 @@
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Canvas;
-import android.graphics.Paint;
import android.graphics.Region;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.util.AttributeSet;
@@ -37,13 +37,13 @@
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewParent;
-import android.view.animation.AccelerateInterpolator;
-import android.view.animation.DecelerateInterpolator;
import android.widget.TextView;
import com.android.launcher3.IconCache.IconLoadRequest;
import com.android.launcher3.model.PackageItemInfo;
+import java.text.NumberFormat;
+
/**
* TextView that draws a bubble behind the text. We cannot use a LineBackgroundSpan
* because we want to make the bubble taller than the text and TextView's clip is
@@ -63,13 +63,6 @@
private static final int DISPLAY_WORKSPACE = 0;
private static final int DISPLAY_ALL_APPS = 1;
- private static final float FAST_SCROLL_FOCUS_MAX_SCALE = 1.15f;
- private static final int FAST_SCROLL_FOCUS_MODE_NONE = 0;
- private static final int FAST_SCROLL_FOCUS_MODE_SCALE_ICON = 1;
- private static final int FAST_SCROLL_FOCUS_MODE_DRAW_CIRCLE_BG = 2;
- private static final int FAST_SCROLL_FOCUS_FADE_IN_DURATION = 175;
- private static final int FAST_SCROLL_FOCUS_FADE_OUT_DURATION = 125;
-
private final Launcher mLauncher;
private Drawable mIcon;
private final Drawable mBackground;
@@ -93,12 +86,6 @@
private boolean mIgnorePressedStateChange;
private boolean mDisableRelayout = false;
- private ObjectAnimator mFastScrollFocusAnimator;
- private Paint mFastScrollFocusBgPaint;
- private float mFastScrollFocusFraction;
- private boolean mFastScrollFocused;
- private final int mFastScrollMode = FAST_SCROLL_FOCUS_MODE_SCALE_ICON;
-
private IconLoadRequest mIconLoadRequest;
public BubbleTextView(Context context) {
@@ -126,7 +113,7 @@
if (display == DISPLAY_WORKSPACE) {
setTextSize(TypedValue.COMPLEX_UNIT_PX, grid.iconTextSizePx);
} else if (display == DISPLAY_ALL_APPS) {
- setTextSize(TypedValue.COMPLEX_UNIT_PX, grid.allAppsIconTextSizePx);
+ setTextSize(TypedValue.COMPLEX_UNIT_SP, grid.allAppsIconTextSizeSp);
defaultIconSize = grid.allAppsIconSizePx;
}
@@ -151,13 +138,6 @@
setShadowLayer(SHADOW_LARGE_RADIUS, 0.0f, SHADOW_Y_OFFSET, SHADOW_LARGE_COLOUR);
}
- if (mFastScrollMode == FAST_SCROLL_FOCUS_MODE_DRAW_CIRCLE_BG) {
- mFastScrollFocusBgPaint = new Paint();
- mFastScrollFocusBgPaint.setAntiAlias(true);
- mFastScrollFocusBgPaint.setColor(
- getResources().getColor(R.color.container_fastscroll_thumb_active_color));
- }
-
setAccessibilityDelegate(LauncherAppState.getInstance().getAccessibilityDelegate());
}
@@ -170,8 +150,9 @@
Bitmap b = info.getIcon(iconCache);
FastBitmapDrawable iconDrawable = mLauncher.createIconDrawable(b);
- iconDrawable.setGhostModeEnabled(info.isDisabled != 0);
-
+ if (info.isDisabled != 0) {
+ iconDrawable.setState(FastBitmapDrawable.State.DISABLED);
+ }
setIcon(iconDrawable, mIconSize);
if (info.contentDescription != null) {
setContentDescription(info.contentDescription);
@@ -211,6 +192,15 @@
}
/**
+ * Used for measurement only, sets some dummy values on this view.
+ */
+ public void applyDummyInfo() {
+ ColorDrawable d = new ColorDrawable();
+ setIcon(mLauncher.resizeIconDrawable(d), mIconSize);
+ setText("");
+ }
+
+ /**
* Overrides the default long press timeout.
*/
public void setLongPressTimeout(int longPressTimeout) {
@@ -259,7 +249,15 @@
private void updateIconState() {
if (mIcon instanceof FastBitmapDrawable) {
- ((FastBitmapDrawable) mIcon).setPressed(isPressed() || mStayPressed);
+ FastBitmapDrawable d = (FastBitmapDrawable) mIcon;
+ if (isPressed() || mStayPressed) {
+ d.animateState(FastBitmapDrawable.State.PRESSED);
+ } else if (getTag() instanceof ShortcutInfo
+ && ((ShortcutInfo) getTag()).isDisabled != 0) {
+ d.animateState(FastBitmapDrawable.State.DISABLED);
+ } else {
+ d.animateState(FastBitmapDrawable.State.NORMAL);
+ }
}
}
@@ -362,18 +360,7 @@
@Override
public void draw(Canvas canvas) {
if (!mCustomShadowsEnabled) {
- // Draw the fast scroll focus bg if we have one
- if (mFastScrollMode == FAST_SCROLL_FOCUS_MODE_DRAW_CIRCLE_BG &&
- mFastScrollFocusFraction > 0f) {
- DeviceProfile grid = mLauncher.getDeviceProfile();
- int iconCenterX = getScrollX() + (getWidth() / 2);
- int iconCenterY = getScrollY() + getPaddingTop() + (grid.iconSizePx / 2);
- canvas.drawCircle(iconCenterX, iconCenterY,
- mFastScrollFocusFraction * (getWidth() / 2), mFastScrollFocusBgPaint);
- }
-
super.draw(canvas);
-
return;
}
@@ -469,6 +456,11 @@
((info.hasStatusFlag(ShortcutInfo.FLAG_INSTALL_SESSION_ACTIVE) ?
info.getInstallProgress() : 0)) : 100;
+ setContentDescription(progressLevel > 0 ?
+ getContext().getString(R.string.app_downloading_title, info.title,
+ NumberFormat.getPercentInstance().format(progressLevel * 0.01)) :
+ getContext().getString(R.string.app_waiting_download_title, info.title));
+
if (mIcon != null) {
final PreloadIconDrawable preloadDrawable;
if (mIcon instanceof PreloadIconDrawable) {
@@ -533,8 +525,13 @@
*/
public void reapplyItemInfo(final ItemInfo info) {
if (getTag() == info) {
+ FastBitmapDrawable.State prevState = FastBitmapDrawable.State.NORMAL;
+ if (mIcon instanceof FastBitmapDrawable) {
+ prevState = ((FastBitmapDrawable) mIcon).getCurrentState();
+ }
mIconLoadRequest = null;
mDisableRelayout = true;
+
if (info instanceof AppInfo) {
applyFromApplicationInfo((AppInfo) info);
} else if (info instanceof ShortcutInfo) {
@@ -550,6 +547,13 @@
} else if (info instanceof PackageItemInfo) {
applyFromPackageItemInfo((PackageItemInfo) info);
}
+
+ // If we are reapplying over an old icon, then we should update the new icon to the same
+ // state as the old icon
+ if (mIcon instanceof FastBitmapDrawable) {
+ ((FastBitmapDrawable) mIcon).setState(prevState);
+ }
+
mDisableRelayout = false;
}
}
@@ -583,55 +587,53 @@
}
}
- // Setters & getters for the animation
- public void setFastScrollFocus(float fraction) {
- mFastScrollFocusFraction = fraction;
- if (mFastScrollMode == FAST_SCROLL_FOCUS_MODE_SCALE_ICON) {
- setScaleX(1f + fraction * (FAST_SCROLL_FOCUS_MAX_SCALE - 1f));
- setScaleY(1f + fraction * (FAST_SCROLL_FOCUS_MAX_SCALE - 1f));
- } else {
- invalidate();
- }
- }
-
- public float getFastScrollFocus() {
- return mFastScrollFocusFraction;
- }
-
@Override
- public void setFastScrollFocused(final boolean focused, boolean animated) {
- if (mFastScrollMode == FAST_SCROLL_FOCUS_MODE_NONE) {
+ public void setFastScrollFocusState(final FastBitmapDrawable.State focusState, boolean animated) {
+ // We can only set the fast scroll focus state on a FastBitmapDrawable
+ if (!(mIcon instanceof FastBitmapDrawable)) {
return;
}
- if (mFastScrollFocused != focused) {
- mFastScrollFocused = focused;
-
- if (animated) {
- // Clean up the previous focus animator
- if (mFastScrollFocusAnimator != null) {
- mFastScrollFocusAnimator.cancel();
- }
- mFastScrollFocusAnimator = ObjectAnimator.ofFloat(this, "fastScrollFocus",
- focused ? 1f : 0f);
- if (focused) {
- mFastScrollFocusAnimator.setInterpolator(new DecelerateInterpolator());
- } else {
- mFastScrollFocusAnimator.setInterpolator(new AccelerateInterpolator());
- }
- mFastScrollFocusAnimator.setDuration(focused ?
- FAST_SCROLL_FOCUS_FADE_IN_DURATION : FAST_SCROLL_FOCUS_FADE_OUT_DURATION);
- mFastScrollFocusAnimator.start();
- } else {
- mFastScrollFocusFraction = focused ? 1f : 0f;
+ FastBitmapDrawable d = (FastBitmapDrawable) mIcon;
+ if (animated) {
+ FastBitmapDrawable.State prevState = d.getCurrentState();
+ if (d.animateState(focusState)) {
+ // If the state was updated, then update the view accordingly
+ animate().scaleX(focusState.viewScale)
+ .scaleY(focusState.viewScale)
+ .setStartDelay(getStartDelayForStateChange(prevState, focusState))
+ .setDuration(d.getDurationForStateChange(prevState, focusState))
+ .start();
+ }
+ } else {
+ if (d.setState(focusState)) {
+ // If the state was updated, then update the view accordingly
+ animate().cancel();
+ setScaleX(focusState.viewScale);
+ setScaleY(focusState.viewScale);
}
}
}
/**
+ * Returns the start delay when animating between certain {@link FastBitmapDrawable} states.
+ */
+ private static int getStartDelayForStateChange(final FastBitmapDrawable.State fromState,
+ final FastBitmapDrawable.State toState) {
+ switch (toState) {
+ case NORMAL:
+ switch (fromState) {
+ case FAST_SCROLL_HIGHLIGHTED:
+ return FastBitmapDrawable.FAST_SCROLL_INACTIVE_DURATION / 4;
+ }
+ }
+ return 0;
+ }
+
+ /**
* Interface to be implemented by the grand parent to allow click shadow effect.
*/
- public static interface BubbleTextShadowHandler {
+ public interface BubbleTextShadowHandler {
void setPressedIcon(BubbleTextView icon, Bitmap background);
}
}
diff --git a/src/com/android/launcher3/ButtonDropTarget.java b/src/com/android/launcher3/ButtonDropTarget.java
index 2baa6d8..40a4678 100644
--- a/src/com/android/launcher3/ButtonDropTarget.java
+++ b/src/com/android/launcher3/ButtonDropTarget.java
@@ -34,6 +34,7 @@
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
+import android.view.accessibility.AccessibilityEvent;
import android.view.animation.DecelerateInterpolator;
import android.view.animation.LinearInterpolator;
import android.widget.TextView;
@@ -123,6 +124,10 @@
mDrawable.setColorFilter(new ColorMatrixColorFilter(mCurrentFilter));
setTextColor(mHoverColor);
}
+ if (d.stateAnnouncer != null) {
+ d.stateAnnouncer.cancel();
+ }
+ sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED);
}
@Override
@@ -301,14 +306,10 @@
setOnClickListener(enable ? this : null);
}
- protected String getAccessibilityDropConfirmation() {
- return null;
- }
-
@Override
public void onClick(View v) {
LauncherAppState.getInstance().getAccessibilityDelegate()
- .handleAccessibleDrop(this, null, getAccessibilityDropConfirmation());
+ .handleAccessibleDrop(this, null, null);
}
public int getTextColor() {
diff --git a/src/com/android/launcher3/CellLayout.java b/src/com/android/launcher3/CellLayout.java
index 84e2d49..94e3e41 100644
--- a/src/com/android/launcher3/CellLayout.java
+++ b/src/com/android/launcher3/CellLayout.java
@@ -25,7 +25,6 @@
import android.annotation.TargetApi;
import android.content.Context;
import android.content.res.Resources;
-import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
@@ -53,6 +52,7 @@
import com.android.launcher3.accessibility.DragAndDropAccessibilityDelegate;
import com.android.launcher3.accessibility.FolderAccessibilityHelper;
import com.android.launcher3.accessibility.WorkspaceAccessibilityHelper;
+import com.android.launcher3.util.ParcelableSparseArray;
import com.android.launcher3.util.Thunk;
import java.util.ArrayList;
@@ -66,7 +66,8 @@
public static final int WORKSPACE_ACCESSIBILITY_DRAG = 2;
public static final int FOLDER_ACCESSIBILITY_DRAG = 1;
- static final String TAG = "CellLayout";
+ private static final String TAG = "CellLayout";
+ private static final boolean LOGD = false;
private Launcher mLauncher;
@Thunk int mCellWidth;
@@ -84,6 +85,7 @@
private int mMaxGap;
private boolean mDropPending = false;
private boolean mIsDragTarget = true;
+ private boolean mJailContent = true;
// These are temporary variables to prevent having to allocate a new object just to
// return an (x, y) value from helper functions. Do NOT use them to maintain other state.
@@ -187,7 +189,6 @@
mLauncher = (Launcher) context;
DeviceProfile grid = mLauncher.getDeviceProfile();
- TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CellLayout, defStyle, 0);
mCellWidth = mCellHeight = -1;
mFixedCellWidth = mFixedCellHeight = -1;
@@ -201,10 +202,7 @@
mPreviousReorderDirection[0] = INVALID_DIRECTION;
mPreviousReorderDirection[1] = INVALID_DIRECTION;
- a.recycle();
-
setAlwaysDrawnWithCacheEnabled(false);
-
final Resources res = getResources();
mHotseatScale = (float) grid.hotseatIconSizePx / grid.iconSizePx;
@@ -244,9 +242,7 @@
// If an animation is started and then stopped very quickly, we can still
// get spurious updates we've cleared the tag. Guard against this.
if (outline == null) {
- @SuppressWarnings("all") // suppress dead code warning
- final boolean debug = false;
- if (debug) {
+ if (LOGD) {
Object val = animation.getAnimatedValue();
Log.d(TAG, "anim " + thisIndex + " update: " + val +
", isStopped " + anim.isStopped());
@@ -424,10 +420,36 @@
}
}
- boolean getIsDragOverlapping() {
+ public boolean getIsDragOverlapping() {
return mIsDragOverlapping;
}
+ public void disableJailContent() {
+ mJailContent = false;
+ }
+
+ @Override
+ protected void dispatchSaveInstanceState(SparseArray<Parcelable> container) {
+ if (mJailContent) {
+ ParcelableSparseArray jail = getJailedArray(container);
+ super.dispatchSaveInstanceState(jail);
+ container.put(R.id.cell_layout_jail_id, jail);
+ } else {
+ super.dispatchSaveInstanceState(container);
+ }
+ }
+
+ @Override
+ protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) {
+ super.dispatchRestoreInstanceState(mJailContent ? getJailedArray(container) : container);
+ }
+
+ private ParcelableSparseArray getJailedArray(SparseArray<Parcelable> container) {
+ final Parcelable parcelable = container.get(R.id.cell_layout_jail_id);
+ return parcelable instanceof ParcelableSparseArray ?
+ (ParcelableSparseArray) parcelable : new ParcelableSparseArray();
+ }
+
@Override
protected void onDraw(Canvas canvas) {
if (!mIsDragTarget) {
@@ -630,6 +652,9 @@
if (lp.cellVSpan < 0) lp.cellVSpan = mCountY;
child.setId(childId);
+ if (LOGD) {
+ Log.d(TAG, "Adding view to ShortcutsAndWidgetsContainer: " + child);
+ }
mShortcutsAndWidgets.addView(child, index, lp);
if (markCells) markCellsAsOccupiedForView(child);
@@ -873,9 +898,12 @@
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
- int offset = getMeasuredWidth() - getPaddingLeft() - getPaddingRight() -
- (mCountX * mCellWidth);
- int left = getPaddingLeft() + (int) Math.ceil(offset / 2f);
+ boolean isFullscreen = mShortcutsAndWidgets.getChildCount() > 0 &&
+ ((LayoutParams) mShortcutsAndWidgets.getChildAt(0).getLayoutParams()).isFullscreen;
+ int left = getPaddingLeft();
+ if (!isFullscreen) {
+ left += (int) Math.ceil(getUnusedHorizontalSpace() / 2f);
+ }
int top = getPaddingTop();
mTouchFeedbackView.layout(left, top,
@@ -886,6 +914,15 @@
top + b - t);
}
+ /**
+ * Returns the amount of space left over after subtracting padding and cells. This space will be
+ * very small, a few pixels at most, and is a result of rounding down when calculating the cell
+ * width in {@link DeviceProfile#calculateCellWidth(int, int)}.
+ */
+ public int getUnusedHorizontalSpace() {
+ return getMeasuredWidth() - getPaddingLeft() - getPaddingRight() - (mCountX * mCellWidth);
+ }
+
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
@@ -1018,8 +1055,8 @@
return false;
}
- void visualizeDropLocation(View v, Bitmap dragOutline, int originX, int originY, int cellX,
- int cellY, int spanX, int spanY, boolean resize, Point dragOffset, Rect dragRegion) {
+ void visualizeDropLocation(View v, Bitmap dragOutline, int cellX, int cellY, int spanX,
+ int spanY, boolean resize, DropTarget.DragObject dragObject) {
final int oldDragCellX = mDragCell[0];
final int oldDragCellY = mDragCell[1];
@@ -1028,6 +1065,9 @@
}
if (cellX != oldDragCellX || cellY != oldDragCellY) {
+ Point dragOffset = dragObject.dragView.getDragVisualizeOffset();
+ Rect dragRegion = dragObject.dragView.getDragRegion();
+
mDragCell[0] = cellX;
mDragCell[1] = cellY;
// Find the top left corner of the rect the object will occupy
@@ -1079,6 +1119,18 @@
mDragOutlineAnims[mDragOutlineCurrent].setTag(dragOutline);
mDragOutlineAnims[mDragOutlineCurrent].animateIn();
+
+ if (dragObject.stateAnnouncer != null) {
+ String msg;
+ if (isHotseat()) {
+ msg = getContext().getString(R.string.move_to_hotseat_position,
+ Math.max(cellX, cellY) + 1);
+ } else {
+ msg = getContext().getString(R.string.move_to_empty_cell,
+ cellY + 1, cellX + 1);
+ }
+ dragObject.stateAnnouncer.announce(msg);
+ }
}
}
@@ -2133,8 +2185,15 @@
}
ValueAnimator va = LauncherAnimUtils.ofFloat(child, 0f, 1f);
a = va;
- va.setRepeatMode(ValueAnimator.REVERSE);
- va.setRepeatCount(ValueAnimator.INFINITE);
+
+ // Animations are disabled in power save mode, causing the repeated animation to jump
+ // spastically between beginning and end states. Since this looks bad, we don't repeat
+ // the animation in power save mode.
+ if (!Utilities.isPowerSaverOn(getContext())) {
+ va.setRepeatMode(ValueAnimator.REVERSE);
+ va.setRepeatCount(ValueAnimator.INFINITE);
+ }
+
va.setDuration(mode == MODE_HINT ? HINT_DURATION : PREVIEW_DURATION);
va.setStartDelay((int) (Math.random() * 60));
va.addUpdateListener(new AnimatorUpdateListener() {
@@ -2655,6 +2714,7 @@
LayoutParams lp = (LayoutParams) child.getLayoutParams();
lp.dropped = true;
child.requestLayout();
+ markCellsAsOccupiedForView(child);
}
}
diff --git a/src/com/android/launcher3/CommonAppTypeParser.java b/src/com/android/launcher3/CommonAppTypeParser.java
index 5314ecf..001e044 100644
--- a/src/com/android/launcher3/CommonAppTypeParser.java
+++ b/src/com/android/launcher3/CommonAppTypeParser.java
@@ -25,7 +25,7 @@
import com.android.launcher3.AutoInstallsLayout.LayoutParserCallback;
import com.android.launcher3.LauncherSettings.Favorites;
-import com.android.launcher3.backup.BackupProtos.Favorite;
+import com.android.launcher3.backup.nano.BackupProtos.Favorite;
import com.android.launcher3.util.Thunk;
import org.xmlpull.v1.XmlPullParserException;
@@ -93,7 +93,7 @@
public MyLayoutParser() {
super(CommonAppTypeParser.this.mContext, null, CommonAppTypeParser.this,
- CommonAppTypeParser.this.mContext.getResources(), mResId, TAG_RESOLVE, 0);
+ CommonAppTypeParser.this.mContext.getResources(), mResId, TAG_RESOLVE);
}
@Override
diff --git a/src/com/android/launcher3/DefaultLayoutParser.java b/src/com/android/launcher3/DefaultLayoutParser.java
index 7b91c67..2bba380 100644
--- a/src/com/android/launcher3/DefaultLayoutParser.java
+++ b/src/com/android/launcher3/DefaultLayoutParser.java
@@ -48,9 +48,8 @@
}
public DefaultLayoutParser(Context context, AppWidgetHost appWidgetHost,
- LayoutParserCallback callback, Resources sourceRes, int layoutId, String rootTag,
- int hotseatAllAppsRank) {
- super(context, appWidgetHost, callback, sourceRes, layoutId, rootTag, hotseatAllAppsRank);
+ LayoutParserCallback callback, Resources sourceRes, int layoutId, String rootTag) {
+ super(context, appWidgetHost, callback, sourceRes, layoutId, rootTag);
}
@Override
diff --git a/src/com/android/launcher3/DeleteDropTarget.java b/src/com/android/launcher3/DeleteDropTarget.java
index 1bff833..edaf525 100644
--- a/src/com/android/launcher3/DeleteDropTarget.java
+++ b/src/com/android/launcher3/DeleteDropTarget.java
@@ -19,7 +19,6 @@
import android.animation.TimeInterpolator;
import android.content.Context;
import android.graphics.PointF;
-import android.os.AsyncTask;
import android.util.AttributeSet;
import android.view.View;
import android.view.animation.AnimationUtils;
@@ -67,44 +66,14 @@
/**
* Removes the item from the workspace. If the view is not null, it also removes the view.
- * @return true if the item was removed.
*/
- public static boolean removeWorkspaceOrFolderItem(Launcher launcher, ItemInfo item, View view) {
- if (item instanceof ShortcutInfo) {
- LauncherModel.deleteItemFromDatabase(launcher, item);
- } else if (item instanceof FolderInfo) {
- FolderInfo folder = (FolderInfo) item;
- launcher.removeFolder(folder);
- LauncherModel.deleteFolderContentsFromDatabase(launcher, folder);
- } else if (item instanceof LauncherAppWidgetInfo) {
- final LauncherAppWidgetInfo widget = (LauncherAppWidgetInfo) item;
-
- // Remove the widget from the workspace
- launcher.removeAppWidget(widget);
- LauncherModel.deleteItemFromDatabase(launcher, widget);
-
- final LauncherAppWidgetHost appWidgetHost = launcher.getAppWidgetHost();
-
- if (appWidgetHost != null && !widget.isCustomWidget()
- && widget.isWidgetIdValid()) {
- // Deleting an app widget ID is a void call but writes to disk before returning
- // to the caller...
- new AsyncTask<Void, Void, Void>() {
- public Void doInBackground(Void ... args) {
- appWidgetHost.deleteAppWidgetId(widget.appWidgetId);
- return null;
- }
- }.executeOnExecutor(Utilities.THREAD_POOL_EXECUTOR);
- }
- } else {
- return false;
- }
-
- if (view != null) {
- launcher.getWorkspace().removeWorkspaceItem(view);
- launcher.getWorkspace().stripEmptyScreens();
- }
- return true;
+ public static void removeWorkspaceOrFolderItem(Launcher launcher, ItemInfo item, View view) {
+ // Remove the item from launcher and the db, we can ignore the containerInfo in this call
+ // because we already remove the drag view from the folder (if the drag originated from
+ // a folder) in Folder.beginDrag()
+ launcher.removeItem(view, item, true /* deleteFromDb */);
+ launcher.getWorkspace().stripEmptyScreens();
+ launcher.getDragLayer().announceForAccessibility(launcher.getString(R.string.item_removed));
}
@Override
@@ -156,9 +125,4 @@
dragLayer.animateView(d.dragView, fling, duration, tInterpolator, onAnimationEndRunnable,
DragLayer.ANIMATION_END_DISAPPEAR, null);
}
-
- @Override
- protected String getAccessibilityDropConfirmation() {
- return getResources().getString(R.string.item_removed);
- }
}
diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java
index 947b164..c6da584 100644
--- a/src/com/android/launcher3/DeviceProfile.java
+++ b/src/com/android/launcher3/DeviceProfile.java
@@ -90,7 +90,7 @@
public int hotseatCellWidthPx;
public int hotseatCellHeightPx;
public int hotseatIconSizePx;
- private int hotseatBarHeightNormalPx, hotseatBarHeightShortPx;
+ private int normalHotseatBarHeightPx, shortHotseatBarHeightPx;
private int hotseatBarHeightPx; // One of the above.
// All apps
@@ -98,13 +98,15 @@
public int allAppsNumPredictiveCols;
public int allAppsButtonVisualSize;
public final int allAppsIconSizePx;
- public final int allAppsIconTextSizePx;
+ public final float allAppsIconTextSizeSp;
// QSB
- private int searchBarSpaceWidthPx;
- private int searchBarSpaceHeightNormalPx, searchBarSpaceHeightTallPx;
+ private int searchBarWidgetInternalPaddingTop, searchBarWidgetInternalPaddingBottom;
+ private int searchBarTopPaddingPx;
+ private int normalSearchBarBottomPaddingPx, tallSearchBarBottomPaddingPx;
+ private int searchBarBottomPaddingPx; // One of the above.
+ private int normalSearchBarSpaceHeightPx, tallSearchBarSpaceHeightPx;
private int searchBarSpaceHeightPx; // One of the above.
- private int searchBarHeight = LauncherCallbacks.SEARCH_BAR_HEIGHT_NORMAL;
public DeviceProfile(Context context, InvariantDeviceProfile inv,
Point minSize, Point maxSize,
@@ -148,7 +150,7 @@
res.getDimensionPixelSize(R.dimen.dynamic_grid_icon_drawable_padding);
// AllApps uses the original non-scaled icon text size
- allAppsIconTextSizePx = Utilities.pxFromDp(inv.iconTextSize, dm);
+ allAppsIconTextSizeSp = inv.iconTextSize;
// AllApps uses the original non-scaled icon size
allAppsIconSizePx = Utilities.pxFromDp(inv.iconSize, dm);
@@ -206,12 +208,26 @@
hotseatIconSizePx = (int) (Utilities.pxFromDp(inv.hotseatIconSize, dm) * scale);
// Search Bar
- searchBarSpaceWidthPx = Math.min(widthPx,
- res.getDimensionPixelSize(R.dimen.dynamic_grid_search_bar_max_width));
- searchBarSpaceHeightNormalPx = getSearchBarTopOffset()
- + res.getDimensionPixelSize(R.dimen.dynamic_grid_search_bar_height);
- searchBarSpaceHeightTallPx = getSearchBarTopOffset()
- + res.getDimensionPixelSize(R.dimen.dynamic_grid_search_bar_height_tall);
+ normalSearchBarSpaceHeightPx = res.getDimensionPixelSize(
+ R.dimen.dynamic_grid_search_bar_height);
+ tallSearchBarSpaceHeightPx = res.getDimensionPixelSize(
+ R.dimen.dynamic_grid_search_bar_height_tall);
+ searchBarWidgetInternalPaddingTop = res.getDimensionPixelSize(
+ R.dimen.qsb_internal_padding_top);
+ searchBarWidgetInternalPaddingBottom = res.getDimensionPixelSize(
+ R.dimen.qsb_internal_padding_bottom);
+ if (isTablet && !isVerticalBarLayout()) {
+ searchBarTopPaddingPx = searchBarWidgetInternalPaddingTop;
+ normalSearchBarBottomPaddingPx = searchBarWidgetInternalPaddingBottom +
+ res.getDimensionPixelSize(R.dimen.dynamic_grid_search_bar_bottom_padding_tablet);
+ tallSearchBarBottomPaddingPx = normalSearchBarBottomPaddingPx;
+ } else {
+ searchBarTopPaddingPx = searchBarWidgetInternalPaddingTop;
+ normalSearchBarBottomPaddingPx = searchBarWidgetInternalPaddingBottom +
+ res.getDimensionPixelSize(R.dimen.dynamic_grid_search_bar_bottom_padding);
+ tallSearchBarBottomPaddingPx = searchBarWidgetInternalPaddingBottom +
+ res.getDimensionPixelSize(R.dimen.dynamic_grid_search_bar_bottom_padding_short);
+ }
// Calculate the actual text height
Paint textPaint = new Paint();
@@ -223,13 +239,16 @@
dragViewScale = (iconSizePx + scaleDps) / iconSizePx;
// Hotseat
- hotseatBarHeightNormalPx = iconSizePx + 4 * edgeMarginPx;
- hotseatBarHeightShortPx = iconSizePx + 2 * edgeMarginPx;
+ normalHotseatBarHeightPx = iconSizePx + 4 * edgeMarginPx;
+ shortHotseatBarHeightPx = iconSizePx + 2 * edgeMarginPx;
hotseatCellWidthPx = iconSizePx;
hotseatCellHeightPx = iconSizePx;
// Folder
- folderCellWidthPx = cellWidthPx + 3 * edgeMarginPx;
+ int folderCellPadding = isTablet || isLandscape ? 6 * edgeMarginPx : 3 * edgeMarginPx;
+ // Don't let the folder get too close to the edges of the screen.
+ folderCellWidthPx = Math.min(cellWidthPx + folderCellPadding,
+ (availableWidthPx - 4 * edgeMarginPx) / inv.numFolderColumns);
folderCellHeightPx = cellHeightPx + edgeMarginPx;
folderBackgroundOffset = -edgeMarginPx;
folderIconSizePx = iconSizePx + 2 * -folderBackgroundOffset;
@@ -251,13 +270,20 @@
allAppsNumPredictiveCols = numPredictiveAppCols;
}
- /** Returns the search bar top offset */
- private int getSearchBarTopOffset() {
- if (isTablet && !isVerticalBarLayout()) {
- return 4 * edgeMarginPx;
- } else {
- return 2 * edgeMarginPx;
+ /** Returns the amount of extra space to allocate to the search bar for vertical padding. */
+ private int getSearchBarTotalVerticalPadding() {
+ return searchBarTopPaddingPx + searchBarBottomPaddingPx;
+ }
+
+ /** Returns the width and height of the search bar, ignoring any padding. */
+ public Point getSearchBarDimensForWidgetOpts(Resources res) {
+ Rect searchBarBounds = getSearchBarBounds(Utilities.isRtl(res));
+ if (isVerticalBarLayout()) {
+ return new Point(searchBarBounds.width(), searchBarBounds.height());
}
+ int widgetInternalPadding = searchBarWidgetInternalPaddingTop +
+ searchBarWidgetInternalPaddingBottom;
+ return new Point(searchBarBounds.width(), searchBarSpaceHeightPx + widgetInternalPadding);
}
/** Returns the search bar bounds in the current orientation */
@@ -265,13 +291,14 @@
Rect bounds = new Rect();
if (isVerticalBarLayout()) {
if (isLayoutRtl) {
- bounds.set(availableWidthPx - searchBarSpaceHeightNormalPx, edgeMarginPx,
+ bounds.set(availableWidthPx - normalSearchBarSpaceHeightPx, edgeMarginPx,
availableWidthPx, availableHeightPx - edgeMarginPx);
} else {
- bounds.set(0, edgeMarginPx, searchBarSpaceHeightNormalPx,
+ bounds.set(0, edgeMarginPx, normalSearchBarSpaceHeightPx,
availableHeightPx - edgeMarginPx);
}
} else {
+ int boundsBottom = searchBarSpaceHeightPx + getSearchBarTotalVerticalPadding();
if (isTablet) {
// Pad the left and right of the workspace to ensure consistent spacing
// between all icons
@@ -280,14 +307,13 @@
// that into account here too.
int gap = (int) ((width - 2 * edgeMarginPx -
(inv.numColumns * cellWidthPx)) / (2 * (inv.numColumns + 1)));
- bounds.set(edgeMarginPx + gap, getSearchBarTopOffset(),
- availableWidthPx - (edgeMarginPx + gap),
- searchBarSpaceHeightPx);
+ bounds.set(edgeMarginPx + gap, 0,
+ availableWidthPx - (edgeMarginPx + gap), boundsBottom);
} else {
bounds.set(desiredWorkspaceLeftRightMarginPx - defaultWidgetPadding.left,
- getSearchBarTopOffset(),
+ 0,
availableWidthPx - (desiredWorkspaceLeftRightMarginPx -
- defaultWidgetPadding.right), searchBarSpaceHeightPx);
+ defaultWidgetPadding.right), boundsBottom);
}
}
return bounds;
@@ -300,21 +326,21 @@
if (isVerticalBarLayout()) {
// Pad the left and right of the workspace with search/hotseat bar sizes
if (isLayoutRtl) {
- padding.set(hotseatBarHeightNormalPx, edgeMarginPx,
+ padding.set(normalHotseatBarHeightPx, edgeMarginPx,
searchBarBounds.width(), edgeMarginPx);
} else {
padding.set(searchBarBounds.width(), edgeMarginPx,
- hotseatBarHeightNormalPx, edgeMarginPx);
+ normalHotseatBarHeightPx, edgeMarginPx);
}
} else {
+ int paddingTop = searchBarBounds.bottom;
+ int paddingBottom = hotseatBarHeightPx + pageIndicatorHeightPx;
if (isTablet) {
// Pad the left and right of the workspace to ensure consistent spacing
// between all icons
float gapScale = 1f + (dragViewScale - 1f) / 2f;
int width = getCurrentWidth();
int height = getCurrentHeight();
- int paddingTop = searchBarBounds.bottom;
- int paddingBottom = hotseatBarHeightPx + pageIndicatorHeightPx;
// The amount of screen space available for left/right padding.
int availablePaddingX = Math.max(0, width - (int) ((inv.numColumns * cellWidthPx) +
((inv.numColumns - 1) * gapScale * cellWidthPx)));
@@ -327,9 +353,9 @@
} else {
// Pad the top and bottom of the workspace with search/hotseat bar sizes
padding.set(desiredWorkspaceLeftRightMarginPx - defaultWidgetPadding.left,
- searchBarBounds.bottom,
+ paddingTop,
desiredWorkspaceLeftRightMarginPx - defaultWidgetPadding.right,
- hotseatBarHeightPx + pageIndicatorHeightPx);
+ paddingBottom);
}
}
return padding;
@@ -357,7 +383,7 @@
// The rect returned will be extended to below the system ui that covers the workspace
Rect getHotseatRect() {
if (isVerticalBarLayout()) {
- return new Rect(availableWidthPx - hotseatBarHeightNormalPx, 0,
+ return new Rect(availableWidthPx - normalHotseatBarHeightPx, 0,
Integer.MAX_VALUE, availableHeightPx);
} else {
return new Rect(0, availableHeightPx - hotseatBarHeightPx,
@@ -395,27 +421,34 @@
return visibleChildren;
}
+ // TODO(twickham): b/25154513
+ public void setSearchBarHeight(int searchBarHeight) {
+ if (searchBarHeight == LauncherCallbacks.SEARCH_BAR_HEIGHT_TALL) {
+ hotseatBarHeightPx = shortHotseatBarHeightPx;
+ searchBarSpaceHeightPx = tallSearchBarSpaceHeightPx;
+ searchBarBottomPaddingPx = tallSearchBarBottomPaddingPx;
+ } else {
+ hotseatBarHeightPx = normalHotseatBarHeightPx;
+ searchBarSpaceHeightPx = normalSearchBarSpaceHeightPx;
+ searchBarBottomPaddingPx = normalSearchBarBottomPaddingPx;
+ }
+ }
+
public void layout(Launcher launcher) {
FrameLayout.LayoutParams lp;
boolean hasVerticalBarLayout = isVerticalBarLayout();
final boolean isLayoutRtl = Utilities.isRtl(launcher.getResources());
// Layout the search bar space
+ Rect searchBarBounds = getSearchBarBounds(isLayoutRtl);
View searchBar = launcher.getSearchDropTargetBar();
lp = (FrameLayout.LayoutParams) searchBar.getLayoutParams();
- searchBarHeight = launcher.getSearchBarHeight();
- if (searchBarHeight == LauncherCallbacks.SEARCH_BAR_HEIGHT_TALL) {
- hotseatBarHeightPx = hotseatBarHeightShortPx;
- searchBarSpaceHeightPx = searchBarSpaceHeightTallPx;
- } else {
- hotseatBarHeightPx = hotseatBarHeightNormalPx;
- searchBarSpaceHeightPx = searchBarSpaceHeightNormalPx;
- }
+ lp.width = searchBarBounds.width();
+ lp.height = searchBarBounds.height();
if (hasVerticalBarLayout) {
// Vertical search bar space -- The search bar is fixed in the layout to be on the left
// of the screen regardless of RTL
lp.gravity = Gravity.LEFT;
- lp.width = searchBarSpaceHeightNormalPx;
LinearLayout targets = (LinearLayout) searchBar.findViewById(R.id.drag_target_bar);
targets.setOrientation(LinearLayout.VERTICAL);
@@ -425,11 +458,7 @@
} else {
// Horizontal search bar space
- lp.gravity = Gravity.TOP;
- lp.height = searchBarSpaceHeightPx;
-
- LinearLayout targets = (LinearLayout) searchBar.findViewById(R.id.drag_target_bar);
- targets.getLayoutParams().width = searchBarSpaceWidthPx;
+ lp.gravity = Gravity.TOP|Gravity.CENTER_HORIZONTAL;
}
searchBar.setLayoutParams(lp);
@@ -456,7 +485,7 @@
// Vertical hotseat -- The hotseat is fixed in the layout to be on the right of the
// screen regardless of RTL
lp.gravity = Gravity.RIGHT;
- lp.width = hotseatBarHeightNormalPx;
+ lp.width = normalHotseatBarHeightPx;
lp.height = LayoutParams.MATCH_PARENT;
hotseat.findViewById(R.id.layout).setPadding(0, 2 * edgeMarginPx, 0, 2 * edgeMarginPx);
} else if (isTablet) {
diff --git a/src/com/android/launcher3/DragController.java b/src/com/android/launcher3/DragController.java
index 2191455..eefb287 100644
--- a/src/com/android/launcher3/DragController.java
+++ b/src/com/android/launcher3/DragController.java
@@ -32,8 +32,10 @@
import android.view.VelocityTracker;
import android.view.View;
import android.view.ViewConfiguration;
+import android.view.accessibility.AccessibilityManager;
import android.view.inputmethod.InputMethodManager;
+import com.android.launcher3.accessibility.DragViewStateAnnouncer;
import com.android.launcher3.util.Thunk;
import java.util.ArrayList;
@@ -145,8 +147,6 @@
/**
* Used to create a new DragLayer from XML.
- *
- * @param context The application's context.
*/
public DragController(Launcher launcher) {
Resources r = launcher.getResources();
@@ -239,6 +239,9 @@
mDragObject = new DropTarget.DragObject();
+ final DragView dragView = mDragObject.dragView = new DragView(mLauncher, b, registrationX,
+ registrationY, 0, 0, b.getWidth(), b.getHeight(), initialDragViewScale);
+
mDragObject.dragComplete = false;
if (mIsAccessibleDrag) {
// For an accessible drag, we assume the view is being dragged from the center.
@@ -248,14 +251,12 @@
} else {
mDragObject.xOffset = mMotionDownX - (dragLayerX + dragRegionLeft);
mDragObject.yOffset = mMotionDownY - (dragLayerY + dragRegionTop);
+ mDragObject.stateAnnouncer = DragViewStateAnnouncer.createFor(dragView);
}
mDragObject.dragSource = source;
mDragObject.dragInfo = dragInfo;
- final DragView dragView = mDragObject.dragView = new DragView(mLauncher, b, registrationX,
- registrationY, 0, 0, b.getWidth(), b.getHeight(), initialDragViewScale);
-
if (dragOffset != null) {
dragView.setDragVisualizeOffset(new Point(dragOffset));
}
@@ -347,8 +348,7 @@
if (rawDragInfo instanceof ShortcutInfo) {
ShortcutInfo dragInfo = (ShortcutInfo) rawDragInfo;
for (ComponentName componentName : cns) {
- // Added null checks to prevent NPE we've seen in the wild
- if (dragInfo != null && dragInfo.intent != null) {
+ if (dragInfo.intent != null) {
ComponentName cn = dragInfo.intent.getComponent();
boolean isSameComponent = cn != null && (cn.equals(componentName) ||
packageNames.contains(cn.getPackageName()));
diff --git a/src/com/android/launcher3/DragLayer.java b/src/com/android/launcher3/DragLayer.java
index 1c18747..ad9063c 100644
--- a/src/com/android/launcher3/DragLayer.java
+++ b/src/com/android/launcher3/DragLayer.java
@@ -565,10 +565,6 @@
resizeFrame.snapToWidget(false);
}
- public void animateViewIntoPosition(DragView dragView, final View child) {
- animateViewIntoPosition(dragView, child, null, null);
- }
-
public void animateViewIntoPosition(DragView dragView, final int[] pos, float alpha,
float scaleX, float scaleY, int animationEndStyle, Runnable onFinishRunnable,
int duration) {
diff --git a/src/com/android/launcher3/DragView.java b/src/com/android/launcher3/DragView.java
index 2acfc61..a584667 100644
--- a/src/com/android/launcher3/DragView.java
+++ b/src/com/android/launcher3/DragView.java
@@ -321,10 +321,10 @@
setTranslationY(touchY - mRegistrationY);
// Post the animation to skip other expensive work happening on the first frame
post(new Runnable() {
- public void run() {
- mAnim.start();
- }
- });
+ public void run() {
+ mAnim.start();
+ }
+ });
}
public void cancelAnimation() {
diff --git a/src/com/android/launcher3/DropTarget.java b/src/com/android/launcher3/DropTarget.java
index c8fac54..4340591 100644
--- a/src/com/android/launcher3/DropTarget.java
+++ b/src/com/android/launcher3/DropTarget.java
@@ -19,6 +19,8 @@
import android.graphics.PointF;
import android.graphics.Rect;
+import com.android.launcher3.accessibility.DragViewStateAnnouncer;
+
/**
* Interface defining an object that can receive a drag.
*
@@ -64,6 +66,8 @@
/** Defers removing the DragView from the DragLayer until after the drop animation. */
public boolean deferDragViewCleanupPostAnimation = true;
+ public DragViewStateAnnouncer stateAnnouncer;
+
public DragObject() {
}
diff --git a/src/com/android/launcher3/FastBitmapDrawable.java b/src/com/android/launcher3/FastBitmapDrawable.java
index 28e923e..d7f1d86 100644
--- a/src/com/android/launcher3/FastBitmapDrawable.java
+++ b/src/com/android/launcher3/FastBitmapDrawable.java
@@ -16,6 +16,7 @@
package com.android.launcher3;
+import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.animation.TimeInterpolator;
import android.graphics.Bitmap;
@@ -28,13 +29,40 @@
import android.graphics.PixelFormat;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffColorFilter;
-import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.util.SparseArray;
+import android.view.animation.DecelerateInterpolator;
public class FastBitmapDrawable extends Drawable {
- static final TimeInterpolator CLICK_FEEDBACK_INTERPOLATOR = new TimeInterpolator() {
+ /**
+ * The possible states that a FastBitmapDrawable can be in.
+ */
+ public enum State {
+
+ NORMAL (0f, 0f, 1f, new DecelerateInterpolator()),
+ PRESSED (0f, 100f / 255f, 1f, CLICK_FEEDBACK_INTERPOLATOR),
+ FAST_SCROLL_HIGHLIGHTED (0f, 0f, 1.15f, new DecelerateInterpolator()),
+ FAST_SCROLL_UNHIGHLIGHTED (0f, 0f, 1f, new DecelerateInterpolator()),
+ DISABLED (1f, 0.5f, 1f, new DecelerateInterpolator());
+
+ public final float desaturation;
+ public final float brightness;
+ /**
+ * Used specifically by the view drawing this FastBitmapDrawable.
+ */
+ public final float viewScale;
+ public final TimeInterpolator interpolator;
+
+ State(float desaturation, float brightness, float viewScale, TimeInterpolator interpolator) {
+ this.desaturation = desaturation;
+ this.brightness = brightness;
+ this.viewScale = viewScale;
+ this.interpolator = interpolator;
+ }
+ }
+
+ public static final TimeInterpolator CLICK_FEEDBACK_INTERPOLATOR = new TimeInterpolator() {
@Override
public float getInterpolation(float input) {
@@ -47,42 +75,46 @@
}
}
};
- static final long CLICK_FEEDBACK_DURATION = 2000;
+ public static final int CLICK_FEEDBACK_DURATION = 2000;
+ public static final int FAST_SCROLL_HIGHLIGHT_DURATION = 225;
+ public static final int FAST_SCROLL_UNHIGHLIGHT_DURATION = 150;
+ public static final int FAST_SCROLL_UNHIGHLIGHT_FROM_NORMAL_DURATION = 225;
+ public static final int FAST_SCROLL_INACTIVE_DURATION = 275;
- private static final int PRESSED_BRIGHTNESS = 100;
- private static ColorMatrix sGhostModeMatrix;
- private static final ColorMatrix sTempMatrix = new ColorMatrix();
+ // Since we don't need 256^2 values for combinations of both the brightness and saturation, we
+ // reduce the value space to a smaller value V, which reduces the number of cached
+ // ColorMatrixColorFilters that we need to keep to V^2
+ private static final int REDUCED_FILTER_VALUE_SPACE = 48;
- /**
- * Store the brightness colors filters to optimize animations during icon press. This
- * only works for non-ghost-mode icons.
- */
- private static final SparseArray<ColorFilter> sCachedBrightnessFilter =
- new SparseArray<ColorFilter>();
+ // A cache of ColorFilters for optimizing brightness and saturation animations
+ private static final SparseArray<ColorFilter> sCachedFilter = new SparseArray<>();
- private static final int GHOST_MODE_MIN_COLOR_RANGE = 130;
+ // Temporary matrices used for calculation
+ private static final ColorMatrix sTempBrightnessMatrix = new ColorMatrix();
+ private static final ColorMatrix sTempFilterMatrix = new ColorMatrix();
private final Paint mPaint = new Paint(Paint.FILTER_BITMAP_FLAG);
private final Bitmap mBitmap;
- private int mAlpha;
+ private State mState = State.NORMAL;
+ // The saturation and brightness are values that are mapped to REDUCED_FILTER_VALUE_SPACE and
+ // as a result, can be used to compose the key for the cached ColorMatrixColorFilters
+ private int mDesaturation = 0;
private int mBrightness = 0;
- private boolean mGhostModeEnabled = false;
+ private int mAlpha = 255;
+ private int mPrevUpdateKey = Integer.MAX_VALUE;
- private boolean mPressed = false;
- private ObjectAnimator mPressedAnimator;
+ // Animators for the fast bitmap drawable's properties
+ private AnimatorSet mPropertyAnimator;
public FastBitmapDrawable(Bitmap b) {
- mAlpha = 255;
mBitmap = b;
setBounds(0, 0, b.getWidth(), b.getHeight());
}
@Override
public void draw(Canvas canvas) {
- final Rect r = getBounds();
- // Draw the bitmap into the bounding rect
- canvas.drawBitmap(mBitmap, null, r, mPaint);
+ canvas.drawBitmap(mBitmap, null, getBounds(), mPaint);
}
@Override
@@ -136,96 +168,191 @@
}
/**
- * When enabled, the icon is grayed out and the contrast is increased to give it a 'ghost'
- * appearance.
+ * Animates this drawable to a new state.
+ *
+ * @return whether the state has changed.
*/
- public void setGhostModeEnabled(boolean enabled) {
- if (mGhostModeEnabled != enabled) {
- mGhostModeEnabled = enabled;
+ public boolean animateState(State newState) {
+ State prevState = mState;
+ if (mState != newState) {
+ mState = newState;
+
+ mPropertyAnimator = cancelAnimator(mPropertyAnimator);
+ mPropertyAnimator = new AnimatorSet();
+ mPropertyAnimator.playTogether(
+ ObjectAnimator
+ .ofFloat(this, "desaturation", newState.desaturation),
+ ObjectAnimator
+ .ofFloat(this, "brightness", newState.brightness));
+ mPropertyAnimator.setInterpolator(newState.interpolator);
+ mPropertyAnimator.setDuration(getDurationForStateChange(prevState, newState));
+ mPropertyAnimator.setStartDelay(getStartDelayForStateChange(prevState, newState));
+ mPropertyAnimator.start();
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Immediately sets this drawable to a new state.
+ *
+ * @return whether the state has changed.
+ */
+ public boolean setState(State newState) {
+ if (mState != newState) {
+ mState = newState;
+
+ mPropertyAnimator = cancelAnimator(mPropertyAnimator);
+
+ setDesaturation(newState.desaturation);
+ setBrightness(newState.brightness);
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Returns the current state.
+ */
+ public State getCurrentState() {
+ return mState;
+ }
+
+ /**
+ * Returns the duration for the state change animation.
+ */
+ public static int getDurationForStateChange(State fromState, State toState) {
+ switch (toState) {
+ case NORMAL:
+ switch (fromState) {
+ case PRESSED:
+ return 0;
+ case FAST_SCROLL_HIGHLIGHTED:
+ case FAST_SCROLL_UNHIGHLIGHTED:
+ return FAST_SCROLL_INACTIVE_DURATION;
+ }
+ case PRESSED:
+ return CLICK_FEEDBACK_DURATION;
+ case FAST_SCROLL_HIGHLIGHTED:
+ return FAST_SCROLL_HIGHLIGHT_DURATION;
+ case FAST_SCROLL_UNHIGHLIGHTED:
+ switch (fromState) {
+ case NORMAL:
+ // When animating from normal state, take a little longer
+ return FAST_SCROLL_UNHIGHLIGHT_FROM_NORMAL_DURATION;
+ default:
+ return FAST_SCROLL_UNHIGHLIGHT_DURATION;
+ }
+ }
+ return 0;
+ }
+
+ /**
+ * Returns the start delay when animating between certain fast scroll states.
+ */
+ public static int getStartDelayForStateChange(State fromState, State toState) {
+ switch (toState) {
+ case FAST_SCROLL_UNHIGHLIGHTED:
+ switch (fromState) {
+ case NORMAL:
+ return FAST_SCROLL_UNHIGHLIGHT_DURATION / 4;
+ }
+ }
+ return 0;
+ }
+
+ /**
+ * Sets the saturation of this icon, 0 [full color] -> 1 [desaturated]
+ */
+ public void setDesaturation(float desaturation) {
+ int newDesaturation = (int) Math.floor(desaturation * REDUCED_FILTER_VALUE_SPACE);
+ if (mDesaturation != newDesaturation) {
+ mDesaturation = newDesaturation;
updateFilter();
}
}
- public void setPressed(boolean pressed) {
- if (mPressed != pressed) {
- mPressed = pressed;
- if (mPressed) {
- mPressedAnimator = ObjectAnimator
- .ofInt(this, "brightness", PRESSED_BRIGHTNESS)
- .setDuration(CLICK_FEEDBACK_DURATION);
- mPressedAnimator.setInterpolator(CLICK_FEEDBACK_INTERPOLATOR);
- mPressedAnimator.start();
- } else if (mPressedAnimator != null) {
- mPressedAnimator.cancel();
- setBrightness(0);
- }
- }
- invalidateSelf();
+ public float getDesaturation() {
+ return (float) mDesaturation / REDUCED_FILTER_VALUE_SPACE;
}
- public boolean isGhostModeEnabled() {
- return mGhostModeEnabled;
- }
-
- public int getBrightness() {
- return mBrightness;
- }
-
- public void setBrightness(int brightness) {
- if (mBrightness != brightness) {
- mBrightness = brightness;
+ /**
+ * Sets the brightness of this icon, 0 [no add. brightness] -> 1 [2bright2furious]
+ */
+ public void setBrightness(float brightness) {
+ int newBrightness = (int) Math.floor(brightness * REDUCED_FILTER_VALUE_SPACE);
+ if (mBrightness != newBrightness) {
+ mBrightness = newBrightness;
updateFilter();
- invalidateSelf();
}
}
+ public float getBrightness() {
+ return (float) mBrightness / REDUCED_FILTER_VALUE_SPACE;
+ }
+
+ /**
+ * Updates the paint to reflect the current brightness and saturation.
+ */
private void updateFilter() {
- if (mGhostModeEnabled) {
- if (sGhostModeMatrix == null) {
- sGhostModeMatrix = new ColorMatrix();
- sGhostModeMatrix.setSaturation(0);
+ boolean usePorterDuffFilter = false;
+ int key = -1;
+ if (mDesaturation > 0) {
+ key = (mDesaturation << 16) | mBrightness;
+ } else if (mBrightness > 0) {
+ // Compose a key with a fully saturated icon if we are just animating brightness
+ key = (1 << 16) | mBrightness;
- // For ghost mode, set the color range to [GHOST_MODE_MIN_COLOR_RANGE, 255]
- float range = (255 - GHOST_MODE_MIN_COLOR_RANGE) / 255.0f;
- sTempMatrix.set(new float[] {
- range, 0, 0, 0, GHOST_MODE_MIN_COLOR_RANGE,
- 0, range, 0, 0, GHOST_MODE_MIN_COLOR_RANGE,
- 0, 0, range, 0, GHOST_MODE_MIN_COLOR_RANGE,
- 0, 0, 0, 1, 0 });
- sGhostModeMatrix.preConcat(sTempMatrix);
- }
+ // We found that in L, ColorFilters cause drawing artifacts with shadows baked into
+ // icons, so just use a PorterDuff filter when we aren't animating saturation
+ usePorterDuffFilter = true;
+ }
- if (mBrightness == 0) {
- mPaint.setColorFilter(new ColorMatrixColorFilter(sGhostModeMatrix));
- } else {
- setBrightnessMatrix(sTempMatrix, mBrightness);
- sTempMatrix.postConcat(sGhostModeMatrix);
- mPaint.setColorFilter(new ColorMatrixColorFilter(sTempMatrix));
- }
- } else if (mBrightness != 0) {
- ColorFilter filter = sCachedBrightnessFilter.get(mBrightness);
+ // Debounce multiple updates on the same frame
+ if (key == mPrevUpdateKey) {
+ return;
+ }
+ mPrevUpdateKey = key;
+
+ if (key != -1) {
+ ColorFilter filter = sCachedFilter.get(key);
if (filter == null) {
- filter = new PorterDuffColorFilter(Color.argb(mBrightness, 255, 255, 255),
- PorterDuff.Mode.SRC_ATOP);
- sCachedBrightnessFilter.put(mBrightness, filter);
+ float brightnessF = getBrightness();
+ int brightnessI = (int) (255 * brightnessF);
+ if (usePorterDuffFilter) {
+ filter = new PorterDuffColorFilter(Color.argb(brightnessI, 255, 255, 255),
+ PorterDuff.Mode.SRC_ATOP);
+ } else {
+ float saturationF = 1f - getDesaturation();
+ sTempFilterMatrix.setSaturation(saturationF);
+ if (mBrightness > 0) {
+ // Brightness: C-new = C-old*(1-amount) + amount
+ float scale = 1f - brightnessF;
+ float[] mat = sTempBrightnessMatrix.getArray();
+ mat[0] = scale;
+ mat[6] = scale;
+ mat[12] = scale;
+ mat[4] = brightnessI;
+ mat[9] = brightnessI;
+ mat[14] = brightnessI;
+ sTempFilterMatrix.preConcat(sTempBrightnessMatrix);
+ }
+ filter = new ColorMatrixColorFilter(sTempFilterMatrix);
+ }
+ sCachedFilter.append(key, filter);
}
mPaint.setColorFilter(filter);
} else {
mPaint.setColorFilter(null);
}
+ invalidateSelf();
}
- private static void setBrightnessMatrix(ColorMatrix matrix, int brightness) {
- // Brightness: C-new = C-old*(1-amount) + amount
- float scale = 1 - brightness / 255.0f;
- matrix.setScale(scale, scale, scale, 1);
- float[] array = matrix.getArray();
-
- // Add the amount to RGB components of the matrix, as per the above formula.
- // Fifth elements in the array correspond to the constant being added to
- // red, blue, green, and alpha channel respectively.
- array[4] = brightness;
- array[9] = brightness;
- array[14] = brightness;
+ private AnimatorSet cancelAnimator(AnimatorSet animator) {
+ if (animator != null) {
+ animator.removeAllListeners();
+ animator.cancel();
+ }
+ return null;
}
}
diff --git a/src/com/android/launcher3/FocusHelper.java b/src/com/android/launcher3/FocusHelper.java
index 57aec32..d59c644 100644
--- a/src/com/android/launcher3/FocusHelper.java
+++ b/src/com/android/launcher3/FocusHelper.java
@@ -45,6 +45,23 @@
}
}
+/**
+ * A keyboard listener we set on full screen pages (e.g. custom content).
+ */
+class FullscreenKeyEventListener implements View.OnKeyListener {
+ @Override
+ public boolean onKey(View v, int keyCode, KeyEvent event) {
+ if (keyCode == KeyEvent.KEYCODE_DPAD_LEFT || keyCode == KeyEvent.KEYCODE_DPAD_RIGHT
+ || keyCode == KeyEvent.KEYCODE_PAGE_DOWN || keyCode == KeyEvent.KEYCODE_PAGE_UP) {
+ // Handle the key event just like a workspace icon would in these cases. In this case,
+ // it will basically act as if there is a single icon in the top left (so you could
+ // think of the fullscreen page as a focusable fullscreen widget).
+ return FocusHelper.handleIconKeyEvent(v, keyCode, event);
+ }
+ return false;
+ }
+}
+
public class FocusHelper {
private static final String TAG = "FocusHelper";
@@ -72,7 +89,6 @@
KeyEvent.keyCodeToString(keyCode)));
}
-
if (!(v.getParent() instanceof ShortcutAndWidgetContainer)) {
if (LauncherAppState.isDogfoodBuild()) {
throw new IllegalStateException("Parent of the focused item is not supported.");
@@ -84,8 +100,6 @@
// Initialize variables.
final ShortcutAndWidgetContainer itemContainer = (ShortcutAndWidgetContainer) v.getParent();
final CellLayout cellLayout = (CellLayout) itemContainer.getParent();
- final int countX = cellLayout.getCountX();
- final int countY = cellLayout.getCountY();
final int iconIndex = itemContainer.indexOfChild(v);
final FolderPagedView pagedView = (FolderPagedView) cellLayout.getParent();
@@ -96,8 +110,8 @@
int[][] matrix = FocusLogic.createSparseMatrix(cellLayout);
// Process focus.
- int newIconIndex = FocusLogic.handleKeyEvent(keyCode, countX,
- countY, matrix, iconIndex, pageIndex, pageCount, isLayoutRtl);
+ int newIconIndex = FocusLogic.handleKeyEvent(keyCode, matrix, iconIndex, pageIndex,
+ pageCount, isLayoutRtl);
if (newIconIndex == FocusLogic.NOOP) {
handleNoopKey(keyCode, v);
return consume;
@@ -114,7 +128,8 @@
pagedView.snapToPage(pageIndex - 1);
child = newParent.getChildAt(
((newIconIndex == FocusLogic.PREVIOUS_PAGE_LEFT_COLUMN)
- ^ newParent.invertLayoutHorizontally()) ? 0 : countX - 1, row);
+ ^ newParent.invertLayoutHorizontally()) ? 0 : matrix.length - 1,
+ row);
}
break;
case FocusLogic.PREVIOUS_PAGE_FIRST_ITEM:
@@ -128,7 +143,7 @@
newParent = getCellLayoutChildrenForIndex(pagedView, pageIndex - 1);
if (newParent != null) {
pagedView.snapToPage(pageIndex - 1);
- child = newParent.getChildAt(countX - 1, countY - 1);
+ child = newParent.getChildAt(matrix.length - 1, matrix[0].length - 1);
}
break;
case FocusLogic.NEXT_PAGE_FIRST_ITEM:
@@ -143,7 +158,8 @@
newParent = getCellLayoutChildrenForIndex(pagedView, pageIndex + 1);
if (newParent != null) {
pagedView.snapToPage(pageIndex + 1);
- child = FocusLogic.getAdjacentChildInNextPage(newParent, v, newIconIndex);
+ child = FocusLogic.getAdjacentChildInNextFolderPage(
+ newParent, v, newIconIndex);
}
break;
case FocusLogic.CURRENT_PAGE_FIRST_ITEM:
@@ -174,7 +190,7 @@
}
/**
- * Handles key events in the workspace hot seat (bottom of the screen).
+ * Handles key events in the workspace hotseat (bottom of the screen).
* <p>Currently we don't special case for the phone UI in different orientations, even though
* the hotseat is on the side in landscape mode. This is to ensure that accessibility
* consistency is maintained across rotations.
@@ -185,7 +201,8 @@
return consume;
}
- DeviceProfile profile = ((Launcher) v.getContext()).getDeviceProfile();
+ final Launcher launcher = (Launcher) v.getContext();
+ final DeviceProfile profile = launcher.getDeviceProfile();
if (DEBUG) {
Log.v(TAG, String.format(
@@ -194,15 +211,13 @@
}
// Initialize the variables.
+ final Workspace workspace = (Workspace) v.getRootView().findViewById(R.id.workspace);
final ShortcutAndWidgetContainer hotseatParent = (ShortcutAndWidgetContainer) v.getParent();
final CellLayout hotseatLayout = (CellLayout) hotseatParent.getParent();
- Hotseat hotseat = (Hotseat) hotseatLayout.getParent();
- Workspace workspace = (Workspace) v.getRootView().findViewById(R.id.workspace);
+ final ItemInfo itemInfo = (ItemInfo) v.getTag();
int pageIndex = workspace.getNextPage();
int pageCount = workspace.getChildCount();
- int countX = -1;
- int countY = -1;
int iconIndex = hotseatParent.indexOfChild(v);
int iconRank = ((CellLayout.LayoutParams) hotseatLayout.getShortcutsAndWidgets()
.getChildAt(iconIndex).getLayoutParams()).cellX;
@@ -221,51 +236,91 @@
if (keyCode == KeyEvent.KEYCODE_DPAD_UP &&
!profile.isVerticalBarLayout()) {
- matrix = FocusLogic.createSparseMatrix(iconLayout, hotseatLayout,
- true /* hotseat horizontal */, profile.inv.hotseatAllAppsRank,
- iconRank == profile.inv.hotseatAllAppsRank /* include all apps icon */);
+ matrix = FocusLogic.createSparseMatrixWithHotseat(iconLayout, hotseatLayout,
+ true /* hotseat horizontal */, profile.inv.hotseatAllAppsRank);
iconIndex += iconParent.getChildCount();
- countX = iconLayout.getCountX();
- countY = iconLayout.getCountY() + hotseatLayout.getCountY();
parent = iconParent;
} else if (keyCode == KeyEvent.KEYCODE_DPAD_LEFT &&
profile.isVerticalBarLayout()) {
- matrix = FocusLogic.createSparseMatrix(iconLayout, hotseatLayout,
- false /* hotseat horizontal */, profile.inv.hotseatAllAppsRank,
- iconRank == profile.inv.hotseatAllAppsRank /* include all apps icon */);
+ matrix = FocusLogic.createSparseMatrixWithHotseat(iconLayout, hotseatLayout,
+ false /* hotseat horizontal */, profile.inv.hotseatAllAppsRank);
iconIndex += iconParent.getChildCount();
- countX = iconLayout.getCountX() + hotseatLayout.getCountX();
- countY = iconLayout.getCountY();
parent = iconParent;
} else if (keyCode == KeyEvent.KEYCODE_DPAD_RIGHT &&
profile.isVerticalBarLayout()) {
keyCode = KeyEvent.KEYCODE_PAGE_DOWN;
- }else {
+ } else if (isUninstallKeyChord(e)) {
+ matrix = FocusLogic.createSparseMatrix(iconLayout);
+ if (UninstallDropTarget.supportsDrop(launcher, itemInfo)) {
+ UninstallDropTarget.startUninstallActivity(launcher, itemInfo);
+ }
+ } else if (isDeleteKeyChord(e)) {
+ matrix = FocusLogic.createSparseMatrix(iconLayout);
+ launcher.removeItem(v, itemInfo, true /* deleteFromDb */);
+ } else {
// For other KEYCODE_DPAD_LEFT and KEYCODE_DPAD_RIGHT navigation, do not use the
// matrix extended with hotseat.
matrix = FocusLogic.createSparseMatrix(hotseatLayout);
- countX = hotseatLayout.getCountX();
- countY = hotseatLayout.getCountY();
parent = hotseatParent;
}
// Process the focus.
- int newIconIndex = FocusLogic.handleKeyEvent(keyCode, countX,
- countY, matrix, iconIndex, pageIndex, pageCount, Utilities.isRtl(v.getResources()));
+ int newIconIndex = FocusLogic.handleKeyEvent(keyCode, matrix, iconIndex, pageIndex,
+ pageCount, Utilities.isRtl(v.getResources()));
View newIcon = null;
- if (newIconIndex == FocusLogic.NEXT_PAGE_FIRST_ITEM) {
- parent = getCellLayoutChildrenForIndex(workspace, pageIndex + 1);
- newIcon = parent.getChildAt(0);
- // TODO(hyunyoungs): handle cases where the child is not an icon but
- // a folder or a widget.
- workspace.snapToPage(pageIndex + 1);
+ switch (newIconIndex) {
+ case FocusLogic.NEXT_PAGE_FIRST_ITEM:
+ parent = getCellLayoutChildrenForIndex(workspace, pageIndex + 1);
+ newIcon = parent.getChildAt(0);
+ // TODO(hyunyoungs): handle cases where the child is not an icon but
+ // a folder or a widget.
+ workspace.snapToPage(pageIndex + 1);
+ break;
+ case FocusLogic.PREVIOUS_PAGE_FIRST_ITEM:
+ parent = getCellLayoutChildrenForIndex(workspace, pageIndex - 1);
+ newIcon = parent.getChildAt(0);
+ // TODO(hyunyoungs): handle cases where the child is not an icon but
+ // a folder or a widget.
+ workspace.snapToPage(pageIndex - 1);
+ break;
+ case FocusLogic.PREVIOUS_PAGE_LAST_ITEM:
+ parent = getCellLayoutChildrenForIndex(workspace, pageIndex - 1);
+ newIcon = parent.getChildAt(parent.getChildCount() - 1);
+ // TODO(hyunyoungs): handle cases where the child is not an icon but
+ // a folder or a widget.
+ workspace.snapToPage(pageIndex - 1);
+ break;
+ case FocusLogic.PREVIOUS_PAGE_LEFT_COLUMN:
+ case FocusLogic.PREVIOUS_PAGE_RIGHT_COLUMN:
+ // Go to the previous page but keep the focus on the same hotseat icon.
+ workspace.snapToPage(pageIndex - 1);
+ // If the page we are going to is fullscreen, have it take the focus from hotseat.
+ CellLayout prevPage = (CellLayout) workspace.getPageAt(pageIndex - 1);
+ boolean isPrevPageFullscreen = ((CellLayout.LayoutParams) prevPage
+ .getShortcutsAndWidgets().getChildAt(0).getLayoutParams()).isFullscreen;
+ if (isPrevPageFullscreen) {
+ workspace.getPageAt(pageIndex - 1).requestFocus();
+ }
+ break;
+ case FocusLogic.NEXT_PAGE_LEFT_COLUMN:
+ case FocusLogic.NEXT_PAGE_RIGHT_COLUMN:
+ // Go to the next page but keep the focus on the same hotseat icon.
+ workspace.snapToPage(pageIndex + 1);
+ // If the page we are going to is fullscreen, have it take the focus from hotseat.
+ CellLayout nextPage = (CellLayout) workspace.getPageAt(pageIndex + 1);
+ boolean isNextPageFullscreen = ((CellLayout.LayoutParams) nextPage
+ .getShortcutsAndWidgets().getChildAt(0).getLayoutParams()).isFullscreen;
+ if (isNextPageFullscreen) {
+ workspace.getPageAt(pageIndex + 1).requestFocus();
+ }
+ break;
}
if (parent == iconParent && newIconIndex >= iconParent.getChildCount()) {
newIconIndex -= iconParent.getChildCount();
}
if (parent != null) {
- if (newIcon == null && newIconIndex >=0) {
+ if (newIcon == null && newIconIndex >= 0) {
newIcon = parent.getChildAt(newIconIndex);
}
if (newIcon != null) {
@@ -301,11 +356,10 @@
final ViewGroup tabs = (ViewGroup) dragLayer.findViewById(R.id.search_drop_target_bar);
final Hotseat hotseat = (Hotseat) dragLayer.findViewById(R.id.hotseat);
+ final ItemInfo itemInfo = (ItemInfo) v.getTag();
final int iconIndex = parent.indexOfChild(v);
final int pageIndex = workspace.indexOfChild(iconLayout);
final int pageCount = workspace.getChildCount();
- int countX = iconLayout.getCountX();
- int countY = iconLayout.getCountY();
CellLayout hotseatLayout = (CellLayout) hotseat.getChildAt(0);
ShortcutAndWidgetContainer hotseatParent = hotseatLayout.getShortcutsAndWidgets();
@@ -315,27 +369,30 @@
// to take a user to the hotseat. For other dpad navigation, do not use the matrix extended
// with the hotseat.
if (keyCode == KeyEvent.KEYCODE_DPAD_DOWN && !profile.isVerticalBarLayout()) {
- matrix = FocusLogic.createSparseMatrix(iconLayout, hotseatLayout, true /* horizontal */,
- profile.inv.hotseatAllAppsRank,
- !hotseat.hasIcons() /* ignore all apps icon, unless there are no other icons */);
- countY = countY + 1;
+ matrix = FocusLogic.createSparseMatrixWithHotseat(iconLayout, hotseatLayout,
+ true /* horizontal */, profile.inv.hotseatAllAppsRank);
} else if (keyCode == KeyEvent.KEYCODE_DPAD_RIGHT &&
profile.isVerticalBarLayout()) {
- matrix = FocusLogic.createSparseMatrix(iconLayout, hotseatLayout, false /* horizontal */,
- profile.inv.hotseatAllAppsRank,
- !hotseat.hasIcons() /* ignore all apps icon, unless there are no other icons */);
- countX = countX + 1;
- } else if (keyCode == KeyEvent.KEYCODE_DEL || keyCode == KeyEvent.KEYCODE_FORWARD_DEL) {
- workspace.removeWorkspaceItem(v);
- return consume;
+ matrix = FocusLogic.createSparseMatrixWithHotseat(iconLayout, hotseatLayout,
+ false /* horizontal */, profile.inv.hotseatAllAppsRank);
+ } else if (isUninstallKeyChord(e)) {
+ matrix = FocusLogic.createSparseMatrix(iconLayout);
+ if (UninstallDropTarget.supportsDrop(launcher, itemInfo)) {
+ UninstallDropTarget.startUninstallActivity(launcher, itemInfo);
+ }
+ } else if (isDeleteKeyChord(e)) {
+ matrix = FocusLogic.createSparseMatrix(iconLayout);
+ launcher.removeItem(v, itemInfo, true /* deleteFromDb */);
} else {
matrix = FocusLogic.createSparseMatrix(iconLayout);
}
// Process the focus.
- int newIconIndex = FocusLogic.handleKeyEvent(keyCode, countX,
- countY, matrix, iconIndex, pageIndex, pageCount, Utilities.isRtl(v.getResources()));
+ int newIconIndex = FocusLogic.handleKeyEvent(keyCode, matrix, iconIndex, pageIndex,
+ pageCount, Utilities.isRtl(v.getResources()));
+ boolean isRtl = Utilities.isRtl(v.getResources());
View newIcon = null;
+ CellLayout workspaceLayout = (CellLayout) workspace.getChildAt(pageIndex);
switch (newIconIndex) {
case FocusLogic.NOOP:
if (keyCode == KeyEvent.KEYCODE_DPAD_UP) {
@@ -350,32 +407,37 @@
}
int row = ((CellLayout.LayoutParams) v.getLayoutParams()).cellY;
parent = getCellLayoutChildrenForIndex(workspace, newPageIndex);
- workspace.snapToPage(newPageIndex);
if (parent != null) {
- workspace.snapToPage(newPageIndex);
iconLayout = (CellLayout) parent.getParent();
- matrix = FocusLogic.createSparseMatrix(iconLayout,
- iconLayout.getCountX(), row);
- newIconIndex = FocusLogic.handleKeyEvent(keyCode, countX + 1, countY,
- matrix, FocusLogic.PIVOT, newPageIndex, pageCount,
- Utilities.isRtl(v.getResources()));
- newIcon = parent.getChildAt(newIconIndex);
+ matrix = FocusLogic.createSparseMatrixWithPivotColumn(iconLayout,
+ iconLayout.getCountX(), row);
+ newIconIndex = FocusLogic.handleKeyEvent(keyCode, matrix, FocusLogic.PIVOT,
+ newPageIndex, pageCount, Utilities.isRtl(v.getResources()));
+ if (newIconIndex == FocusLogic.NEXT_PAGE_FIRST_ITEM) {
+ newIcon = handleNextPageFirstItem(workspace, hotseatLayout, pageIndex,
+ isRtl);
+ } else if (newIconIndex == FocusLogic.PREVIOUS_PAGE_LAST_ITEM) {
+ newIcon = handlePreviousPageLastItem(workspace, hotseatLayout, pageIndex,
+ isRtl);
+ } else {
+ newIcon = parent.getChildAt(newIconIndex);
+ }
}
break;
case FocusLogic.PREVIOUS_PAGE_FIRST_ITEM:
- parent = getCellLayoutChildrenForIndex(workspace, pageIndex - 1);
- newIcon = parent.getChildAt(0);
- workspace.snapToPage(pageIndex - 1);
+ workspaceLayout = (CellLayout) workspace.getChildAt(pageIndex - 1);
+ newIcon = getFirstFocusableIconInReadingOrder(workspaceLayout, isRtl);
+ if (newIcon == null) {
+ // Check the hotseat if no focusable item was found on the workspace.
+ newIcon = getFirstFocusableIconInReadingOrder(hotseatLayout, isRtl);
+ workspace.snapToPage(pageIndex - 1);
+ }
break;
case FocusLogic.PREVIOUS_PAGE_LAST_ITEM:
- parent = getCellLayoutChildrenForIndex(workspace, pageIndex - 1);
- newIcon = parent.getChildAt(parent.getChildCount() - 1);
- workspace.snapToPage(pageIndex - 1);
+ newIcon = handlePreviousPageLastItem(workspace, hotseatLayout, pageIndex, isRtl);
break;
case FocusLogic.NEXT_PAGE_FIRST_ITEM:
- parent = getCellLayoutChildrenForIndex(workspace, pageIndex + 1);
- newIcon = parent.getChildAt(0);
- workspace.snapToPage(pageIndex + 1);
+ newIcon = handleNextPageFirstItem(workspace, hotseatLayout, pageIndex, isRtl);
break;
case FocusLogic.NEXT_PAGE_LEFT_COLUMN:
case FocusLogic.PREVIOUS_PAGE_LEFT_COLUMN:
@@ -383,24 +445,37 @@
if (newIconIndex == FocusLogic.PREVIOUS_PAGE_LEFT_COLUMN) {
newPageIndex = pageIndex - 1;
}
- workspace.snapToPage(newPageIndex);
row = ((CellLayout.LayoutParams) v.getLayoutParams()).cellY;
parent = getCellLayoutChildrenForIndex(workspace, newPageIndex);
if (parent != null) {
- workspace.snapToPage(newPageIndex);
iconLayout = (CellLayout) parent.getParent();
- matrix = FocusLogic.createSparseMatrix(iconLayout, -1, row);
- newIconIndex = FocusLogic.handleKeyEvent(keyCode, countX + 1, countY,
- matrix, FocusLogic.PIVOT, newPageIndex, pageCount,
- Utilities.isRtl(v.getResources()));
- newIcon = parent.getChildAt(newIconIndex);
+ matrix = FocusLogic.createSparseMatrixWithPivotColumn(iconLayout, -1, row);
+ newIconIndex = FocusLogic.handleKeyEvent(keyCode, matrix, FocusLogic.PIVOT,
+ newPageIndex, pageCount, Utilities.isRtl(v.getResources()));
+ if (newIconIndex == FocusLogic.NEXT_PAGE_FIRST_ITEM) {
+ newIcon = handleNextPageFirstItem(workspace, hotseatLayout, pageIndex,
+ isRtl);
+ } else if (newIconIndex == FocusLogic.PREVIOUS_PAGE_LAST_ITEM) {
+ newIcon = handlePreviousPageLastItem(workspace, hotseatLayout, pageIndex,
+ isRtl);
+ } else {
+ newIcon = parent.getChildAt(newIconIndex);
+ }
}
break;
case FocusLogic.CURRENT_PAGE_FIRST_ITEM:
- newIcon = parent.getChildAt(0);
+ newIcon = getFirstFocusableIconInReadingOrder(workspaceLayout, isRtl);
+ if (newIcon == null) {
+ // Check the hotseat if no focusable item was found on the workspace.
+ newIcon = getFirstFocusableIconInReadingOrder(hotseatLayout, isRtl);
+ }
break;
case FocusLogic.CURRENT_PAGE_LAST_ITEM:
- newIcon = parent.getChildAt(parent.getChildCount() - 1);
+ newIcon = getFirstFocusableIconInReverseReadingOrder(workspaceLayout, isRtl);
+ if (newIcon == null) {
+ // Check the hotseat if no focusable item was found on the workspace.
+ newIcon = getFirstFocusableIconInReverseReadingOrder(hotseatLayout, isRtl);
+ }
break;
default:
// current page, some item.
@@ -457,4 +532,81 @@
break;
}
}
+
+ /**
+ * Returns whether the key event represents a valid uninstall key chord.
+ */
+ private static boolean isUninstallKeyChord(KeyEvent event) {
+ int keyCode = event.getKeyCode();
+ return (keyCode == KeyEvent.KEYCODE_DEL || keyCode == KeyEvent.KEYCODE_FORWARD_DEL) &&
+ event.hasModifiers(KeyEvent.META_CTRL_ON | KeyEvent.META_SHIFT_ON);
+ }
+
+ /**
+ * Returns whether the key event represents a valid delete key chord.
+ */
+ private static boolean isDeleteKeyChord(KeyEvent event) {
+ int keyCode = event.getKeyCode();
+ return (keyCode == KeyEvent.KEYCODE_DEL || keyCode == KeyEvent.KEYCODE_FORWARD_DEL) &&
+ event.hasModifiers(KeyEvent.META_CTRL_ON);
+ }
+
+ private static View handlePreviousPageLastItem(Workspace workspace, CellLayout hotseatLayout,
+ int pageIndex, boolean isRtl) {
+ if (pageIndex - 1 < 0) {
+ return null;
+ }
+ CellLayout workspaceLayout = (CellLayout) workspace.getChildAt(pageIndex - 1);
+ View newIcon = getFirstFocusableIconInReverseReadingOrder(workspaceLayout, isRtl);
+ if (newIcon == null) {
+ // Check the hotseat if no focusable item was found on the workspace.
+ newIcon = getFirstFocusableIconInReverseReadingOrder(hotseatLayout,isRtl);
+ workspace.snapToPage(pageIndex - 1);
+ }
+ return newIcon;
+ }
+
+ private static View handleNextPageFirstItem(Workspace workspace, CellLayout hotseatLayout,
+ int pageIndex, boolean isRtl) {
+ if (pageIndex + 1 >= workspace.getPageCount()) {
+ return null;
+ }
+ CellLayout workspaceLayout = (CellLayout) workspace.getChildAt(pageIndex + 1);
+ View newIcon = getFirstFocusableIconInReadingOrder(workspaceLayout, isRtl);
+ if (newIcon == null) {
+ // Check the hotseat if no focusable item was found on the workspace.
+ newIcon = getFirstFocusableIconInReadingOrder(hotseatLayout, isRtl);
+ workspace.snapToPage(pageIndex + 1);
+ }
+ return newIcon;
+ }
+
+ private static View getFirstFocusableIconInReadingOrder(CellLayout cellLayout, boolean isRtl) {
+ View icon;
+ int countX = cellLayout.getCountX();
+ for (int y = 0; y < cellLayout.getCountY(); y++) {
+ int increment = isRtl ? -1 : 1;
+ for (int x = isRtl ? countX - 1 : 0; 0 <= x && x < countX; x += increment) {
+ if ((icon = cellLayout.getChildAt(x, y)) != null && icon.isFocusable()) {
+ return icon;
+ }
+ }
+ }
+ return null;
+ }
+
+ private static View getFirstFocusableIconInReverseReadingOrder(CellLayout cellLayout,
+ boolean isRtl) {
+ View icon;
+ int countX = cellLayout.getCountX();
+ for (int y = cellLayout.getCountY() - 1; y >= 0; y--) {
+ int increment = isRtl ? 1 : -1;
+ for (int x = isRtl ? 0 : countX - 1; 0 <= x && x < countX; x += increment) {
+ if ((icon = cellLayout.getChildAt(x, y)) != null && icon.isFocusable()) {
+ return icon;
+ }
+ }
+ }
+ return null;
+ }
}
diff --git a/src/com/android/launcher3/FocusIndicatorView.java b/src/com/android/launcher3/FocusIndicatorView.java
index ecf93e4..58b38eb 100644
--- a/src/com/android/launcher3/FocusIndicatorView.java
+++ b/src/com/android/launcher3/FocusIndicatorView.java
@@ -30,6 +30,7 @@
// It can be any number >0. The view is resized using scaleX and scaleY.
static final int DEFAULT_LAYOUT_SIZE = 100;
+
private static final float MIN_VISIBLE_ALPHA = 0.2f;
private static final long ANIM_DURATION = 150;
@@ -41,6 +42,7 @@
private View mLastFocusedView;
private boolean mInitiated;
+ private final OnFocusChangeListener mHideIndicatorOnFocusListener;
private Pair<View, Boolean> mPendingCall;
@@ -52,6 +54,16 @@
super(context, attrs);
setAlpha(0);
setBackgroundColor(getResources().getColor(R.color.focused_background));
+
+ mHideIndicatorOnFocusListener = new OnFocusChangeListener() {
+ @Override
+ public void onFocusChange(View v, boolean hasFocus) {
+ if (hasFocus) {
+ endCurrentAnimation();
+ setAlpha(0);
+ }
+ }
+ };
}
@Override
@@ -66,6 +78,13 @@
}
}
+ /**
+ * Sets the alpha of this FocusIndicatorView to 0 when a view with this listener receives focus.
+ */
+ public View.OnFocusChangeListener getHideIndicatorOnFocusListener() {
+ return mHideIndicatorOnFocusListener;
+ }
+
@Override
public void onFocusChange(View v, boolean hasFocus) {
mPendingCall = null;
diff --git a/src/com/android/launcher3/Folder.java b/src/com/android/launcher3/Folder.java
index c1aa356..9cc94ae 100644
--- a/src/com/android/launcher3/Folder.java
+++ b/src/com/android/launcher3/Folder.java
@@ -318,9 +318,10 @@
sendCustomAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED,
String.format(getContext().getString(R.string.folder_renamed), newTitle));
}
- // In order to clear the focus from the text field, we set the focus on ourself. This
- // ensures that every time the field is clicked, focus is gained, giving reliable behavior.
- requestFocus();
+
+ // This ensures that focus is gained every time the field is clicked, which selects all
+ // the text and brings up the soft keyboard if necessary.
+ mFolderName.clearFocus();
Selection.setSelection((Spannable) mFolderName.getText(), 0, 0);
mIsEditingName = false;
@@ -414,7 +415,7 @@
/**
* Creates a new UserFolder, inflated from R.layout.user_folder.
*
- * @param context The application's context.
+ * @param launcher The main activity.
*
* @return A new UserFolder.
*/
@@ -451,6 +452,11 @@
mContent.snapToPageImmediately(0);
}
+ // This is set to true in close(), but isn't reset to false until onDropCompleted(). This
+ // leads to an consistent state if you drag out of the folder and drag back in without
+ // dropping. One resulting issue is that replaceFolderWithFinalItem() can be called twice.
+ mDeleteFolderOnDropCompleted = false;
+
Animator openFolderAnim = null;
final Runnable onCompleteRunnable;
if (!Utilities.ATLEAST_LOLLIPOP) {
@@ -541,10 +547,7 @@
public void onAnimationEnd(Animator animation) {
mState = STATE_OPEN;
- if (onCompleteRunnable != null) {
- onCompleteRunnable.run();
- }
-
+ onCompleteRunnable.run();
mContent.setFocusOnFirstChild();
}
});
@@ -639,9 +642,8 @@
oa.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
- onCloseComplete();
setLayerType(LAYER_TYPE_NONE, null);
- mState = STATE_SMALL;
+ close(true);
}
@Override
public void onAnimationStart(Animator animation) {
@@ -655,6 +657,34 @@
oa.start();
}
+ public void close(boolean wasAnimated) {
+ // TODO: Clear all active animations.
+ DragLayer parent = (DragLayer) getParent();
+ if (parent != null) {
+ parent.removeView(this);
+ }
+ mDragController.removeDropTarget(this);
+ clearFocus();
+ if (wasAnimated) {
+ mFolderIcon.requestFocus();
+ }
+
+ if (mRearrangeOnClose) {
+ rearrangeChildren();
+ mRearrangeOnClose = false;
+ }
+ if (getItemCount() <= 1) {
+ if (!mDragInProgress && !mSuppressFolderDeletion) {
+ replaceFolderWithFinalItem();
+ } else if (mDragInProgress) {
+ mDeleteFolderOnDropCompleted = true;
+ }
+ }
+ mSuppressFolderDeletion = false;
+ clearDragInfo();
+ mState = STATE_SMALL;
+ }
+
public boolean acceptDrop(DragObject d) {
final ItemInfo item = (ItemInfo) d.dragInfo;
final int itemType = item.itemType;
@@ -706,6 +736,11 @@
mReorderAlarm.setOnAlarmListener(mReorderAlarmListener);
mReorderAlarm.setAlarm(REORDER_DELAY);
mPrevTargetRank = mTargetRank;
+
+ if (d.stateAnnouncer != null) {
+ d.stateAnnouncer.announce(getContext().getString(R.string.move_to_position,
+ mTargetRank + 1));
+ }
}
float x = r[0];
@@ -867,7 +902,6 @@
// Show the animation, next time something is added to the folder.
mInfo.setOption(FolderInfo.FLAG_MULTI_PAGE_ANIMATION, false, mLauncher);
}
-
}
@Override
@@ -1082,63 +1116,42 @@
return mContent.getItemCount();
}
- @Thunk void onCloseComplete() {
- DragLayer parent = (DragLayer) getParent();
- if (parent != null) {
- parent.removeView(this);
- }
- mDragController.removeDropTarget((DropTarget) this);
- clearFocus();
- mFolderIcon.requestFocus();
-
- if (mRearrangeOnClose) {
- rearrangeChildren();
- mRearrangeOnClose = false;
- }
- if (getItemCount() <= 1) {
- if (!mDragInProgress && !mSuppressFolderDeletion) {
- replaceFolderWithFinalItem();
- } else if (mDragInProgress) {
- mDeleteFolderOnDropCompleted = true;
- }
- }
- mSuppressFolderDeletion = false;
- clearDragInfo();
- }
-
@Thunk void replaceFolderWithFinalItem() {
// Add the last remaining child to the workspace in place of the folder
Runnable onCompleteRunnable = new Runnable() {
@Override
public void run() {
- CellLayout cellLayout = mLauncher.getCellLayout(mInfo.container, mInfo.screenId);
+ int itemCount = mInfo.contents.size();
+ if (itemCount <= 1) {
+ View newIcon = null;
- View child = null;
- // Move the item from the folder to the workspace, in the position of the folder
- if (getItemCount() == 1) {
- ShortcutInfo finalItem = mInfo.contents.get(0);
- child = mLauncher.createShortcut(cellLayout, finalItem);
- LauncherModel.addOrMoveItemInDatabase(mLauncher, finalItem, mInfo.container,
- mInfo.screenId, mInfo.cellX, mInfo.cellY);
- }
- if (getItemCount() <= 1) {
- // Remove the folder
- LauncherModel.deleteItemFromDatabase(mLauncher, mInfo);
- if (cellLayout != null) {
- // b/12446428 -- sometimes the cell layout has already gone away?
- cellLayout.removeView(mFolderIcon);
+ if (itemCount == 1) {
+ // Move the item from the folder to the workspace, in the position of the
+ // folder
+ CellLayout cellLayout = mLauncher.getCellLayout(mInfo.container,
+ mInfo.screenId);
+ ShortcutInfo finalItem = mInfo.contents.remove(0);
+ newIcon = mLauncher.createShortcut(cellLayout, finalItem);
+ LauncherModel.addOrMoveItemInDatabase(mLauncher, finalItem, mInfo.container,
+ mInfo.screenId, mInfo.cellX, mInfo.cellY);
}
+
+ // Remove the folder
+ mLauncher.removeItem(mFolderIcon, mInfo, true /* deleteFromDb */);
if (mFolderIcon instanceof DropTarget) {
mDragController.removeDropTarget((DropTarget) mFolderIcon);
}
- mLauncher.removeFolder(mInfo);
- }
- // We add the child after removing the folder to prevent both from existing at
- // the same time in the CellLayout. We need to add the new item with addInScreenFromBind()
- // to ensure that hotseat items are placed correctly.
- if (child != null) {
- mLauncher.getWorkspace().addInScreenFromBind(child, mInfo.container, mInfo.screenId,
- mInfo.cellX, mInfo.cellY, mInfo.spanX, mInfo.spanY);
+
+ if (newIcon != null) {
+ // We add the child after removing the folder to prevent both from existing
+ // at the same time in the CellLayout. We need to add the new item with
+ // addInScreenFromBind() to ensure that hotseat items are placed correctly.
+ mLauncher.getWorkspace().addInScreenFromBind(newIcon, mInfo.container,
+ mInfo.screenId, mInfo.cellX, mInfo.cellY, mInfo.spanX, mInfo.spanY);
+
+ // Focus the newly created child
+ newIcon.requestFocus();
+ }
}
}
};
@@ -1155,15 +1168,37 @@
return mDestroyed;
}
- // This method keeps track of the last item in the folder for the purposes
+ // This method keeps track of the first and last item in the folder for the purposes
// of keyboard focus
public void updateTextViewFocus() {
- View lastChild = mContent.getLastItem();
- if (lastChild != null) {
+ final View firstChild = mContent.getFirstItem();
+ final View lastChild = mContent.getLastItem();
+ if (firstChild != null && lastChild != null) {
mFolderName.setNextFocusDownId(lastChild.getId());
mFolderName.setNextFocusRightId(lastChild.getId());
mFolderName.setNextFocusLeftId(lastChild.getId());
mFolderName.setNextFocusUpId(lastChild.getId());
+ // Hitting TAB from the folder name wraps around to the first item on the current
+ // folder page, and hitting SHIFT+TAB from that item wraps back to the folder name.
+ mFolderName.setNextFocusForwardId(firstChild.getId());
+ // When clicking off the folder when editing the name, this Folder gains focus. When
+ // pressing an arrow key from that state, give the focus to the first item.
+ this.setNextFocusDownId(firstChild.getId());
+ this.setNextFocusRightId(firstChild.getId());
+ this.setNextFocusLeftId(firstChild.getId());
+ this.setNextFocusUpId(firstChild.getId());
+ // When pressing shift+tab in the above state, give the focus to the last item.
+ setOnKeyListener(new OnKeyListener() {
+ @Override
+ public boolean onKey(View v, int keyCode, KeyEvent event) {
+ boolean isShiftPlusTab = keyCode == KeyEvent.KEYCODE_TAB &&
+ event.hasModifiers(KeyEvent.META_SHIFT_ON);
+ if (isShiftPlusTab && Folder.this.isFocused()) {
+ return lastChild.requestFocus();
+ }
+ return false;
+ }
+ });
}
}
@@ -1284,7 +1319,11 @@
rearrangeChildren();
}
if (getItemCount() <= 1) {
- replaceFolderWithFinalItem();
+ if (mInfo.opened) {
+ mLauncher.closeFolder(this, true);
+ } else {
+ replaceFolderWithFinalItem();
+ }
}
}
@@ -1326,8 +1365,12 @@
}
public void onFocusChange(View v, boolean hasFocus) {
- if (v == mFolderName && hasFocus) {
- startEditingFolderName();
+ if (v == mFolderName) {
+ if (hasFocus) {
+ startEditingFolderName();
+ } else {
+ dismissEditingName();
+ }
}
}
@@ -1339,7 +1382,7 @@
}
@Override
- public void fillInLaunchSourceData(Bundle sourceData) {
+ public void fillInLaunchSourceData(View v, Bundle sourceData) {
// Fill in from the folder icon's launch source provider first
Stats.LaunchSourceUtils.populateSourceDataFromAncestorProvider(mFolderIcon, sourceData);
sourceData.putString(Stats.SOURCE_EXTRA_SUB_CONTAINER, Stats.SUB_CONTAINER_FOLDER);
diff --git a/src/com/android/launcher3/FolderIcon.java b/src/com/android/launcher3/FolderIcon.java
index 8d534d2..d7b55b3 100644
--- a/src/com/android/launcher3/FolderIcon.java
+++ b/src/com/android/launcher3/FolderIcon.java
@@ -520,7 +520,7 @@
}
class PreviewItemDrawingParams {
- PreviewItemDrawingParams(float transX, float transY, float scale, int overlayAlpha) {
+ PreviewItemDrawingParams(float transX, float transY, float scale, float overlayAlpha) {
this.transX = transX;
this.transY = transY;
this.scale = scale;
@@ -529,7 +529,7 @@
float transX;
float transY;
float scale;
- int overlayAlpha;
+ float overlayAlpha;
Drawable drawable;
}
@@ -561,7 +561,7 @@
float transY = mAvailableSpaceInPreview - (offset + scaledSize + scaleOffsetCorrection) + getPaddingTop();
float transX = (mAvailableSpaceInPreview - scaledSize) / 2;
float totalScale = mBaselineIconScale * scale;
- final int overlayAlpha = (int) (80 * (1 - r));
+ final float overlayAlpha = (80 * (1 - r)) / 255f;
if (params == null) {
params = new PreviewItemDrawingParams(transX, transY, totalScale, overlayAlpha);
@@ -585,12 +585,12 @@
d.setBounds(0, 0, mIntrinsicIconSize, mIntrinsicIconSize);
if (d instanceof FastBitmapDrawable) {
FastBitmapDrawable fd = (FastBitmapDrawable) d;
- int oldBrightness = fd.getBrightness();
+ float oldBrightness = fd.getBrightness();
fd.setBrightness(params.overlayAlpha);
d.draw(canvas);
fd.setBrightness(oldBrightness);
} else {
- d.setColorFilter(Color.argb(params.overlayAlpha, 255, 255, 255),
+ d.setColorFilter(Color.argb((int) (params.overlayAlpha * 255), 255, 255, 255),
PorterDuff.Mode.SRC_ATOP);
d.draw(canvas);
d.clearColorFilter();
diff --git a/src/com/android/launcher3/FolderPagedView.java b/src/com/android/launcher3/FolderPagedView.java
index cc9c573..d503d2c 100644
--- a/src/com/android/launcher3/FolderPagedView.java
+++ b/src/com/android/launcher3/FolderPagedView.java
@@ -402,16 +402,28 @@
return !ALLOW_FOLDER_SCROLL && getItemCount() >= mMaxItemsPerPage;
}
+ public View getFirstItem() {
+ if (getChildCount() < 1) {
+ return null;
+ }
+ ShortcutAndWidgetContainer currContainer = getCurrentCellLayout().getShortcutsAndWidgets();
+ if (mGridCountX > 0) {
+ return currContainer.getChildAt(0, 0);
+ } else {
+ return currContainer.getChildAt(0);
+ }
+ }
+
public View getLastItem() {
if (getChildCount() < 1) {
return null;
}
- ShortcutAndWidgetContainer lastContainer = getCurrentCellLayout().getShortcutsAndWidgets();
- int lastRank = lastContainer.getChildCount() - 1;
+ ShortcutAndWidgetContainer currContainer = getCurrentCellLayout().getShortcutsAndWidgets();
+ int lastRank = currContainer.getChildCount() - 1;
if (mGridCountX > 0) {
- return lastContainer.getChildAt(lastRank % mGridCountX, lastRank / mGridCountX);
+ return currContainer.getChildAt(lastRank % mGridCountX, lastRank / mGridCountX);
} else {
- return lastContainer.getChildAt(lastRank);
+ return currContainer.getChildAt(lastRank);
}
}
diff --git a/src/com/android/launcher3/Hotseat.java b/src/com/android/launcher3/Hotseat.java
index 98912f5..3e83876 100644
--- a/src/com/android/launcher3/Hotseat.java
+++ b/src/com/android/launcher3/Hotseat.java
@@ -23,6 +23,7 @@
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.MotionEvent;
+import android.view.View;
import android.widget.FrameLayout;
import android.widget.TextView;
@@ -69,7 +70,7 @@
public void setOnLongClickListener(OnLongClickListener l) {
mContent.setOnLongClickListener(l);
}
-
+
/* Get the orientation invariant order of the item in the hotseat for persistence. */
int getOrderInHotseat(int x, int y) {
return mHasVerticalHotseat ? (mContent.getCountY() - y - 1) : x;
@@ -153,7 +154,7 @@
}
@Override
- public void fillInLaunchSourceData(Bundle sourceData) {
+ public void fillInLaunchSourceData(View v, Bundle sourceData) {
sourceData.putString(Stats.SOURCE_EXTRA_CONTAINER, Stats.CONTAINER_HOTSEAT);
}
}
diff --git a/src/com/android/launcher3/IconCache.java b/src/com/android/launcher3/IconCache.java
index 59ab839..05ad538 100644
--- a/src/com/android/launcher3/IconCache.java
+++ b/src/com/android/launcher3/IconCache.java
@@ -28,7 +28,7 @@
import android.content.res.Resources;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
-import android.database.sqlite.SQLiteOpenHelper;
+import android.database.sqlite.SQLiteException;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
@@ -45,8 +45,10 @@
import com.android.launcher3.compat.LauncherAppsCompat;
import com.android.launcher3.compat.UserHandleCompat;
import com.android.launcher3.compat.UserManagerCompat;
+import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.model.PackageItemInfo;
import com.android.launcher3.util.ComponentKey;
+import com.android.launcher3.util.SQLiteCacheHelper;
import com.android.launcher3.util.Thunk;
import java.util.Collections;
@@ -179,15 +181,7 @@
private Bitmap makeDefaultIcon(UserHandleCompat user) {
Drawable unbadged = getFullResDefaultActivityIcon();
- Drawable d = mUserManager.getBadgedDrawableForUser(unbadged, user);
- Bitmap b = Bitmap.createBitmap(Math.max(d.getIntrinsicWidth(), 1),
- Math.max(d.getIntrinsicHeight(), 1),
- Bitmap.Config.ARGB_8888);
- Canvas c = new Canvas(b);
- d.setBounds(0, 0, b.getWidth(), b.getHeight());
- d.draw(c);
- c.setBitmap(null);
- return b;
+ return Utilities.createBadgedIconBitmap(unbadged, user, mContext);
}
/**
@@ -237,9 +231,9 @@
public synchronized void removeIconsForPkg(String packageName, UserHandleCompat user) {
removeFromMemCacheLocked(packageName, user);
long userSerial = mUserManager.getSerialNumberForUser(user);
- mIconDb.getWritableDatabase().delete(IconDB.TABLE_NAME,
+ mIconDb.delete(
IconDB.COLUMN_COMPONENT + " LIKE ? AND " + IconDB.COLUMN_USER + " = ?",
- new String[] {packageName + "/%", Long.toString(userSerial)});
+ new String[]{packageName + "/%", Long.toString(userSerial)});
}
public void updateDbIcons(Set<String> ignorePackagesForMainUser) {
@@ -282,58 +276,65 @@
componentMap.put(app.getComponentName(), app);
}
- Cursor c = mIconDb.getReadableDatabase().query(IconDB.TABLE_NAME,
- new String[] {IconDB.COLUMN_ROWID, IconDB.COLUMN_COMPONENT,
- IconDB.COLUMN_LAST_UPDATED, IconDB.COLUMN_VERSION,
- IconDB.COLUMN_SYSTEM_STATE},
- IconDB.COLUMN_USER + " = ? ",
- new String[] {Long.toString(userSerial)},
- null, null, null);
-
- final int indexComponent = c.getColumnIndex(IconDB.COLUMN_COMPONENT);
- final int indexLastUpdate = c.getColumnIndex(IconDB.COLUMN_LAST_UPDATED);
- final int indexVersion = c.getColumnIndex(IconDB.COLUMN_VERSION);
- final int rowIndex = c.getColumnIndex(IconDB.COLUMN_ROWID);
- final int systemStateIndex = c.getColumnIndex(IconDB.COLUMN_SYSTEM_STATE);
-
HashSet<Integer> itemsToRemove = new HashSet<Integer>();
Stack<LauncherActivityInfoCompat> appsToUpdate = new Stack<>();
- while (c.moveToNext()) {
- String cn = c.getString(indexComponent);
- ComponentName component = ComponentName.unflattenFromString(cn);
- PackageInfo info = pkgInfoMap.get(component.getPackageName());
- if (info == null) {
- if (!ignorePackages.contains(component.getPackageName())) {
+ Cursor c = null;
+ try {
+ c = mIconDb.query(
+ new String[]{IconDB.COLUMN_ROWID, IconDB.COLUMN_COMPONENT,
+ IconDB.COLUMN_LAST_UPDATED, IconDB.COLUMN_VERSION,
+ IconDB.COLUMN_SYSTEM_STATE},
+ IconDB.COLUMN_USER + " = ? ",
+ new String[]{Long.toString(userSerial)});
+
+ final int indexComponent = c.getColumnIndex(IconDB.COLUMN_COMPONENT);
+ final int indexLastUpdate = c.getColumnIndex(IconDB.COLUMN_LAST_UPDATED);
+ final int indexVersion = c.getColumnIndex(IconDB.COLUMN_VERSION);
+ final int rowIndex = c.getColumnIndex(IconDB.COLUMN_ROWID);
+ final int systemStateIndex = c.getColumnIndex(IconDB.COLUMN_SYSTEM_STATE);
+
+ while (c.moveToNext()) {
+ String cn = c.getString(indexComponent);
+ ComponentName component = ComponentName.unflattenFromString(cn);
+ PackageInfo info = pkgInfoMap.get(component.getPackageName());
+ if (info == null) {
+ if (!ignorePackages.contains(component.getPackageName())) {
+ remove(component, user);
+ itemsToRemove.add(c.getInt(rowIndex));
+ }
+ continue;
+ }
+ if ((info.applicationInfo.flags & ApplicationInfo.FLAG_IS_DATA_ONLY) != 0) {
+ // Application is not present
+ continue;
+ }
+
+ long updateTime = c.getLong(indexLastUpdate);
+ int version = c.getInt(indexVersion);
+ LauncherActivityInfoCompat app = componentMap.remove(component);
+ if (version == info.versionCode && updateTime == info.lastUpdateTime &&
+ TextUtils.equals(mSystemState, c.getString(systemStateIndex))) {
+ continue;
+ }
+ if (app == null) {
remove(component, user);
itemsToRemove.add(c.getInt(rowIndex));
+ } else {
+ appsToUpdate.add(app);
}
- continue;
}
- if ((info.applicationInfo.flags & ApplicationInfo.FLAG_IS_DATA_ONLY) != 0) {
- // Application is not present
- continue;
- }
-
- long updateTime = c.getLong(indexLastUpdate);
- int version = c.getInt(indexVersion);
- LauncherActivityInfoCompat app = componentMap.remove(component);
- if (version == info.versionCode && updateTime == info.lastUpdateTime &&
- TextUtils.equals(mSystemState, c.getString(systemStateIndex))) {
- continue;
- }
- if (app == null) {
- remove(component, user);
- itemsToRemove.add(c.getInt(rowIndex));
- } else {
- appsToUpdate.add(app);
+ } catch (SQLiteException e) {
+ Log.d(TAG, "Error reading icon cache", e);
+ // Continue updating whatever we have read so far
+ } finally {
+ if (c != null) {
+ c.close();
}
}
- c.close();
if (!itemsToRemove.isEmpty()) {
- mIconDb.getWritableDatabase().delete(IconDB.TABLE_NAME,
- Utilities.createDbSelectionQuery(IconDB.COLUMN_ROWID, itemsToRemove),
- null);
+ mIconDb.delete(
+ Utilities.createDbSelectionQuery(IconDB.COLUMN_ROWID, itemsToRemove), null);
}
// Insert remaining apps.
@@ -363,8 +364,7 @@
values.put(IconDB.COLUMN_USER, userSerial);
values.put(IconDB.COLUMN_LAST_UPDATED, info.lastUpdateTime);
values.put(IconDB.COLUMN_VERSION, info.versionCode);
- mIconDb.getWritableDatabase().insertWithOnConflict(IconDB.TABLE_NAME, null, values,
- SQLiteDatabase.CONFLICT_REPLACE);
+ mIconDb.insertOrReplace(values);
}
@Thunk ContentValues updateCacheAndGetContentValues(LauncherActivityInfoCompat app,
@@ -380,7 +380,8 @@
}
if (entry == null) {
entry = new CacheEntry();
- entry.icon = Utilities.createIconBitmap(app.getBadgedIcon(mIconDpi), mContext);
+ entry.icon = Utilities.createBadgedIconBitmap(
+ app.getIcon(mIconDpi), app.getUser(), mContext);
}
entry.title = app.getLabel();
entry.contentDescription = mUserManager.getBadgedLabelForUser(entry.title, app.getUser());
@@ -542,7 +543,8 @@
// Check the DB first.
if (!getEntryFromDB(cacheKey, entry, useLowResIcon)) {
if (info != null) {
- entry.icon = Utilities.createIconBitmap(info.getBadgedIcon(mIconDpi), mContext);
+ entry.icon = Utilities.createBadgedIconBitmap(
+ info.getIcon(mIconDpi), info.getUser(), mContext);
} else {
if (usePackageIcon) {
CacheEntry packageEntry = getEntryForPackageLocked(
@@ -623,9 +625,8 @@
if (appInfo == null) {
throw new NameNotFoundException("ApplicationInfo is null");
}
- Drawable drawable = mUserManager.getBadgedDrawableForUser(
- appInfo.loadIcon(mPackageManager), user);
- entry.icon = Utilities.createIconBitmap(drawable, mContext);
+ entry.icon = Utilities.createBadgedIconBitmap(
+ appInfo.loadIcon(mPackageManager), user, mContext);
entry.title = appInfo.loadLabel(mPackageManager);
entry.contentDescription = mUserManager.getBadgedLabelForUser(entry.title, user);
entry.isLowResIcon = false;
@@ -678,19 +679,18 @@
label, Color.TRANSPARENT);
values.put(IconDB.COLUMN_COMPONENT, componentName.flattenToString());
values.put(IconDB.COLUMN_USER, userSerial);
- mIconDb.getWritableDatabase().insertWithOnConflict(IconDB.TABLE_NAME, null, values,
- SQLiteDatabase.CONFLICT_REPLACE);
+ mIconDb.insertOrReplace(values);
}
private boolean getEntryFromDB(ComponentKey cacheKey, CacheEntry entry, boolean lowRes) {
- Cursor c = mIconDb.getReadableDatabase().query(IconDB.TABLE_NAME,
- new String[] {lowRes ? IconDB.COLUMN_ICON_LOW_RES : IconDB.COLUMN_ICON,
+ Cursor c = null;
+ try {
+ c = mIconDb.query(
+ new String[]{lowRes ? IconDB.COLUMN_ICON_LOW_RES : IconDB.COLUMN_ICON,
IconDB.COLUMN_LABEL},
IconDB.COLUMN_COMPONENT + " = ? AND " + IconDB.COLUMN_USER + " = ?",
- new String[] {cacheKey.componentName.flattenToString(),
- Long.toString(mUserManager.getSerialNumberForUser(cacheKey.user))},
- null, null, null);
- try {
+ new String[]{cacheKey.componentName.flattenToString(),
+ Long.toString(mUserManager.getSerialNumberForUser(cacheKey.user))});
if (c.moveToNext()) {
entry.icon = loadIconNoResize(c, 0, lowRes ? mLowResOptions : null);
entry.isLowResIcon = lowRes;
@@ -704,8 +704,12 @@
}
return true;
}
+ } catch (SQLiteException e) {
+ Log.d(TAG, "Error reading icon cache", e);
} finally {
- c.close();
+ if (c != null) {
+ c.close();
+ }
}
return false;
}
@@ -751,9 +755,9 @@
LauncherActivityInfoCompat app = mAppsToUpdate.pop();
String cn = app.getComponentName().flattenToString();
ContentValues values = updateCacheAndGetContentValues(app, true);
- mIconDb.getWritableDatabase().update(IconDB.TABLE_NAME, values,
+ mIconDb.update(values,
IconDB.COLUMN_COMPONENT + " = ? AND " + IconDB.COLUMN_USER + " = ?",
- new String[] {cn, Long.toString(mUserSerial)});
+ new String[]{cn, Long.toString(mUserSerial)});
mUpdatedPackages.add(app.getComponentName().getPackageName());
if (mAppsToUpdate.isEmpty() && !mUpdatedPackages.isEmpty()) {
@@ -788,9 +792,12 @@
mSystemState = Locale.getDefault().toString();
}
- private static final class IconDB extends SQLiteOpenHelper {
+ private static final class IconDB extends SQLiteCacheHelper {
private final static int DB_VERSION = 7;
+ private final static int RELEASE_VERSION = DB_VERSION +
+ (FeatureFlags.LAUNCHER3_ICON_NORMALIZATION ? 1 : 0);
+
private final static String TABLE_NAME = "icons";
private final static String COLUMN_ROWID = "rowid";
private final static String COLUMN_COMPONENT = "componentName";
@@ -803,11 +810,11 @@
private final static String COLUMN_SYSTEM_STATE = "system_state";
public IconDB(Context context) {
- super(context, LauncherFiles.APP_ICONS_DB, null, DB_VERSION);
+ super(context, LauncherFiles.APP_ICONS_DB, RELEASE_VERSION, TABLE_NAME);
}
@Override
- public void onCreate(SQLiteDatabase db) {
+ protected void onCreateTable(SQLiteDatabase db) {
db.execSQL("CREATE TABLE IF NOT EXISTS " + TABLE_NAME + " (" +
COLUMN_COMPONENT + " TEXT NOT NULL, " +
COLUMN_USER + " INTEGER NOT NULL, " +
@@ -820,25 +827,6 @@
"PRIMARY KEY (" + COLUMN_COMPONENT + ", " + COLUMN_USER + ") " +
");");
}
-
- @Override
- public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
- if (oldVersion != newVersion) {
- clearDB(db);
- }
- }
-
- @Override
- public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {
- if (oldVersion != newVersion) {
- clearDB(db);
- }
- }
-
- private void clearDB(SQLiteDatabase db) {
- db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME);
- onCreate(db);
- }
}
private ContentValues newContentValues(Bitmap icon, String label, int lowResBackgroundColor) {
diff --git a/src/com/android/launcher3/InstallShortcutReceiver.java b/src/com/android/launcher3/InstallShortcutReceiver.java
index 3fc8fc0..46b9b7d 100644
--- a/src/com/android/launcher3/InstallShortcutReceiver.java
+++ b/src/com/android/launcher3/InstallShortcutReceiver.java
@@ -82,7 +82,7 @@
strings = new HashSet<String>(strings);
}
strings.add(encoded);
- sharedPrefs.edit().putStringSet(APPS_PENDING_INSTALL, strings).commit();
+ sharedPrefs.edit().putStringSet(APPS_PENDING_INSTALL, strings).apply();
}
}
}
@@ -92,8 +92,7 @@
if (packageNames.isEmpty()) {
return;
}
- String spKey = LauncherAppState.getSharedPreferencesKey();
- SharedPreferences sp = context.getSharedPreferences(spKey, Context.MODE_PRIVATE);
+ SharedPreferences sp = Utilities.getPrefs(context);
synchronized(sLock) {
Set<String> strings = sp.getStringSet(APPS_PENDING_INSTALL, null);
if (DBG) {
@@ -111,7 +110,7 @@
newStringsIter.remove();
}
}
- sp.edit().putStringSet(APPS_PENDING_INSTALL, newStrings).commit();
+ sp.edit().putStringSet(APPS_PENDING_INSTALL, newStrings).apply();
}
}
}
@@ -132,7 +131,7 @@
infos.add(info);
}
}
- sharedPrefs.edit().putStringSet(APPS_PENDING_INSTALL, new HashSet<String>()).commit();
+ sharedPrefs.edit().putStringSet(APPS_PENDING_INSTALL, new HashSet<String>()).apply();
return infos;
}
}
@@ -145,40 +144,53 @@
if (!ACTION_INSTALL_SHORTCUT.equals(data.getAction())) {
return;
}
-
- PendingInstallShortcutInfo info = new PendingInstallShortcutInfo(data, context);
- if (info.launchIntent == null || info.label == null) {
- if (DBG) Log.e(TAG, "Invalid install shortcut intent");
- return;
+ PendingInstallShortcutInfo info = createPendingInfo(context, data);
+ if (info != null) {
+ queuePendingShortcutInfo(info, context);
}
-
- info = convertToLauncherActivityIfPossible(info);
- queuePendingShortcutInfo(info, context);
}
- public static ShortcutInfo fromShortcutIntent(Context context, Intent data) {
+ /**
+ * @return true is the extra is either null or is of type {@param type}
+ */
+ private static boolean isValidExtraType(Intent intent, String key, Class type) {
+ Object extra = intent.getParcelableExtra(key);
+ return extra == null || type.isInstance(extra);
+ }
+
+ /**
+ * Verifies the intent and creates a {@link PendingInstallShortcutInfo}
+ */
+ private static PendingInstallShortcutInfo createPendingInfo(Context context, Intent data) {
+ if (!isValidExtraType(data, Intent.EXTRA_SHORTCUT_INTENT, Intent.class) ||
+ !(isValidExtraType(data, Intent.EXTRA_SHORTCUT_ICON_RESOURCE,
+ Intent.ShortcutIconResource.class)) ||
+ !(isValidExtraType(data, Intent.EXTRA_SHORTCUT_ICON, Bitmap.class))) {
+
+ if (DBG) Log.e(TAG, "Invalid install shortcut intent");
+ return null;
+ }
+
PendingInstallShortcutInfo info = new PendingInstallShortcutInfo(data, context);
if (info.launchIntent == null || info.label == null) {
if (DBG) Log.e(TAG, "Invalid install shortcut intent");
return null;
}
- info = convertToLauncherActivityIfPossible(info);
- return info.getShortcutInfo();
+
+ return convertToLauncherActivityIfPossible(info);
}
- static void queueInstallShortcut(LauncherActivityInfoCompat info, Context context) {
- queuePendingShortcutInfo(new PendingInstallShortcutInfo(info, context), context);
+ public static ShortcutInfo fromShortcutIntent(Context context, Intent data) {
+ PendingInstallShortcutInfo info = createPendingInfo(context, data);
+ return info == null ? null : info.getShortcutInfo();
}
private static void queuePendingShortcutInfo(PendingInstallShortcutInfo info, Context context) {
// Queue the item up for adding if launcher has not loaded properly yet
- LauncherAppState.setApplicationContext(context.getApplicationContext());
LauncherAppState app = LauncherAppState.getInstance();
boolean launcherNotLoaded = app.getModel().getCallback() == null;
- String spKey = LauncherAppState.getSharedPreferencesKey();
- SharedPreferences sp = context.getSharedPreferences(spKey, Context.MODE_PRIVATE);
- addToInstallQueue(sp, info);
+ addToInstallQueue(Utilities.getPrefs(context), info);
if (!mUseInstallQueue && !launcherNotLoaded) {
flushInstallQueue(context);
}
@@ -192,22 +204,21 @@
flushInstallQueue(context);
}
static void flushInstallQueue(Context context) {
- String spKey = LauncherAppState.getSharedPreferencesKey();
- SharedPreferences sp = context.getSharedPreferences(spKey, Context.MODE_PRIVATE);
+ SharedPreferences sp = Utilities.getPrefs(context);
ArrayList<PendingInstallShortcutInfo> installQueue = getAndClearInstallQueue(sp, context);
if (!installQueue.isEmpty()) {
Iterator<PendingInstallShortcutInfo> iter = installQueue.iterator();
ArrayList<ItemInfo> addShortcuts = new ArrayList<ItemInfo>();
while (iter.hasNext()) {
final PendingInstallShortcutInfo pendingInfo = iter.next();
- final Intent intent = pendingInfo.launchIntent;
// If the intent specifies a package, make sure the package exists
String packageName = pendingInfo.getTargetPackage();
if (!TextUtils.isEmpty(packageName)) {
UserHandleCompat myUserHandle = UserHandleCompat.myUserHandle();
if (!LauncherModel.isValidPackage(context, packageName, myUserHandle)) {
- if (DBG) Log.d(TAG, "Ignoring shortcut for absent package:" + intent);
+ if (DBG) Log.d(TAG, "Ignoring shortcut for absent package: "
+ + pendingInfo.launchIntent);
continue;
}
}
@@ -352,7 +363,7 @@
return packageName;
}
- public boolean isLuncherActivity() {
+ public boolean isLauncherActivity() {
return activityInfo != null;
}
}
@@ -395,9 +406,7 @@
}
return new PendingInstallShortcutInfo(data, context);
- } catch (JSONException e) {
- Log.d(TAG, "Exception reading shortcut to add: " + e);
- } catch (URISyntaxException e) {
+ } catch (JSONException | URISyntaxException e) {
Log.d(TAG, "Exception reading shortcut to add: " + e);
}
return null;
@@ -410,7 +419,7 @@
*/
private static PendingInstallShortcutInfo convertToLauncherActivityIfPossible(
PendingInstallShortcutInfo original) {
- if (original.isLuncherActivity()) {
+ if (original.isLauncherActivity()) {
// Already an activity target
return original;
}
diff --git a/src/com/android/launcher3/InvariantDeviceProfile.java b/src/com/android/launcher3/InvariantDeviceProfile.java
index d91104a..b3a8bbc 100644
--- a/src/com/android/launcher3/InvariantDeviceProfile.java
+++ b/src/com/android/launcher3/InvariantDeviceProfile.java
@@ -19,7 +19,6 @@
import android.annotation.TargetApi;
import android.content.Context;
import android.graphics.Point;
-import android.os.Build;
import android.util.DisplayMetrics;
import android.view.Display;
import android.view.WindowManager;
@@ -66,10 +65,10 @@
*/
public int numFolderRows;
public int numFolderColumns;
- float iconSize;
- int iconBitmapSize;
- int fillResIconDpi;
- float iconTextSize;
+ public float iconSize;
+ public int iconBitmapSize;
+ public int fillResIconDpi;
+ public float iconTextSize;
/**
* Number of icons inside the hotseat area.
@@ -116,7 +115,7 @@
defaultLayoutId = dlId;
}
- @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
+ @TargetApi(23)
InvariantDeviceProfile(Context context) {
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
Display display = wm.getDefaultDisplay();
@@ -174,9 +173,9 @@
// width, height, #rows, #columns, #folder rows, #folder columns,
// iconSize, iconTextSize, #hotseat, #hotseatIconSize, defaultLayoutId.
predefinedDeviceProfiles.add(new InvariantDeviceProfile("Super Short Stubby",
- 255, 300, 2, 3, 2, 3, 3, 48, 13, 3, 48, R.xml.default_workspace_4x4));
+ 255, 300, 2, 3, 2, 3, 3, 48, 13, 3, 48, R.xml.default_workspace_3x3));
predefinedDeviceProfiles.add(new InvariantDeviceProfile("Shorter Stubby",
- 255, 400, 3, 3, 3, 3, 3, 48, 13, 3, 48, R.xml.default_workspace_4x4));
+ 255, 400, 3, 3, 3, 3, 3, 48, 13, 3, 48, R.xml.default_workspace_3x3));
predefinedDeviceProfiles.add(new InvariantDeviceProfile("Short Stubby",
275, 420, 3, 4, 3, 4, 4, 48, 13, 5, 48, R.xml.default_workspace_4x4));
predefinedDeviceProfiles.add(new InvariantDeviceProfile("Stubby",
@@ -184,9 +183,9 @@
predefinedDeviceProfiles.add(new InvariantDeviceProfile("Nexus S",
296, 491.33f, 4, 4, 4, 4, 4, 48, 13, 5, 48, R.xml.default_workspace_4x4));
predefinedDeviceProfiles.add(new InvariantDeviceProfile("Nexus 4",
- 335, 567, 4, 4, 4, 4, 4, DEFAULT_ICON_SIZE_DP, 13, 5, 56, R.xml.default_workspace_4x4));
- predefinedDeviceProfiles.add(new InvariantDeviceProfile("Nexus 5",
359, 567, 4, 4, 4, 4, 4, DEFAULT_ICON_SIZE_DP, 13, 5, 56, R.xml.default_workspace_4x4));
+ predefinedDeviceProfiles.add(new InvariantDeviceProfile("Nexus 5",
+ 335, 567, 4, 4, 4, 4, 4, DEFAULT_ICON_SIZE_DP, 13, 5, 56, R.xml.default_workspace_4x4));
predefinedDeviceProfiles.add(new InvariantDeviceProfile("Large Phone",
406, 694, 5, 5, 4, 4, 4, 64, 14.4f, 5, 56, R.xml.default_workspace_5x5));
// The tablet profile is odd in that the landscape orientation
@@ -197,7 +196,7 @@
predefinedDeviceProfiles.add(new InvariantDeviceProfile("Nexus 10",
727, 1207, 5, 6, 4, 5, 4, 76, 14.4f, 7, 76, R.xml.default_workspace_5x6));
predefinedDeviceProfiles.add(new InvariantDeviceProfile("20-inch Tablet",
- 1527, 2527, 7, 7, 6, 6, 4, 100, 20, 7, 72, R.xml.default_workspace_4x4));
+ 1527, 2527, 7, 7, 6, 6, 4, 100, 20, 7, 72, R.xml.default_workspace_5x6));
return predefinedDeviceProfiles;
}
@@ -252,8 +251,8 @@
ArrayList<InvariantDeviceProfile> pointsByNearness = points;
Collections.sort(pointsByNearness, new Comparator<InvariantDeviceProfile>() {
public int compare(InvariantDeviceProfile a, InvariantDeviceProfile b) {
- return (int) (dist(width, height, a.minWidthDps, a.minHeightDps)
- - dist(width, height, b.minWidthDps, b.minHeightDps));
+ return Float.compare(dist(width, height, a.minWidthDps, a.minHeightDps),
+ dist(width, height, b.minWidthDps, b.minHeightDps));
}
});
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 9c321a8..0599eb8 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -52,6 +52,7 @@
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
+import android.graphics.Point;
import android.graphics.PorterDuff;
import android.graphics.Rect;
import android.graphics.drawable.ColorDrawable;
@@ -72,7 +73,6 @@
import android.text.method.TextKeyListener;
import android.util.Log;
import android.view.Display;
-import android.view.Gravity;
import android.view.HapticFeedbackConstants;
import android.view.KeyEvent;
import android.view.LayoutInflater;
@@ -85,13 +85,11 @@
import android.view.ViewGroup;
import android.view.ViewStub;
import android.view.ViewTreeObserver;
-import android.view.Window;
import android.view.WindowManager;
import android.view.accessibility.AccessibilityEvent;
import android.view.animation.OvershootInterpolator;
import android.view.inputmethod.InputMethodManager;
import android.widget.Advanceable;
-import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
@@ -107,6 +105,7 @@
import com.android.launcher3.model.WidgetsModel;
import com.android.launcher3.util.ComponentKey;
import com.android.launcher3.util.LongArrayMap;
+import com.android.launcher3.util.TestingUtils;
import com.android.launcher3.util.Thunk;
import com.android.launcher3.widget.PendingAddWidgetInfo;
import com.android.launcher3.widget.WidgetHostViewLoader;
@@ -124,7 +123,6 @@
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
-import java.util.concurrent.atomic.AtomicInteger;
/**
* Default launcher application.
@@ -195,8 +193,6 @@
private static final String RUNTIME_STATE_PENDING_ADD_WIDGET_INFO = "launcher.add_widget_info";
// Type: parcelable
private static final String RUNTIME_STATE_PENDING_ADD_WIDGET_ID = "launcher.add_widget_id";
- // Type: int[]
- private static final String RUNTIME_STATE_VIEW_IDS = "launcher.view_ids";
static final String INTRO_SCREEN_DISMISSED = "launcher.intro_screen_dismissed";
static final String FIRST_RUN_ACTIVITY_DISPLAYED = "launcher.first_run_activity_displayed";
@@ -205,9 +201,6 @@
static final String ACTION_FIRST_LOAD_COMPLETE =
"com.android.launcher3.action.FIRST_LOAD_COMPLETE";
- public static final String SHOW_WEIGHT_WATCHER = "debug.show_mem";
- public static final boolean SHOW_WEIGHT_WATCHER_DEFAULT = false;
-
private static final String QSB_WIDGET_ID = "qsb_widget_id";
private static final String QSB_WIDGET_PROVIDER = "qsb_widget_provider";
@@ -230,9 +223,6 @@
private static final int ON_ACTIVITY_RESULT_ANIMATION_DELAY = 500;
private static final int ACTIVITY_START_DELAY = 1000;
- private HashMap<Integer, Integer> mItemIdToViewId = new HashMap<Integer, Integer>();
- private static final AtomicInteger sNextGeneratedId = new AtomicInteger(1);
-
// How long to wait before the new-shortcut animation automatically pans the workspace
private static int NEW_APPS_PAGE_MOVE_DELAY = 500;
private static int NEW_APPS_ANIMATION_INACTIVE_TIMEOUT_SECONDS = 5;
@@ -248,7 +238,8 @@
private View mPageIndicators;
@Thunk DragLayer mDragLayer;
private DragController mDragController;
- private View mWeightWatcher;
+
+ public View mWeightWatcher;
private AppWidgetManagerCompat mAppWidgetManager;
private LauncherAppWidgetHost mAppWidgetHost;
@@ -358,10 +349,9 @@
protected static HashMap<String, CustomAppWidget> sCustomAppWidgets =
new HashMap<String, CustomAppWidget>();
- private static final boolean ENABLE_CUSTOM_WIDGET_TEST = false;
static {
- if (ENABLE_CUSTOM_WIDGET_TEST) {
- sCustomAppWidgets.put(DummyWidget.class.getName(), new DummyWidget());
+ if (TestingUtils.ENABLE_CUSTOM_WIDGET_TEST) {
+ TestingUtils.addDummyWidget(sCustomAppWidgets);
}
}
@@ -427,7 +417,6 @@
super.onCreate(savedInstanceState);
- LauncherAppState.setApplicationContext(getApplicationContext());
LauncherAppState app = LauncherAppState.getInstance();
// Load configuration-specific DeviceProfile
@@ -436,8 +425,7 @@
app.getInvariantDeviceProfile().landscapeProfile
: app.getInvariantDeviceProfile().portraitProfile;
- mSharedPrefs = getSharedPreferences(LauncherAppState.getSharedPreferencesKey(),
- Context.MODE_PRIVATE);
+ mSharedPrefs = Utilities.getPrefs(this);
mIsSafeModeEnabled = getPackageManager().isSafeMode();
mModel = app.setLauncher(this);
mIconCache = app.getIconCache();
@@ -465,6 +453,8 @@
setContentView(R.layout.launcher);
+ app.getInvariantDeviceProfile().landscapeProfile.setSearchBarHeight(getSearchBarHeight());
+ app.getInvariantDeviceProfile().portraitProfile.setSearchBarHeight(getSearchBarHeight());
setupViews();
mDeviceProfile.layout(this);
@@ -658,34 +648,12 @@
return !isWorkspaceLoading();
}
- @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
- public static int generateViewId() {
- if (Utilities.ATLEAST_JB_MR1) {
- return View.generateViewId();
- } else {
- // View.generateViewId() is not available. The following fallback logic is a copy
- // of its implementation.
- for (;;) {
- final int result = sNextGeneratedId.get();
- // aapt-generated IDs have the high byte nonzero; clamp to the range under that.
- int newValue = result + 1;
- if (newValue > 0x00FFFFFF) newValue = 1; // Roll over to 1, not 0.
- if (sNextGeneratedId.compareAndSet(result, newValue)) {
- return result;
- }
- }
- }
- }
-
public int getViewIdForItem(ItemInfo info) {
- // This cast is safe given the > 2B range for int.
- int itemId = (int) info.id;
- if (mItemIdToViewId.containsKey(itemId)) {
- return mItemIdToViewId.get(itemId);
- }
- int viewId = generateViewId();
- mItemIdToViewId.put(itemId, viewId);
- return viewId;
+ // aapt-generated IDs have the high byte nonzero; clamp to the range under that.
+ // This cast is safe as long as the id < 0x00FFFFFF
+ // Since we jail all the dynamically generated views, there should be no clashes
+ // with any other views.
+ return (int) info.id;
}
/**
@@ -932,8 +900,7 @@
}
@Thunk void completeTwoStageWidgetDrop(final int resultCode, final int appWidgetId) {
- CellLayout cellLayout =
- (CellLayout) mWorkspace.getScreenWithId(mPendingAddInfo.screenId);
+ CellLayout cellLayout = mWorkspace.getScreenWithId(mPendingAddInfo.screenId);
Runnable onCompleteRunnable = null;
int animationType = 0;
@@ -1067,7 +1034,9 @@
// Consequently, the widgets will be inflated in the orientation of the foreground activity
// (framework issue). On resuming, we ensure that any widgets are inflated for the current
// orientation.
- getWorkspace().reinflateWidgetsIfNecessary();
+ if (!isWorkspaceLoading()) {
+ getWorkspace().reinflateWidgetsIfNecessary();
+ }
reinflateQSBIfNecessary();
if (DEBUG_RESUME_TIME) {
@@ -1303,6 +1272,29 @@
return handled;
}
+ @Override
+ public boolean onKeyUp(int keyCode, KeyEvent event) {
+ if (keyCode == KeyEvent.KEYCODE_MENU) {
+ // Ignore the menu key if we are currently dragging or are on the custom content screen
+ if (!isOnCustomContent() && !mDragController.isDragging()) {
+ // Close any open folders
+ closeFolder();
+
+ // Stop resizing any widgets
+ mWorkspace.exitWidgetResizeMode();
+
+ // Show the overview mode if we are on the workspace
+ if (mState == State.WORKSPACE && !mWorkspace.isInOverviewMode() &&
+ !mWorkspace.isSwitchingState()) {
+ mOverviewPanel.requestFocus();
+ showOverviewMode(true, true /* requestButtonFocus */);
+ }
+ }
+ return true;
+ }
+ return super.onKeyUp(keyCode, event);
+ }
+
private String getTypedText() {
return mDefaultKeySsb.toString();
}
@@ -1334,7 +1326,6 @@
*
* @param savedState The previous state.
*/
- @SuppressWarnings("unchecked")
private void restoreState(Bundle savedState) {
if (savedState == null) {
return;
@@ -1370,9 +1361,6 @@
setWaitingForResult(true);
mRestoring = true;
}
-
- mItemIdToViewId = (HashMap<Integer, Integer>)
- savedState.getSerializable(RUNTIME_STATE_VIEW_IDS);
}
/**
@@ -1401,45 +1389,8 @@
mHotseat.setOnLongClickListener(this);
}
- mOverviewPanel = (ViewGroup) findViewById(R.id.overview_panel);
- mWidgetsButton = findViewById(R.id.widget_button);
- mWidgetsButton.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View arg0) {
- if (!mWorkspace.isSwitchingState()) {
- onClickAddWidgetButton(arg0);
- }
- }
- });
- mWidgetsButton.setOnTouchListener(getHapticFeedbackTouchListener());
-
- View wallpaperButton = findViewById(R.id.wallpaper_button);
- wallpaperButton.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View arg0) {
- if (!mWorkspace.isSwitchingState()) {
- onClickWallpaperPicker(arg0);
- }
- }
- });
- wallpaperButton.setOnTouchListener(getHapticFeedbackTouchListener());
-
- View settingsButton = findViewById(R.id.settings_button);
- if (hasSettings()) {
- settingsButton.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View arg0) {
- if (!mWorkspace.isSwitchingState()) {
- onClickSettingsButton(arg0);
- }
- }
- });
- settingsButton.setOnTouchListener(getHapticFeedbackTouchListener());
- } else {
- settingsButton.setVisibility(View.GONE);
- }
-
- mOverviewPanel.setAlpha(0f);
+ // Setup the overview panel
+ setupOverviewPanel();
// Setup the workspace
mWorkspace.setHapticFeedbackEnabled(false);
@@ -1470,22 +1421,69 @@
mSearchDropTargetBar.setQsbSearchBar(getOrCreateQsbBar());
}
- if (getResources().getBoolean(R.bool.debug_memory_enabled)) {
- Log.v(TAG, "adding WeightWatcher");
- mWeightWatcher = new WeightWatcher(this);
- mWeightWatcher.setAlpha(0.5f);
- ((FrameLayout) mLauncherView).addView(mWeightWatcher,
- new FrameLayout.LayoutParams(
- FrameLayout.LayoutParams.MATCH_PARENT,
- FrameLayout.LayoutParams.WRAP_CONTENT,
- Gravity.BOTTOM)
- );
-
- boolean show = shouldShowWeightWatcher();
- mWeightWatcher.setVisibility(show ? View.VISIBLE : View.GONE);
+ if (TestingUtils.MEMORY_DUMP_ENABLED) {
+ TestingUtils.addWeightWatcher(this);
}
}
+ private void setupOverviewPanel() {
+ mOverviewPanel = (ViewGroup) findViewById(R.id.overview_panel);
+
+ // Long-clicking buttons in the overview panel does the same thing as clicking them.
+ OnLongClickListener performClickOnLongClick = new OnLongClickListener() {
+ @Override
+ public boolean onLongClick(View v) {
+ return v.performClick();
+ }
+ };
+
+ // Bind wallpaper button actions
+ View wallpaperButton = findViewById(R.id.wallpaper_button);
+ wallpaperButton.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ if (!mWorkspace.isSwitchingState()) {
+ onClickWallpaperPicker(view);
+ }
+ }
+ });
+ wallpaperButton.setOnLongClickListener(performClickOnLongClick);
+ wallpaperButton.setOnTouchListener(getHapticFeedbackTouchListener());
+
+ // Bind widget button actions
+ mWidgetsButton = findViewById(R.id.widget_button);
+ mWidgetsButton.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ if (!mWorkspace.isSwitchingState()) {
+ onClickAddWidgetButton(view);
+ }
+ }
+ });
+ mWidgetsButton.setOnLongClickListener(performClickOnLongClick);
+ mWidgetsButton.setOnTouchListener(getHapticFeedbackTouchListener());
+
+ // Bind settings actions
+ View settingsButton = findViewById(R.id.settings_button);
+ boolean hasSettings = hasSettings();
+ if (hasSettings) {
+ settingsButton.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ if (!mWorkspace.isSwitchingState()) {
+ onClickSettingsButton(view);
+ }
+ }
+ });
+ settingsButton.setOnLongClickListener(performClickOnLongClick);
+ settingsButton.setOnTouchListener(getHapticFeedbackTouchListener());
+ } else {
+ settingsButton.setVisibility(View.GONE);
+ }
+
+ mOverviewPanel.setAlpha(0f);
+ }
+
/**
* Sets the all apps button. This method is called from {@link Hotseat}.
*/
@@ -1622,18 +1620,28 @@
// The AppWidgetHostView has already been inflated and instantiated
launcherInfo.hostView = hostView;
}
- launcherInfo.hostView.setTag(launcherInfo);
launcherInfo.hostView.setVisibility(View.VISIBLE);
- launcherInfo.notifyWidgetSizeChanged(this);
-
- mWorkspace.addInScreen(launcherInfo.hostView, container, screenId, info.cellX,
- info.cellY, launcherInfo.spanX, launcherInfo.spanY, isWorkspaceLocked());
-
- addWidgetToAutoAdvanceIfNeeded(launcherInfo.hostView, appWidgetInfo);
+ addAppWidgetToWorkspace(launcherInfo, appWidgetInfo, isWorkspaceLocked());
}
resetAddInfo();
}
+ private void addAppWidgetToWorkspace(LauncherAppWidgetInfo item,
+ LauncherAppWidgetProviderInfo appWidgetInfo, boolean insert) {
+ item.hostView.setTag(item);
+ item.onBindAppWidget(this);
+
+ item.hostView.setFocusable(true);
+ item.hostView.setOnFocusChangeListener(mFocusHandler);
+
+ mWorkspace.addInScreen(item.hostView, item.container, item.screenId,
+ item.cellX, item.cellY, item.spanX, item.spanY, insert);
+
+ if (!item.isCustomWidget()) {
+ addWidgetToAutoAdvanceIfNeeded(item.hostView, appWidgetInfo);
+ }
+ }
+
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
@@ -1647,7 +1655,10 @@
// processing a multi-step drop
if (mAppsView != null && mWidgetsView != null &&
mPendingAddInfo.container == ItemInfo.NO_ID) {
- showWorkspace(false);
+ if (!showWorkspace(false)) {
+ // If we are already on the workspace, then manually reset all apps
+ mAppsView.reset();
+ }
}
} else if (Intent.ACTION_USER_PRESENT.equals(action)) {
mUserPresent = true;
@@ -1680,31 +1691,10 @@
}
registerReceiver(mReceiver, filter);
FirstFrameAnimatorHelper.initializeDrawListener(getWindow().getDecorView());
- setupTransparentSystemBarsForLollipop();
mAttached = true;
mVisible = true;
}
- /**
- * Sets up transparent navigation and status bars in Lollipop.
- * This method is a no-op for other platform versions.
- */
- @TargetApi(Build.VERSION_CODES.LOLLIPOP)
- private void setupTransparentSystemBarsForLollipop() {
- if (Utilities.ATLEAST_LOLLIPOP) {
- Window window = getWindow();
- window.getAttributes().systemUiVisibility |=
- (View.SYSTEM_UI_FLAG_LAYOUT_STABLE
- | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
- | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);
- window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS
- | WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
- window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
- window.setStatusBarColor(Color.TRANSPARENT);
- window.setNavigationBarColor(Color.TRANSPARENT);
- }
- }
-
@Override
public void onDetachedFromWindow() {
super.onDetachedFromWindow();
@@ -1742,14 +1732,14 @@
mWorkspace.postDelayed(mBuildLayersRunnable, 500);
final ViewTreeObserver.OnDrawListener listener = this;
mWorkspace.post(new Runnable() {
- public void run() {
- if (mWorkspace != null &&
- mWorkspace.getViewTreeObserver() != null) {
- mWorkspace.getViewTreeObserver().
- removeOnDrawListener(listener);
- }
+ public void run() {
+ if (mWorkspace != null &&
+ mWorkspace.getViewTreeObserver() != null) {
+ mWorkspace.getViewTreeObserver().
+ removeOnDrawListener(listener);
}
- });
+ }
+ });
return;
}
});
@@ -1807,7 +1797,7 @@
}
});
- void addWidgetToAutoAdvanceIfNeeded(View hostView, AppWidgetProviderInfo appWidgetInfo) {
+ private void addWidgetToAutoAdvanceIfNeeded(View hostView, AppWidgetProviderInfo appWidgetInfo) {
if (appWidgetInfo == null || appWidgetInfo.autoAdvanceViewId == -1) return;
View v = hostView.findViewById(appWidgetInfo.autoAdvanceViewId);
if (v instanceof Advanceable) {
@@ -1817,18 +1807,13 @@
}
}
- void removeWidgetToAutoAdvance(View hostView) {
+ private void removeWidgetToAutoAdvance(View hostView) {
if (mWidgetsToAdvance.containsKey(hostView)) {
mWidgetsToAdvance.remove(hostView);
updateAutoAdvanceState();
}
}
- public void removeAppWidget(LauncherAppWidgetInfo launcherInfo) {
- removeWidgetToAutoAdvance(launcherInfo.hostView);
- launcherInfo.hostView = null;
- }
-
public void showOutOfSpaceMessage(boolean isHotseatLayout) {
int strId = (isHotseatLayout ? R.string.hotseat_out_of_space : R.string.out_of_space);
Toast.makeText(this, getString(strId), Toast.LENGTH_SHORT).show();
@@ -1910,7 +1895,7 @@
// In all these cases, only animate if we're already on home
mWorkspace.exitWidgetResizeMode();
- closeFolder();
+ closeFolder(alreadyOnHome);
exitSpringLoadedDragMode();
// If we are already on home, then just animate back to the workspace,
@@ -1923,7 +1908,7 @@
final View v = getWindow().peekDecorView();
if (v != null && v.getWindowToken() != null) {
- InputMethodManager imm = (InputMethodManager)getSystemService(
+ InputMethodManager imm = (InputMethodManager) getSystemService(
INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(v.getWindowToken(), 0);
}
@@ -1962,7 +1947,9 @@
mWorkspace.post(new Runnable() {
@Override
public void run() {
- mWorkspace.moveToDefaultScreen(true);
+ if (mWorkspace != null) {
+ mWorkspace.moveToDefaultScreen(true);
+ }
}
});
}
@@ -1992,7 +1979,7 @@
outState.putInt(RUNTIME_STATE, mState.ordinal());
// We close any open folder since it will not be re-opened, and we need to make sure
// this state is reflected.
- closeFolder();
+ closeFolder(false);
if (mPendingAddInfo.container != ItemInfo.NO_ID && mPendingAddInfo.screenId > -1 &&
mWaitingForResult) {
@@ -2008,7 +1995,6 @@
// Save the current widgets tray?
// TODO(hyunyoungs)
- outState.putSerializable(RUNTIME_STATE_VIEW_IDS, mItemIdToViewId);
if (mLauncherCallbacks != null) {
mLauncherCallbacks.onSaveInstanceState(outState);
@@ -2194,22 +2180,9 @@
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
super.onPrepareOptionsMenu(menu);
- if (!isOnCustomContent()) {
- // Close any open folders
- closeFolder();
- // Stop resizing any widgets
- mWorkspace.exitWidgetResizeMode();
- if (!mWorkspace.isInOverviewMode()) {
- // Show the overview mode
- showOverviewMode(true);
- } else {
- showWorkspace(true);
- }
- }
if (mLauncherCallbacks != null) {
return mLauncherCallbacks.onPrepareOptionsMenu(menu);
}
-
return false;
}
@@ -2259,8 +2232,11 @@
mPendingAddInfo.dropPos = null;
}
- void addAppWidgetImpl(final int appWidgetId, final ItemInfo info, final
+ void addAppWidgetFromDropImpl(final int appWidgetId, final ItemInfo info, final
AppWidgetHostView boundWidget, final LauncherAppWidgetProviderInfo appWidgetInfo) {
+ if (LOGD) {
+ Log.d(TAG, "Adding widget from drop");
+ }
addAppWidgetImpl(appWidgetId, info, boundWidget, appWidgetInfo, 0);
}
@@ -2368,8 +2344,14 @@
AppWidgetHostView hostView = info.boundWidget;
int appWidgetId;
if (hostView != null) {
+ // In the case where we've prebound the widget, we remove it from the DragLayer
+ if (LOGD) {
+ Log.d(TAG, "Removing widget view from drag layer and setting boundWidget to null");
+ }
+ getDragLayer().removeView(hostView);
+
appWidgetId = hostView.getAppWidgetId();
- addAppWidgetImpl(appWidgetId, info, hostView, info.info);
+ addAppWidgetFromDropImpl(appWidgetId, info, hostView, info.info);
// Clear the boundWidget so that it doesn't get destroyed.
info.boundWidget = null;
@@ -2382,7 +2364,7 @@
boolean success = mAppWidgetManager.bindAppWidgetIdIfAllowed(
appWidgetId, info.info, options);
if (success) {
- addAppWidgetImpl(appWidgetId, info, null, info.info);
+ addAppWidgetFromDropImpl(appWidgetId, info, null, info.info);
} else {
mPendingAddWidgetInfo = info.info;
Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_BIND);
@@ -2418,10 +2400,72 @@
return newFolder;
}
- void removeFolder(FolderInfo folder) {
+ /**
+ * Unbinds the view for the specified item, and removes the item and all its children.
+ *
+ * @param v the view being removed.
+ * @param itemInfo the {@link ItemInfo} for this view.
+ * @param deleteFromDb whether or not to delete this item from the db.
+ */
+ public boolean removeItem(View v, ItemInfo itemInfo, boolean deleteFromDb) {
+ if (itemInfo instanceof ShortcutInfo) {
+ // Remove the shortcut from the folder before removing it from launcher
+ FolderInfo folderInfo = sFolders.get(itemInfo.container);
+ if (folderInfo != null) {
+ folderInfo.remove((ShortcutInfo) itemInfo);
+ } else {
+ mWorkspace.removeWorkspaceItem(v);
+ }
+ if (deleteFromDb) {
+ LauncherModel.deleteItemFromDatabase(this, itemInfo);
+ }
+ } else if (itemInfo instanceof FolderInfo) {
+ final FolderInfo folderInfo = (FolderInfo) itemInfo;
+ unbindFolder(folderInfo);
+ mWorkspace.removeWorkspaceItem(v);
+ if (deleteFromDb) {
+ LauncherModel.deleteFolderAndContentsFromDatabase(this, folderInfo);
+ }
+ } else if (itemInfo instanceof LauncherAppWidgetInfo) {
+ final LauncherAppWidgetInfo widgetInfo = (LauncherAppWidgetInfo) itemInfo;
+ mWorkspace.removeWorkspaceItem(v);
+ removeWidgetToAutoAdvance(widgetInfo.hostView);
+ widgetInfo.hostView = null;
+ if (deleteFromDb) {
+ deleteWidgetInfo(widgetInfo);
+ }
+
+ } else {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Unbinds any launcher references to the folder.
+ */
+ private void unbindFolder(FolderInfo folder) {
sFolders.remove(folder.id);
}
+ /**
+ * Deletes the widget info and the widget id.
+ */
+ private void deleteWidgetInfo(final LauncherAppWidgetInfo widgetInfo) {
+ final LauncherAppWidgetHost appWidgetHost = getAppWidgetHost();
+ if (appWidgetHost != null && !widgetInfo.isCustomWidget() && widgetInfo.isWidgetIdValid()) {
+ // Deleting an app widget ID is a void call but writes to disk before returning
+ // to the caller...
+ new AsyncTask<Void, Void, Void>() {
+ public Void doInBackground(Void ... args) {
+ appWidgetHost.deleteAppWidgetId(widgetInfo.appWidgetId);
+ return null;
+ }
+ }.executeOnExecutor(Utilities.THREAD_POOL_EXECUTOR);
+ }
+ LauncherModel.deleteItemFromDatabase(this, widgetInfo);
+ }
+
@Override
public boolean dispatchKeyEvent(KeyEvent event) {
if (event.getAction() == KeyEvent.ACTION_DOWN) {
@@ -2485,6 +2529,9 @@
if (mAppWidgetHost != null) {
mAppWidgetHost.startListening();
}
+
+ // Recreate the QSB, as the widget has been reset.
+ bindSearchProviderChanged();
}
/**
@@ -2644,21 +2691,6 @@
return;
}
- final Intent intent = shortcut.intent;
-
- // Check for special shortcuts
- if (intent.getComponent() != null) {
- final String shortcutClass = intent.getComponent().getClassName();
-
- if (shortcutClass.equals(MemoryDumpActivity.class.getName())) {
- MemoryDumpActivity.startDump(this);
- return;
- } else if (shortcutClass.equals(ToggleWeightWatcher.class.getName())) {
- toggleShowWeightWatcher();
- return;
- }
- }
-
// Check for abandoned promise
if ((v instanceof BubbleTextView)
&& shortcut.isPromise()
@@ -2744,7 +2776,7 @@
if (openFolder != null) {
folderScreen = mWorkspace.getPageForView(openFolder);
// .. and close it
- closeFolder(openFolder);
+ closeFolder(openFolder, true);
if (folderScreen != mWorkspace.getCurrentPage()) {
// Close any folder open on the current screen
closeFolder();
@@ -3082,9 +3114,13 @@
}
oa.setDuration(getResources().getInteger(R.integer.config_folderExpandDuration));
oa.start();
+ if (Utilities.isPowerSaverOn(this)) {
+ // Animations are disabled in battery saver mode, so just skip to the end state.
+ oa.end();
+ }
}
- private void shrinkAndFadeInFolderIcon(final FolderIcon fi) {
+ private void shrinkAndFadeInFolderIcon(final FolderIcon fi, boolean animate) {
if (fi == null) return;
PropertyValuesHolder alpha = PropertyValuesHolder.ofFloat("alpha", 1.0f);
PropertyValuesHolder scaleX = PropertyValuesHolder.ofFloat("scaleX", 1.0f);
@@ -3110,6 +3146,9 @@
}
});
oa.start();
+ if (!animate) {
+ oa.end();
+ }
}
/**
@@ -3153,30 +3192,38 @@
}
public void closeFolder() {
+ closeFolder(true);
+ }
+
+ public void closeFolder(boolean animate) {
Folder folder = mWorkspace != null ? mWorkspace.getOpenFolder() : null;
if (folder != null) {
if (folder.isEditingName()) {
folder.dismissEditingName();
}
- closeFolder(folder);
+ closeFolder(folder, animate);
}
}
- public void closeFolder(Folder folder) {
+ public void closeFolder(Folder folder, boolean animate) {
folder.getInfo().opened = false;
ViewGroup parent = (ViewGroup) folder.getParent().getParent();
if (parent != null) {
FolderIcon fi = (FolderIcon) mWorkspace.getViewForTag(folder.mInfo);
- shrinkAndFadeInFolderIcon(fi);
+ shrinkAndFadeInFolderIcon(fi, animate);
if (fi != null) {
((CellLayout.LayoutParams) fi.getLayoutParams()).canReorder = true;
}
}
- folder.animateClosed();
+ if (animate) {
+ folder.animateClosed();
+ } else {
+ folder.close(false);
+ }
- // Notify the accessibility manager that this folder "window" has disappeard and no
- // longer occludeds the workspace items
+ // Notify the accessibility manager that this folder "window" has disappeared and no
+ // longer occludes the workspace items
getDragLayer().sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
}
@@ -3315,20 +3362,32 @@
}
}
- public void showWorkspace(boolean animated) {
- showWorkspace(WorkspaceStateTransitionAnimation.SCROLL_TO_CURRENT_PAGE, animated, null);
+ /**
+ * @return whether or not the Launcher state changed.
+ */
+ public boolean showWorkspace(boolean animated) {
+ return showWorkspace(WorkspaceStateTransitionAnimation.SCROLL_TO_CURRENT_PAGE, animated, null);
}
- public void showWorkspace(boolean animated, Runnable onCompleteRunnable) {
- showWorkspace(WorkspaceStateTransitionAnimation.SCROLL_TO_CURRENT_PAGE, animated,
+ /**
+ * @return whether or not the Launcher state changed.
+ */
+ public boolean showWorkspace(boolean animated, Runnable onCompleteRunnable) {
+ return showWorkspace(WorkspaceStateTransitionAnimation.SCROLL_TO_CURRENT_PAGE, animated,
onCompleteRunnable);
}
- protected void showWorkspace(int snapToPage, boolean animated) {
- showWorkspace(snapToPage, animated, null);
+ /**
+ * @return whether or not the Launcher state changed.
+ */
+ protected boolean showWorkspace(int snapToPage, boolean animated) {
+ return showWorkspace(snapToPage, animated, null);
}
- void showWorkspace(int snapToPage, boolean animated, Runnable onCompleteRunnable) {
+ /**
+ * @return whether or not the Launcher state changed.
+ */
+ boolean showWorkspace(int snapToPage, boolean animated, Runnable onCompleteRunnable) {
boolean changed = mState != State.WORKSPACE ||
mWorkspace.getState() != Workspace.State.NORMAL;
if (changed) {
@@ -3354,14 +3413,38 @@
getWindow().getDecorView()
.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
}
+ return changed;
}
+ /**
+ * Shows the overview button.
+ */
void showOverviewMode(boolean animated) {
+ showOverviewMode(animated, false);
+ }
+
+ /**
+ * Shows the overview button, and if {@param requestButtonFocus} is set, will force the focus
+ * onto one of the overview panel buttons.
+ */
+ void showOverviewMode(boolean animated, boolean requestButtonFocus) {
+ Runnable postAnimRunnable = null;
+ if (requestButtonFocus) {
+ postAnimRunnable = new Runnable() {
+ @Override
+ public void run() {
+ // Hitting the menu button when in touch mode does not trigger touch mode to
+ // be disabled, so if requested, force focus on one of the overview panel
+ // buttons.
+ mOverviewPanel.requestFocusFromTouch();
+ }
+ };
+ }
mWorkspace.setVisibility(View.VISIBLE);
mStateTransitionAnimation.startAnimationToWorkspace(mState, mWorkspace.getState(),
Workspace.State.OVERVIEW,
WorkspaceStateTransitionAnimation.SCROLL_TO_CURRENT_PAGE, animated,
- null /* onCompleteRunnable */);
+ postAnimRunnable);
mState = State.WORKSPACE;
}
@@ -3516,8 +3599,12 @@
// NO-OP
}
+ public boolean launcherCallbacksProvidesSearch() {
+ return (mLauncherCallbacks != null && mLauncherCallbacks.providesSearch());
+ }
+
public View getOrCreateQsbBar() {
- if (mLauncherCallbacks != null && mLauncherCallbacks.providesSearch()) {
+ if (launcherCallbacksProvidesSearch()) {
return mLauncherCallbacks.getQsbBar();
}
@@ -3536,33 +3623,35 @@
DeviceProfile portraitProfile = app.getInvariantDeviceProfile().portraitProfile;
DeviceProfile landscapeProfile = app.getInvariantDeviceProfile().landscapeProfile;
float density = getResources().getDisplayMetrics().density;
- Rect searchBounds = portraitProfile.getSearchBarBounds(Utilities.isRtl(getResources()));
- int maxHeight = (int) (searchBounds.height() / density);
+ Point searchDimens = portraitProfile.getSearchBarDimensForWidgetOpts(getResources());
+ int maxHeight = (int) (searchDimens.y / density);
int minHeight = maxHeight;
- int maxWidth = (int) (searchBounds.width() / density);
+ int maxWidth = (int) (searchDimens.x / density);
int minWidth = maxWidth;
if (!landscapeProfile.isVerticalBarLayout()) {
- searchBounds = landscapeProfile.getSearchBarBounds(Utilities.isRtl(getResources()));
- maxHeight = (int) Math.max(maxHeight, searchBounds.height() / density);
- minHeight = (int) Math.min(minHeight, searchBounds.height() / density);
- maxWidth = (int) Math.max(maxWidth, searchBounds.width() / density);
- minWidth = (int) Math.min(minWidth, searchBounds.width() / density);
+ searchDimens = landscapeProfile.getSearchBarDimensForWidgetOpts(getResources());
+ maxHeight = (int) Math.max(maxHeight, searchDimens.y / density);
+ minHeight = (int) Math.min(minHeight, searchDimens.y / density);
+ maxWidth = (int) Math.max(maxWidth, searchDimens.x / density);
+ minWidth = (int) Math.min(minWidth, searchDimens.x / density);
}
opts.putInt(AppWidgetManager.OPTION_APPWIDGET_MAX_HEIGHT, maxHeight);
opts.putInt(AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT, minHeight);
opts.putInt(AppWidgetManager.OPTION_APPWIDGET_MAX_WIDTH, maxWidth);
opts.putInt(AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH, minWidth);
+ if (LOGD) {
+ Log.d(TAG, "QSB widget options: maxHeight=" + maxHeight + " minHeight=" + minHeight
+ + " maxWidth=" + maxWidth + " minWidth=" + minWidth);
+ }
if (mLauncherCallbacks != null) {
opts.putAll(mLauncherCallbacks.getAdditionalSearchWidgetOptions());
}
- SharedPreferences sp = getSharedPreferences(
- LauncherAppState.getSharedPreferencesKey(), MODE_PRIVATE);
- int widgetId = sp.getInt(QSB_WIDGET_ID, -1);
+ int widgetId = mSharedPrefs.getInt(QSB_WIDGET_ID, -1);
AppWidgetProviderInfo widgetInfo = mAppWidgetManager.getAppWidgetInfo(widgetId);
if (!searchProvider.provider.flattenToString().equals(
- sp.getString(QSB_WIDGET_PROVIDER, null))
+ mSharedPrefs.getString(QSB_WIDGET_PROVIDER, null))
|| (widgetInfo == null)
|| !widgetInfo.provider.equals(searchProvider.provider)) {
// A valid widget is not already bound.
@@ -3580,10 +3669,10 @@
widgetId = -1;
}
- sp.edit()
+ mSharedPrefs.edit()
.putInt(QSB_WIDGET_ID, widgetId)
.putString(QSB_WIDGET_PROVIDER, searchProvider.provider.flattenToString())
- .commit();
+ .apply();
}
mAppWidgetHost.setQsbWidgetId(widgetId);
@@ -3754,30 +3843,6 @@
}
}
- private boolean shouldShowWeightWatcher() {
- String spKey = LauncherAppState.getSharedPreferencesKey();
- SharedPreferences sp = getSharedPreferences(spKey, Context.MODE_PRIVATE);
- boolean show = sp.getBoolean(SHOW_WEIGHT_WATCHER, SHOW_WEIGHT_WATCHER_DEFAULT);
-
- return show;
- }
-
- private void toggleShowWeightWatcher() {
- String spKey = LauncherAppState.getSharedPreferencesKey();
- SharedPreferences sp = getSharedPreferences(spKey, Context.MODE_PRIVATE);
- boolean show = sp.getBoolean(SHOW_WEIGHT_WATCHER, true);
-
- show = !show;
-
- SharedPreferences.Editor editor = sp.edit();
- editor.putBoolean(SHOW_WEIGHT_WATCHER, show);
- editor.commit();
-
- if (mWeightWatcher != null) {
- mWeightWatcher.setVisibility(show ? View.VISIBLE : View.GONE);
- }
- }
-
public void bindAppsAdded(final ArrayList<Long> newScreens,
final ArrayList<ItemInfo> addNotAnimated,
final ArrayList<ItemInfo> addAnimated,
@@ -3820,6 +3885,7 @@
*
* Implementation of the method from LauncherModel.Callbacks.
*/
+ @Override
public void bindItems(final ArrayList<ItemInfo> shortcuts, final int start, final int end,
final boolean forceAnimateIcons) {
Runnable r = new Runnable() {
@@ -3986,8 +4052,7 @@
pendingInfo.spanY = item.spanY;
pendingInfo.minSpanX = item.minSpanX;
pendingInfo.minSpanY = item.minSpanY;
- Bundle options = null;
- WidgetHostViewLoader.getDefaultOptionsForWidget(this, pendingInfo);
+ Bundle options = WidgetHostViewLoader.getDefaultOptionsForWidget(this, pendingInfo);
int newWidgetId = mAppWidgetHost.allocateAppWidgetId();
boolean success = mAppWidgetManager.bindAppWidgetIdIfAllowed(
@@ -4029,6 +4094,15 @@
+ appWidgetInfo.provider);
}
+ // Verify that we own the widget
+ AppWidgetProviderInfo info = mAppWidgetManager.getAppWidgetInfo(appWidgetId);
+ if (info == null || appWidgetInfo == null ||
+ !info.provider.equals(appWidgetInfo.provider)) {
+ Log.e(TAG, "Removing invalid widget: id=" + item.appWidgetId);
+ deleteWidgetInfo(item);
+ return;
+ }
+
item.hostView = mAppWidgetHost.createView(this, appWidgetId, appWidgetInfo);
item.minSpanX = appWidgetInfo.minSpanX;
item.minSpanY = appWidgetInfo.minSpanY;
@@ -4042,15 +4116,7 @@
item.hostView.setOnClickListener(this);
}
- item.hostView.setTag(item);
- item.onBindAppWidget(this);
-
- workspace.addInScreen(item.hostView, item.container, item.screenId, item.cellX,
- item.cellY, item.spanX, item.spanY, false);
- if (!item.isCustomWidget()) {
- addWidgetToAutoAdvanceIfNeeded(item.hostView, appWidgetInfo);
- }
-
+ addAppWidgetToWorkspace(item, appWidgetInfo, false);
workspace.requestLayout();
if (DEBUG_WIDGETS) {
@@ -4683,8 +4749,9 @@
/**
* Resizes an icon drawable to the correct icon size.
*/
- public void resizeIconDrawable(Drawable icon) {
+ public Drawable resizeIconDrawable(Drawable icon) {
icon.setBounds(0, 0, mDeviceProfile.iconSizePx, mDeviceProfile.iconSizePx);
+ return icon;
}
/**
diff --git a/src/com/android/launcher3/LauncherAnimUtils.java b/src/com/android/launcher3/LauncherAnimUtils.java
index 6a248a3..fa20f03 100644
--- a/src/com/android/launcher3/LauncherAnimUtils.java
+++ b/src/com/android/launcher3/LauncherAnimUtils.java
@@ -24,7 +24,6 @@
import android.annotation.TargetApi;
import android.os.Build;
import android.view.View;
-import android.view.ViewAnimationUtils;
import android.view.ViewTreeObserver;
import com.android.launcher3.util.UiThreadCircularReveal;
@@ -59,24 +58,25 @@
// it should be cancelled
public static void startAnimationAfterNextDraw(final Animator animator, final View view) {
view.getViewTreeObserver().addOnDrawListener(new ViewTreeObserver.OnDrawListener() {
- private boolean mStarted = false;
- public void onDraw() {
- if (mStarted) return;
- mStarted = true;
- // Use this as a signal that the animation was cancelled
- if (animator.getDuration() == 0) {
- return;
- }
- animator.start();
+ private boolean mStarted = false;
- final ViewTreeObserver.OnDrawListener listener = this;
- view.post(new Runnable() {
- public void run() {
- view.getViewTreeObserver().removeOnDrawListener(listener);
- }
- });
+ public void onDraw() {
+ if (mStarted) return;
+ mStarted = true;
+ // Use this as a signal that the animation was cancelled
+ if (animator.getDuration() == 0) {
+ return;
}
- });
+ animator.start();
+
+ final ViewTreeObserver.OnDrawListener listener = this;
+ view.post(new Runnable() {
+ public void run() {
+ view.getViewTreeObserver().removeOnDrawListener(listener);
+ }
+ });
+ }
+ });
}
public static void onDestroyActivity() {
diff --git a/src/com/android/launcher3/LauncherAppState.java b/src/com/android/launcher3/LauncherAppState.java
index d87ad67..430d193 100644
--- a/src/com/android/launcher3/LauncherAppState.java
+++ b/src/com/android/launcher3/LauncherAppState.java
@@ -27,6 +27,8 @@
import com.android.launcher3.compat.LauncherAppsCompat;
import com.android.launcher3.compat.PackageInstallerCompat;
import com.android.launcher3.compat.UserManagerCompat;
+import com.android.launcher3.util.ConfigMonitor;
+import com.android.launcher3.util.TestingUtils;
import com.android.launcher3.util.Thunk;
import java.lang.ref.WeakReference;
@@ -79,8 +81,8 @@
Log.v(Launcher.TAG, "LauncherAppState inited");
- if (sContext.getResources().getBoolean(R.bool.debug_memory_enabled)) {
- MemoryTracker.startTrackingMe(sContext, "L");
+ if (TestingUtils.MEMORY_DUMP_ENABLED) {
+ TestingUtils.startTrackingMemory(sContext);
}
mInvariantDeviceProfile = new InvariantDeviceProfile(sContext);
@@ -103,6 +105,7 @@
sContext.registerReceiver(mModel, filter);
UserManagerCompat.getInstance(sContext).enableAndResetCache();
+ new ConfigMonitor(sContext).register();
}
/**
@@ -152,14 +155,10 @@
return sLauncherProvider.get();
}
- public static String getSharedPreferencesKey() {
- return LauncherFiles.SHARED_PREFERENCES_KEY;
- }
-
public WidgetPreviewLoader getWidgetCache() {
return mWidgetCache;
}
-
+
public void onWallpaperChanged() {
mWallpaperChangedSinceLastCheck = true;
}
diff --git a/src/com/android/launcher3/LauncherAppWidgetHost.java b/src/com/android/launcher3/LauncherAppWidgetHost.java
index 6c3a1e8..b07ccc3 100644
--- a/src/com/android/launcher3/LauncherAppWidgetHost.java
+++ b/src/com/android/launcher3/LauncherAppWidgetHost.java
@@ -20,6 +20,7 @@
import android.appwidget.AppWidgetHostView;
import android.appwidget.AppWidgetProviderInfo;
import android.content.Context;
+import android.os.DeadObjectException;
import android.os.TransactionTooLargeException;
import android.view.LayoutInflater;
import android.view.View;
@@ -69,7 +70,8 @@
try {
super.startListening();
} catch (Exception e) {
- if (e.getCause() instanceof TransactionTooLargeException) {
+ if (e.getCause() instanceof TransactionTooLargeException ||
+ e.getCause() instanceof DeadObjectException) {
// We're willing to let this slide. The exception is being caused by the list of
// RemoteViews which is being passed back. The startListening relationship will
// have been established by this point, and we will end up populating the
@@ -125,5 +127,8 @@
LauncherAppWidgetProviderInfo info = LauncherAppWidgetProviderInfo.fromProviderInfo(
mLauncher, appWidget);
super.onProviderChanged(appWidgetId, info);
+ // The super method updates the dimensions of the providerInfo. Update the
+ // launcher spans accordingly.
+ info.initSpans();
}
}
diff --git a/src/com/android/launcher3/LauncherAppWidgetHostView.java b/src/com/android/launcher3/LauncherAppWidgetHostView.java
index cf461a5..c49d43f 100644
--- a/src/com/android/launcher3/LauncherAppWidgetHostView.java
+++ b/src/com/android/launcher3/LauncherAppWidgetHostView.java
@@ -19,6 +19,8 @@
import android.appwidget.AppWidgetHostView;
import android.appwidget.AppWidgetProviderInfo;
import android.content.Context;
+import android.graphics.Rect;
+import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
@@ -28,6 +30,8 @@
import com.android.launcher3.DragLayer.TouchCompleteListener;
+import java.util.ArrayList;
+
/**
* {@inheritDoc}
*/
@@ -43,6 +47,8 @@
private float mSlop;
+ private boolean mChildrenFocused;
+
public LauncherAppWidgetHostView(Context context) {
super(context);
mContext = context;
@@ -175,6 +181,90 @@
@Override
public int getDescendantFocusability() {
- return ViewGroup.FOCUS_BLOCK_DESCENDANTS;
+ return mChildrenFocused ? ViewGroup.FOCUS_BEFORE_DESCENDANTS
+ : ViewGroup.FOCUS_BLOCK_DESCENDANTS;
+ }
+
+ @Override
+ public boolean dispatchKeyEvent(KeyEvent event) {
+ if (mChildrenFocused && event.getKeyCode() == KeyEvent.KEYCODE_ESCAPE
+ && event.getAction() == KeyEvent.ACTION_UP) {
+ mChildrenFocused = false;
+ requestFocus();
+ return true;
+ }
+ return super.dispatchKeyEvent(event);
+ }
+
+ @Override
+ public boolean onKeyDown(int keyCode, KeyEvent event) {
+ if (!mChildrenFocused && keyCode == KeyEvent.KEYCODE_ENTER) {
+ event.startTracking();
+ return true;
+ }
+ return super.onKeyDown(keyCode, event);
+ }
+
+ @Override
+ public boolean onKeyUp(int keyCode, KeyEvent event) {
+ if (event.isTracking()) {
+ if (!mChildrenFocused && keyCode == KeyEvent.KEYCODE_ENTER) {
+ mChildrenFocused = true;
+ ArrayList<View> focusableChildren = getFocusables(FOCUS_FORWARD);
+ focusableChildren.remove(this);
+ int childrenCount = focusableChildren.size();
+ switch (childrenCount) {
+ case 0:
+ mChildrenFocused = false;
+ break;
+ case 1: {
+ if (getTag() instanceof ItemInfo) {
+ ItemInfo item = (ItemInfo) getTag();
+ if (item.spanX == 1 && item.spanY == 1) {
+ focusableChildren.get(0).performClick();
+ mChildrenFocused = false;
+ return true;
+ }
+ }
+ // continue;
+ }
+ default:
+ focusableChildren.get(0).requestFocus();
+ return true;
+ }
+ }
+ }
+ return super.onKeyUp(keyCode, event);
+ }
+
+ @Override
+ protected void onFocusChanged(boolean gainFocus, int direction, Rect previouslyFocusedRect) {
+ if (gainFocus) {
+ mChildrenFocused = false;
+ }
+ super.onFocusChanged(gainFocus, direction, previouslyFocusedRect);
+ }
+
+ @Override
+ public void requestChildFocus(View child, View focused) {
+ super.requestChildFocus(child, focused);
+ dispatchChildFocus(focused != null);
+ }
+
+ @Override
+ public void clearChildFocus(View child) {
+ super.clearChildFocus(child);
+ dispatchChildFocus(false);
+ }
+
+ @Override
+ public boolean dispatchUnhandledMove(View focused, int direction) {
+ return mChildrenFocused;
+ }
+
+ private void dispatchChildFocus(boolean focused) {
+ if (getOnFocusChangeListener() != null) {
+ getOnFocusChangeListener().onFocusChange(this, focused || isFocused());
+ }
}
}
diff --git a/src/com/android/launcher3/LauncherAppWidgetInfo.java b/src/com/android/launcher3/LauncherAppWidgetInfo.java
index 882f7e2..55edf45 100644
--- a/src/com/android/launcher3/LauncherAppWidgetInfo.java
+++ b/src/com/android/launcher3/LauncherAppWidgetInfo.java
@@ -123,17 +123,11 @@
*/
void onBindAppWidget(Launcher launcher) {
if (!mHasNotifiedInitialWidgetSizeChanged) {
- notifyWidgetSizeChanged(launcher);
+ AppWidgetResizeFrame.updateWidgetSizeRanges(hostView, launcher, spanX, spanY);
+ mHasNotifiedInitialWidgetSizeChanged = true;
}
}
- /**
- * Trigger an update callback to the widget to notify it that its size has changed.
- */
- void notifyWidgetSizeChanged(Launcher launcher) {
- AppWidgetResizeFrame.updateWidgetSizeRanges(hostView, launcher, spanX, spanY);
- mHasNotifiedInitialWidgetSizeChanged = true;
- }
@Override
public String toString() {
diff --git a/src/com/android/launcher3/LauncherAppWidgetProviderInfo.java b/src/com/android/launcher3/LauncherAppWidgetProviderInfo.java
index 71a08a8..28d8052 100644
--- a/src/com/android/launcher3/LauncherAppWidgetProviderInfo.java
+++ b/src/com/android/launcher3/LauncherAppWidgetProviderInfo.java
@@ -59,7 +59,7 @@
initSpans();
}
- private void initSpans() {
+ public void initSpans() {
LauncherAppState app = LauncherAppState.getInstance();
InvariantDeviceProfile idp = app.getInvariantDeviceProfile();
diff --git a/src/com/android/launcher3/LauncherBackupAgentHelper.java b/src/com/android/launcher3/LauncherBackupAgentHelper.java
index 8eb4e63..6619aaf 100644
--- a/src/com/android/launcher3/LauncherBackupAgentHelper.java
+++ b/src/com/android/launcher3/LauncherBackupAgentHelper.java
@@ -30,7 +30,7 @@
public class LauncherBackupAgentHelper extends BackupAgentHelper {
- private static final String TAG = "LauncherBackupAgentHelper";
+ private static final String TAG = "LauncherBAHelper";
private static final String LAUNCHER_DATA_PREFIX = "L";
@@ -91,7 +91,7 @@
if (hasData && mHelper.restoreSuccessful) {
LauncherAppState.getLauncherProvider().clearFlagEmptyDbCreated();
- LauncherClings.synchonouslyMarkFirstRunClingDismissed(this);
+ LauncherClings.markFirstRunClingDismissed(this);
// Rank was added in v4.
if (mHelper.restoredBackupVersion <= 3) {
diff --git a/src/com/android/launcher3/LauncherBackupHelper.java b/src/com/android/launcher3/LauncherBackupHelper.java
index 2d11d3a..47d1ce9 100644
--- a/src/com/android/launcher3/LauncherBackupHelper.java
+++ b/src/com/android/launcher3/LauncherBackupHelper.java
@@ -41,15 +41,15 @@
import com.android.launcher3.LauncherSettings.Favorites;
import com.android.launcher3.LauncherSettings.WorkspaceScreens;
-import com.android.launcher3.backup.BackupProtos;
-import com.android.launcher3.backup.BackupProtos.CheckedMessage;
-import com.android.launcher3.backup.BackupProtos.DeviceProfieData;
-import com.android.launcher3.backup.BackupProtos.Favorite;
-import com.android.launcher3.backup.BackupProtos.Journal;
-import com.android.launcher3.backup.BackupProtos.Key;
-import com.android.launcher3.backup.BackupProtos.Resource;
-import com.android.launcher3.backup.BackupProtos.Screen;
-import com.android.launcher3.backup.BackupProtos.Widget;
+import com.android.launcher3.backup.nano.BackupProtos;
+import com.android.launcher3.backup.nano.BackupProtos.CheckedMessage;
+import com.android.launcher3.backup.nano.BackupProtos.DeviceProfieData;
+import com.android.launcher3.backup.nano.BackupProtos.Favorite;
+import com.android.launcher3.backup.nano.BackupProtos.Journal;
+import com.android.launcher3.backup.nano.BackupProtos.Key;
+import com.android.launcher3.backup.nano.BackupProtos.Resource;
+import com.android.launcher3.backup.nano.BackupProtos.Screen;
+import com.android.launcher3.backup.nano.BackupProtos.Widget;
import com.android.launcher3.compat.UserHandleCompat;
import com.android.launcher3.compat.UserManagerCompat;
import com.android.launcher3.model.MigrateFromRestoreTask;
@@ -768,13 +768,10 @@
try {
Key key = Key.parseFrom(Base64.decode(backupKey, Base64.DEFAULT));
if (key.checksum != checkKey(key)) {
- key = null;
throw new InvalidBackupException("invalid key read from stream" + backupKey);
}
return key;
- } catch (InvalidProtocolBufferNanoException e) {
- throw new InvalidBackupException(e);
- } catch (IllegalArgumentException e) {
+ } catch (InvalidProtocolBufferNanoException | IllegalArgumentException e) {
throw new InvalidBackupException(e);
}
}
@@ -1137,9 +1134,8 @@
* @param journal a Journal protocol buffer
*/
private void writeJournal(ParcelFileDescriptor newState, Journal journal) {
- FileOutputStream outStream = null;
try {
- outStream = new FileOutputStream(newState.getFileDescriptor());
+ FileOutputStream outStream = new FileOutputStream(newState.getFileDescriptor());
final byte[] journalBytes = writeCheckedBytes(journal);
outStream.write(journalBytes);
outStream.close();
diff --git a/src/com/android/launcher3/LauncherClings.java b/src/com/android/launcher3/LauncherClings.java
index 18fe8ef..5c1e830 100644
--- a/src/com/android/launcher3/LauncherClings.java
+++ b/src/com/android/launcher3/LauncherClings.java
@@ -73,9 +73,7 @@
LauncherModel.LOADER_FLAG_CLEAR_WORKSPACE
| LauncherModel.LOADER_FLAG_MIGRATE_SHORTCUTS);
// Set the flag to skip the folder cling
- String spKey = LauncherAppState.getSharedPreferencesKey();
- SharedPreferences sp = mLauncher.getSharedPreferences(spKey, Context.MODE_PRIVATE);
- SharedPreferences.Editor editor = sp.edit();
+ SharedPreferences.Editor editor = Utilities.getPrefs(mLauncher).edit();
editor.putBoolean(Launcher.USER_HAS_MIGRATED, true);
editor.apply();
// Disable the migration cling
@@ -253,11 +251,9 @@
!sharedPrefs.getBoolean(MIGRATION_CLING_DISMISSED_KEY, false);
}
- public static void synchonouslyMarkFirstRunClingDismissed(Context ctx) {
- SharedPreferences prefs = ctx.getSharedPreferences(
- LauncherAppState.getSharedPreferencesKey(), Context.MODE_PRIVATE);
- SharedPreferences.Editor editor = prefs.edit();
- editor.putBoolean(WORKSPACE_CLING_DISMISSED_KEY, true);
- editor.commit();
+ public static void markFirstRunClingDismissed(Context ctx) {
+ Utilities.getPrefs(ctx).edit()
+ .putBoolean(WORKSPACE_CLING_DISMISSED_KEY, true)
+ .apply();
}
}
diff --git a/src/com/android/launcher3/LauncherModel.java b/src/com/android/launcher3/LauncherModel.java
index 6e1aa2a..a34e001 100644
--- a/src/com/android/launcher3/LauncherModel.java
+++ b/src/com/android/launcher3/LauncherModel.java
@@ -1072,8 +1072,6 @@
/**
* Removes the specified item from the database
- * @param context
- * @param item
*/
public static void deleteItemFromDatabase(Context context, final ItemInfo item) {
ArrayList<ItemInfo> items = new ArrayList<ItemInfo>();
@@ -1083,8 +1081,6 @@
/**
* Removes the specified items from the database
- * @param context
- * @param item
*/
static void deleteItemsFromDatabase(Context context, final ArrayList<? extends ItemInfo> items) {
final ContentResolver cr = context.getContentResolver();
@@ -1175,9 +1171,9 @@
}
/**
- * Remove the contents of the specified folder from the database
+ * Remove the specified folder and all its contents from the database.
*/
- public static void deleteFolderContentsFromDatabase(Context context, final FolderInfo info) {
+ public static void deleteFolderAndContentsFromDatabase(Context context, final FolderInfo info) {
final ContentResolver cr = context.getContentResolver();
Runnable r = new Runnable() {
@@ -2391,7 +2387,7 @@
Collections.sort(allWorkspaceItems, new Comparator<ItemInfo>() {
@Override
public int compare(ItemInfo lhs, ItemInfo rhs) {
- return (int) (lhs.container - rhs.container);
+ return Utilities.longCompare(lhs.container, rhs.container);
}
});
for (ItemInfo info : allWorkspaceItems) {
@@ -2473,7 +2469,7 @@
lhs.cellY * cellCountX + lhs.cellX);
long rr = (rhs.container * containerOffset + rhs.screenId * screenOffset +
rhs.cellY * cellCountX + rhs.cellX);
- return (int) (lr - rr);
+ return Utilities.longCompare(lr, rr);
}
});
}
@@ -3557,7 +3553,7 @@
ComponentName componentName = intent.getComponent();
if (componentName == null) {
- Log.d(TAG, "Missing component found in getShortcutInfo: " + componentName);
+ Log.d(TAG, "Missing component found in getShortcutInfo");
return null;
}
diff --git a/src/com/android/launcher3/LauncherProvider.java b/src/com/android/launcher3/LauncherProvider.java
index 8791e9e..7674d2a 100644
--- a/src/com/android/launcher3/LauncherProvider.java
+++ b/src/com/android/launcher3/LauncherProvider.java
@@ -57,7 +57,6 @@
import com.android.launcher3.util.ManagedProfileHeuristic;
import com.android.launcher3.util.Thunk;
-import java.io.File;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Collections;
@@ -84,6 +83,10 @@
@Override
public boolean onCreate() {
final Context context = getContext();
+ // The content provider exists for the entire duration of the launcher main process and
+ // is the first component to get created. Initializing application context here ensures
+ // that LauncherAppState always exists in the main process.
+ LauncherAppState.setApplicationContext(context.getApplicationContext());
StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskWrites();
mOpenHelper = new DatabaseHelper(context);
StrictMode.setThreadPolicy(oldPolicy);
@@ -257,17 +260,13 @@
case LauncherSettings.Settings.METHOD_GET_BOOLEAN: {
Bundle result = new Bundle();
result.putBoolean(LauncherSettings.Settings.EXTRA_VALUE,
- getContext().getSharedPreferences(
- LauncherAppState.getSharedPreferencesKey(), Context.MODE_PRIVATE)
- .getBoolean(arg, extras.getBoolean(
- LauncherSettings.Settings.EXTRA_DEFAULT_VALUE)));
+ Utilities.getPrefs(getContext()).getBoolean(arg, extras.getBoolean(
+ LauncherSettings.Settings.EXTRA_DEFAULT_VALUE)));
return result;
}
case LauncherSettings.Settings.METHOD_SET_BOOLEAN: {
boolean value = extras.getBoolean(LauncherSettings.Settings.EXTRA_VALUE);
- getContext().getSharedPreferences(
- LauncherAppState.getSharedPreferencesKey(), Context.MODE_PRIVATE)
- .edit().putBoolean(arg, value).apply();
+ Utilities.getPrefs(getContext()).edit().putBoolean(arg, value).apply();
if (mListener != null) {
mListener.onSettingsChanged(arg, value);
}
@@ -331,10 +330,6 @@
return mOpenHelper.generateNewItemId();
}
- public void updateMaxItemId(long id) {
- mOpenHelper.updateMaxItemId(id);
- }
-
public long generateNewScreenId() {
return mOpenHelper.generateNewScreenId();
}
@@ -347,11 +342,7 @@
}
public void clearFlagEmptyDbCreated() {
- String spKey = LauncherAppState.getSharedPreferencesKey();
- getContext().getSharedPreferences(spKey, Context.MODE_PRIVATE)
- .edit()
- .remove(EMPTY_DATABASE_CREATED)
- .commit();
+ Utilities.getPrefs(getContext()).edit().remove(EMPTY_DATABASE_CREATED).commit();
}
/**
@@ -362,8 +353,7 @@
* 4) The default configuration for the particular device
*/
synchronized public void loadDefaultFavoritesIfNecessary() {
- String spKey = LauncherAppState.getSharedPreferencesKey();
- SharedPreferences sp = getContext().getSharedPreferences(spKey, Context.MODE_PRIVATE);
+ SharedPreferences sp = Utilities.getPrefs(getContext());
if (sp.getBoolean(EMPTY_DATABASE_CREATED, false)) {
Log.d(TAG, "loading default workspace");
@@ -463,14 +453,7 @@
public void deleteDatabase() {
// Are you sure? (y/n)
- final SQLiteDatabase db = mOpenHelper.getWritableDatabase();
- final File dbFile = new File(db.getPath());
- mOpenHelper.close();
- if (dbFile.exists()) {
- SQLiteDatabase.deleteDatabase(dbFile);
- }
- mOpenHelper = new DatabaseHelper(getContext());
- mOpenHelper.mListener = mListener;
+ mOpenHelper.createEmptyDB(mOpenHelper.getWritableDatabase());
}
private static class DatabaseHelper extends SQLiteOpenHelper implements LayoutParserCallback {
@@ -488,6 +471,16 @@
mContext = context;
mAppWidgetHost = new AppWidgetHost(context, Launcher.APPWIDGET_HOST_ID);
+ // Table creation sometimes fails silently, which leads to a crash loop.
+ // This way, we will try to create a table every time after crash, so the device
+ // would eventually be able to recover.
+ if (!tableExists(TABLE_FAVORITES) || !tableExists(TABLE_WORKSPACE_SCREENS)) {
+ Log.e(TAG, "Tables are missing after onCreate has been called. Trying to recreate");
+ // This operation is a no-op if the table already exists.
+ addFavoritesTable(getWritableDatabase(), true);
+ addWorkspacesTable(getWritableDatabase(), true);
+ }
+
// In the case where neither onCreate nor onUpgrade gets called, we read the maxId from
// the DB here
if (mMaxItemId == -1) {
@@ -498,6 +491,18 @@
}
}
+ private boolean tableExists(String tableName) {
+ Cursor c = getReadableDatabase().query(
+ true, "sqlite_master", new String[] {"tbl_name"},
+ "tbl_name = ?", new String[] {tableName},
+ null, null, null, null, null);
+ try {
+ return c.getCount() > 0;
+ } finally {
+ c.close();
+ }
+ }
+
public boolean wasNewDbCreated() {
return mNewDbCreated;
}
@@ -510,37 +515,8 @@
mMaxScreenId = 0;
mNewDbCreated = true;
- UserManagerCompat userManager = UserManagerCompat.getInstance(mContext);
- long userSerialNumber = userManager.getSerialNumberForUser(
- UserHandleCompat.myUserHandle());
-
- db.execSQL("CREATE TABLE favorites (" +
- "_id INTEGER PRIMARY KEY," +
- "title TEXT," +
- "intent TEXT," +
- "container INTEGER," +
- "screen INTEGER," +
- "cellX INTEGER," +
- "cellY INTEGER," +
- "spanX INTEGER," +
- "spanY INTEGER," +
- "itemType INTEGER," +
- "appWidgetId INTEGER NOT NULL DEFAULT -1," +
- "isShortcut INTEGER," +
- "iconType INTEGER," +
- "iconPackage TEXT," +
- "iconResource TEXT," +
- "icon BLOB," +
- "uri TEXT," +
- "displayMode INTEGER," +
- "appWidgetProvider TEXT," +
- "modified INTEGER NOT NULL DEFAULT 0," +
- "restored INTEGER NOT NULL DEFAULT 0," +
- "profileId INTEGER DEFAULT " + userSerialNumber + "," +
- "rank INTEGER NOT NULL DEFAULT 0," +
- "options INTEGER NOT NULL DEFAULT 0" +
- ");");
- addWorkspacesTable(db);
+ addFavoritesTable(db, false);
+ addWorkspacesTable(db, false);
// Database was just created, so wipe any previous widgets
if (mAppWidgetHost != null) {
@@ -571,8 +547,43 @@
ManagedProfileHeuristic.processAllUsers(Collections.<UserHandleCompat>emptyList(), mContext);
}
- private void addWorkspacesTable(SQLiteDatabase db) {
- db.execSQL("CREATE TABLE " + TABLE_WORKSPACE_SCREENS + " (" +
+ private void addFavoritesTable(SQLiteDatabase db, boolean optional) {
+ UserManagerCompat userManager = UserManagerCompat.getInstance(mContext);
+ long userSerialNumber = userManager.getSerialNumberForUser(
+ UserHandleCompat.myUserHandle());
+ String ifNotExists = optional ? " IF NOT EXISTS " : "";
+
+ db.execSQL("CREATE TABLE " + ifNotExists + TABLE_FAVORITES + " (" +
+ "_id INTEGER PRIMARY KEY," +
+ "title TEXT," +
+ "intent TEXT," +
+ "container INTEGER," +
+ "screen INTEGER," +
+ "cellX INTEGER," +
+ "cellY INTEGER," +
+ "spanX INTEGER," +
+ "spanY INTEGER," +
+ "itemType INTEGER," +
+ "appWidgetId INTEGER NOT NULL DEFAULT -1," +
+ "isShortcut INTEGER," +
+ "iconType INTEGER," +
+ "iconPackage TEXT," +
+ "iconResource TEXT," +
+ "icon BLOB," +
+ "uri TEXT," +
+ "displayMode INTEGER," +
+ "appWidgetProvider TEXT," +
+ "modified INTEGER NOT NULL DEFAULT 0," +
+ "restored INTEGER NOT NULL DEFAULT 0," +
+ "profileId INTEGER DEFAULT " + userSerialNumber + "," +
+ "rank INTEGER NOT NULL DEFAULT 0," +
+ "options INTEGER NOT NULL DEFAULT 0" +
+ ");");
+ }
+
+ private void addWorkspacesTable(SQLiteDatabase db, boolean optional) {
+ String ifNotExists = optional ? " IF NOT EXISTS " : "";
+ db.execSQL("CREATE TABLE " + ifNotExists + TABLE_WORKSPACE_SCREENS + " (" +
LauncherSettings.WorkspaceScreens._ID + " INTEGER PRIMARY KEY," +
LauncherSettings.WorkspaceScreens.SCREEN_RANK + " INTEGER," +
LauncherSettings.ChangeLogColumns.MODIFIED + " INTEGER NOT NULL DEFAULT 0" +
@@ -611,15 +622,11 @@
}
private void setFlagJustLoadedOldDb() {
- String spKey = LauncherAppState.getSharedPreferencesKey();
- SharedPreferences sp = mContext.getSharedPreferences(spKey, Context.MODE_PRIVATE);
- sp.edit().putBoolean(EMPTY_DATABASE_CREATED, false).commit();
+ Utilities.getPrefs(mContext).edit().putBoolean(EMPTY_DATABASE_CREATED, false).commit();
}
private void setFlagEmptyDbCreated() {
- String spKey = LauncherAppState.getSharedPreferencesKey();
- SharedPreferences sp = mContext.getSharedPreferences(spKey, Context.MODE_PRIVATE);
- sp.edit().putBoolean(EMPTY_DATABASE_CREATED, true).commit();
+ Utilities.getPrefs(mContext).edit().putBoolean(EMPTY_DATABASE_CREATED, true).commit();
}
@Override
@@ -632,7 +639,7 @@
// With the new shrink-wrapped and re-orderable workspaces, it makes sense
// to persist workspace screens and their relative order.
mMaxScreenId = 0;
- addWorkspacesTable(db);
+ addWorkspacesTable(db, false);
}
case 13: {
db.beginTransaction();
@@ -678,7 +685,7 @@
// available (tablet users). Because one of the possible cling flows (migration)
// is very destructive (wipes out workspaces), we want to prevent this from showing
// until clear data. We do so by marking that the clings have been shown.
- LauncherClings.synchonouslyMarkFirstRunClingDismissed(mContext);
+ LauncherClings.markFirstRunClingDismissed(mContext);
}
case 17: {
// No-op
@@ -828,7 +835,7 @@
}
db.execSQL("DROP TABLE IF EXISTS " + TABLE_WORKSPACE_SCREENS);
- addWorkspacesTable(db);
+ addWorkspacesTable(db, false);
// Add all screen ids back
int total = sortedIDs.size();
@@ -926,10 +933,6 @@
return dbInsertAndCheck(this, db, TABLE_FAVORITES, null, values);
}
- public void updateMaxItemId(long id) {
- mMaxItemId = id + 1;
- }
-
public void checkId(String table, ContentValues values) {
long id = values.getAsLong(LauncherSettings.BaseLauncherColumns._ID);
if (table == LauncherProvider.TABLE_WORKSPACE_SCREENS) {
diff --git a/src/com/android/launcher3/LauncherRootView.java b/src/com/android/launcher3/LauncherRootView.java
index e8c11c4..71ccd85 100644
--- a/src/com/android/launcher3/LauncherRootView.java
+++ b/src/com/android/launcher3/LauncherRootView.java
@@ -1,17 +1,69 @@
package com.android.launcher3;
+import android.annotation.TargetApi;
+import android.app.ActivityManager;
import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
import android.graphics.Rect;
import android.util.AttributeSet;
+import android.view.View;
public class LauncherRootView extends InsettableFrameLayout {
+
+ private final Paint mOpaquePaint;
+ private boolean mDrawRightInsetBar;
+
+ private View mAlignedView;
+
public LauncherRootView(Context context, AttributeSet attrs) {
super(context, attrs);
+
+ mOpaquePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+ mOpaquePaint.setColor(Color.BLACK);
+ mOpaquePaint.setStyle(Paint.Style.FILL);
}
@Override
+ protected void onFinishInflate() {
+ if (getChildCount() > 0) {
+ // LauncherRootView contains only one child, which should be aligned
+ // based on the horizontal insets.
+ mAlignedView = getChildAt(0);
+ }
+ super.onFinishInflate();
+ }
+
+ @TargetApi(23)
+ @Override
protected boolean fitSystemWindows(Rect insets) {
- setInsets(insets);
+ mDrawRightInsetBar = insets.right > 0 &&
+ (!Utilities.ATLEAST_MARSHMALLOW ||
+ getContext().getSystemService(ActivityManager.class).isLowRamDevice());
+ setInsets(mDrawRightInsetBar ? new Rect(0, insets.top, 0, insets.bottom) : insets);
+
+ if (mAlignedView != null) {
+ // Apply margins on aligned view to handle left/right insets.
+ MarginLayoutParams lp = (MarginLayoutParams) mAlignedView.getLayoutParams();
+ if (lp.leftMargin != insets.left || lp.rightMargin != insets.right) {
+ lp.leftMargin = insets.left;
+ lp.rightMargin = insets.right;
+ mAlignedView.setLayoutParams(lp);
+ }
+ }
+
return true; // I'll take it from here
}
+
+ @Override
+ protected void dispatchDraw(Canvas canvas) {
+ super.dispatchDraw(canvas);
+
+ // If the right inset is opaque, draw a black rectangle to ensure that is stays opaque.
+ if (mDrawRightInsetBar) {
+ int width = getWidth();
+ canvas.drawRect(width - mInsets.right, 0, width, getHeight(), mOpaquePaint);
+ }
+ }
}
\ No newline at end of file
diff --git a/src/com/android/launcher3/LauncherStateTransitionAnimation.java b/src/com/android/launcher3/LauncherStateTransitionAnimation.java
index cdde8c1..83b12a9 100644
--- a/src/com/android/launcher3/LauncherStateTransitionAnimation.java
+++ b/src/com/android/launcher3/LauncherStateTransitionAnimation.java
@@ -22,6 +22,7 @@
import android.animation.ObjectAnimator;
import android.animation.PropertyValuesHolder;
import android.animation.TimeInterpolator;
+import android.animation.ValueAnimator;
import android.annotation.SuppressLint;
import android.content.res.Resources;
import android.util.Log;
@@ -229,6 +230,8 @@
startWorkspaceSearchBarAnimation(animation, fromWorkspaceState, toWorkspaceState,
animated ? revealDuration : 0, overlaySearchBarView);
+ Animator updateTransitionStepAnim = dispatchOnLauncherTransitionStepAnim(fromView, toView);
+
if (animated && initialized) {
// Setup the reveal view animation
int width = revealView.getMeasuredWidth();
@@ -274,7 +277,7 @@
if (overlaySearchBarView != null) {
overlaySearchBarView.setAlpha(0f);
ObjectAnimator searchBarAlpha = ObjectAnimator.ofFloat(overlaySearchBarView, "alpha", 0f, 1f);
- searchBarAlpha.setDuration(100);
+ searchBarAlpha.setDuration(revealDuration / 2);
searchBarAlpha.setInterpolator(new AccelerateInterpolator(1.5f));
layerViews.put(overlaySearchBarView, BUILD_AND_SET_LAYER);
animation.play(searchBarAlpha);
@@ -342,11 +345,12 @@
animation.play(workspaceAnim);
}
+ animation.play(updateTransitionStepAnim);
+
// Dispatch the prepare transition signal
dispatchOnLauncherTransitionPrepare(fromView, animated, false);
dispatchOnLauncherTransitionPrepare(toView, animated, false);
-
final AnimatorSet stateAnimation = animation;
final Runnable startAnimRunnable = new Runnable() {
public void run() {
@@ -402,6 +406,24 @@
}
/**
+ * Returns an Animator that calls {@link #dispatchOnLauncherTransitionStep(View, float)} on
+ * {@param fromView} and {@param toView} as the animation interpolates.
+ *
+ * This is a bit hacky: we create a dummy ValueAnimator just for the AnimatorUpdateListener.
+ */
+ private Animator dispatchOnLauncherTransitionStepAnim(final View fromView, final View toView) {
+ ValueAnimator updateAnimator = ValueAnimator.ofFloat(0, 1);
+ updateAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+ @Override
+ public void onAnimationUpdate(ValueAnimator animation) {
+ dispatchOnLauncherTransitionStep(fromView, animation.getAnimatedFraction());
+ dispatchOnLauncherTransitionStep(toView, animation.getAnimatedFraction());
+ }
+ });
+ return updateAnimator;
+ }
+
+ /**
* Starts and animation to the workspace from the apps view.
*/
private void startAnimationToWorkspaceFromAllApps(final Workspace.State fromWorkspaceState,
@@ -509,12 +531,16 @@
startWorkspaceSearchBarAnimation(animation, fromWorkspaceState, toWorkspaceState,
animated ? revealDuration : 0, overlaySearchBarView);
+ Animator updateTransitionStepAnim = dispatchOnLauncherTransitionStepAnim(fromView, toView);
+
if (animated && initialized) {
// Play the workspace animation
if (workspaceAnim != null) {
animation.play(workspaceAnim);
}
+ animation.play(updateTransitionStepAnim);
+
// hideAppsCustomizeHelper is called in some cases when it is already hidden
// don't perform all these no-op animations. In particularly, this was causing
// the all-apps button to pop in and out.
@@ -593,8 +619,8 @@
if (overlaySearchBarView != null) {
overlaySearchBarView.setAlpha(1f);
ObjectAnimator searchAlpha = ObjectAnimator.ofFloat(overlaySearchBarView, "alpha", 1f, 0f);
- searchAlpha.setDuration(material ? 100 : 150);
- searchAlpha.setInterpolator(decelerateInterpolator);
+ searchAlpha.setDuration(revealDuration / 2);
+ searchAlpha.setInterpolator(new AccelerateInterpolator(1.5f));
searchAlpha.setStartDelay(material ? 0 : itemsAlphaStagger + SINGLE_FRAME_DELAY);
layerViews.put(overlaySearchBarView, BUILD_AND_SET_LAYER);
animation.play(searchAlpha);
@@ -615,11 +641,11 @@
}
animation.play(reveal);
}
-
- dispatchOnLauncherTransitionPrepare(fromView, animated, true);
- dispatchOnLauncherTransitionPrepare(toView, animated, true);
}
+ dispatchOnLauncherTransitionPrepare(fromView, animated, true);
+ dispatchOnLauncherTransitionPrepare(toView, animated, true);
+
animation.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
@@ -710,28 +736,29 @@
toWorkspaceState.getSearchDropTargetBarState();
if (overlaySearchBar != null) {
- if ((toWorkspaceState == Workspace.State.NORMAL) &&
- (fromWorkspaceState == Workspace.State.NORMAL_HIDDEN)) {
- // If we are transitioning from the overlay to the workspace, then show the
- // workspace search bar immediately and let the overlay search bar fade out on top
- mLauncher.getSearchDropTargetBar().animateToState(toSearchBarState, 0);
- } else if (fromWorkspaceState == Workspace.State.NORMAL) {
- // If we are transitioning from the workspace to the overlay, then keep the
- // workspace search bar visible until the overlay search bar fades in on top
- animation.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- mLauncher.getSearchDropTargetBar().animateToState(toSearchBarState, 0);
- }
- });
- } else {
- // Otherwise, then just animate the workspace search bar normally
- mLauncher.getSearchDropTargetBar().animateToState(toSearchBarState, duration);
+ if (mLauncher.launcherCallbacksProvidesSearch()) {
+ if ((toWorkspaceState == Workspace.State.NORMAL) &&
+ (fromWorkspaceState == Workspace.State.NORMAL_HIDDEN)) {
+ // If we are transitioning from the overlay to the workspace, then show the
+ // workspace search bar immediately and let the overlay search bar fade out on
+ // top
+ mLauncher.getSearchDropTargetBar().animateToState(toSearchBarState, 0);
+ return;
+ } else if (fromWorkspaceState == Workspace.State.NORMAL) {
+ // If we are transitioning from the workspace to the overlay, then keep the
+ // workspace search bar visible until the overlay search bar fades in on top
+ animation.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ mLauncher.getSearchDropTargetBar().animateToState(toSearchBarState, 0);
+ }
+ });
+ return;
+ }
}
- } else {
- // If there is no overlay search bar, then just animate the workspace search bar
- mLauncher.getSearchDropTargetBar().animateToState(toSearchBarState, duration);
}
+ // Fallback to the default search bar animation otherwise
+ mLauncher.getSearchDropTargetBar().animateToState(toSearchBarState, duration);
}
/**
diff --git a/src/com/android/launcher3/PageIndicatorMarker.java b/src/com/android/launcher3/PageIndicatorMarker.java
index f012db7..7bf21dd 100644
--- a/src/com/android/launcher3/PageIndicatorMarker.java
+++ b/src/com/android/launcher3/PageIndicatorMarker.java
@@ -45,6 +45,7 @@
}
protected void onFinishInflate() {
+ super.onFinishInflate();
mActiveMarker = (ImageView) findViewById(R.id.active);
mInactiveMarker = (ImageView) findViewById(R.id.inactive);
}
diff --git a/src/com/android/launcher3/PagedView.java b/src/com/android/launcher3/PagedView.java
index 05f0a05..b6d3cc4 100644
--- a/src/com/android/launcher3/PagedView.java
+++ b/src/com/android/launcher3/PagedView.java
@@ -1177,6 +1177,7 @@
canvas.rotate(90);
getEdgeVerticalPostion(sTmpIntPoint);
+
canvas.translate(sTmpIntPoint[0] - display.top, -display.width());
mEdgeGlowRight.setSize(sTmpIntPoint[1] - sTmpIntPoint[0], display.width());
if (mEdgeGlowRight.draw(canvas)) {
@@ -1219,7 +1220,17 @@
@Override
public boolean dispatchUnhandledMove(View focused, int direction) {
- // XXX-RTL: This will be fixed in a future CL
+ if (super.dispatchUnhandledMove(focused, direction)) {
+ return true;
+ }
+
+ if (mIsRtl) {
+ if (direction == View.FOCUS_LEFT) {
+ direction = View.FOCUS_RIGHT;
+ } else if (direction == View.FOCUS_RIGHT) {
+ direction = View.FOCUS_LEFT;
+ }
+ }
if (direction == View.FOCUS_LEFT) {
if (getCurrentPage() > 0) {
snapToPage(getCurrentPage() - 1);
@@ -1231,7 +1242,7 @@
return true;
}
}
- return super.dispatchUnhandledMove(focused, direction);
+ return false;
}
@Override
@@ -2072,11 +2083,6 @@
whichPage = validateNewPage(whichPage);
mNextPage = whichPage;
- View focusedChild = getFocusedChild();
- if (focusedChild != null && whichPage != mCurrentPage &&
- focusedChild == getPageAt(mCurrentPage)) {
- focusedChild.clearFocus();
- }
pageBeginMoving();
awakenScrollBars(duration);
diff --git a/src/com/android/launcher3/PendingAppWidgetHostView.java b/src/com/android/launcher3/PendingAppWidgetHostView.java
index 40eadab..85d8658 100644
--- a/src/com/android/launcher3/PendingAppWidgetHostView.java
+++ b/src/com/android/launcher3/PendingAppWidgetHostView.java
@@ -133,7 +133,7 @@
// 3) Setup icon in the center and app icon in the top right corner.
if (mDisabledForSafeMode) {
FastBitmapDrawable disabledIcon = mLauncher.createIconDrawable(mIcon);
- disabledIcon.setGhostModeEnabled(true);
+ disabledIcon.setState(FastBitmapDrawable.State.DISABLED);
mCenterDrawable = disabledIcon;
mSettingIconDrawable = null;
} else if (isReadyForClickSetup()) {
@@ -218,7 +218,7 @@
mRect.offsetTo((getWidth() - mRect.width()) / 2, (getHeight() - mRect.height()) / 2);
mCenterDrawable.setBounds(mRect);
} else {
- float iconSize = Math.min(availableWidth, availableHeight);
+ float iconSize = Math.max(0, Math.min(availableWidth, availableHeight));
// Use twice the setting size factor, as the setting is drawn at a corner and the
// icon is drawn in the center.
diff --git a/src/com/android/launcher3/PreloadIconDrawable.java b/src/com/android/launcher3/PreloadIconDrawable.java
index 45e4b2c..908c8b9 100644
--- a/src/com/android/launcher3/PreloadIconDrawable.java
+++ b/src/com/android/launcher3/PreloadIconDrawable.java
@@ -179,7 +179,8 @@
mPaint.setColor(getIndicatorColor());
}
if (mIcon instanceof FastBitmapDrawable) {
- ((FastBitmapDrawable) mIcon).setGhostModeEnabled(level <= 0);
+ ((FastBitmapDrawable) mIcon).setState(level <= 0 ?
+ FastBitmapDrawable.State.DISABLED : FastBitmapDrawable.State.NORMAL);
}
invalidateSelf();
diff --git a/src/com/android/launcher3/ShortcutAndWidgetContainer.java b/src/com/android/launcher3/ShortcutAndWidgetContainer.java
index 157b48a..21e72e9 100644
--- a/src/com/android/launcher3/ShortcutAndWidgetContainer.java
+++ b/src/com/android/launcher3/ShortcutAndWidgetContainer.java
@@ -23,7 +23,6 @@
import android.graphics.Rect;
import android.view.View;
import android.view.ViewGroup;
-import android.view.ViewGroup.LayoutParams;
public class ShortcutAndWidgetContainer extends ViewGroup {
static final String TAG = "CellLayoutChildren";
@@ -164,8 +163,7 @@
lp.height = getMeasuredHeight();
}
int childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(lp.width, MeasureSpec.EXACTLY);
- int childheightMeasureSpec = MeasureSpec.makeMeasureSpec(lp.height,
- MeasureSpec.EXACTLY);
+ int childheightMeasureSpec = MeasureSpec.makeMeasureSpec(lp.height, MeasureSpec.EXACTLY);
child.measure(childWidthMeasureSpec, childheightMeasureSpec);
}
diff --git a/src/com/android/launcher3/ShortcutInfo.java b/src/com/android/launcher3/ShortcutInfo.java
index 5766cf2..6bdcb4b 100644
--- a/src/com/android/launcher3/ShortcutInfo.java
+++ b/src/com/android/launcher3/ShortcutInfo.java
@@ -52,7 +52,7 @@
public static final int FLAG_AUTOINTALL_ICON = 2; //0B10;
/**
- * The icon is being installed. If {@link FLAG_RESTORED_ICON} or {@link FLAG_AUTOINTALL_ICON}
+ * The icon is being installed. If {@link #FLAG_RESTORED_ICON} or {@link #FLAG_AUTOINTALL_ICON}
* is set, then the icon is either being installed or is in a broken state.
*/
public static final int FLAG_INSTALL_SESSION_ACTIVE = 4; // 0B100;
@@ -126,19 +126,14 @@
private int mInstallProgress;
/**
- * Refer {@link AppInfo#firstInstallTime}.
- */
- public long firstInstallTime;
-
- /**
- * TODO move this to {@link status}
+ * TODO move this to {@link #status}
*/
int flags = 0;
/**
* If this shortcut is a placeholder, then intent will be a market intent for the package, and
* this will hold the original intent from the database. Otherwise, null.
- * Refer {@link #FLAG_RESTORE_PENDING}, {@link #FLAG_INSTALL_PENDING}
+ * Refer {@link #FLAG_RESTORED_ICON}, {@link #FLAG_AUTOINTALL_ICON}
*/
Intent promisedIntent;
@@ -172,7 +167,6 @@
mIcon = info.mIcon; // TODO: should make a copy here. maybe we don't need this ctor at all
customIcon = info.customIcon;
flags = info.flags;
- firstInstallTime = info.firstInstallTime;
user = info.user;
status = info.status;
}
@@ -184,7 +178,6 @@
intent = new Intent(info.intent);
customIcon = false;
flags = info.flags;
- firstInstallTime = info.firstInstallTime;
}
public void setIcon(Bitmap b) {
@@ -293,7 +286,6 @@
shortcut.intent = AppInfo.makeLaunchIntent(context, info, info.getUser());
shortcut.itemType = LauncherSettings.Favorites.ITEM_TYPE_APPLICATION;
shortcut.flags = AppInfo.initFlags(info);
- shortcut.firstInstallTime = info.getFirstInstallTime();
return shortcut;
}
}
diff --git a/src/com/android/launcher3/Stats.java b/src/com/android/launcher3/Stats.java
index cb0e252..83bca85 100644
--- a/src/com/android/launcher3/Stats.java
+++ b/src/com/android/launcher3/Stats.java
@@ -31,7 +31,7 @@
* Implemented by containers to provide a launch source for a given child.
*/
public interface LaunchSourceProvider {
- void fillInLaunchSourceData(Bundle sourceData);
+ void fillInLaunchSourceData(View v, Bundle sourceData);
}
/**
@@ -70,7 +70,7 @@
}
if (provider != null) {
- provider.fillInLaunchSourceData(sourceData);
+ provider.fillInLaunchSourceData(v, sourceData);
} else if (LauncherAppState.isDogfoodBuild()) {
throw new RuntimeException("Expected LaunchSourceProvider");
}
diff --git a/src/com/android/launcher3/ToggleWeightWatcher.java b/src/com/android/launcher3/ToggleWeightWatcher.java
deleted file mode 100644
index 33701a2..0000000
--- a/src/com/android/launcher3/ToggleWeightWatcher.java
+++ /dev/null
@@ -1,7 +0,0 @@
-package com.android.launcher3;
-
-import android.app.Activity;
-
-public class ToggleWeightWatcher extends Activity {
-
-}
diff --git a/src/com/android/launcher3/Utilities.java b/src/com/android/launcher3/Utilities.java
index 6521f15..f9524a1 100644
--- a/src/com/android/launcher3/Utilities.java
+++ b/src/com/android/launcher3/Utilities.java
@@ -46,8 +46,12 @@
import android.graphics.drawable.PaintDrawable;
import android.os.Build;
import android.os.Bundle;
+import android.os.PowerManager;
import android.os.Process;
+import android.text.Spannable;
+import android.text.SpannableString;
import android.text.TextUtils;
+import android.text.style.TtsSpan;
import android.util.DisplayMetrics;
import android.util.Log;
import android.util.Pair;
@@ -56,6 +60,10 @@
import android.view.View;
import android.widget.Toast;
+import com.android.launcher3.compat.UserHandleCompat;
+import com.android.launcher3.config.FeatureFlags;
+import com.android.launcher3.util.IconNormalizer;
+
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.ArrayList;
@@ -134,7 +142,7 @@
public static boolean isAllowRotationPrefEnabled(Context context, boolean multiProcess) {
SharedPreferences sharedPrefs = context.getSharedPreferences(
- LauncherAppState.getSharedPreferencesKey(), Context.MODE_PRIVATE | (multiProcess ?
+ LauncherFiles.SHARED_PREFERENCES_KEY, Context.MODE_PRIVATE | (multiProcess ?
Context.MODE_MULTI_PROCESS : 0));
boolean allowRotationPref = sharedPrefs.getBoolean(ALLOW_ROTATION_PREFERENCE_KEY, false);
return sForceEnableRotation || allowRotationPref;
@@ -191,9 +199,41 @@
}
/**
+ * Returns a bitmap suitable for the all apps view. The icon is badged for {@param user}.
+ * The bitmap is also visually normalized with other icons.
+ */
+ @TargetApi(Build.VERSION_CODES.LOLLIPOP)
+ public static Bitmap createBadgedIconBitmap(
+ Drawable icon, UserHandleCompat user, Context context) {
+ float scale = FeatureFlags.LAUNCHER3_ICON_NORMALIZATION ?
+ IconNormalizer.getInstance().getScale(icon) : 1;
+ Bitmap bitmap = createIconBitmap(icon, context, scale);
+ if (Utilities.ATLEAST_LOLLIPOP && user != null
+ && !UserHandleCompat.myUserHandle().equals(user)) {
+ BitmapDrawable drawable = new BitmapDrawable(context.getResources(), bitmap);
+ Drawable badged = context.getPackageManager().getUserBadgedIcon(
+ drawable, user.getUser());
+ if (badged instanceof BitmapDrawable) {
+ return ((BitmapDrawable) badged).getBitmap();
+ } else {
+ return createIconBitmap(badged, context);
+ }
+ } else {
+ return bitmap;
+ }
+ }
+
+ /**
* Returns a bitmap suitable for the all apps view.
*/
public static Bitmap createIconBitmap(Drawable icon, Context context) {
+ return createIconBitmap(icon, context, 1.0f /* scale */);
+ }
+
+ /**
+ * @param scale the scale to apply before drawing {@param icon} on the canvas
+ */
+ public static Bitmap createIconBitmap(Drawable icon, Context context, float scale) {
synchronized (sCanvas) {
final int iconBitmapSize = getIconBitmapSize();
@@ -249,7 +289,10 @@
sOldBounds.set(icon.getBounds());
icon.setBounds(left, top, left+width, top+height);
+ canvas.save(Canvas.MATRIX_SAVE_FLAG);
+ canvas.scale(scale, scale, textureWidth / 2, textureHeight / 2);
icon.draw(canvas);
+ canvas.restore();
icon.setBounds(sOldBounds);
canvas.setBitmap(null);
@@ -306,7 +349,7 @@
}
/**
- * Inverse of {@link #getDescendantCoordRelativeToSelf(View, int[])}.
+ * Inverse of {@link #getDescendantCoordRelativeToParent(View, View, int[], boolean)}.
*/
public static float mapCoordInSelfToDescendent(View descendant, View root,
int[] coord) {
@@ -726,4 +769,40 @@
public static String createDbSelectionQuery(String columnName, Iterable<?> values) {
return String.format(Locale.ENGLISH, "%s IN (%s)", columnName, TextUtils.join(", ", values));
}
+
+ /**
+ * Wraps a message with a TTS span, so that a different message is spoken than
+ * what is getting displayed.
+ * @param msg original message
+ * @param ttsMsg message to be spoken
+ */
+ @TargetApi(Build.VERSION_CODES.LOLLIPOP)
+ public static CharSequence wrapForTts(CharSequence msg, String ttsMsg) {
+ if (Utilities.ATLEAST_LOLLIPOP) {
+ SpannableString spanned = new SpannableString(msg);
+ spanned.setSpan(new TtsSpan.TextBuilder(ttsMsg).build(),
+ 0, spanned.length(), Spannable.SPAN_INCLUSIVE_INCLUSIVE);
+ return spanned;
+ } else {
+ return msg;
+ }
+ }
+
+ /**
+ * Replacement for Long.compare() which was added in API level 19.
+ */
+ public static int longCompare(long lhs, long rhs) {
+ return lhs < rhs ? -1 : (lhs == rhs ? 0 : 1);
+ }
+
+ public static SharedPreferences getPrefs(Context context) {
+ return context.getSharedPreferences(
+ LauncherFiles.SHARED_PREFERENCES_KEY, Context.MODE_PRIVATE);
+ }
+
+ @TargetApi(Build.VERSION_CODES.LOLLIPOP)
+ public static boolean isPowerSaverOn(Context context) {
+ PowerManager powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
+ return ATLEAST_LOLLIPOP && powerManager.isPowerSaveMode();
+ }
}
diff --git a/src/com/android/launcher3/WallpaperChangedReceiver.java b/src/com/android/launcher3/WallpaperChangedReceiver.java
index 2d5612f..c24fbff 100644
--- a/src/com/android/launcher3/WallpaperChangedReceiver.java
+++ b/src/com/android/launcher3/WallpaperChangedReceiver.java
@@ -22,8 +22,6 @@
public class WallpaperChangedReceiver extends BroadcastReceiver {
public void onReceive(Context context, Intent data) {
- LauncherAppState.setApplicationContext(context.getApplicationContext());
- LauncherAppState appState = LauncherAppState.getInstance();
- appState.onWallpaperChanged();
+ LauncherAppState.getInstance().onWallpaperChanged();
}
}
diff --git a/src/com/android/launcher3/WidgetPreviewLoader.java b/src/com/android/launcher3/WidgetPreviewLoader.java
index 603b072..b27fa60 100644
--- a/src/com/android/launcher3/WidgetPreviewLoader.java
+++ b/src/com/android/launcher3/WidgetPreviewLoader.java
@@ -10,7 +10,6 @@
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
-import android.database.sqlite.SQLiteOpenHelper;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory;
@@ -32,6 +31,7 @@
import com.android.launcher3.compat.UserHandleCompat;
import com.android.launcher3.compat.UserManagerCompat;
import com.android.launcher3.util.ComponentKey;
+import com.android.launcher3.util.SQLiteCacheHelper;
import com.android.launcher3.util.Thunk;
import com.android.launcher3.widget.WidgetCell;
@@ -104,7 +104,7 @@
* The DB holds the generated previews for various components. Previews can also have different
* sizes (landscape vs portrait).
*/
- private static class CacheDb extends SQLiteOpenHelper {
+ private static class CacheDb extends SQLiteCacheHelper {
private static final int DB_VERSION = 4;
private static final String TABLE_NAME = "shortcut_and_widget_previews";
@@ -117,11 +117,11 @@
private static final String COLUMN_PREVIEW_BITMAP = "preview_bitmap";
public CacheDb(Context context) {
- super(context, LauncherFiles.WIDGET_PREVIEWS_DB, null, DB_VERSION);
+ super(context, LauncherFiles.WIDGET_PREVIEWS_DB, DB_VERSION, TABLE_NAME);
}
@Override
- public void onCreate(SQLiteDatabase database) {
+ public void onCreateTable(SQLiteDatabase database) {
database.execSQL("CREATE TABLE IF NOT EXISTS " + TABLE_NAME + " (" +
COLUMN_COMPONENT + " TEXT NOT NULL, " +
COLUMN_USER + " INTEGER NOT NULL, " +
@@ -133,25 +133,6 @@
"PRIMARY KEY (" + COLUMN_COMPONENT + ", " + COLUMN_USER + ", " + COLUMN_SIZE + ") " +
");");
}
-
- @Override
- public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
- if (oldVersion != newVersion) {
- clearDB(db);
- }
- }
-
- @Override
- public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {
- if (oldVersion != newVersion) {
- clearDB(db);
- }
- }
-
- private void clearDB(SQLiteDatabase db) {
- db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME);
- onCreate(db);
- }
}
private WidgetCacheKey getObjectKey(Object o, String size) {
@@ -176,13 +157,7 @@
values.put(CacheDb.COLUMN_VERSION, versions[0]);
values.put(CacheDb.COLUMN_LAST_UPDATED, versions[1]);
values.put(CacheDb.COLUMN_PREVIEW_BITMAP, Utilities.flattenBitmap(preview));
-
- try {
- mDb.getWritableDatabase().insertWithOnConflict(CacheDb.TABLE_NAME, null, values,
- SQLiteDatabase.CONFLICT_REPLACE);
- } catch (SQLException e) {
- Log.e(TAG, "Error saving image to DB", e);
- }
+ mDb.insertOrReplace(values);
}
public void removePackage(String packageName, UserHandleCompat user) {
@@ -194,13 +169,9 @@
mPackageVersions.remove(packageName);
}
- try {
- mDb.getWritableDatabase().delete(CacheDb.TABLE_NAME,
- CacheDb.COLUMN_PACKAGE + " = ? AND " + CacheDb.COLUMN_USER + " = ?",
- new String[] {packageName, Long.toString(userSerial)});
- } catch (SQLException e) {
- Log.e(TAG, "Unable to delete items from DB", e);
- }
+ mDb.delete(
+ CacheDb.COLUMN_PACKAGE + " = ? AND " + CacheDb.COLUMN_USER + " = ?",
+ new String[]{packageName, Long.toString(userSerial)});
}
/**
@@ -238,10 +209,10 @@
LongSparseArray<HashSet<String>> packagesToDelete = new LongSparseArray<>();
Cursor c = null;
try {
- c = mDb.getReadableDatabase().query(CacheDb.TABLE_NAME,
- new String[] {CacheDb.COLUMN_USER, CacheDb.COLUMN_PACKAGE,
- CacheDb.COLUMN_LAST_UPDATED, CacheDb.COLUMN_VERSION},
- null, null, null, null, null);
+ c = mDb.query(
+ new String[]{CacheDb.COLUMN_USER, CacheDb.COLUMN_PACKAGE,
+ CacheDb.COLUMN_LAST_UPDATED, CacheDb.COLUMN_VERSION},
+ null, null);
while (c.moveToNext()) {
long userId = c.getLong(0);
String pkg = c.getString(1);
@@ -274,7 +245,7 @@
}
}
} catch (SQLException e) {
- Log.e(TAG, "Error updatating widget previews", e);
+ Log.e(TAG, "Error updating widget previews", e);
} finally {
if (c != null) {
c.close();
@@ -288,16 +259,15 @@
@Thunk Bitmap readFromDb(WidgetCacheKey key, Bitmap recycle, PreviewLoadTask loadTask) {
Cursor cursor = null;
try {
- cursor = mDb.getReadableDatabase().query(
- CacheDb.TABLE_NAME,
- new String[] { CacheDb.COLUMN_PREVIEW_BITMAP },
- CacheDb.COLUMN_COMPONENT + " = ? AND " + CacheDb.COLUMN_USER + " = ? AND " + CacheDb.COLUMN_SIZE + " = ?",
- new String[] {
+ cursor = mDb.query(
+ new String[]{CacheDb.COLUMN_PREVIEW_BITMAP},
+ CacheDb.COLUMN_COMPONENT + " = ? AND " + CacheDb.COLUMN_USER + " = ? AND "
+ + CacheDb.COLUMN_SIZE + " = ?",
+ new String[]{
key.componentName.flattenToString(),
Long.toString(mUserManager.getSerialNumberForUser(key.user)),
key.size
- },
- null, null, null);
+ });
// If cancelled, skip getting the blob and decoding it into a bitmap
if (loadTask.isCancelled()) {
return null;
@@ -428,8 +398,9 @@
float iconScale = Math.min((float) smallestSide / (appIconSize + 2 * minOffset), scale);
try {
- Drawable icon = mutateOnMainThread(mManager.loadIcon(info, mIconCache));
+ Drawable icon = mManager.loadIcon(info, mIconCache);
if (icon != null) {
+ icon = mutateOnMainThread(icon);
int hoffset = (int) ((tileW - appIconSize * iconScale) / 2) + x;
int yoffset = (int) ((tileH - appIconSize * iconScale) / 2);
icon.setBounds(hoffset, yoffset,
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index c1a2aed..56801ff 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -67,6 +67,7 @@
import com.android.launcher3.accessibility.LauncherAccessibilityDelegate;
import com.android.launcher3.accessibility.LauncherAccessibilityDelegate.AccessibilityDragSource;
import com.android.launcher3.accessibility.OverviewScreenAccessibilityDelegate;
+import com.android.launcher3.accessibility.WorkspaceAccessibilityHelper;
import com.android.launcher3.compat.UserHandleCompat;
import com.android.launcher3.util.LongArrayMap;
import com.android.launcher3.util.Thunk;
@@ -358,7 +359,7 @@
if (getChildCount() > 0) {
// Use the first non-custom page to estimate the child position
CellLayout cl = (CellLayout) getChildAt(numCustomPages());
- Rect r = estimateItemPosition(cl, itemInfo, 0, 0, itemInfo.spanX, itemInfo.spanY);
+ Rect r = estimateItemPosition(cl, 0, 0, itemInfo.spanX, itemInfo.spanY);
size[0] = r.width();
size[1] = r.height();
if (springLoaded) {
@@ -373,8 +374,7 @@
}
}
- public Rect estimateItemPosition(CellLayout cl, ItemInfo pendingInfo,
- int hCell, int vCell, int hSpan, int vSpan) {
+ public Rect estimateItemPosition(CellLayout cl, int hCell, int vCell, int hSpan, int vSpan) {
Rect r = new Rect();
cl.cellToRect(hCell, vCell, hSpan, vSpan, r);
return r;
@@ -578,6 +578,7 @@
CellLayout customScreen = (CellLayout)
mLauncher.getLayoutInflater().inflate(R.layout.workspace_screen, this, false);
customScreen.disableDragTarget();
+ customScreen.disableJailContent();
mWorkspaceScreens.put(CUSTOM_CONTENT_SCREEN_ID, customScreen);
mScreenOrder.add(0, CUSTOM_CONTENT_SCREEN_ID);
@@ -649,6 +650,10 @@
parent.removeView(customContent);
}
customScreen.removeAllViews();
+ customContent.setFocusable(true);
+ customContent.setOnKeyListener(new FullscreenKeyEventListener());
+ customContent.setOnFocusChangeListener(mLauncher.mFocusHandler
+ .getHideIndicatorOnFocusListener());
customScreen.addViewToCellLayout(customContent, 0, 0, lp, true);
mCustomContentDescription = description;
@@ -1118,9 +1123,9 @@
LauncherAppWidgetInfo info = (LauncherAppWidgetInfo) v.getTag();
LauncherAppWidgetHostView lahv = (LauncherAppWidgetHostView) info.hostView;
if (lahv != null && lahv.isReinflateRequired()) {
- mLauncher.removeAppWidget(info);
- // Remove the current widget which is inflated with the wrong orientation
- cl.removeView(lahv);
+ // Remove and rebind the current widget (which was inflated in the wrong
+ // orientation), but don't delete it from the database
+ mLauncher.removeItem(lahv, info, false /* deleteFromDb */);
mLauncher.bindAppWidget(info);
}
}
@@ -1541,6 +1546,13 @@
}
@Override
+ protected void determineScrollingStart(MotionEvent ev, float touchSlopScale) {
+ if (!isSwitchingState()) {
+ super.determineScrollingStart(ev, touchSlopScale);
+ }
+ }
+
+ @Override
public void announceForAccessibility(CharSequence text) {
// Don't announce if apps is on top of us.
if (!mLauncher.isAppsViewVisible()) {
@@ -2024,7 +2036,7 @@
}
setImportantForAccessibility((mState == State.NORMAL || mState == State.OVERVIEW)
? IMPORTANT_FOR_ACCESSIBILITY_AUTO
- : IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS);
+ : IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS);
} else {
int accessible = mState == State.NORMAL ?
IMPORTANT_FOR_ACCESSIBILITY_AUTO :
@@ -2058,6 +2070,7 @@
@Override
public void onLauncherTransitionPrepare(Launcher l, boolean animated, boolean toWorkspace) {
mIsSwitchingState = true;
+ mTransitionProgress = 0;
// Invalidate here to ensure that the pages are rendered during the state change transition.
invalidate();
@@ -2473,14 +2486,17 @@
return true;
}
- boolean willCreateUserFolder(ItemInfo info, CellLayout target, int[] targetCell, float
- distance, boolean considerTimeout) {
+ boolean willCreateUserFolder(ItemInfo info, CellLayout target, int[] targetCell,
+ float distance, boolean considerTimeout) {
if (distance > mMaxDistanceForFolderCreation) return false;
View dropOverView = target.getChildAt(targetCell[0], targetCell[1]);
+ return willCreateUserFolder(info, dropOverView, considerTimeout);
+ }
+ boolean willCreateUserFolder(ItemInfo info, View dropOverView, boolean considerTimeout) {
if (dropOverView != null) {
CellLayout.LayoutParams lp = (CellLayout.LayoutParams) dropOverView.getLayoutParams();
- if (lp.useTmpCoords && (lp.tmpCellX != lp.cellX || lp.tmpCellY != lp.tmpCellY)) {
+ if (lp.useTmpCoords && (lp.tmpCellX != lp.cellX || lp.tmpCellY != lp.cellY)) {
return false;
}
}
@@ -2497,7 +2513,7 @@
boolean aboveShortcut = (dropOverView.getTag() instanceof ShortcutInfo);
boolean willBecomeShortcut =
(info.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION ||
- info.itemType == LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT);
+ info.itemType == LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT);
return (aboveShortcut && willBecomeShortcut);
}
@@ -2506,10 +2522,13 @@
float distance) {
if (distance > mMaxDistanceForFolderCreation) return false;
View dropOverView = target.getChildAt(targetCell[0], targetCell[1]);
+ return willAddToExistingUserFolder(dragInfo, dropOverView);
+ }
+ boolean willAddToExistingUserFolder(Object dragInfo, View dropOverView) {
if (dropOverView != null) {
CellLayout.LayoutParams lp = (CellLayout.LayoutParams) dropOverView.getLayoutParams();
- if (lp.useTmpCoords && (lp.tmpCellX != lp.cellX || lp.tmpCellY != lp.tmpCellY)) {
+ if (lp.useTmpCoords && (lp.tmpCellX != lp.cellX || lp.tmpCellY != lp.cellY)) {
return false;
}
}
@@ -2538,7 +2557,7 @@
if (v == null || hasntMoved || !mCreateUserFolderOnDrop) return false;
mCreateUserFolderOnDrop = false;
- final long screenId = (targetCell == null) ? mDragInfo.screenId : getIdForScreen(target);
+ final long screenId = getIdForScreen(target);
boolean aboveShortcut = (v.getTag() instanceof ShortcutInfo);
boolean willBecomeShortcut = (newView.getTag() instanceof ShortcutInfo);
@@ -3209,8 +3228,6 @@
mapPointFromSelfToChild(mDragTargetLayout, mDragViewVisualCenter, null);
}
- ItemInfo info = (ItemInfo) d.dragInfo;
-
int minSpanX = item.spanX;
int minSpanY = item.spanY;
if (item.minSpanX > 0 && item.minSpanY > 0) {
@@ -3229,11 +3246,7 @@
float targetCellDistance = mDragTargetLayout.getDistanceFromCell(
mDragViewVisualCenter[0], mDragViewVisualCenter[1], mTargetCell);
- final View dragOverView = mDragTargetLayout.getChildAt(mTargetCell[0],
- mTargetCell[1]);
-
- manageFolderFeedback(info, mDragTargetLayout, mTargetCell,
- targetCellDistance, dragOverView, d.accessibleDrag);
+ manageFolderFeedback(mDragTargetLayout, mTargetCell, targetCellDistance, d);
boolean nearestDropOccupied = mDragTargetLayout.isNearestDropLocationOccupied((int)
mDragViewVisualCenter[0], (int) mDragViewVisualCenter[1], item.spanX,
@@ -3241,9 +3254,7 @@
if (!nearestDropOccupied) {
mDragTargetLayout.visualizeDropLocation(child, mDragOutline,
- (int) mDragViewVisualCenter[0], (int) mDragViewVisualCenter[1],
- mTargetCell[0], mTargetCell[1], item.spanX, item.spanY, false,
- d.dragView.getDragVisualizeOffset(), d.dragView.getDragRegion());
+ mTargetCell[0], mTargetCell[1], item.spanX, item.spanY, false, d);
} else if ((mDragMode == DRAG_MODE_NONE || mDragMode == DRAG_MODE_REORDER)
&& !mReorderAlarm.alarmPending() && (mLastReorderX != reorderX ||
mLastReorderY != reorderY)) {
@@ -3256,7 +3267,7 @@
// Otherwise, if we aren't adding to or creating a folder and there's no pending
// reorder, then we schedule a reorder
ReorderAlarmListener listener = new ReorderAlarmListener(mDragViewVisualCenter,
- minSpanX, minSpanY, item.spanX, item.spanY, d.dragView, child);
+ minSpanX, minSpanY, item.spanX, item.spanY, d, child);
mReorderAlarm.setOnAlarmListener(listener);
mReorderAlarm.setAlarm(REORDER_TIMEOUT);
}
@@ -3270,28 +3281,34 @@
}
}
- private void manageFolderFeedback(ItemInfo info, CellLayout targetLayout,
- int[] targetCell, float distance, View dragOverView, boolean accessibleDrag) {
- boolean userFolderPending = willCreateUserFolder(info, targetLayout, targetCell, distance,
- false);
+ private void manageFolderFeedback(CellLayout targetLayout,
+ int[] targetCell, float distance, DragObject dragObject) {
+ if (distance > mMaxDistanceForFolderCreation) return;
+
+ final View dragOverView = mDragTargetLayout.getChildAt(mTargetCell[0], mTargetCell[1]);
+ ItemInfo info = (ItemInfo) dragObject.dragInfo;
+ boolean userFolderPending = willCreateUserFolder(info, dragOverView, false);
if (mDragMode == DRAG_MODE_NONE && userFolderPending &&
!mFolderCreationAlarm.alarmPending()) {
FolderCreationAlarmListener listener = new
FolderCreationAlarmListener(targetLayout, targetCell[0], targetCell[1]);
- if (!accessibleDrag) {
+ if (!dragObject.accessibleDrag) {
mFolderCreationAlarm.setOnAlarmListener(listener);
mFolderCreationAlarm.setAlarm(FOLDER_CREATION_TIMEOUT);
} else {
listener.onAlarm(mFolderCreationAlarm);
}
+
+ if (dragObject.stateAnnouncer != null) {
+ dragObject.stateAnnouncer.announce(WorkspaceAccessibilityHelper
+ .getDescriptionForDropOver(dragOverView, getContext()));
+ }
return;
}
- boolean willAddToFolder =
- willAddToExistingUserFolder(info, targetLayout, targetCell, distance);
-
+ boolean willAddToFolder = willAddToExistingUserFolder(info, dragOverView);
if (willAddToFolder && mDragMode == DRAG_MODE_NONE) {
mDragOverFolderIcon = ((FolderIcon) dragOverView);
mDragOverFolderIcon.onDragEnter(info);
@@ -3299,6 +3316,11 @@
targetLayout.clearDragOutlines();
}
setDragMode(DRAG_MODE_ADD_TO_FOLDER);
+
+ if (dragObject.stateAnnouncer != null) {
+ dragObject.stateAnnouncer.announce(WorkspaceAccessibilityHelper
+ .getDescriptionForDropOver(dragOverView, getContext()));
+ }
return;
}
@@ -3308,8 +3330,6 @@
if (mDragMode == DRAG_MODE_CREATE_FOLDER && !userFolderPending) {
setDragMode(DRAG_MODE_NONE);
}
-
- return;
}
class FolderCreationAlarmListener implements OnAlarmListener {
@@ -3341,18 +3361,18 @@
class ReorderAlarmListener implements OnAlarmListener {
float[] dragViewCenter;
int minSpanX, minSpanY, spanX, spanY;
- DragView dragView;
+ DragObject dragObject;
View child;
public ReorderAlarmListener(float[] dragViewCenter, int minSpanX, int minSpanY, int spanX,
- int spanY, DragView dragView, View child) {
+ int spanY, DragObject dragObject, View child) {
this.dragViewCenter = dragViewCenter;
this.minSpanX = minSpanX;
this.minSpanY = minSpanY;
this.spanX = spanX;
this.spanY = spanY;
this.child = child;
- this.dragView = dragView;
+ this.dragObject = dragObject;
}
public void onAlarm(Alarm alarm) {
@@ -3375,9 +3395,7 @@
boolean resize = resultSpan[0] != spanX || resultSpan[1] != spanY;
mDragTargetLayout.visualizeDropLocation(child, mDragOutline,
- (int) mDragViewVisualCenter[0], (int) mDragViewVisualCenter[1],
- mTargetCell[0], mTargetCell[1], resultSpan[0], resultSpan[1], resize,
- dragView.getDragVisualizeOffset(), dragView.getDragRegion());
+ mTargetCell[0], mTargetCell[1], resultSpan[0], resultSpan[1], resize, dragObject);
}
}
@@ -3496,11 +3514,11 @@
boolean isWidget = pendingInfo.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET
|| pendingInfo.itemType == LauncherSettings.Favorites.ITEM_TYPE_CUSTOM_APPWIDGET;
- View finalView = isWidget ? ((PendingAddWidgetInfo) pendingInfo).boundWidget : null;
+ AppWidgetHostView finalView = isWidget ?
+ ((PendingAddWidgetInfo) pendingInfo).boundWidget : null;
- if (finalView instanceof AppWidgetHostView && updateWidgetSize) {
- AppWidgetHostView awhv = (AppWidgetHostView) finalView;
- AppWidgetResizeFrame.updateWidgetSizeRanges(awhv, mLauncher, item.spanX,
+ if (finalView != null && updateWidgetSize) {
+ AppWidgetResizeFrame.updateWidgetSizeRanges(finalView, mLauncher, item.spanX,
item.spanY);
}
@@ -3600,14 +3618,13 @@
}
private void getFinalPositionForDropAnimation(int[] loc, float[] scaleXY,
- DragView dragView, CellLayout layout, ItemInfo info, int[] targetCell,
- boolean external, boolean scale) {
+ DragView dragView, CellLayout layout, ItemInfo info, int[] targetCell, boolean scale) {
// Now we animate the dragView, (ie. the widget or shortcut preview) into its final
// location and size on the home screen.
int spanX = info.spanX;
int spanY = info.spanY;
- Rect r = estimateItemPosition(layout, info, targetCell[0], targetCell[1], spanX, spanY);
+ Rect r = estimateItemPosition(layout, targetCell[0], targetCell[1], spanX, spanY);
loc[0] = r.left;
loc[1] = r.top;
@@ -3628,14 +3645,15 @@
// The animation will scale the dragView about its center, so we need to center about
// the final location.
- loc[0] -= (dragView.getMeasuredWidth() - cellLayoutScale * r.width()) / 2;
+ loc[0] -= (dragView.getMeasuredWidth() - cellLayoutScale * r.width()) / 2
+ - Math.ceil(layout.getUnusedHorizontalSpace() / 2f);
loc[1] -= (dragView.getMeasuredHeight() - cellLayoutScale * r.height()) / 2;
scaleXY[0] = dragViewScaleX * cellLayoutScale;
scaleXY[1] = dragViewScaleY * cellLayoutScale;
}
- public void animateWidgetDrop(ItemInfo info, CellLayout cellLayout, DragView dragView,
+ public void animateWidgetDrop(ItemInfo info, CellLayout cellLayout, final DragView dragView,
final Runnable onCompleteRunnable, int animationType, final View finalView,
boolean external) {
Rect from = new Rect();
@@ -3645,16 +3663,11 @@
float scaleXY[] = new float[2];
boolean scalePreview = !(info instanceof PendingAddShortcutInfo);
getFinalPositionForDropAnimation(finalPos, scaleXY, dragView, cellLayout, info, mTargetCell,
- external, scalePreview);
+ scalePreview);
Resources res = mLauncher.getResources();
final int duration = res.getInteger(R.integer.config_dropAnimMaxDuration) - 200;
- // In the case where we've prebound the widget, we remove it from the DragLayer
- if (finalView instanceof AppWidgetHostView && external) {
- mLauncher.getDragLayer().removeView(finalView);
- }
-
boolean isWidget = info.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET ||
info.itemType == LauncherSettings.Favorites.ITEM_TYPE_CUSTOM_APPWIDGET;
if ((animationType == ANIMATE_INTO_POSITION_AND_RESIZE || external) && finalView != null) {
@@ -3674,7 +3687,7 @@
if (animationType == ANIMATE_INTO_POSITION_AND_REMAIN) {
endStyle = DragLayer.ANIMATION_END_REMAIN_VISIBLE;
} else {
- endStyle = DragLayer.ANIMATION_END_DISAPPEAR;;
+ endStyle = DragLayer.ANIMATION_END_DISAPPEAR;
}
Runnable onComplete = new Runnable() {
@@ -4472,8 +4485,17 @@
private String getPageDescription(int page) {
int delta = numCustomPages();
+ int nScreens = getChildCount() - delta;
+ int extraScreenId = mScreenOrder.indexOf(EXTRA_EMPTY_SCREEN_ID);
+ if (extraScreenId >= 0 && nScreens > 1) {
+ if (page == extraScreenId) {
+ return getContext().getString(R.string.workspace_new_page);
+ }
+ nScreens--;
+ }
return String.format(getContext().getString(R.string.workspace_scroll_format),
- page + 1 - delta, getChildCount() - delta);
+ page + 1 - delta, nScreens);
+
}
public void getLocationInDragLayer(int[] loc) {
@@ -4481,7 +4503,7 @@
}
@Override
- public void fillInLaunchSourceData(Bundle sourceData) {
+ public void fillInLaunchSourceData(View v, Bundle sourceData) {
sourceData.putString(Stats.SOURCE_EXTRA_CONTAINER, Stats.CONTAINER_HOMESCREEN);
sourceData.putInt(Stats.SOURCE_EXTRA_CONTAINER_PAGE, getCurrentPage());
}
@@ -4523,12 +4545,9 @@
for (LauncherAppWidgetInfo info : mInfos) {
if (info.hostView instanceof PendingAppWidgetHostView) {
+ // Remove and rebind the current widget, but don't delete it from the database
PendingAppWidgetHostView view = (PendingAppWidgetHostView) info.hostView;
- mLauncher.removeAppWidget(info);
-
- CellLayout cl = (CellLayout) view.getParent().getParent();
- // Remove the current widget
- cl.removeView(view);
+ mLauncher.removeItem(view, info, false /* deleteFromDb */);
mLauncher.bindAppWidget(info);
}
}
diff --git a/src/com/android/launcher3/accessibility/DragViewStateAnnouncer.java b/src/com/android/launcher3/accessibility/DragViewStateAnnouncer.java
new file mode 100644
index 0000000..8ff82dd
--- /dev/null
+++ b/src/com/android/launcher3/accessibility/DragViewStateAnnouncer.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2015 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.launcher3.accessibility;
+
+import android.content.Context;
+import android.view.View;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityManager;
+
+/**
+ * Periodically sends accessibility events to announce ongoing state changed. Based on the
+ * implementation in ProgressBar.
+ */
+public class DragViewStateAnnouncer implements Runnable {
+
+ private static final int TIMEOUT_SEND_ACCESSIBILITY_EVENT = 200;
+
+ private final View mTargetView;
+
+ private DragViewStateAnnouncer(View view) {
+ mTargetView = view;
+ }
+
+ public void announce(CharSequence msg) {
+ mTargetView.setContentDescription(msg);
+ mTargetView.removeCallbacks(this);
+ mTargetView.postDelayed(this, TIMEOUT_SEND_ACCESSIBILITY_EVENT);
+ }
+
+ public void cancel() {
+ mTargetView.removeCallbacks(this);
+ }
+
+ @Override
+ public void run() {
+ mTargetView.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED);
+ }
+
+ public static DragViewStateAnnouncer createFor(View v) {
+ if (((AccessibilityManager) v.getContext().getSystemService(Context.ACCESSIBILITY_SERVICE))
+ .isEnabled()) {
+ return new DragViewStateAnnouncer(v);
+ } else {
+ return null;
+ }
+ }
+}
diff --git a/src/com/android/launcher3/accessibility/LauncherAccessibilityDelegate.java b/src/com/android/launcher3/accessibility/LauncherAccessibilityDelegate.java
index fe7b25e..2306b77 100644
--- a/src/com/android/launcher3/accessibility/LauncherAccessibilityDelegate.java
+++ b/src/com/android/launcher3/accessibility/LauncherAccessibilityDelegate.java
@@ -134,11 +134,8 @@
public boolean performAction(final View host, final ItemInfo item, int action) {
if (action == REMOVE) {
- if (DeleteDropTarget.removeWorkspaceOrFolderItem(mLauncher, item, host)) {
- announceConfirmation(R.string.item_removed);
- return true;
- }
- return false;
+ DeleteDropTarget.removeWorkspaceOrFolderItem(mLauncher, item, host);
+ return true;
} else if (action == INFO) {
InfoDropTarget.startDetailsActivityForInfo(item, mLauncher);
return true;
@@ -175,7 +172,7 @@
return true;
} else if (action == MOVE_TO_WORKSPACE) {
Folder folder = mLauncher.getWorkspace().getOpenFolder();
- mLauncher.closeFolder(folder);
+ mLauncher.closeFolder(folder, true);
ShortcutInfo info = (ShortcutInfo) item;
folder.getInfo().remove(info);
diff --git a/src/com/android/launcher3/accessibility/WorkspaceAccessibilityHelper.java b/src/com/android/launcher3/accessibility/WorkspaceAccessibilityHelper.java
index 80ddc13..73b824b 100644
--- a/src/com/android/launcher3/accessibility/WorkspaceAccessibilityHelper.java
+++ b/src/com/android/launcher3/accessibility/WorkspaceAccessibilityHelper.java
@@ -16,6 +16,7 @@
package com.android.launcher3.accessibility;
+import android.content.Context;
import android.text.TextUtils;
import android.view.View;
@@ -140,26 +141,30 @@
return mContext.getString(R.string.move_to_empty_cell, y + 1, x + 1);
}
} else {
- ItemInfo info = (ItemInfo) child.getTag();
- if (info instanceof ShortcutInfo) {
- return mContext.getString(R.string.create_folder_with, info.title);
- } else if (info instanceof FolderInfo) {
- if (TextUtils.isEmpty(info.title)) {
- // Find the first item in the folder.
- FolderInfo folder = (FolderInfo) info;
- ShortcutInfo firstItem = null;
- for (ShortcutInfo shortcut : folder.contents) {
- if (firstItem == null || firstItem.rank > shortcut.rank) {
- firstItem = shortcut;
- }
- }
+ return getDescriptionForDropOver(child, mContext);
+ }
+ }
- if (firstItem != null) {
- return mContext.getString(R.string.add_to_folder_with_app, firstItem.title);
+ public static String getDescriptionForDropOver(View overChild, Context context) {
+ ItemInfo info = (ItemInfo) overChild.getTag();
+ if (info instanceof ShortcutInfo) {
+ return context.getString(R.string.create_folder_with, info.title);
+ } else if (info instanceof FolderInfo) {
+ if (TextUtils.isEmpty(info.title)) {
+ // Find the first item in the folder.
+ FolderInfo folder = (FolderInfo) info;
+ ShortcutInfo firstItem = null;
+ for (ShortcutInfo shortcut : folder.contents) {
+ if (firstItem == null || firstItem.rank > shortcut.rank) {
+ firstItem = shortcut;
}
}
- return mContext.getString(R.string.add_to_folder, info.title);
+
+ if (firstItem != null) {
+ return context.getString(R.string.add_to_folder_with_app, firstItem.title);
+ }
}
+ return context.getString(R.string.add_to_folder, info.title);
}
return "";
}
diff --git a/src/com/android/launcher3/allapps/AllAppsContainerView.java b/src/com/android/launcher3/allapps/AllAppsContainerView.java
index 88c6aca..f9bb134 100644
--- a/src/com/android/launcher3/allapps/AllAppsContainerView.java
+++ b/src/com/android/launcher3/allapps/AllAppsContainerView.java
@@ -28,6 +28,7 @@
import android.text.method.TextKeyListener;
import android.util.AttributeSet;
import android.view.KeyEvent;
+import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
@@ -35,6 +36,7 @@
import android.widget.LinearLayout;
import com.android.launcher3.AppInfo;
import com.android.launcher3.BaseContainerView;
+import com.android.launcher3.BubbleTextView;
import com.android.launcher3.CellLayout;
import com.android.launcher3.DeleteDropTarget;
import com.android.launcher3.DeviceProfile;
@@ -290,6 +292,15 @@
}
}
+ /**
+ * Resets the state of AllApps.
+ */
+ public void reset() {
+ // Reset the search bar and base recycler view after transitioning home
+ mSearchBarController.reset();
+ mAppsRecyclerView.reset();
+ }
+
@Override
protected void onFinishInflate() {
super.onFinishInflate();
@@ -323,6 +334,21 @@
mAppsRecyclerView.addItemDecoration(mItemDecoration);
}
+ // Precalculate the prediction icon and normal icon sizes
+ LayoutInflater layoutInflater = LayoutInflater.from(getContext());
+ BubbleTextView icon = (BubbleTextView) layoutInflater.inflate(
+ R.layout.all_apps_icon, this, false);
+ icon.applyDummyInfo();
+ icon.measure(MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE, MeasureSpec.AT_MOST),
+ MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE, MeasureSpec.AT_MOST));
+ BubbleTextView predIcon = (BubbleTextView) layoutInflater.inflate(
+ R.layout.all_apps_prediction_bar_icon, this, false);
+ predIcon.applyDummyInfo();
+ predIcon.measure(MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE, MeasureSpec.AT_MOST),
+ MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE, MeasureSpec.AT_MOST));
+ mAppsRecyclerView.setPremeasuredIconHeights(predIcon.getMeasuredHeight(),
+ icon.getMeasuredHeight());
+
updateBackgroundAndPaddings();
}
@@ -555,9 +581,7 @@
@Override
public void onLauncherTransitionEnd(Launcher l, boolean animated, boolean toWorkspace) {
if (toWorkspace) {
- // Reset the search bar and base recycler view after transitioning home
- mSearchBarController.reset();
- mAppsRecyclerView.reset();
+ reset();
}
}
diff --git a/src/com/android/launcher3/allapps/AllAppsFastScrollHelper.java b/src/com/android/launcher3/allapps/AllAppsFastScrollHelper.java
new file mode 100644
index 0000000..73de45e
--- /dev/null
+++ b/src/com/android/launcher3/allapps/AllAppsFastScrollHelper.java
@@ -0,0 +1,230 @@
+/*
+ * Copyright (C) 2015 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.launcher3.allapps;
+
+import android.support.v7.widget.RecyclerView;
+import android.view.View;
+
+import com.android.launcher3.BaseRecyclerView;
+import com.android.launcher3.BaseRecyclerViewFastScrollBar;
+import com.android.launcher3.FastBitmapDrawable;
+import com.android.launcher3.util.Thunk;
+
+import java.util.HashSet;
+
+public class AllAppsFastScrollHelper implements AllAppsGridAdapter.BindViewCallback {
+
+ private static final int INITIAL_TOUCH_SETTLING_DURATION = 100;
+ private static final int REPEAT_TOUCH_SETTLING_DURATION = 200;
+ private static final float FAST_SCROLL_TOUCH_VELOCITY_BARRIER = 1900f;
+
+ private AllAppsRecyclerView mRv;
+ private AlphabeticalAppsList mApps;
+
+ // Keeps track of the current and targetted fast scroll section (the section to scroll to after
+ // the initial delay)
+ int mTargetFastScrollPosition = -1;
+ @Thunk String mCurrentFastScrollSection;
+ @Thunk String mTargetFastScrollSection;
+
+ // The settled states affect the delay before the fast scroll animation is applied
+ private boolean mHasFastScrollTouchSettled;
+ private boolean mHasFastScrollTouchSettledAtLeastOnce;
+
+ // Set of all views animated during fast scroll. We keep track of these ourselves since there
+ // is no way to reset a view once it gets scrapped or recycled without other hacks
+ private HashSet<BaseRecyclerViewFastScrollBar.FastScrollFocusableView> mTrackedFastScrollViews =
+ new HashSet<>();
+
+ // Smooth fast-scroll animation frames
+ @Thunk int mFastScrollFrameIndex;
+ @Thunk final int[] mFastScrollFrames = new int[10];
+
+ /**
+ * This runnable runs a single frame of the smooth scroll animation and posts the next frame
+ * if necessary.
+ */
+ @Thunk Runnable mSmoothSnapNextFrameRunnable = new Runnable() {
+ @Override
+ public void run() {
+ if (mFastScrollFrameIndex < mFastScrollFrames.length) {
+ mRv.scrollBy(0, mFastScrollFrames[mFastScrollFrameIndex]);
+ mFastScrollFrameIndex++;
+ mRv.postOnAnimation(mSmoothSnapNextFrameRunnable);
+ }
+ }
+ };
+
+ /**
+ * This runnable updates the current fast scroll section to the target fastscroll section.
+ */
+ Runnable mFastScrollToTargetSectionRunnable = new Runnable() {
+ @Override
+ public void run() {
+ // Update to the target section
+ mCurrentFastScrollSection = mTargetFastScrollSection;
+ mHasFastScrollTouchSettled = true;
+ mHasFastScrollTouchSettledAtLeastOnce = true;
+ updateTrackedViewsFastScrollFocusState();
+ }
+ };
+
+ public AllAppsFastScrollHelper(AllAppsRecyclerView rv, AlphabeticalAppsList apps) {
+ mRv = rv;
+ mApps = apps;
+ }
+
+ public void onSetAdapter(AllAppsGridAdapter adapter) {
+ adapter.setBindViewCallback(this);
+ }
+
+ /**
+ * Smooth scrolls the recycler view to the given section.
+ *
+ * @return whether the fastscroller can scroll to the new section.
+ */
+ public boolean smoothScrollToSection(int scrollY, int availableScrollHeight,
+ AlphabeticalAppsList.FastScrollSectionInfo info) {
+ if (mTargetFastScrollPosition != info.fastScrollToItem.position) {
+ mTargetFastScrollPosition = info.fastScrollToItem.position;
+ smoothSnapToPosition(scrollY, availableScrollHeight, info);
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Smoothly snaps to a given position. We do this manually by calculating the keyframes
+ * ourselves and animating the scroll on the recycler view.
+ */
+ private void smoothSnapToPosition(int scrollY, int availableScrollHeight,
+ AlphabeticalAppsList.FastScrollSectionInfo info) {
+ mRv.removeCallbacks(mSmoothSnapNextFrameRunnable);
+ mRv.removeCallbacks(mFastScrollToTargetSectionRunnable);
+
+ trackAllChildViews();
+ if (mHasFastScrollTouchSettled) {
+ // In this case, the user has already settled once (and the fast scroll state has
+ // animated) and they are just fine-tuning their section from the last section, so
+ // we should make it feel fast and update immediately.
+ mCurrentFastScrollSection = info.sectionName;
+ mTargetFastScrollSection = null;
+ updateTrackedViewsFastScrollFocusState();
+ } else {
+ // Otherwise, the user has scrubbed really far, and we don't want to distract the user
+ // with the flashing fast scroll state change animation in addition to the fast scroll
+ // section popup, so reset the views to normal, and wait for the touch to settle again
+ // before animating the fast scroll state.
+ mCurrentFastScrollSection = null;
+ mTargetFastScrollSection = info.sectionName;
+ mHasFastScrollTouchSettled = false;
+ updateTrackedViewsFastScrollFocusState();
+
+ // Delay scrolling to a new section until after some duration. If the user has been
+ // scrubbing a while and makes multiple big jumps, then reduce the time needed for the
+ // fast scroll to settle so it doesn't feel so long.
+ mRv.postDelayed(mFastScrollToTargetSectionRunnable,
+ mHasFastScrollTouchSettledAtLeastOnce ?
+ REPEAT_TOUCH_SETTLING_DURATION :
+ INITIAL_TOUCH_SETTLING_DURATION);
+ }
+
+ // Calculate the full animation from the current scroll position to the final scroll
+ // position, and then run the animation for the duration.
+ int newScrollY = Math.min(availableScrollHeight,
+ mRv.getPaddingTop() + mRv.getTop(info.fastScrollToItem.rowIndex));
+ int numFrames = mFastScrollFrames.length;
+ for (int i = 0; i < numFrames; i++) {
+ // TODO(winsonc): We can interpolate this as well.
+ mFastScrollFrames[i] = (newScrollY - scrollY) / numFrames;
+ }
+ mFastScrollFrameIndex = 0;
+ mRv.postOnAnimation(mSmoothSnapNextFrameRunnable);
+ }
+
+ public void onFastScrollCompleted() {
+ // TODO(winsonc): Handle the case when the user scrolls and releases before the animation
+ // runs
+
+ // Stop animating the fast scroll position and state
+ mRv.removeCallbacks(mSmoothSnapNextFrameRunnable);
+ mRv.removeCallbacks(mFastScrollToTargetSectionRunnable);
+
+ // Reset the tracking variables
+ mHasFastScrollTouchSettled = false;
+ mHasFastScrollTouchSettledAtLeastOnce = false;
+ mCurrentFastScrollSection = null;
+ mTargetFastScrollSection = null;
+ mTargetFastScrollPosition = -1;
+
+ updateTrackedViewsFastScrollFocusState();
+ mTrackedFastScrollViews.clear();
+ }
+
+ @Override
+ public void onBindView(AllAppsGridAdapter.ViewHolder holder) {
+ // Update newly bound views to the current fast scroll state if we are fast scrolling
+ if (mCurrentFastScrollSection != null || mTargetFastScrollSection != null) {
+ if (holder.mContent instanceof BaseRecyclerViewFastScrollBar.FastScrollFocusableView) {
+ BaseRecyclerViewFastScrollBar.FastScrollFocusableView v =
+ (BaseRecyclerViewFastScrollBar.FastScrollFocusableView) holder.mContent;
+ updateViewFastScrollFocusState(v, holder.getPosition(), false /* animated */);
+ mTrackedFastScrollViews.add(v);
+ }
+ }
+ }
+
+ /**
+ * Starts tracking all the recycler view's children which are FastScrollFocusableViews.
+ */
+ private void trackAllChildViews() {
+ int childCount = mRv.getChildCount();
+ for (int i = 0; i < childCount; i++) {
+ View v = mRv.getChildAt(i);
+ if (v instanceof BaseRecyclerViewFastScrollBar.FastScrollFocusableView) {
+ mTrackedFastScrollViews.add((BaseRecyclerViewFastScrollBar.FastScrollFocusableView) v);
+ }
+ }
+ }
+
+ /**
+ * Updates the fast scroll focus on all the children.
+ */
+ private void updateTrackedViewsFastScrollFocusState() {
+ for (BaseRecyclerViewFastScrollBar.FastScrollFocusableView v : mTrackedFastScrollViews) {
+ RecyclerView.ViewHolder viewHolder = mRv.getChildViewHolder((View) v);
+ int pos = (viewHolder != null) ? viewHolder.getPosition() : -1;
+ updateViewFastScrollFocusState(v, pos, true);
+ }
+ }
+
+ /**
+ * Updates the fast scroll focus on all a given view.
+ */
+ private void updateViewFastScrollFocusState(BaseRecyclerViewFastScrollBar.FastScrollFocusableView v,
+ int pos, boolean animated) {
+ FastBitmapDrawable.State newState = FastBitmapDrawable.State.NORMAL;
+ if (mCurrentFastScrollSection != null && pos > -1) {
+ AlphabeticalAppsList.AdapterItem item = mApps.getAdapterItems().get(pos);
+ boolean highlight = item.sectionName.equals(mCurrentFastScrollSection) &&
+ item.position == mTargetFastScrollPosition;
+ newState = highlight ?
+ FastBitmapDrawable.State.FAST_SCROLL_HIGHLIGHTED :
+ FastBitmapDrawable.State.FAST_SCROLL_UNHIGHLIGHTED;
+ }
+ v.setFastScrollFocusState(newState, animated);
+ }
+}
diff --git a/src/com/android/launcher3/allapps/AllAppsGridAdapter.java b/src/com/android/launcher3/allapps/AllAppsGridAdapter.java
index dfad22f..38a3e3c 100644
--- a/src/com/android/launcher3/allapps/AllAppsGridAdapter.java
+++ b/src/com/android/launcher3/allapps/AllAppsGridAdapter.java
@@ -70,6 +70,10 @@
// The message to continue to a market search when there are no filtered results
public static final int SEARCH_MARKET_VIEW_TYPE = 5;
+ public interface BindViewCallback {
+ public void onBindView(ViewHolder holder);
+ }
+
/**
* ViewHolder for each icon.
*/
@@ -329,6 +333,7 @@
private View.OnTouchListener mTouchListener;
private View.OnClickListener mIconClickListener;
private View.OnLongClickListener mIconLongClickListener;
+ private BindViewCallback mBindViewCallback;
@Thunk final Rect mBackgroundPadding = new Rect();
@Thunk int mPredictionBarDividerOffset;
@Thunk int mAppsPerRow;
@@ -426,6 +431,13 @@
}
/**
+ * Sets the callback for when views are bound.
+ */
+ public void setBindViewCallback(BindViewCallback cb) {
+ mBindViewCallback = cb;
+ }
+
+ /**
* Notifies the adapter of the background padding so that it can draw things correctly in the
* item decorator.
*/
@@ -534,6 +546,15 @@
}
break;
}
+ if (mBindViewCallback != null) {
+ mBindViewCallback.onBindView(holder);
+ }
+ }
+
+ @Override
+ public boolean onFailedToRecycleView(ViewHolder holder) {
+ // Always recycle and we will reset the view when it is bound
+ return true;
}
@Override
diff --git a/src/com/android/launcher3/allapps/AllAppsRecyclerView.java b/src/com/android/launcher3/allapps/AllAppsRecyclerView.java
index 2f66e2c..1cb03c9 100644
--- a/src/com/android/launcher3/allapps/AllAppsRecyclerView.java
+++ b/src/com/android/launcher3/allapps/AllAppsRecyclerView.java
@@ -15,24 +15,21 @@
*/
package com.android.launcher3.allapps;
-import android.animation.ObjectAnimator;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
-import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.AttributeSet;
import android.view.View;
import com.android.launcher3.BaseRecyclerView;
-import com.android.launcher3.BaseRecyclerViewFastScrollBar;
+import com.android.launcher3.BubbleTextView;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.R;
import com.android.launcher3.Stats;
import com.android.launcher3.Utilities;
-import com.android.launcher3.util.Thunk;
import java.util.List;
@@ -42,25 +39,17 @@
public class AllAppsRecyclerView extends BaseRecyclerView
implements Stats.LaunchSourceProvider {
- private static final int FAST_SCROLL_MODE_JUMP_TO_FIRST_ICON = 0;
- private static final int FAST_SCROLL_MODE_FREE_SCROLL = 1;
-
- private static final int FAST_SCROLL_BAR_MODE_DISTRIBUTE_BY_ROW = 0;
- private static final int FAST_SCROLL_BAR_MODE_DISTRIBUTE_BY_SECTIONS = 1;
-
private AlphabeticalAppsList mApps;
+ private AllAppsFastScrollHelper mFastScrollHelper;
+ private BaseRecyclerView.ScrollPositionState mScrollPosState =
+ new BaseRecyclerView.ScrollPositionState();
private int mNumAppsPerRow;
- @Thunk BaseRecyclerViewFastScrollBar.FastScrollFocusableView mLastFastScrollFocusedView;
- @Thunk int mPrevFastScrollFocusedPosition;
- @Thunk int mFastScrollFrameIndex;
- @Thunk final int[] mFastScrollFrames = new int[10];
+ // The specific icon heights that we use to calculate scroll
+ private int mPredictionIconHeight;
+ private int mIconHeight;
- private final int mFastScrollMode = FAST_SCROLL_MODE_JUMP_TO_FIRST_ICON;
- private final int mScrollBarMode = FAST_SCROLL_BAR_MODE_DISTRIBUTE_BY_ROW;
-
- private ScrollPositionState mScrollPosState = new ScrollPositionState();
-
+ // The empty-search result background
private AllAppsBackgroundDrawable mEmptySearchBackground;
private int mEmptySearchBackgroundTopOffset;
@@ -79,8 +68,8 @@
public AllAppsRecyclerView(Context context, AttributeSet attrs, int defStyleAttr,
int defStyleRes) {
super(context, attrs, defStyleAttr);
-
Resources res = getResources();
+ addOnItemTouchListener(this);
mScrollbar.setDetachThumbOnFastScroll();
mEmptySearchBackgroundTopOffset = res.getDimensionPixelSize(
R.dimen.all_apps_empty_search_bg_top_offset);
@@ -91,6 +80,7 @@
*/
public void setApps(AlphabeticalAppsList apps) {
mApps = apps;
+ mFastScrollHelper = new AllAppsFastScrollHelper(this, apps);
}
/**
@@ -110,6 +100,14 @@
}
/**
+ * Sets the heights of the icons in this view (for scroll calculations).
+ */
+ public void setPremeasuredIconHeights(int predictionIconHeight, int iconHeight) {
+ mPredictionIconHeight = predictionIconHeight;
+ mIconHeight = iconHeight;
+ }
+
+ /**
* Scrolls this recycler view to the top.
*/
public void scrollToTop() {
@@ -126,6 +124,7 @@
*/
@Override
protected void dispatchDraw(Canvas canvas) {
+ // Clip to ensure that we don't draw the overscroll effect beyond the background bounds
canvas.clipRect(mBackgroundPadding.left, mBackgroundPadding.top,
getWidth() - mBackgroundPadding.right,
getHeight() - mBackgroundPadding.bottom);
@@ -157,20 +156,25 @@
}
@Override
- protected void onFinishInflate() {
- super.onFinishInflate();
-
- // Bind event handlers
- addOnItemTouchListener(this);
- }
-
- @Override
- public void fillInLaunchSourceData(Bundle sourceData) {
+ public void fillInLaunchSourceData(View v, Bundle sourceData) {
sourceData.putString(Stats.SOURCE_EXTRA_CONTAINER, Stats.CONTAINER_ALL_APPS);
if (mApps.hasFilter()) {
sourceData.putString(Stats.SOURCE_EXTRA_SUB_CONTAINER,
Stats.SUB_CONTAINER_ALL_APPS_SEARCH);
} else {
+ if (v instanceof BubbleTextView) {
+ BubbleTextView icon = (BubbleTextView) v;
+ int position = getChildPosition(icon);
+ if (position != NO_POSITION) {
+ List<AlphabeticalAppsList.AdapterItem> items = mApps.getAdapterItems();
+ AlphabeticalAppsList.AdapterItem item = items.get(position);
+ if (item.viewType == AllAppsGridAdapter.PREDICTION_ICON_VIEW_TYPE) {
+ sourceData.putString(Stats.SOURCE_EXTRA_SUB_CONTAINER,
+ Stats.SUB_CONTAINER_ALL_APPS_PREDICTION);
+ return;
+ }
+ }
+ }
sourceData.putString(Stats.SOURCE_EXTRA_SUB_CONTAINER,
Stats.SUB_CONTAINER_ALL_APPS_A_Z);
}
@@ -212,63 +216,31 @@
List<AlphabeticalAppsList.FastScrollSectionInfo> fastScrollSections =
mApps.getFastScrollerSections();
AlphabeticalAppsList.FastScrollSectionInfo lastInfo = fastScrollSections.get(0);
- if (mScrollBarMode == FAST_SCROLL_BAR_MODE_DISTRIBUTE_BY_ROW) {
- for (int i = 1; i < fastScrollSections.size(); i++) {
- AlphabeticalAppsList.FastScrollSectionInfo info = fastScrollSections.get(i);
- if (info.touchFraction > touchFraction) {
- break;
- }
- lastInfo = info;
+ for (int i = 1; i < fastScrollSections.size(); i++) {
+ AlphabeticalAppsList.FastScrollSectionInfo info = fastScrollSections.get(i);
+ if (info.touchFraction > touchFraction) {
+ break;
}
- } else if (mScrollBarMode == FAST_SCROLL_BAR_MODE_DISTRIBUTE_BY_SECTIONS){
- lastInfo = fastScrollSections.get((int) (touchFraction * (fastScrollSections.size() - 1)));
- } else {
- throw new RuntimeException("Unexpected scroll bar mode");
+ lastInfo = info;
}
- // Map the touch position back to the scroll of the recycler view
- getCurScrollState(mScrollPosState);
- int availableScrollHeight = getAvailableScrollHeight(rowCount, mScrollPosState.rowHeight);
- LinearLayoutManager layoutManager = (LinearLayoutManager) getLayoutManager();
- if (mFastScrollMode == FAST_SCROLL_MODE_FREE_SCROLL) {
- layoutManager.scrollToPositionWithOffset(0, (int) -(availableScrollHeight * touchFraction));
- }
-
- if (mPrevFastScrollFocusedPosition != lastInfo.fastScrollToItem.position) {
- mPrevFastScrollFocusedPosition = lastInfo.fastScrollToItem.position;
-
- // Reset the last focused view
- if (mLastFastScrollFocusedView != null) {
- mLastFastScrollFocusedView.setFastScrollFocused(false, true);
- mLastFastScrollFocusedView = null;
- }
-
- if (mFastScrollMode == FAST_SCROLL_MODE_JUMP_TO_FIRST_ICON) {
- smoothSnapToPosition(mPrevFastScrollFocusedPosition, mScrollPosState);
- } else if (mFastScrollMode == FAST_SCROLL_MODE_FREE_SCROLL) {
- final ViewHolder vh = findViewHolderForPosition(mPrevFastScrollFocusedPosition);
- if (vh != null &&
- vh.itemView instanceof BaseRecyclerViewFastScrollBar.FastScrollFocusableView) {
- mLastFastScrollFocusedView =
- (BaseRecyclerViewFastScrollBar.FastScrollFocusableView) vh.itemView;
- mLastFastScrollFocusedView.setFastScrollFocused(true, true);
- }
- } else {
- throw new RuntimeException("Unexpected fast scroll mode");
- }
- }
+ // Update the fast scroll
+ int scrollY = getScrollTop(mScrollPosState);
+ int availableScrollHeight = getAvailableScrollHeight(mApps.getNumAppRows());
+ mFastScrollHelper.smoothScrollToSection(scrollY, availableScrollHeight, lastInfo);
return lastInfo.sectionName;
}
@Override
public void onFastScrollCompleted() {
super.onFastScrollCompleted();
- // Reset and clean up the last focused view
- if (mLastFastScrollFocusedView != null) {
- mLastFastScrollFocusedView.setFastScrollFocused(false, true);
- mLastFastScrollFocusedView = null;
- }
- mPrevFastScrollFocusedPosition = -1;
+ mFastScrollHelper.onFastScrollCompleted();
+ }
+
+ @Override
+ public void setAdapter(Adapter adapter) {
+ super.setAdapter(adapter);
+ mFastScrollHelper.onSetAdapter((AllAppsGridAdapter) adapter);
}
/**
@@ -286,7 +258,7 @@
// Find the index and height of the first visible row (all rows have the same height)
int rowCount = mApps.getNumAppRows();
- getCurScrollState(mScrollPosState);
+ getCurScrollState(mScrollPosState, -1);
if (mScrollPosState.rowIndex < 0) {
mScrollbar.setThumbOffset(-1, -1);
return;
@@ -294,7 +266,7 @@
// Only show the scrollbar if there is height to be scrolled
int availableScrollBarHeight = getAvailableScrollBarHeight();
- int availableScrollHeight = getAvailableScrollHeight(mApps.getNumAppRows(), mScrollPosState.rowHeight);
+ int availableScrollHeight = getAvailableScrollHeight(mApps.getNumAppRows());
if (availableScrollHeight <= 0) {
mScrollbar.setThumbOffset(-1, -1);
return;
@@ -303,8 +275,7 @@
// Calculate the current scroll position, the scrollY of the recycler view accounts for the
// view padding, while the scrollBarY is drawn right up to the background padding (ignoring
// padding)
- int scrollY = getPaddingTop() +
- (mScrollPosState.rowIndex * mScrollPosState.rowHeight) - mScrollPosState.rowTopOffset;
+ int scrollY = getScrollTop(mScrollPosState);
int scrollBarY = mBackgroundPadding.top +
(int) (((float) scrollY / availableScrollHeight) * availableScrollBarHeight);
@@ -355,58 +326,12 @@
}
/**
- * This runnable runs a single frame of the smooth scroll animation and posts the next frame
- * if necessary.
- */
- @Thunk Runnable mSmoothSnapNextFrameRunnable = new Runnable() {
- @Override
- public void run() {
- if (mFastScrollFrameIndex < mFastScrollFrames.length) {
- scrollBy(0, mFastScrollFrames[mFastScrollFrameIndex]);
- mFastScrollFrameIndex++;
- postOnAnimation(mSmoothSnapNextFrameRunnable);
- } else {
- // Animation completed, set the fast scroll state on the target view
- final ViewHolder vh = findViewHolderForPosition(mPrevFastScrollFocusedPosition);
- if (vh != null &&
- vh.itemView instanceof BaseRecyclerViewFastScrollBar.FastScrollFocusableView &&
- mLastFastScrollFocusedView != vh.itemView) {
- mLastFastScrollFocusedView =
- (BaseRecyclerViewFastScrollBar.FastScrollFocusableView) vh.itemView;
- mLastFastScrollFocusedView.setFastScrollFocused(true, true);
- }
- }
- }
- };
-
- /**
- * Smoothly snaps to a given position. We do this manually by calculating the keyframes
- * ourselves and animating the scroll on the recycler view.
- */
- private void smoothSnapToPosition(final int position, ScrollPositionState scrollPosState) {
- removeCallbacks(mSmoothSnapNextFrameRunnable);
-
- // Calculate the full animation from the current scroll position to the final scroll
- // position, and then run the animation for the duration.
- int curScrollY = getPaddingTop() +
- (scrollPosState.rowIndex * scrollPosState.rowHeight) - scrollPosState.rowTopOffset;
- int newScrollY = getScrollAtPosition(position, scrollPosState.rowHeight);
- int numFrames = mFastScrollFrames.length;
- for (int i = 0; i < numFrames; i++) {
- // TODO(winsonc): We can interpolate this as well.
- mFastScrollFrames[i] = (newScrollY - curScrollY) / numFrames;
- }
- mFastScrollFrameIndex = 0;
- postOnAnimation(mSmoothSnapNextFrameRunnable);
- }
-
- /**
* Returns the current scroll state of the apps rows.
*/
- protected void getCurScrollState(ScrollPositionState stateOut) {
+ protected void getCurScrollState(ScrollPositionState stateOut, int viewTypeMask) {
stateOut.rowIndex = -1;
stateOut.rowTopOffset = -1;
- stateOut.rowHeight = -1;
+ stateOut.itemPos = -1;
// Return early if there are no items or we haven't been measured
List<AlphabeticalAppsList.AdapterItem> items = mApps.getAdapterItems();
@@ -420,29 +345,31 @@
int position = getChildPosition(child);
if (position != NO_POSITION) {
AlphabeticalAppsList.AdapterItem item = items.get(position);
- if (item.viewType == AllAppsGridAdapter.ICON_VIEW_TYPE ||
- item.viewType == AllAppsGridAdapter.PREDICTION_ICON_VIEW_TYPE) {
+ if ((item.viewType & viewTypeMask) != 0) {
stateOut.rowIndex = item.rowIndex;
stateOut.rowTopOffset = getLayoutManager().getDecoratedTop(child);
- stateOut.rowHeight = child.getHeight();
- break;
+ stateOut.itemPos = position;
+ return;
}
}
}
+ return;
}
- /**
- * Returns the scrollY for the given position in the adapter.
- */
- private int getScrollAtPosition(int position, int rowHeight) {
- AlphabeticalAppsList.AdapterItem item = mApps.getAdapterItems().get(position);
- if (item.viewType == AllAppsGridAdapter.ICON_VIEW_TYPE ||
- item.viewType == AllAppsGridAdapter.PREDICTION_ICON_VIEW_TYPE) {
- int offset = item.rowIndex > 0 ? getPaddingTop() : 0;
- return offset + item.rowIndex * rowHeight;
- } else {
+ @Override
+ protected boolean supportsFastScrolling() {
+ // Only allow fast scrolling when the user is not searching, since the results are not
+ // grouped in a meaningful order
+ return !mApps.hasFilter();
+ }
+
+ protected int getTop(int rowIndex) {
+ if (getChildCount() == 0 || rowIndex <= 0) {
return 0;
}
+
+ // The prediction bar icons have more padding, so account for that in the row offset
+ return mPredictionIconHeight + (rowIndex - 1) * mIconHeight;
}
/**
diff --git a/src/com/android/launcher3/compat/AppWidgetManagerCompatVL.java b/src/com/android/launcher3/compat/AppWidgetManagerCompatVL.java
index 13712d8..b3c5cc2 100644
--- a/src/com/android/launcher3/compat/AppWidgetManagerCompatVL.java
+++ b/src/com/android/launcher3/compat/AppWidgetManagerCompatVL.java
@@ -90,9 +90,7 @@
AppWidgetHost host, int requestCode) {
try {
host.startAppWidgetConfigureActivityForResult(activity, widgetId, 0, requestCode, null);
- } catch (ActivityNotFoundException e) {
- Toast.makeText(activity, R.string.activity_not_found, Toast.LENGTH_SHORT).show();
- } catch (SecurityException e) {
+ } catch (ActivityNotFoundException | SecurityException e) {
Toast.makeText(activity, R.string.activity_not_found, Toast.LENGTH_SHORT).show();
}
}
diff --git a/src/com/android/launcher3/compat/LauncherActivityInfoCompat.java b/src/com/android/launcher3/compat/LauncherActivityInfoCompat.java
index 07ef0ef..0bc9588 100644
--- a/src/com/android/launcher3/compat/LauncherActivityInfoCompat.java
+++ b/src/com/android/launcher3/compat/LauncherActivityInfoCompat.java
@@ -33,7 +33,6 @@
public abstract Drawable getIcon(int density);
public abstract ApplicationInfo getApplicationInfo();
public abstract long getFirstInstallTime();
- public abstract Drawable getBadgedIcon(int density);
/**
* Creates a LauncherActivityInfoCompat for the primary user.
diff --git a/src/com/android/launcher3/compat/LauncherActivityInfoCompatV16.java b/src/com/android/launcher3/compat/LauncherActivityInfoCompatV16.java
index ea51aac..fee0376 100644
--- a/src/com/android/launcher3/compat/LauncherActivityInfoCompatV16.java
+++ b/src/com/android/launcher3/compat/LauncherActivityInfoCompatV16.java
@@ -93,8 +93,4 @@
public String getName() {
return mActivityInfo.name;
}
-
- public Drawable getBadgedIcon(int density) {
- return getIcon(density);
- }
}
diff --git a/src/com/android/launcher3/compat/LauncherActivityInfoCompatVL.java b/src/com/android/launcher3/compat/LauncherActivityInfoCompatVL.java
index 4448758..67c5c27 100644
--- a/src/com/android/launcher3/compat/LauncherActivityInfoCompatVL.java
+++ b/src/com/android/launcher3/compat/LauncherActivityInfoCompatVL.java
@@ -55,8 +55,4 @@
public long getFirstInstallTime() {
return mLauncherActivityInfo.getFirstInstallTime();
}
-
- public Drawable getBadgedIcon(int density) {
- return mLauncherActivityInfo.getBadgedIcon(density);
- }
}
diff --git a/src/com/android/launcher3/compat/PackageInstallerCompatVL.java b/src/com/android/launcher3/compat/PackageInstallerCompatVL.java
index 3ad5101..4aa667e 100644
--- a/src/com/android/launcher3/compat/PackageInstallerCompatVL.java
+++ b/src/com/android/launcher3/compat/PackageInstallerCompatVL.java
@@ -43,7 +43,6 @@
PackageInstallerCompatVL(Context context) {
mInstaller = context.getPackageManager().getPackageInstaller();
- LauncherAppState.setApplicationContext(context.getApplicationContext());
mCache = LauncherAppState.getInstance().getIconCache();
mWorker = new Handler(LauncherModel.getWorkerLooper());
@@ -107,7 +106,7 @@
@Override
public void onProgressChanged(int sessionId, float progress) {
SessionInfo session = mInstaller.getSessionInfo(sessionId);
- if (session != null) {
+ if (session != null && session.getAppPackageName() != null) {
sendUpdate(new PackageInstallInfo(session.getAppPackageName(),
STATUS_INSTALLING,
(int) (session.getProgress() * 100)));
@@ -124,7 +123,7 @@
private void pushSessionDisplayToLauncher(int sessionId) {
SessionInfo session = mInstaller.getSessionInfo(sessionId);
- if (session != null) {
+ if (session != null && session.getAppPackageName() != null) {
addSessionInfoToCahce(session, UserHandleCompat.myUserHandle());
LauncherAppState app = LauncherAppState.getInstanceNoCreate();
diff --git a/src/com/android/launcher3/compat/UserHandleCompat.java b/src/com/android/launcher3/compat/UserHandleCompat.java
index 567022b..9479908 100644
--- a/src/com/android/launcher3/compat/UserHandleCompat.java
+++ b/src/com/android/launcher3/compat/UserHandleCompat.java
@@ -49,7 +49,7 @@
}
}
- UserHandle getUser() {
+ public UserHandle getUser() {
return mUser;
}
diff --git a/src/com/android/launcher3/compat/UserManagerCompat.java b/src/com/android/launcher3/compat/UserManagerCompat.java
index f708004..6b7cba8 100644
--- a/src/com/android/launcher3/compat/UserManagerCompat.java
+++ b/src/com/android/launcher3/compat/UserManagerCompat.java
@@ -17,8 +17,6 @@
package com.android.launcher3.compat;
import android.content.Context;
-import android.graphics.drawable.Drawable;
-import android.os.Build;
import com.android.launcher3.Utilities;
@@ -54,7 +52,6 @@
public abstract List<UserHandleCompat> getUserProfiles();
public abstract long getSerialNumberForUser(UserHandleCompat user);
public abstract UserHandleCompat getUserForSerialNumber(long serialNumber);
- public abstract Drawable getBadgedDrawableForUser(Drawable unbadged, UserHandleCompat user);
public abstract CharSequence getBadgedLabelForUser(CharSequence label, UserHandleCompat user);
public abstract long getUserCreationTime(UserHandleCompat user);
}
diff --git a/src/com/android/launcher3/compat/UserManagerCompatV16.java b/src/com/android/launcher3/compat/UserManagerCompatV16.java
index 85aee57..fcd7555 100644
--- a/src/com/android/launcher3/compat/UserManagerCompatV16.java
+++ b/src/com/android/launcher3/compat/UserManagerCompatV16.java
@@ -16,8 +16,6 @@
package com.android.launcher3.compat;
-import android.graphics.drawable.Drawable;
-
import java.util.ArrayList;
import java.util.List;
@@ -36,11 +34,6 @@
return UserHandleCompat.myUserHandle();
}
- public Drawable getBadgedDrawableForUser(Drawable unbadged,
- UserHandleCompat user) {
- return unbadged;
- }
-
public long getSerialNumberForUser(UserHandleCompat user) {
return 0;
}
diff --git a/src/com/android/launcher3/compat/UserManagerCompatVL.java b/src/com/android/launcher3/compat/UserManagerCompatVL.java
index dc3ec3c..c53d702 100644
--- a/src/com/android/launcher3/compat/UserManagerCompatVL.java
+++ b/src/com/android/launcher3/compat/UserManagerCompatVL.java
@@ -21,11 +21,9 @@
import android.content.Context;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
-import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.UserHandle;
-import com.android.launcher3.LauncherAppState;
import com.android.launcher3.Utilities;
import com.android.launcher3.util.LongArrayMap;
@@ -87,11 +85,6 @@
}
@Override
- public Drawable getBadgedDrawableForUser(Drawable unbadged, UserHandleCompat user) {
- return mPm.getUserBadgedIcon(unbadged, user.getUser());
- }
-
- @Override
public CharSequence getBadgedLabelForUser(CharSequence label, UserHandleCompat user) {
if (user == null) {
return label;
@@ -104,8 +97,7 @@
if (Utilities.ATLEAST_MARSHMALLOW) {
return mUserManager.getUserCreationTime(user.getUser());
}
- SharedPreferences prefs = mContext.getSharedPreferences(
- LauncherAppState.getSharedPreferencesKey(), Context.MODE_PRIVATE);
+ SharedPreferences prefs = Utilities.getPrefs(mContext);
String key = USER_CREATION_TIME_KEY + getSerialNumberForUser(user);
if (!prefs.contains(key)) {
prefs.edit().putLong(key, System.currentTimeMillis()).apply();
diff --git a/src/com/android/launcher3/config/FeatureFlags.java b/src/com/android/launcher3/config/FeatureFlags.java
new file mode 100644
index 0000000..c16bdac
--- /dev/null
+++ b/src/com/android/launcher3/config/FeatureFlags.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2015 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.launcher3.config;
+
+/**
+ * Defines a set of flags used to control various launcher behaviors
+ * All the flags must be defined as
+ * public static final boolean LAUNCHER3_FLAG_NAME = true/false;
+ *
+ * Use LAUNCHER3_ prefix for prevent namespace conflicts.
+ */
+public final class FeatureFlags {
+
+ private FeatureFlags() {}
+
+ public static final boolean IS_DEV_BUILD = false;
+ public static final boolean IS_ALPHA_BUILD = false;
+ public static final boolean IS_RELEASE_BUILD = true;
+
+ // Custom flags go below this
+ public static final boolean LAUNCHER3_ICON_NORMALIZATION = true;
+
+}
diff --git a/src/com/android/launcher3/model/MigrateFromRestoreTask.java b/src/com/android/launcher3/model/MigrateFromRestoreTask.java
index 6a529f6..786ab60 100644
--- a/src/com/android/launcher3/model/MigrateFromRestoreTask.java
+++ b/src/com/android/launcher3/model/MigrateFromRestoreTask.java
@@ -71,7 +71,7 @@
public MigrateFromRestoreTask(Context context) {
mContext = context;
- SharedPreferences prefs = prefs(context);
+ SharedPreferences prefs = Utilities.getPrefs(context);
Point sourceSize = parsePoint(prefs.getString(KEY_MIGRATION_SOURCE_SIZE, ""));
mSrcX = sourceSize.x;
mSrcY = sourceSize.y;
@@ -632,9 +632,9 @@
mEntryToRemove.add(entry.id);
continue;
}
-
entries.add(entry);
}
+ c.close();
return entries;
}
@@ -655,7 +655,7 @@
mEntryToRemove.add(c.getLong(0));
}
}
-
+ c.close();
return total;
}
@@ -745,23 +745,19 @@
public static void markForMigration(Context context, int srcX, int srcY,
HashSet<String> widgets) {
- prefs(context).edit()
+ Utilities.getPrefs(context).edit()
.putString(KEY_MIGRATION_SOURCE_SIZE, srcX + "," + srcY)
.putStringSet(KEY_MIGRATION_WIDGET_MINSIZE, widgets)
.apply();
}
public static boolean shouldRunTask(Context context) {
- return !TextUtils.isEmpty(prefs(context).getString(KEY_MIGRATION_SOURCE_SIZE, ""));
+ return !TextUtils.isEmpty(Utilities.getPrefs(context).getString(KEY_MIGRATION_SOURCE_SIZE, ""));
}
public static void clearFlags(Context context) {
- prefs(context).edit().remove(KEY_MIGRATION_SOURCE_SIZE)
+ Utilities.getPrefs(context).edit().remove(KEY_MIGRATION_SOURCE_SIZE)
.remove(KEY_MIGRATION_WIDGET_MINSIZE).commit();
}
- private static SharedPreferences prefs(Context context) {
- return context.getSharedPreferences(LauncherAppState.getSharedPreferencesKey(),
- Context.MODE_PRIVATE);
- }
}
diff --git a/src/com/android/launcher3/DummyWidget.java b/src/com/android/launcher3/testing/DummyWidget.java
similarity index 82%
rename from src/com/android/launcher3/DummyWidget.java
rename to src/com/android/launcher3/testing/DummyWidget.java
index 59cd805..df887ac 100644
--- a/src/com/android/launcher3/DummyWidget.java
+++ b/src/com/android/launcher3/testing/DummyWidget.java
@@ -1,7 +1,10 @@
-package com.android.launcher3;
+package com.android.launcher3.testing;
import android.appwidget.AppWidgetProviderInfo;
+import com.android.launcher3.CustomAppWidget;
+import com.android.launcher3.R;
+
public class DummyWidget implements CustomAppWidget {
@Override
public String getLabel() {
@@ -20,7 +23,7 @@
@Override
public int getWidgetLayout() {
- return R.layout.dummy_widget;
+ return R.layout.zzz_dummy_widget;
}
@Override
diff --git a/src/com/android/launcher3/MemoryDumpActivity.java b/src/com/android/launcher3/testing/MemoryDumpActivity.java
similarity index 93%
rename from src/com/android/launcher3/MemoryDumpActivity.java
rename to src/com/android/launcher3/testing/MemoryDumpActivity.java
index d79be80..9bcf92b 100644
--- a/src/com/android/launcher3/MemoryDumpActivity.java
+++ b/src/com/android/launcher3/testing/MemoryDumpActivity.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.launcher3;
+package com.android.launcher3.testing;
import android.app.Activity;
import android.content.ComponentName;
@@ -23,10 +23,20 @@
import android.content.ServiceConnection;
import android.content.pm.PackageManager;
import android.net.Uri;
-import android.os.*;
+import android.os.Build;
+import android.os.Bundle;
+import android.os.Environment;
+import android.os.IBinder;
import android.util.Log;
-import java.io.*;
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.zip.ZipEntry;
diff --git a/src/com/android/launcher3/MemoryTracker.java b/src/com/android/launcher3/testing/MemoryTracker.java
similarity index 92%
rename from src/com/android/launcher3/MemoryTracker.java
rename to src/com/android/launcher3/testing/MemoryTracker.java
index 067a50f..ed2a312 100644
--- a/src/com/android/launcher3/MemoryTracker.java
+++ b/src/com/android/launcher3/testing/MemoryTracker.java
@@ -14,22 +14,28 @@
* limitations under the License.
*/
-package com.android.launcher3;
+package com.android.launcher3.testing;
import android.app.ActivityManager;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
-import android.os.*;
+import android.os.Binder;
+import android.os.Debug;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Message;
+import android.os.SystemClock;
import android.util.Log;
import android.util.LongSparseArray;
+import com.android.launcher3.util.TestingUtils;
+
import java.util.ArrayList;
import java.util.List;
public class MemoryTracker extends Service {
public static final String TAG = MemoryTracker.class.getSimpleName();
- public static final String ACTION_START_TRACKING = "com.android.launcher3.action.START_TRACKING";
private static final long UPDATE_RATE = 5000;
@@ -83,14 +89,6 @@
ActivityManager mAm;
- public static void startTrackingMe(Context context, String name) {
- context.startService(new Intent(context, MemoryTracker.class)
- .setAction(MemoryTracker.ACTION_START_TRACKING)
- .putExtra("pid", android.os.Process.myPid())
- .putExtra("name", name)
- );
- }
-
public ProcessMemInfo getMemInfo(int pid) {
return mData.get(pid);
}
@@ -190,7 +188,7 @@
Log.v(TAG, "Received start id " + startId + ": " + intent);
if (intent != null) {
- if (ACTION_START_TRACKING.equals(intent.getAction())) {
+ if (TestingUtils.ACTION_START_TRACKING.equals(intent.getAction())) {
final int pid = intent.getIntExtra("pid", -1);
final String name = intent.getStringExtra("name");
final long start = intent.getLongExtra("start", System.currentTimeMillis());
diff --git a/src/com/android/launcher3/testing/ToggleWeightWatcher.java b/src/com/android/launcher3/testing/ToggleWeightWatcher.java
new file mode 100644
index 0000000..e08ec3a
--- /dev/null
+++ b/src/com/android/launcher3/testing/ToggleWeightWatcher.java
@@ -0,0 +1,31 @@
+package com.android.launcher3.testing;
+
+import android.app.Activity;
+import android.content.SharedPreferences;
+import android.os.Bundle;
+import android.view.View;
+
+import com.android.launcher3.Launcher;
+import com.android.launcher3.LauncherAppState;
+import com.android.launcher3.Utilities;
+import com.android.launcher3.util.TestingUtils;
+
+public class ToggleWeightWatcher extends Activity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ SharedPreferences sp = Utilities.getPrefs(this);
+ boolean show = sp.getBoolean(TestingUtils.SHOW_WEIGHT_WATCHER, true);
+
+ show = !show;
+ sp.edit().putBoolean(TestingUtils.SHOW_WEIGHT_WATCHER, show).apply();
+
+ Launcher launcher = (Launcher) LauncherAppState.getInstance().getModel().getCallback();
+ if (launcher != null && launcher.mWeightWatcher != null) {
+ launcher.mWeightWatcher.setVisibility(show ? View.VISIBLE : View.GONE);
+ }
+ finish();
+ }
+}
diff --git a/src/com/android/launcher3/WeightWatcher.java b/src/com/android/launcher3/testing/WeightWatcher.java
similarity index 98%
rename from src/com/android/launcher3/WeightWatcher.java
rename to src/com/android/launcher3/testing/WeightWatcher.java
index 7568479..a26a2b6 100644
--- a/src/com/android/launcher3/WeightWatcher.java
+++ b/src/com/android/launcher3/testing/WeightWatcher.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.launcher3;
+package com.android.launcher3.testing;
import android.content.ComponentName;
import android.content.Context;
@@ -116,10 +116,6 @@
}
}
- public WeightWatcher(Context context) {
- this(context, null);
- }
-
@Override
public void onAttachedToWindow() {
super.onAttachedToWindow();
diff --git a/src/com/android/launcher3/util/ConfigMonitor.java b/src/com/android/launcher3/util/ConfigMonitor.java
new file mode 100644
index 0000000..c61fa88
--- /dev/null
+++ b/src/com/android/launcher3/util/ConfigMonitor.java
@@ -0,0 +1,55 @@
+package com.android.launcher3.util;
+
+/**
+ * Copyright (C) 2015 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.
+ */
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.res.Configuration;
+import android.util.Log;
+
+/**
+ * {@link BroadcastReceiver} which watches configuration changes and
+ * restarts the process in case changes which affect the device profile.
+ */
+public class ConfigMonitor extends BroadcastReceiver {
+
+ private final Context mContext;
+ private final float mFontScale;
+
+ public ConfigMonitor(Context context) {
+ mContext = context;
+
+ Configuration config = context.getResources().getConfiguration();
+ mFontScale = config.fontScale;
+ }
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ Configuration config = context.getResources().getConfiguration();
+ if (mFontScale != config.fontScale) {
+ Log.d("ConfigMonitor", "Configuration changed, restarting launcher");
+ mContext.unregisterReceiver(this);
+ android.os.Process.killProcess(android.os.Process.myPid());
+ }
+ }
+
+ public void register() {
+ mContext.registerReceiver(this, new IntentFilter(Intent.ACTION_CONFIGURATION_CHANGED));
+ }
+}
diff --git a/src/com/android/launcher3/util/FocusLogic.java b/src/com/android/launcher3/util/FocusLogic.java
index 696eabe..a5498f7 100644
--- a/src/com/android/launcher3/util/FocusLogic.java
+++ b/src/com/android/launcher3/util/FocusLogic.java
@@ -22,9 +22,6 @@
import android.view.ViewGroup;
import com.android.launcher3.CellLayout;
-import com.android.launcher3.DeviceProfile;
-import com.android.launcher3.Launcher;
-import com.android.launcher3.LauncherAppState;
import com.android.launcher3.ShortcutAndWidgetContainer;
import java.util.Arrays;
@@ -51,7 +48,7 @@
private static final String TAG = "FocusLogic";
private static final boolean DEBUG = false;
- // Item and page index related constant used by {@link #handleKeyEvent}.
+ /** Item and page index related constant used by {@link #handleKeyEvent}. */
public static final int NOOP = -1;
public static final int PREVIOUS_PAGE_RIGHT_COLUMN = -2;
@@ -66,6 +63,8 @@
public static final int NEXT_PAGE_LEFT_COLUMN = -9;
public static final int NEXT_PAGE_RIGHT_COLUMN = -10;
+ public static final int ALL_APPS_COLUMN = -11;
+
// Matrix related constant.
public static final int EMPTY = -1;
public static final int PIVOT = 100;
@@ -81,8 +80,11 @@
keyCode == KeyEvent.KEYCODE_DEL || keyCode == KeyEvent.KEYCODE_FORWARD_DEL);
}
- public static int handleKeyEvent(int keyCode, int cntX, int cntY,
- int [][] map, int iconIdx, int pageIndex, int pageCount, boolean isRtl) {
+ public static int handleKeyEvent(int keyCode, int [][] map, int iconIdx, int pageIndex,
+ int pageCount, boolean isRtl) {
+
+ int cntX = map == null ? -1 : map.length;
+ int cntY = map == null ? -1 : map[0].length;
if (DEBUG) {
Log.v(TAG, String.format(
@@ -93,16 +95,16 @@
int newIndex = NOOP;
switch (keyCode) {
case KeyEvent.KEYCODE_DPAD_LEFT:
- newIndex = handleDpadHorizontal(iconIdx, cntX, cntY, map, -1 /*increment*/);
- if (isRtl && newIndex == NOOP && pageIndex > 0) {
+ newIndex = handleDpadHorizontal(iconIdx, cntX, cntY, map, -1 /*increment*/, isRtl);
+ if (!isRtl && newIndex == NOOP && pageIndex > 0) {
newIndex = PREVIOUS_PAGE_RIGHT_COLUMN;
} else if (isRtl && newIndex == NOOP && pageIndex < pageCount - 1) {
newIndex = NEXT_PAGE_RIGHT_COLUMN;
}
break;
case KeyEvent.KEYCODE_DPAD_RIGHT:
- newIndex = handleDpadHorizontal(iconIdx, cntX, cntY, map, 1 /*increment*/);
- if (isRtl && newIndex == NOOP && pageIndex < pageCount - 1) {
+ newIndex = handleDpadHorizontal(iconIdx, cntX, cntY, map, 1 /*increment*/, isRtl);
+ if (!isRtl && newIndex == NOOP && pageIndex < pageCount - 1) {
newIndex = NEXT_PAGE_LEFT_COLUMN;
} else if (isRtl && newIndex == NOOP && pageIndex > 0) {
newIndex = PREVIOUS_PAGE_LEFT_COLUMN;
@@ -168,8 +170,12 @@
// Iterate thru the children.
for (int i = 0; i < parent.getChildCount(); i++ ) {
- int cx = ((CellLayout.LayoutParams) parent.getChildAt(i).getLayoutParams()).cellX;
- int cy = ((CellLayout.LayoutParams) parent.getChildAt(i).getLayoutParams()).cellY;
+ View cell = parent.getChildAt(i);
+ if (!cell.isFocusable()) {
+ continue;
+ }
+ int cx = ((CellLayout.LayoutParams) cell.getLayoutParams()).cellX;
+ int cy = ((CellLayout.LayoutParams) cell.getLayoutParams()).cellY;
matrix[invert ? (m - cx - 1) : cx][cy] = i;
}
if (DEBUG) {
@@ -184,51 +190,67 @@
* in portrait orientation. In landscape, [(icon + hotseat) column count x (icon row count)]
*/
// TODO: get rid of the dynamic matrix creation
- public static int[][] createSparseMatrix(CellLayout iconLayout, CellLayout hotseatLayout,
- boolean isHorizontal, int allappsiconRank, boolean includeAllappsicon) {
+ public static int[][] createSparseMatrixWithHotseat(CellLayout iconLayout,
+ CellLayout hotseatLayout, boolean isHotseatHorizontal, int allappsiconRank) {
ViewGroup iconParent = iconLayout.getShortcutsAndWidgets();
ViewGroup hotseatParent = hotseatLayout.getShortcutsAndWidgets();
+ boolean moreIconsInHotseatThanWorkspace = isHotseatHorizontal ?
+ hotseatLayout.getCountX() > iconLayout.getCountX() :
+ hotseatLayout.getCountY() > iconLayout.getCountY();
+
int m, n;
- if (isHorizontal) {
- m = iconLayout.getCountX();
+ if (isHotseatHorizontal) {
+ m = hotseatLayout.getCountX();
n = iconLayout.getCountY() + hotseatLayout.getCountY();
} else {
m = iconLayout.getCountX() + hotseatLayout.getCountX();
- n = iconLayout.getCountY();
+ n = hotseatLayout.getCountY();
}
int[][] matrix = createFullMatrix(m, n);
-
- // Iterate thru the children of the top parent.
+ if (moreIconsInHotseatThanWorkspace) {
+ if (isHotseatHorizontal) {
+ for (int j = 0; j < n; j++) {
+ matrix[allappsiconRank][j] = ALL_APPS_COLUMN;
+ }
+ } else {
+ for (int j = 0; j < m; j++) {
+ matrix[j][allappsiconRank] = ALL_APPS_COLUMN;
+ }
+ }
+ }
+ // Iterate thru the children of the workspace.
for (int i = 0; i < iconParent.getChildCount(); i++) {
- int cx = ((CellLayout.LayoutParams) iconParent.getChildAt(i).getLayoutParams()).cellX;
- int cy = ((CellLayout.LayoutParams) iconParent.getChildAt(i).getLayoutParams()).cellY;
+ View cell = iconParent.getChildAt(i);
+ if (!cell.isFocusable()) {
+ continue;
+ }
+ int cx = ((CellLayout.LayoutParams) cell.getLayoutParams()).cellX;
+ int cy = ((CellLayout.LayoutParams) cell.getLayoutParams()).cellY;
+ if (moreIconsInHotseatThanWorkspace) {
+ if (isHotseatHorizontal && cx >= allappsiconRank) {
+ // Add 1 to account for the All Apps button.
+ cx++;
+ }
+ if (!isHotseatHorizontal && cy >= allappsiconRank) {
+ // Add 1 to account for the All Apps button.
+ cy++;
+ }
+ }
matrix[cx][cy] = i;
}
- // Iterate thru the children of the bottom parent
- // The hotseat view group contains one more item than iconLayout column count.
- // If {@param allappsiconRank} not negative, then the last icon in the hotseat
- // is truncated. If it is negative, then all apps icon index is not inserted.
- for(int i = hotseatParent.getChildCount() - 1; i >= (includeAllappsicon ? 0 : 1); i--) {
- int delta = 0;
- if (isHorizontal) {
+ // Iterate thru the children of the hotseat.
+ for (int i = hotseatParent.getChildCount() - 1; i >= 0; i--) {
+ if (isHotseatHorizontal) {
int cx = ((CellLayout.LayoutParams)
hotseatParent.getChildAt(i).getLayoutParams()).cellX;
- if ((includeAllappsicon && cx >= allappsiconRank) ||
- (!includeAllappsicon && cx > allappsiconRank)) {
- delta = -1;
- }
- matrix[cx + delta][iconLayout.getCountY()] = iconParent.getChildCount() + i;
+ matrix[cx][iconLayout.getCountY()] = iconParent.getChildCount() + i;
} else {
int cy = ((CellLayout.LayoutParams)
hotseatParent.getChildAt(i).getLayoutParams()).cellY;
- if ((includeAllappsicon && cy >= allappsiconRank) ||
- (!includeAllappsicon && cy > allappsiconRank)) {
- delta = -1;
- }
- matrix[iconLayout.getCountX()][cy + delta] = iconParent.getChildCount() + i;
+ matrix[iconLayout.getCountX()][cy] = iconParent.getChildCount() + i;
}
}
if (DEBUG) {
@@ -248,7 +270,8 @@
* @param pivotY y coordinate of the focused item in the current page
*/
// TODO: get rid of the dynamic matrix creation
- public static int[][] createSparseMatrix(CellLayout iconLayout, int pivotX, int pivotY) {
+ public static int[][] createSparseMatrixWithPivotColumn(CellLayout iconLayout,
+ int pivotX, int pivotY) {
ViewGroup iconParent = iconLayout.getShortcutsAndWidgets();
@@ -256,8 +279,12 @@
// Iterate thru the children of the top parent.
for (int i = 0; i < iconParent.getChildCount(); i++) {
- int cx = ((CellLayout.LayoutParams) iconParent.getChildAt(i).getLayoutParams()).cellX;
- int cy = ((CellLayout.LayoutParams) iconParent.getChildAt(i).getLayoutParams()).cellY;
+ View cell = iconParent.getChildAt(i);
+ if (!cell.isFocusable()) {
+ continue;
+ }
+ int cx = ((CellLayout.LayoutParams) cell.getLayoutParams()).cellX;
+ int cy = ((CellLayout.LayoutParams) cell.getLayoutParams()).cellY;
if (pivotX < 0) {
matrix[cx - pivotX][cy] = i;
} else {
@@ -291,7 +318,7 @@
*/
// TODO: add unit tests to verify all permutation.
private static int handleDpadHorizontal(int iconIdx, int cntX, int cntY,
- int[][] matrix, int increment) {
+ int[][] matrix, int increment, boolean isRtl) {
if(matrix == null) {
throw new IllegalStateException("Dpad navigation requires a matrix.");
}
@@ -314,8 +341,9 @@
}
// Rule1: check first in the horizontal direction
- for (int i = xPos + increment; 0 <= i && i < cntX; i = i + increment) {
- if ((newIconIndex = inspectMatrix(i, yPos, cntX, cntY, matrix)) != NOOP) {
+ for (int x = xPos + increment; 0 <= x && x < cntX; x += increment) {
+ if ((newIconIndex = inspectMatrix(x, yPos, cntX, cntY, matrix)) != NOOP
+ && newIconIndex != ALL_APPS_COLUMN) {
return newIconIndex;
}
}
@@ -324,19 +352,41 @@
// (x2-n, yPos + 2*increment), (x2-n, yPos - 2*increment)
int nextYPos1;
int nextYPos2;
- int i = -1;
+ boolean haveCrossedAllAppsColumn1 = false;
+ boolean haveCrossedAllAppsColumn2 = false;
+ int x = -1;
for (int coeff = 1; coeff < cntY; coeff++) {
nextYPos1 = yPos + coeff * increment;
nextYPos2 = yPos - coeff * increment;
- for (i = xPos + increment * coeff; 0 <= i && i < cntX; i = i + increment) {
- if ((newIconIndex = inspectMatrix(i, nextYPos1, cntX, cntY, matrix)) != NOOP) {
+ x = xPos + increment * coeff;
+ if (inspectMatrix(x, nextYPos1, cntX, cntY, matrix) == ALL_APPS_COLUMN) {
+ haveCrossedAllAppsColumn1 = true;
+ }
+ if (inspectMatrix(x, nextYPos2, cntX, cntY, matrix) == ALL_APPS_COLUMN) {
+ haveCrossedAllAppsColumn2 = true;
+ }
+ for (; 0 <= x && x < cntX; x += increment) {
+ int offset1 = haveCrossedAllAppsColumn1 && x < cntX - 1 ? increment : 0;
+ newIconIndex = inspectMatrix(x, nextYPos1 + offset1, cntX, cntY, matrix);
+ if (newIconIndex != NOOP) {
return newIconIndex;
}
- if ((newIconIndex = inspectMatrix(i, nextYPos2, cntX, cntY, matrix)) != NOOP) {
+ int offset2 = haveCrossedAllAppsColumn2 && x < cntX - 1 ? -increment : 0;
+ newIconIndex = inspectMatrix(x, nextYPos2 + offset2, cntX, cntY, matrix);
+ if (newIconIndex != NOOP) {
return newIconIndex;
}
}
}
+
+ // Rule3: if switching between pages, do a brute-force search to find an item that was
+ // missed by rules 1 and 2 (such as when going from a bottom right icon to top left)
+ if (iconIdx == PIVOT) {
+ if (isRtl) {
+ return increment < 0 ? NEXT_PAGE_FIRST_ITEM : PREVIOUS_PAGE_LAST_ITEM;
+ }
+ return increment < 0 ? PREVIOUS_PAGE_LAST_ITEM : NEXT_PAGE_FIRST_ITEM;
+ }
return newIconIndex;
}
@@ -375,8 +425,9 @@
}
// Rule1: check first in the dpad direction
- for (int j = yPos + increment; 0 <= j && j <cntY && 0 <= j; j = j + increment) {
- if ((newIconIndex = inspectMatrix(xPos, j, cntX, cntY, matrix)) != NOOP) {
+ for (int y = yPos + increment; 0 <= y && y <cntY && 0 <= y; y += increment) {
+ if ((newIconIndex = inspectMatrix(xPos, y, cntX, cntY, matrix)) != NOOP
+ && newIconIndex != ALL_APPS_COLUMN) {
return newIconIndex;
}
}
@@ -385,15 +436,28 @@
// (xPos + 2*increment, y_(2-n))), (xPos - 2*increment, y_(2-n))
int nextXPos1;
int nextXPos2;
- int j = -1;
+ boolean haveCrossedAllAppsColumn1 = false;
+ boolean haveCrossedAllAppsColumn2 = false;
+ int y = -1;
for (int coeff = 1; coeff < cntX; coeff++) {
nextXPos1 = xPos + coeff * increment;
nextXPos2 = xPos - coeff * increment;
- for (j = yPos + increment * coeff; 0 <= j && j < cntY; j = j + increment) {
- if ((newIconIndex = inspectMatrix(nextXPos1, j, cntX, cntY, matrix)) != NOOP) {
+ y = yPos + increment * coeff;
+ if (inspectMatrix(nextXPos1, y, cntX, cntY, matrix) == ALL_APPS_COLUMN) {
+ haveCrossedAllAppsColumn1 = true;
+ }
+ if (inspectMatrix(nextXPos2, y, cntX, cntY, matrix) == ALL_APPS_COLUMN) {
+ haveCrossedAllAppsColumn2 = true;
+ }
+ for (; 0 <= y && y < cntY; y = y + increment) {
+ int offset1 = haveCrossedAllAppsColumn1 && y < cntY - 1 ? increment : 0;
+ newIconIndex = inspectMatrix(nextXPos1 + offset1, y, cntX, cntY, matrix);
+ if (newIconIndex != NOOP) {
return newIconIndex;
}
- if ((newIconIndex = inspectMatrix(nextXPos2, j, cntX, cntY, matrix)) != NOOP) {
+ int offset2 = haveCrossedAllAppsColumn2 && y < cntY - 1 ? -increment : 0;
+ newIconIndex = inspectMatrix(nextXPos2 + offset2, y, cntX, cntY, matrix);
+ if (newIconIndex != NOOP) {
return newIconIndex;
}
}
@@ -460,6 +524,7 @@
case CURRENT_PAGE_LAST_ITEM: return "CURRENT_PAGE_LAST";
case NEXT_PAGE_FIRST_ITEM: return "NEXT_PAGE_FIRST";
case NEXT_PAGE_LEFT_COLUMN: return "NEXT_PAGE_LEFT_COLUMN";
+ case ALL_APPS_COLUMN: return "ALL_APPS_COLUMN";
default:
return Integer.toString(index);
}
@@ -485,9 +550,9 @@
/**
* @param edgeColumn the column of the new icon. either {@link #NEXT_PAGE_LEFT_COLUMN} or
* {@link #NEXT_PAGE_RIGHT_COLUMN}
- * @return the view adjacent to {@param oldView} in the {@param nextPage}.
+ * @return the view adjacent to {@param oldView} in the {@param nextPage} of the folder.
*/
- public static View getAdjacentChildInNextPage(
+ public static View getAdjacentChildInNextFolderPage(
ShortcutAndWidgetContainer nextPage, View oldView, int edgeColumn) {
final int newRow = ((CellLayout.LayoutParams) oldView.getLayoutParams()).cellY;
diff --git a/src/com/android/launcher3/util/IconNormalizer.java b/src/com/android/launcher3/util/IconNormalizer.java
new file mode 100644
index 0000000..001cac0
--- /dev/null
+++ b/src/com/android/launcher3/util/IconNormalizer.java
@@ -0,0 +1,239 @@
+/*
+ * Copyright (C) 2015 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.launcher3.util;
+
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.drawable.Drawable;
+
+import com.android.launcher3.LauncherAppState;
+
+import java.nio.ByteBuffer;
+
+public class IconNormalizer {
+
+ // Ratio of icon visible area to full icon size for a square shaped icon
+ private static final float MAX_SQUARE_AREA_FACTOR = 359.0f / 576;
+ // Ratio of icon visible area to full icon size for a circular shaped icon
+ private static final float MAX_CIRCLE_AREA_FACTOR = 380.0f / 576;
+
+ private static final float CIRCLE_AREA_BY_RECT = (float) Math.PI / 4;
+
+ // Slope used to calculate icon visible area to full icon size for any generic shaped icon.
+ private static final float LINEAR_SCALE_SLOPE =
+ (MAX_CIRCLE_AREA_FACTOR - MAX_SQUARE_AREA_FACTOR) / (1 - CIRCLE_AREA_BY_RECT);
+
+ private static final int MIN_VISIBLE_ALPHA = 40;
+
+ private static final Object LOCK = new Object();
+ private static IconNormalizer sIconNormalizer;
+
+ private final int mMaxSize;
+ private final Bitmap mBitmap;
+ private final Canvas mCanvas;
+ private final byte[] mPixels;
+
+ // for each y, stores the position of the leftmost x and the rightmost x
+ private final float[] mLeftBorder;
+ private final float[] mRightBorder;
+
+ private IconNormalizer() {
+ // Use twice the icon size as maximum size to avoid scaling down twice.
+ mMaxSize = LauncherAppState.getInstance().getInvariantDeviceProfile().iconBitmapSize * 2;
+ mBitmap = Bitmap.createBitmap(mMaxSize, mMaxSize, Bitmap.Config.ALPHA_8);
+ mCanvas = new Canvas(mBitmap);
+ mPixels = new byte[mMaxSize * mMaxSize];
+
+ mLeftBorder = new float[mMaxSize];
+ mRightBorder = new float[mMaxSize];
+ }
+
+ /**
+ * Returns the amount by which the {@param d} should be scaled (in both dimensions) so that it
+ * matches the design guidelines for a launcher icon.
+ *
+ * We first calculate the convex hull of the visible portion of the icon.
+ * This hull then compared with the bounding rectangle of the hull to find how closely it
+ * resembles a circle and a square, by comparing the ratio of the areas. Note that this is not an
+ * ideal solution but it gives satisfactory result without affecting the performance.
+ *
+ * This closeness is used to determine the ratio of hull area to the full icon size.
+ * Refer {@link #MAX_CIRCLE_AREA_FACTOR} and {@link #MAX_SQUARE_AREA_FACTOR}
+ */
+ public synchronized float getScale(Drawable d) {
+ int width = d.getIntrinsicWidth();
+ int height = d.getIntrinsicHeight();
+ if (width <= 0 || height <= 0) {
+ width = width <= 0 || width > mMaxSize ? mMaxSize : width;
+ height = height <= 0 || height > mMaxSize ? mMaxSize : height;
+ } else if (width > mMaxSize || height > mMaxSize) {
+ int max = Math.max(width, height);
+ width = mMaxSize * width / max;
+ height = mMaxSize * height / max;
+ }
+
+ mBitmap.eraseColor(Color.TRANSPARENT);
+ d.setBounds(0, 0, width, height);
+ d.draw(mCanvas);
+
+ ByteBuffer buffer = ByteBuffer.wrap(mPixels);
+ buffer.rewind();
+ mBitmap.copyPixelsToBuffer(buffer);
+
+ // Overall bounds of the visible icon.
+ int topY = -1;
+ int bottomY = -1;
+ int leftX = mMaxSize + 1;
+ int rightX = -1;
+
+ // Create border by going through all pixels one row at a time and for each row find
+ // the first and the last non-transparent pixel. Set those values to mLeftBorder and
+ // mRightBorder and use -1 if there are no visible pixel in the row.
+
+ // buffer position
+ int index = 0;
+ // buffer shift after every row, width of buffer = mMaxSize
+ int rowSizeDiff = mMaxSize - width;
+ // first and last position for any row.
+ int firstX, lastX;
+
+ for (int y = 0; y < height; y++) {
+ firstX = lastX = -1;
+ for (int x = 0; x < width; x++) {
+ if ((mPixels[index] & 0xFF) > MIN_VISIBLE_ALPHA) {
+ if (firstX == -1) {
+ firstX = x;
+ }
+ lastX = x;
+ }
+ index++;
+ }
+ index += rowSizeDiff;
+
+ mLeftBorder[y] = firstX;
+ mRightBorder[y] = lastX;
+
+ // If there is at least one visible pixel, update the overall bounds.
+ if (firstX != -1) {
+ bottomY = y;
+ if (topY == -1) {
+ topY = y;
+ }
+
+ leftX = Math.min(leftX, firstX);
+ rightX = Math.max(rightX, lastX);
+ }
+ }
+
+ if (topY == -1 || rightX == -1) {
+ // No valid pixels found. Do not scale.
+ return 1;
+ }
+
+ convertToConvexArray(mLeftBorder, 1, topY, bottomY);
+ convertToConvexArray(mRightBorder, -1, topY, bottomY);
+
+ // Area of the convex hull
+ float area = 0;
+ for (int y = 0; y < height; y++) {
+ if (mLeftBorder[y] <= -1) {
+ continue;
+ }
+ area += mRightBorder[y] - mLeftBorder[y] + 1;
+ }
+
+ // Area of the rectangle required to fit the convex hull
+ float rectArea = (bottomY + 1 - topY) * (rightX + 1 - leftX);
+ float hullByRect = area / rectArea;
+
+ float scaleRequired;
+ if (hullByRect < CIRCLE_AREA_BY_RECT) {
+ scaleRequired = MAX_CIRCLE_AREA_FACTOR;
+ } else {
+ scaleRequired = MAX_SQUARE_AREA_FACTOR + LINEAR_SCALE_SLOPE * (1 - hullByRect);
+ }
+
+ float areaScale = area / (width * height);
+ // Use sqrt of the final ratio as the images is scaled across both width and height.
+ float scale = areaScale > scaleRequired ? (float) Math.sqrt(scaleRequired / areaScale) : 1;
+ return scale;
+ }
+
+ /**
+ * Modifies {@param xCordinates} to represent a convex border. Fills in all missing values
+ * (except on either ends) with appropriate values.
+ * @param xCordinates map of x coordinate per y.
+ * @param direction 1 for left border and -1 for right border.
+ * @param topY the first Y position (inclusive) with a valid value.
+ * @param bottomY the last Y position (inclusive) with a valid value.
+ */
+ private static void convertToConvexArray(
+ float[] xCordinates, int direction, int topY, int bottomY) {
+ int total = xCordinates.length;
+ // The tangent at each pixel.
+ float[] angles = new float[total - 1];
+
+ int first = topY; // First valid y coordinate
+ int last = -1; // Last valid y coordinate which didn't have a missing value
+
+ float lastAngle = Float.MAX_VALUE;
+
+ for (int i = topY + 1; i <= bottomY; i++) {
+ if (xCordinates[i] <= -1) {
+ continue;
+ }
+ int start;
+
+ if (lastAngle == Float.MAX_VALUE) {
+ start = first;
+ } else {
+ float currentAngle = (xCordinates[i] - xCordinates[last]) / (i - last);
+ start = last;
+ // If this position creates a concave angle, keep moving up until we find a
+ // position which creates a convex angle.
+ if ((currentAngle - lastAngle) * direction < 0) {
+ while (start > first) {
+ start --;
+ currentAngle = (xCordinates[i] - xCordinates[start]) / (i - start);
+ if ((currentAngle - angles[start]) * direction >= 0) {
+ break;
+ }
+ }
+ }
+ }
+
+ // Reset from last check
+ lastAngle = (xCordinates[i] - xCordinates[start]) / (i - start);
+ // Update all the points from start.
+ for (int j = start; j < i; j++) {
+ angles[j] = lastAngle;
+ xCordinates[j] = xCordinates[start] + lastAngle * (j - start);
+ }
+ last = i;
+ }
+ }
+
+ public static IconNormalizer getInstance() {
+ synchronized (LOCK) {
+ if (sIconNormalizer == null) {
+ sIconNormalizer = new IconNormalizer();
+ }
+ }
+ return sIconNormalizer;
+ }
+}
diff --git a/src/com/android/launcher3/util/ManagedProfileHeuristic.java b/src/com/android/launcher3/util/ManagedProfileHeuristic.java
index 74fc92a..fb9bbb2 100644
--- a/src/com/android/launcher3/util/ManagedProfileHeuristic.java
+++ b/src/com/android/launcher3/util/ManagedProfileHeuristic.java
@@ -42,6 +42,7 @@
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
+import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@@ -85,6 +86,7 @@
private ArrayList<ShortcutInfo> mHomescreenApps;
private ArrayList<ShortcutInfo> mWorkFolderApps;
+ private HashMap<ShortcutInfo, Long> mShortcutToInstallTimeMap;
private ManagedProfileHeuristic(Context context, UserHandleCompat user) {
mContext = context;
@@ -100,32 +102,29 @@
Context.MODE_PRIVATE);
}
+ private void initVars() {
+ mHomescreenApps = new ArrayList<>();
+ mWorkFolderApps = new ArrayList<>();
+ mShortcutToInstallTimeMap = new HashMap<>();
+ }
+
/**
* Checks the list of user apps and adds icons for newly installed apps on the homescreen or
* workfolder.
*/
public void processUserApps(List<LauncherActivityInfoCompat> apps) {
- mHomescreenApps = new ArrayList<>();
- mWorkFolderApps = new ArrayList<>();
+ initVars();
HashSet<String> packageSet = new HashSet<>();
final boolean userAppsExisted = getUserApps(packageSet);
boolean newPackageAdded = false;
-
for (LauncherActivityInfoCompat info : apps) {
String packageName = info.getComponentName().getPackageName();
if (!packageSet.contains(packageName)) {
packageSet.add(packageName);
newPackageAdded = true;
-
- try {
- PackageInfo pkgInfo = mContext.getPackageManager()
- .getPackageInfo(packageName, PackageManager.GET_UNINSTALLED_PACKAGES);
- markForAddition(info, pkgInfo.firstInstallTime);
- } catch (NameNotFoundException e) {
- Log.e(TAG, "Unknown package " + packageName, e);
- }
+ markForAddition(info, info.getFirstInstallTime());
}
}
@@ -142,7 +141,22 @@
ArrayList<ShortcutInfo> targetList =
(installTime <= mUserCreationTime + AUTO_ADD_TO_FOLDER_DURATION) ?
mWorkFolderApps : mHomescreenApps;
- targetList.add(ShortcutInfo.fromActivityInfo(info, mContext));
+ ShortcutInfo si = ShortcutInfo.fromActivityInfo(info, mContext);
+ mShortcutToInstallTimeMap.put(si, installTime);
+ targetList.add(si);
+ }
+
+ private void sortList(ArrayList<ShortcutInfo> infos) {
+ Collections.sort(infos, new Comparator<ShortcutInfo>() {
+
+ @Override
+ public int compare(ShortcutInfo lhs, ShortcutInfo rhs) {
+ Long lhsTime = mShortcutToInstallTimeMap.get(lhs);
+ Long rhsTime = mShortcutToInstallTimeMap.get(rhs);
+ return Utilities.longCompare(lhsTime == null ? 0 : lhsTime,
+ rhsTime == null ? 0 : rhsTime);
+ }
+ });
}
/**
@@ -152,13 +166,7 @@
if (mWorkFolderApps.isEmpty()) {
return;
}
- Collections.sort(mWorkFolderApps, new Comparator<ShortcutInfo>() {
-
- @Override
- public int compare(ShortcutInfo lhs, ShortcutInfo rhs) {
- return Long.compare(lhs.firstInstallTime, rhs.firstInstallTime);
- }
- });
+ sortList(mWorkFolderApps);
// Try to get a work folder.
String folderIdKey = USER_FOLDER_ID_PREFIX + mUserSerial;
@@ -222,6 +230,7 @@
finalizeWorkFolder();
if (addHomeScreenShortcuts && !mHomescreenApps.isEmpty()) {
+ sortList(mHomescreenApps);
mModel.addAndBindAddedWorkspaceItems(mContext, mHomescreenApps);
}
}
@@ -230,9 +239,7 @@
* Updates the list of installed apps and adds any new icons on homescreen or work folder.
*/
public void processPackageAdd(String[] packages) {
- mHomescreenApps = new ArrayList<>();
- mWorkFolderApps = new ArrayList<>();
-
+ initVars();
HashSet<String> packageSet = new HashSet<>();
final boolean userAppsExisted = getUserApps(packageSet);
diff --git a/src/com/android/launcher3/util/ParcelableSparseArray.java b/src/com/android/launcher3/util/ParcelableSparseArray.java
new file mode 100644
index 0000000..093577e
--- /dev/null
+++ b/src/com/android/launcher3/util/ParcelableSparseArray.java
@@ -0,0 +1,52 @@
+/**
+ * Copyright (C) 2015 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.launcher3.util;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.SparseArray;
+
+public class ParcelableSparseArray extends SparseArray<Parcelable> implements Parcelable {
+ public int describeContents() {
+ return 0;
+ }
+
+ public void writeToParcel(Parcel dest, int flags) {
+ final int count = size();
+ dest.writeInt(count);
+ for (int i = 0; i < count; i++) {
+ dest.writeInt(keyAt(i));
+ dest.writeParcelable(valueAt(i), 0);
+ }
+ }
+
+ public static final Parcelable.Creator<ParcelableSparseArray> CREATOR =
+ new Parcelable.Creator<ParcelableSparseArray>() {
+ public ParcelableSparseArray createFromParcel(Parcel source) {
+ final ParcelableSparseArray array = new ParcelableSparseArray();
+ final ClassLoader loader = array.getClass().getClassLoader();
+ final int count = source.readInt();
+ for (int i = 0; i < count; i++) {
+ array.put(source.readInt(), source.readParcelable(loader));
+ }
+ return array;
+ }
+
+ public ParcelableSparseArray[] newArray(int size) {
+ return new ParcelableSparseArray[size];
+ }
+ };
+}
diff --git a/src/com/android/launcher3/util/SQLiteCacheHelper.java b/src/com/android/launcher3/util/SQLiteCacheHelper.java
new file mode 100644
index 0000000..62a30d0
--- /dev/null
+++ b/src/com/android/launcher3/util/SQLiteCacheHelper.java
@@ -0,0 +1,128 @@
+package com.android.launcher3.util;
+
+import android.content.ContentValues;
+import android.content.Context;
+import android.database.Cursor;
+import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteException;
+import android.database.sqlite.SQLiteFullException;
+import android.database.sqlite.SQLiteOpenHelper;
+import android.util.Log;
+
+/**
+ * An extension of {@link SQLiteOpenHelper} with utility methods for a single table cache DB.
+ * Any exception during write operations are ignored, and any version change causes a DB reset.
+ */
+public abstract class SQLiteCacheHelper {
+ private static final String TAG = "SQLiteCacheHelper";
+
+ private final String mTableName;
+ private final MySQLiteOpenHelper mOpenHelper;
+
+ private boolean mIgnoreWrites;
+
+ public SQLiteCacheHelper(Context context, String name, int version, String tableName) {
+ mTableName = tableName;
+ mOpenHelper = new MySQLiteOpenHelper(context, name, version);
+
+ mIgnoreWrites = false;
+ }
+
+ /**
+ * @see SQLiteDatabase#update(String, ContentValues, String, String[])
+ */
+ public void update(ContentValues values, String whereClause, String[] whereArgs) {
+ if (mIgnoreWrites) {
+ return;
+ }
+ try {
+ mOpenHelper.getWritableDatabase().update(mTableName, values, whereClause, whereArgs);
+ } catch (SQLiteFullException e) {
+ onDiskFull(e);
+ } catch (SQLiteException e) {
+ Log.d(TAG, "Ignoring sqlite exception", e);
+ }
+ }
+
+ /**
+ * @see SQLiteDatabase#delete(String, String, String[])
+ */
+ public void delete(String whereClause, String[] whereArgs) {
+ if (mIgnoreWrites) {
+ return;
+ }
+ try {
+ mOpenHelper.getWritableDatabase().delete(mTableName, whereClause, whereArgs);
+ } catch (SQLiteFullException e) {
+ onDiskFull(e);
+ } catch (SQLiteException e) {
+ Log.d(TAG, "Ignoring sqlite exception", e);
+ }
+ }
+
+ /**
+ * @see SQLiteDatabase#insertWithOnConflict(String, String, ContentValues, int)
+ */
+ public void insertOrReplace(ContentValues values) {
+ if (mIgnoreWrites) {
+ return;
+ }
+ try {
+ mOpenHelper.getWritableDatabase().insertWithOnConflict(
+ mTableName, null, values, SQLiteDatabase.CONFLICT_REPLACE);
+ } catch (SQLiteFullException e) {
+ onDiskFull(e);
+ } catch (SQLiteException e) {
+ Log.d(TAG, "Ignoring sqlite exception", e);
+ }
+ }
+
+ private void onDiskFull(SQLiteFullException e) {
+ Log.e(TAG, "Disk full, all write operations will be ignored", e);
+ mIgnoreWrites = true;
+ }
+
+ /**
+ * @see SQLiteDatabase#query(String, String[], String, String[], String, String, String)
+ */
+ public Cursor query(String[] columns, String selection, String[] selectionArgs) {
+ return mOpenHelper.getReadableDatabase().query(
+ mTableName, columns, selection, selectionArgs, null, null, null);
+ }
+
+ protected abstract void onCreateTable(SQLiteDatabase db);
+
+ /**
+ * A private inner class to prevent direct DB access.
+ */
+ private class MySQLiteOpenHelper extends SQLiteOpenHelper {
+
+ public MySQLiteOpenHelper(Context context, String name, int version) {
+ super(context, name, null, version);
+ }
+
+ @Override
+ public void onCreate(SQLiteDatabase db) {
+ onCreateTable(db);
+ }
+
+ @Override
+ public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
+ if (oldVersion != newVersion) {
+ clearDB(db);
+ }
+ }
+
+ @Override
+ public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {
+ if (oldVersion != newVersion) {
+ clearDB(db);
+ }
+ }
+
+ private void clearDB(SQLiteDatabase db) {
+ db.execSQL("DROP TABLE IF EXISTS " + mTableName);
+ onCreate(db);
+ }
+ }
+}
diff --git a/src/com/android/launcher3/util/TestingUtils.java b/src/com/android/launcher3/util/TestingUtils.java
new file mode 100644
index 0000000..665c371
--- /dev/null
+++ b/src/com/android/launcher3/util/TestingUtils.java
@@ -0,0 +1,72 @@
+package com.android.launcher3.util;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.util.Log;
+import android.view.Gravity;
+import android.view.View;
+import android.widget.FrameLayout;
+
+import com.android.launcher3.CustomAppWidget;
+import com.android.launcher3.Launcher;
+import com.android.launcher3.LauncherAppState;
+import com.android.launcher3.R;
+import com.android.launcher3.Utilities;
+
+import java.util.HashMap;
+
+public class TestingUtils {
+
+ public static final String MEMORY_TRACKER = "com.android.launcher3.testing.MemoryTracker";
+ public static final String ACTION_START_TRACKING = "com.android.launcher3.action.START_TRACKING";
+
+ public static final boolean MEMORY_DUMP_ENABLED = false;
+ public static final String SHOW_WEIGHT_WATCHER = "debug.show_mem";
+
+ public static final boolean ENABLE_CUSTOM_WIDGET_TEST = false;
+ public static final String DUMMY_WIDGET = "com.android.launcher3.testing.DummyWidget";
+
+ public static void startTrackingMemory(Context context) {
+ if (MEMORY_DUMP_ENABLED) {
+ context.startService(new Intent()
+ .setComponent(new ComponentName(context.getPackageName(), MEMORY_TRACKER))
+ .setAction(ACTION_START_TRACKING)
+ .putExtra("pid", android.os.Process.myPid())
+ .putExtra("name", "L"));
+ }
+ }
+
+ public static void addWeightWatcher(Launcher launcher) {
+ if (MEMORY_DUMP_ENABLED) {
+ boolean show = Utilities.getPrefs(launcher).getBoolean(SHOW_WEIGHT_WATCHER, true);
+
+ int id = launcher.getResources().getIdentifier("zzz_weight_watcher", "layout",
+ launcher.getPackageName());
+ View watcher = launcher.getLayoutInflater().inflate(id, null);
+ watcher.setAlpha(0.5f);
+ ((FrameLayout) launcher.findViewById(R.id.launcher)).addView(watcher,
+ new FrameLayout.LayoutParams(
+ FrameLayout.LayoutParams.MATCH_PARENT,
+ FrameLayout.LayoutParams.WRAP_CONTENT,
+ Gravity.BOTTOM)
+ );
+
+ watcher.setVisibility(show ? View.VISIBLE : View.GONE);
+ launcher.mWeightWatcher = watcher;
+ }
+ }
+
+ public static void addDummyWidget(HashMap<String, CustomAppWidget> set) {
+ if (ENABLE_CUSTOM_WIDGET_TEST) {
+ try {
+ Class<?> clazz = Class.forName(DUMMY_WIDGET);
+ CustomAppWidget widget = (CustomAppWidget) clazz.newInstance();
+ set.put(widget.getClass().getName(), widget);
+ } catch (Exception e) {
+ Log.e("TestingUtils", "Error adding dummy widget", e);
+ }
+ }
+ }
+}
diff --git a/src/com/android/launcher3/widget/WidgetHostViewLoader.java b/src/com/android/launcher3/widget/WidgetHostViewLoader.java
index 461aebb..5d3af52 100644
--- a/src/com/android/launcher3/widget/WidgetHostViewLoader.java
+++ b/src/com/android/launcher3/widget/WidgetHostViewLoader.java
@@ -4,13 +4,13 @@
import android.appwidget.AppWidgetManager;
import android.content.Context;
import android.graphics.Rect;
-import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
+import android.util.Log;
import android.view.View;
import com.android.launcher3.AppWidgetResizeFrame;
-import com.android.launcher3.DragController.DragListener;
+import com.android.launcher3.DragController;
import com.android.launcher3.DragLayer;
import com.android.launcher3.DragSource;
import com.android.launcher3.Launcher;
@@ -19,7 +19,9 @@
import com.android.launcher3.compat.AppWidgetManagerCompat;
import com.android.launcher3.util.Thunk;
-public class WidgetHostViewLoader implements DragListener {
+public class WidgetHostViewLoader implements DragController.DragListener {
+ private static final String TAG = "WidgetHostViewLoader";
+ private static final boolean LOGD = false;
/* Runnables to handle inflation and binding. */
@Thunk Runnable mInflateWidgetRunnable = null;
@@ -48,6 +50,10 @@
@Override
public void onDragEnd() {
+ if (LOGD) {
+ Log.d(TAG, "Cleaning up in onDragEnd()...");
+ }
+
// Cleanup up preloading state.
mLauncher.getDragController().removeDragListener(this);
@@ -62,6 +68,9 @@
// The widget was inflated and added to the DragLayer -- remove it.
if (mInfo.boundWidget != null) {
+ if (LOGD) {
+ Log.d(TAG, "...removing widget from drag layer");
+ }
mLauncher.getDragLayer().removeView(mInfo.boundWidget);
mLauncher.getAppWidgetHost().deleteAppWidgetId(mInfo.boundWidget.getAppWidgetId());
mInfo.boundWidget = null;
@@ -89,6 +98,9 @@
@Override
public void run() {
mWidgetLoadingId = mLauncher.getAppWidgetHost().allocateAppWidgetId();
+ if (LOGD) {
+ Log.d(TAG, "Binding widget, id: " + mWidgetLoadingId);
+ }
if(AppWidgetManagerCompat.getInstance(mLauncher).bindAppWidgetIdIfAllowed(
mWidgetLoadingId, pInfo, options)) {
@@ -101,6 +113,9 @@
mInflateWidgetRunnable = new Runnable() {
@Override
public void run() {
+ if (LOGD) {
+ Log.d(TAG, "Inflating widget, id: " + mWidgetLoadingId);
+ }
if (mWidgetLoadingId == -1) {
return;
}
@@ -120,11 +135,17 @@
lp.x = lp.y = 0;
lp.customPosition = true;
hostView.setLayoutParams(lp);
+ if (LOGD) {
+ Log.d(TAG, "Adding host view to drag layer");
+ }
mLauncher.getDragLayer().addView(hostView);
mView.setTag(mInfo);
}
};
+ if (LOGD) {
+ Log.d(TAG, "About to bind/inflate widget");
+ }
mHandler.post(mBindWidgetRunnable);
return true;
}
diff --git a/src/com/android/launcher3/widget/WidgetsContainerView.java b/src/com/android/launcher3/widget/WidgetsContainerView.java
index 0c6ea31..b780f59 100644
--- a/src/com/android/launcher3/widget/WidgetsContainerView.java
+++ b/src/com/android/launcher3/widget/WidgetsContainerView.java
@@ -52,10 +52,9 @@
* The widgets list view container.
*/
public class WidgetsContainerView extends BaseContainerView
- implements View.OnLongClickListener, View.OnClickListener, DragSource{
-
+ implements View.OnLongClickListener, View.OnClickListener, DragSource {
private static final String TAG = "WidgetsContainerView";
- private static final boolean DEBUG = false;
+ private static final boolean LOGD = false;
/* Coefficient multiplied to the screen height for preloading widgets. */
private static final int PRELOAD_SCREEN_HEIGHT_MULTIPLE = 1;
@@ -92,13 +91,14 @@
mDragController = mLauncher.getDragController();
mAdapter = new WidgetsListAdapter(context, this, this, mLauncher);
mIconCache = (LauncherAppState.getInstance()).getIconCache();
- if (DEBUG) {
+ if (LOGD) {
Log.d(TAG, "WidgetsContainerView constructor");
}
}
@Override
protected void onFinishInflate() {
+ super.onFinishInflate();
mContent = findViewById(R.id.content);
mView = (WidgetsRecyclerView) findViewById(R.id.widgets_list_view);
mView.setAdapter(mAdapter);
@@ -148,14 +148,17 @@
if (mWidgetInstructionToast != null) {
mWidgetInstructionToast.cancel();
}
- mWidgetInstructionToast = Toast.makeText(getContext(),R.string.long_press_widget_to_add,
- Toast.LENGTH_SHORT);
+
+ CharSequence msg = Utilities.wrapForTts(
+ getContext().getText(R.string.long_press_widget_to_add),
+ getContext().getString(R.string.long_accessible_way_to_add));
+ mWidgetInstructionToast = Toast.makeText(getContext(), msg, Toast.LENGTH_SHORT);
mWidgetInstructionToast.show();
}
@Override
public boolean onLongClick(View v) {
- if (DEBUG) {
+ if (LOGD) {
Log.d(TAG, String.format("onLonglick [v=%s]", v));
}
// Return early if this is not initiated from a touch
@@ -164,14 +167,13 @@
if (!mLauncher.isWidgetsViewVisible() ||
mLauncher.getWorkspace().isSwitchingState()) return false;
// Return if global dragging is not enabled
- Log.d(TAG, String.format("onLonglick dragging enabled?.", v));
if (!mLauncher.isDraggingEnabled()) return false;
boolean status = beginDragging(v);
if (status && v.getTag() instanceof PendingAddWidgetInfo) {
WidgetHostViewLoader hostLoader = new WidgetHostViewLoader(mLauncher, v);
boolean preloadStatus = hostLoader.preloadWidget();
- if (DEBUG) {
+ if (LOGD) {
Log.d(TAG, String.format("preloading widget [status=%s]", preloadStatus));
}
mLauncher.getDragController().addDragListener(hostLoader);
@@ -300,6 +302,9 @@
@Override
public void onDropCompleted(View target, DragObject d, boolean isFlingToDelete,
boolean success) {
+ if (LOGD) {
+ Log.d(TAG, "onDropCompleted");
+ }
if (isFlingToDelete || !success || (target != mLauncher.getWorkspace() &&
!(target instanceof DeleteDropTarget) && !(target instanceof Folder))) {
// Exit spring loaded mode if we have not successfully dropped or have not handled the
diff --git a/src/com/android/launcher3/widget/WidgetsRecyclerView.java b/src/com/android/launcher3/widget/WidgetsRecyclerView.java
index 884bdc4..fe9c51c 100644
--- a/src/com/android/launcher3/widget/WidgetsRecyclerView.java
+++ b/src/com/android/launcher3/widget/WidgetsRecyclerView.java
@@ -102,9 +102,9 @@
// Stop the scroller if it is scrolling
stopScroll();
- getCurScrollState(mScrollPosState);
+ getCurScrollState(mScrollPosState, -1);
float pos = rowCount * touchFraction;
- int availableScrollHeight = getAvailableScrollHeight(rowCount, mScrollPosState.rowHeight);
+ int availableScrollHeight = getAvailableScrollHeight(rowCount);
LinearLayoutManager layoutManager = ((LinearLayoutManager) getLayoutManager());
layoutManager.scrollToPositionWithOffset(0, (int) -(availableScrollHeight * touchFraction));
@@ -131,7 +131,7 @@
}
// Skip early if, there no child laid out in the container.
- getCurScrollState(mScrollPosState);
+ getCurScrollState(mScrollPosState, -1);
if (mScrollPosState.rowIndex < 0) {
mScrollbar.setThumbOffset(-1, -1);
return;
@@ -143,10 +143,10 @@
/**
* Returns the current scroll state.
*/
- protected void getCurScrollState(ScrollPositionState stateOut) {
+ protected void getCurScrollState(ScrollPositionState stateOut, int viewTypeMask) {
stateOut.rowIndex = -1;
stateOut.rowTopOffset = -1;
- stateOut.rowHeight = -1;
+ stateOut.itemPos = -1;
// Skip early if widgets are not bound.
if (mWidgets == null) {
@@ -163,6 +163,17 @@
stateOut.rowIndex = position;
stateOut.rowTopOffset = getLayoutManager().getDecoratedTop(child);
- stateOut.rowHeight = child.getHeight();
+ stateOut.itemPos = position;
+ }
+
+ @Override
+ protected int getTop(int rowIndex) {
+ if (getChildCount() == 0) {
+ return 0;
+ }
+
+ // All the rows are the same height, return any child height
+ View child = getChildAt(0);
+ return child.getMeasuredHeight() * rowIndex;
}
}
\ No newline at end of file
diff --git a/tests/AndroidManifest.xml b/tests/AndroidManifest.xml
index 42ae5a3..8acc5e9 100644
--- a/tests/AndroidManifest.xml
+++ b/tests/AndroidManifest.xml
@@ -1,4 +1,4 @@
-<?xml version="2.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2015 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
@@ -15,15 +15,17 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
package="com.android.launcher3.tests">
+ <uses-sdk tools:overrideLibrary="android.support.test.uiautomator.v18"/>
+
<application>
<uses-library android:name="android.test.runner" />
</application>
<instrumentation
android:name="android.test.InstrumentationTestRunner"
- android:targetPackage="com.android.launcher3"
- android:label="Unit tests for Launcher3">
+ android:targetPackage="com.android.launcher3" >
</instrumentation>
</manifest>
diff --git a/tests/src/com/android/launcher3/InvariantDeviceProfileTest.java b/tests/src/com/android/launcher3/InvariantDeviceProfileTest.java
index a99ae4f..db3f72f 100644
--- a/tests/src/com/android/launcher3/InvariantDeviceProfileTest.java
+++ b/tests/src/com/android/launcher3/InvariantDeviceProfileTest.java
@@ -15,15 +15,14 @@
*/
package com.android.launcher3;
+import android.content.res.Resources;
+import android.graphics.Point;
import android.graphics.PointF;
+import android.graphics.Rect;
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.SmallTest;
import android.util.Log;
-import com.android.launcher3.DeviceProfile;
-import com.android.launcher3.InvariantDeviceProfile;
-import com.android.launcher3.util.FocusLogic;
-
import java.util.ArrayList;
/**
@@ -123,4 +122,72 @@
// Add more tests for other devices, however, running them once on a single device is enough
// for verifying that for a platform version, the WindowManager and DisplayMetrics is
// working as intended.
+
+ /**
+ * Make sure that the height for the QSB is what we expect in normal mode.
+ */
+ public void testQsbNormalHeight() {
+ Resources resources = getContext().getResources();
+ DeviceProfile landscapeProfile = mInvariantProfile.landscapeProfile;
+ DeviceProfile portraitProfile = mInvariantProfile.portraitProfile;
+ landscapeProfile.setSearchBarHeight(LauncherCallbacks.SEARCH_BAR_HEIGHT_NORMAL);
+ portraitProfile.setSearchBarHeight(LauncherCallbacks.SEARCH_BAR_HEIGHT_NORMAL);
+ Rect portraitBounds = portraitProfile.getSearchBarBounds(true); // RTL shouldn't matter.
+ int portraitHeight = (int) Utilities.dpiFromPx(portraitBounds.height(),
+ resources.getDisplayMetrics());
+ Rect landscapeBounds = landscapeProfile.getSearchBarBounds(true); // RTL shouldn't matter.
+ int landscapeHeight = (int) Utilities.dpiFromPx(landscapeBounds.height(),
+ resources.getDisplayMetrics());
+ if (portraitProfile.isTablet) {
+ assertEquals(8 + 48 + 24, portraitHeight);
+ } else {
+ assertEquals(8 + 48 + 12, portraitHeight);
+ }
+ // Make sure the height that we pass in the widget options bundle is the height of the
+ // search bar + 8dps padding top and bottom.
+ Point portraitDimens = portraitProfile.getSearchBarDimensForWidgetOpts(resources);
+ int portraitWidgetOptsHeight = portraitDimens.y;
+ Point landscapeDimens = landscapeProfile.getSearchBarDimensForWidgetOpts(resources);
+ int landscapeWidgetOptsHeight = landscapeDimens.y;
+ assertEquals(8 + 48 + 8, (int) Utilities.dpiFromPx(portraitWidgetOptsHeight,
+ resources.getDisplayMetrics()));
+ if (!landscapeProfile.isVerticalBarLayout()) {
+ assertEquals(portraitHeight, landscapeHeight);
+ assertEquals(portraitWidgetOptsHeight, landscapeWidgetOptsHeight);
+ }
+ }
+
+ /**
+ * Make sure that the height for the QSB is what we expect in tall mode.
+ */
+ public void testQsbTallHeight() {
+ Resources resources = getContext().getResources();
+ DeviceProfile landscapeProfile = mInvariantProfile.landscapeProfile;
+ DeviceProfile portraitProfile = mInvariantProfile.portraitProfile;
+ landscapeProfile.setSearchBarHeight(LauncherCallbacks.SEARCH_BAR_HEIGHT_TALL);
+ portraitProfile.setSearchBarHeight(LauncherCallbacks.SEARCH_BAR_HEIGHT_TALL);
+ Rect portraitBounds = portraitProfile.getSearchBarBounds(true); // RTL shouldn't matter.
+ int portraitHeight = (int) Utilities.dpiFromPx(portraitBounds.height(),
+ resources.getDisplayMetrics());
+ Rect landscapeBounds = landscapeProfile.getSearchBarBounds(true); // RTL shouldn't matter.
+ int landscapeHeight = (int) Utilities.dpiFromPx(landscapeBounds.height(),
+ resources.getDisplayMetrics());
+ if (portraitProfile.isTablet) {
+ assertEquals(8 + 80 + 24, portraitHeight);
+ } else {
+ assertEquals(8 + 80 + 2, portraitHeight);
+ }
+ // Make sure the height that we pass in the widget options bundle is the height of the
+ // search bar + 8dps padding top and bottom.
+ Point portraitDimens = portraitProfile.getSearchBarDimensForWidgetOpts(resources);
+ int portraitWidgetOptsHeight = portraitDimens.y;
+ Point landscapeDimens = landscapeProfile.getSearchBarDimensForWidgetOpts(resources);
+ int landscapeWidgetOptsHeight = landscapeDimens.y;
+ assertEquals(8 + 80 + 8, (int) Utilities.dpiFromPx(portraitWidgetOptsHeight,
+ resources.getDisplayMetrics()));
+ if (!landscapeProfile.isVerticalBarLayout()) {
+ assertEquals(portraitHeight, landscapeHeight);
+ assertEquals(portraitWidgetOptsHeight, landscapeWidgetOptsHeight);
+ }
+ }
}
diff --git a/tests/src/com/android/launcher3/QuickAddWidgetTest.java b/tests/src/com/android/launcher3/QuickAddWidgetTest.java
new file mode 100644
index 0000000..8c563f3
--- /dev/null
+++ b/tests/src/com/android/launcher3/QuickAddWidgetTest.java
@@ -0,0 +1,81 @@
+package com.android.launcher3;
+
+import android.content.Intent;
+import android.graphics.Point;
+import android.os.SystemClock;
+import android.support.test.uiautomator.By;
+import android.support.test.uiautomator.Direction;
+import android.support.test.uiautomator.UiDevice;
+import android.support.test.uiautomator.UiObject2;
+import android.support.test.uiautomator.Until;
+import android.test.InstrumentationTestCase;
+import android.view.MotionEvent;
+import android.view.ViewConfiguration;
+
+import java.util.List;
+
+/**
+ * Add an arbitrary widget from the widget picker very quickly to test potential race conditions.
+ */
+public class QuickAddWidgetTest extends InstrumentationTestCase {
+ private UiDevice mDevice;
+ private String mTargetPackage;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ mDevice = UiDevice.getInstance(getInstrumentation());
+
+ // Set Launcher3 as home.
+ mTargetPackage = getInstrumentation().getTargetContext().getPackageName();
+ Intent homeIntent = new Intent(Intent.ACTION_MAIN)
+ .addCategory(Intent.CATEGORY_HOME)
+ .setPackage(mTargetPackage)
+ .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ getInstrumentation().getContext().startActivity(homeIntent);
+ mDevice.wait(Until.hasObject(By.pkg(mTargetPackage).depth(0)), 3000);
+ }
+
+ public void testAddWidgetQuickly() throws Exception {
+ mDevice.pressMenu(); // Enter overview mode.
+ mDevice.wait(Until.findObject(By.text("Widgets")), 3000).click();
+ UiObject2 calendarWidget = getWidgetByName("Calendar");
+ Point center = calendarWidget.getVisibleCenter();
+ // Touch widget just long enough to pick it up (longPressTimeout), then let go immediately.
+ getInstrumentation().sendPointerSync(MotionEvent.obtain(SystemClock.uptimeMillis(),
+ SystemClock.uptimeMillis(), MotionEvent.ACTION_DOWN, center.x, center.y, 0));
+ Thread.sleep(ViewConfiguration.getLongPressTimeout());
+ getInstrumentation().sendPointerSync(MotionEvent.obtain(SystemClock.uptimeMillis(),
+ SystemClock.uptimeMillis(), MotionEvent.ACTION_UP, center.x, center.y, 0));
+
+ assertTrue("Drag was never started", isOnHomescreen());
+ }
+
+ private UiObject2 getWidgetByName(String name) {
+ UiObject2 widgetsList = mDevice.wait(Until.findObject(By.res(mTargetPackage,
+ "widgets_list_view")), 3000);
+ do {
+ UiObject2 widget = getVisibleWidgetByName(name);
+ if (widget != null) {
+ return widget;
+ }
+ } while (widgetsList.scroll(Direction.DOWN, 1f));
+ return getVisibleWidgetByName(name);
+ }
+
+ private UiObject2 getVisibleWidgetByName(String name) {
+ List<UiObject2> visibleWidgets = mDevice.wait(Until.findObjects(By.clazz(
+ "android.widget.LinearLayout")), 3000);
+ for (UiObject2 widget : visibleWidgets) {
+ if (widget.hasObject(By.text(name))) {
+ return widget;
+ }
+ }
+ return null;
+ }
+
+ private boolean isOnHomescreen() {
+ return mDevice.wait(Until.hasObject(By.res(mTargetPackage, "hotseat")), 3000);
+ }
+}
diff --git a/tests/src/com/android/launcher3/RotationPreferenceTest.java b/tests/src/com/android/launcher3/RotationPreferenceTest.java
new file mode 100644
index 0000000..0168ee6
--- /dev/null
+++ b/tests/src/com/android/launcher3/RotationPreferenceTest.java
@@ -0,0 +1,88 @@
+package com.android.launcher3;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.graphics.Rect;
+import android.support.test.uiautomator.UiDevice;
+import android.support.test.uiautomator.UiObject;
+import android.support.test.uiautomator.UiSelector;
+import android.test.InstrumentationTestCase;
+
+/**
+ * Test for auto rotate preference.
+ */
+public class RotationPreferenceTest extends InstrumentationTestCase {
+
+ private UiDevice mDevice;
+ private Context mTargetContext;
+ private String mTargetPackage;
+
+ private SharedPreferences mPrefs;
+ private boolean mOriginalRotationValue;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ mDevice = UiDevice.getInstance(getInstrumentation());
+ mTargetContext = getInstrumentation().getTargetContext();
+ mTargetPackage = mTargetContext.getPackageName();
+ mPrefs = Utilities.getPrefs(mTargetContext);
+ mOriginalRotationValue = mPrefs.getBoolean(Utilities.ALLOW_ROTATION_PREFERENCE_KEY, false);
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ setRotationEnabled(mOriginalRotationValue);
+ super.tearDown();
+ }
+
+ public void testRotation_disabled() throws Exception {
+ if (mTargetContext.getResources().getBoolean(R.bool.allow_rotation)) {
+ // This is a tablet. The test is only valid to mobile devices.
+ return;
+ }
+
+ setRotationEnabled(false);
+ mDevice.setOrientationRight();
+ goToLauncher();
+
+ Rect hotseat = getHotseatBounds();
+ assertTrue(hotseat.width() > hotseat.height());
+ }
+
+ public void testRotation_enabled() throws Exception {
+ if (mTargetContext.getResources().getBoolean(R.bool.allow_rotation)) {
+ // This is a tablet. The test is only valid to mobile devices.
+ return;
+ }
+
+ setRotationEnabled(true);
+ mDevice.setOrientationRight();
+ goToLauncher();
+
+ Rect hotseat = getHotseatBounds();
+ assertTrue(hotseat.width() < hotseat.height());
+ }
+
+ private void goToLauncher() {
+ Intent homeIntent = new Intent(Intent.ACTION_MAIN)
+ .addCategory(Intent.CATEGORY_HOME)
+ .setPackage(mTargetPackage)
+ .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ getInstrumentation().getContext().startActivity(homeIntent);
+ mDevice.findObject(new UiSelector().packageName(mTargetPackage)).waitForExists(6000);
+ }
+
+ private void setRotationEnabled(boolean enabled) {
+ mPrefs.edit().putBoolean(Utilities.ALLOW_ROTATION_PREFERENCE_KEY, enabled).commit();
+ }
+
+ private Rect getHotseatBounds() throws Exception {
+ UiObject hotseat = mDevice.findObject(
+ new UiSelector().resourceId(mTargetPackage + ":id/hotseat"));
+ hotseat.waitForExists(6000);
+ return hotseat.getVisibleBounds();
+ }
+}
diff --git a/tests/src/com/android/launcher3/util/FocusLogicTest.java b/tests/src/com/android/launcher3/util/FocusLogicTest.java
index ea87014..a0d17c8 100644
--- a/tests/src/com/android/launcher3/util/FocusLogicTest.java
+++ b/tests/src/com/android/launcher3/util/FocusLogicTest.java
@@ -19,6 +19,7 @@
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.SmallTest;
import android.view.KeyEvent;
+import android.view.View;
import com.android.launcher3.util.FocusLogic;
@@ -57,4 +58,200 @@
// may get created in real world to test this method. OR 2) Move all the matrix
// management routine to celllayout and write tests for them.
}
+
+ public void testMoveFromBottomRightToBottomLeft() {
+ int[][] map = transpose(new int[][] {
+ {-1, 0, -1, -1, -1, -1},
+ {-1, -1, -1, -1, -1, -1},
+ {-1, -1, -1, -1, -1, -1},
+ {-1, -1, -1, -1, -1, -1},
+ {100, 1, -1, -1, -1, -1},
+ });
+ int i = FocusLogic.handleKeyEvent(KeyEvent.KEYCODE_DPAD_RIGHT, map, 100, 1, 2, false);
+ assertEquals(1, i);
+ }
+
+ public void testMoveFromBottomRightToTopLeft() {
+ int[][] map = transpose(new int[][] {
+ {-1, 0, -1, -1, -1, -1},
+ {-1, -1, -1, -1, -1, -1},
+ {-1, -1, -1, -1, -1, -1},
+ {-1, -1, -1, -1, -1, -1},
+ {100, -1, -1, -1, -1, -1},
+ });
+ int i = FocusLogic.handleKeyEvent(KeyEvent.KEYCODE_DPAD_RIGHT, map, 100, 1, 2, false);
+ assertEquals(FocusLogic.NEXT_PAGE_FIRST_ITEM, i);
+ }
+
+ public void testMoveIntoHotseatWithEqualHotseatAndWorkspaceColumns() {
+ // Test going from an icon right above the All Apps button to the All Apps button.
+ int[][] map = transpose(new int[][] {
+ {-1, -1, -1, -1, -1},
+ {-1, -1, -1, -1, -1},
+ {-1, -1, -1, -1, -1},
+ {-1, -1, 0, -1, -1},
+ { 2, 3, 1, 4, 5},
+ });
+ int i = FocusLogic.handleKeyEvent(KeyEvent.KEYCODE_DPAD_DOWN, map, 0, 1, 1, true);
+ assertEquals(1, i);
+ // Test going from an icon above and to the right of the All Apps
+ // button to an icon to the right of the All Apps button.
+ map = transpose(new int[][] {
+ {-1, -1, -1, -1, -1},
+ {-1, -1, -1, -1, -1},
+ {-1, -1, -1, -1, -1},
+ {-1, -1, -1, 0, -1},
+ { 2, 3, 1, 4, 5},
+ });
+ i = FocusLogic.handleKeyEvent(KeyEvent.KEYCODE_DPAD_DOWN, map, 0, 1, 1, true);
+ assertEquals(4, i);
+ }
+
+ public void testMoveIntoHotseatWithExtraColumnForAllApps() {
+ // Test going from an icon above and to the left
+ // of the All Apps button to the All Apps button.
+ int[][] map = transpose(new int[][] {
+ {-1, -1, -1,-11, -1, -1, -1},
+ {-1, -1, -1,-11, -1, -1, -1},
+ {-1, -1, -1,-11, -1, -1, -1},
+ {-1, -1, -1,-11, -1, -1, -1},
+ {-1, -1, 0,-11, -1, -1, -1},
+ {-1, -1, -1, 1, 1, -1, -1},
+ });
+ int i = FocusLogic.handleKeyEvent(KeyEvent.KEYCODE_DPAD_DOWN, map, 0, 1, 1, true);
+ assertEquals(1, i);
+ // Test going from an icon above and to the right
+ // of the All Apps button to the All Apps button.
+ map = transpose(new int[][] {
+ {-1, -1, -1,-11, -1, -1, -1},
+ {-1, -1, -1,-11, -1, -1, -1},
+ {-1, -1, -1,-11, -1, -1, -1},
+ {-1, -1, -1,-11, -1, -1, -1},
+ {-1, -1, -1,-11, 0, -1, -1},
+ {-1, -1, -1, 1, -1, -1, -1},
+ });
+ i = FocusLogic.handleKeyEvent(KeyEvent.KEYCODE_DPAD_DOWN, map, 0, 1, 1, true);
+ assertEquals(1, i);
+ // Test going from the All Apps button to an icon
+ // above and to the right of the All Apps button.
+ map = transpose(new int[][] {
+ {-1, -1, -1,-11, -1, -1, -1},
+ {-1, -1, -1,-11, -1, -1, -1},
+ {-1, -1, -1,-11, -1, -1, -1},
+ {-1, -1, -1,-11, -1, -1, -1},
+ {-1, -1, -1,-11, 0, -1, -1},
+ {-1, -1, -1, 1, -1, -1, -1},
+ });
+ i = FocusLogic.handleKeyEvent(KeyEvent.KEYCODE_DPAD_UP, map, 1, 1, 1, true);
+ assertEquals(0, i);
+ // Test going from an icon above and to the left of the
+ // All Apps button in landscape to the All Apps button.
+ map = transpose(new int[][] {
+ { -1, -1, -1, -1, -1},
+ { -1, -1, -1, 0, -1},
+ {-11,-11,-11,-11, 1},
+ { -1, -1, -1, -1, -1},
+ { -1, -1, -1, -1, -1},
+ });
+ i = FocusLogic.handleKeyEvent(KeyEvent.KEYCODE_DPAD_RIGHT, map, 0, 1, 1, true);
+ assertEquals(1, i);
+ // Test going from the All Apps button in landscape to
+ // an icon above and to the left of the All Apps button.
+ map = transpose(new int[][] {
+ { -1, -1, -1, -1, -1},
+ { -1, -1, -1, 0, -1},
+ {-11,-11,-11,-11, 1},
+ { -1, -1, -1, -1, -1},
+ { -1, -1, -1, -1, -1},
+ });
+ i = FocusLogic.handleKeyEvent(KeyEvent.KEYCODE_DPAD_LEFT, map, 1, 1, 1, true);
+ assertEquals(0, i);
+ // Test that going to the hotseat always goes to the same row as the original icon.
+ map = transpose(new int[][]{
+ { 0, 1, 2,-11, 3, 4, 5},
+ {-1, -1, -1,-11, -1, -1, -1},
+ {-1, -1, -1,-11, -1, -1, -1},
+ {-1, -1, -1,-11, -1, -1, -1},
+ {-1, -1, -1,-11, -1, -1, -1},
+ { 7, 8, 9, 6, 10, 11, 12},
+ });
+ i = FocusLogic.handleKeyEvent(KeyEvent.KEYCODE_DPAD_DOWN, map, 0, 1, 1, true);
+ assertEquals(7, i);
+ i = FocusLogic.handleKeyEvent(KeyEvent.KEYCODE_DPAD_DOWN, map, 1, 1, 1, true);
+ assertEquals(8, i);
+ i = FocusLogic.handleKeyEvent(KeyEvent.KEYCODE_DPAD_DOWN, map, 2, 1, 1, true);
+ assertEquals(9, i);
+ i = FocusLogic.handleKeyEvent(KeyEvent.KEYCODE_DPAD_DOWN, map, 3, 1, 1, true);
+ assertEquals(10, i);
+ i = FocusLogic.handleKeyEvent(KeyEvent.KEYCODE_DPAD_DOWN, map, 4, 1, 1, true);
+ assertEquals(11, i);
+ i = FocusLogic.handleKeyEvent(KeyEvent.KEYCODE_DPAD_DOWN, map, 5, 1, 1, true);
+ assertEquals(12, i);
+ }
+
+ public void testCrossingAllAppsColumn() {
+ // Test crossing from left to right in portrait.
+ int[][] map = transpose(new int[][] {
+ {-1, -1,-11, -1, -1},
+ {-1, 0,-11, -1, -1},
+ {-1, -1,-11, 1, -1},
+ {-1, -1,-11, -1, -1},
+ {-1, -1, 2, -1, -1},
+ });
+ int i = FocusLogic.handleKeyEvent(KeyEvent.KEYCODE_DPAD_DOWN, map, 0, 1, 1, true);
+ assertEquals(1, i);
+ // Test crossing from right to left in portrait.
+ map = transpose(new int[][] {
+ {-1, -1,-11, -1, -1},
+ {-1, -1,-11, 0, -1},
+ {-1, 1,-11, -1, -1},
+ {-1, -1,-11, -1, -1},
+ {-1, -1, 2, -1, -1},
+ });
+ i = FocusLogic.handleKeyEvent(KeyEvent.KEYCODE_DPAD_DOWN, map, 0, 1, 1, true);
+ assertEquals(1, i);
+ // Test crossing from left to right in landscape.
+ map = transpose(new int[][] {
+ { -1, -1, -1, -1, -1},
+ { -1, -1, -1, 0, -1},
+ {-11,-11,-11,-11, 2},
+ { -1, 1, -1, -1, -1},
+ { -1, -1 -1, -1, -1},
+ });
+ i = FocusLogic.handleKeyEvent(KeyEvent.KEYCODE_DPAD_LEFT, map, 0, 1, 1, true);
+ assertEquals(1, i);
+ // Test crossing from right to left in landscape.
+ map = transpose(new int[][] {
+ { -1, -1, -1, -1, -1},
+ { -1, 0, -1, -1, -1},
+ {-11,-11,-11,-11, 2},
+ { -1, -1, 1, -1, -1},
+ { -1, -1, -1, -1, -1},
+ });
+ i = FocusLogic.handleKeyEvent(KeyEvent.KEYCODE_DPAD_RIGHT, map, 0, 1, 1, true);
+ assertEquals(1, i);
+ // Test NOT crossing it, if the All Apps button is the only suitable candidate.
+ map = transpose(new int[][]{
+ {-1, 0, -1, -1, -1},
+ {-1, 1, -1, -1, -1},
+ {-11, -11, -11, -11, 4},
+ {-1, 2, -1, -1, -1},
+ {-1, 3, -1, -1, -1},
+ });
+ i = FocusLogic.handleKeyEvent(KeyEvent.KEYCODE_DPAD_RIGHT, map, 1, 1, 1, true);
+ assertEquals(4, i);
+ i = FocusLogic.handleKeyEvent(KeyEvent.KEYCODE_DPAD_RIGHT, map, 2, 1, 1, true);
+ assertEquals(4, i);
+ }
+
+ /** Transposes the matrix so that we can write it in human-readable format in the tests. */
+ private int[][] transpose(int[][] m) {
+ int[][] t = new int[m[0].length][m.length];
+ for (int i = 0; i < m.length; i++) {
+ for (int j = 0; j < m[0].length; j++) {
+ t[j][i] = m[i][j];
+ }
+ }
+ return t;
+ }
}