summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore9
-rw-r--r--Android.mk15
-rw-r--r--AndroidManifest.xml51
-rw-r--r--WallpaperPicker/AndroidManifest.xml4
-rw-r--r--WallpaperPicker/res/drawable-hdpi/ic_images.pngbin1935 -> 354 bytes
-rw-r--r--WallpaperPicker/res/drawable-mdpi/ic_images.pngbin1332 -> 249 bytes
-rw-r--r--WallpaperPicker/res/drawable-xhdpi/ic_images.pngbin2480 -> 431 bytes
-rw-r--r--WallpaperPicker/res/drawable-xxhdpi/ic_images.pngbin2097 -> 621 bytes
-rw-r--r--WallpaperPicker/res/drawable-xxxhdpi/ic_images.pngbin0 -> 845 bytes
-rw-r--r--WallpaperPicker/res/layout/wallpaper_cropper.xml3
-rw-r--r--WallpaperPicker/res/layout/wallpaper_picker.xml42
-rw-r--r--WallpaperPicker/res/layout/wallpaper_picker_image_picker_item.xml1
-rw-r--r--WallpaperPicker/res/layout/wallpaper_picker_item.xml1
-rw-r--r--WallpaperPicker/res/layout/wallpaper_picker_live_wallpaper_item.xml1
-rw-r--r--WallpaperPicker/res/layout/wallpaper_picker_third_party_item.xml1
-rw-r--r--WallpaperPicker/res/values-af/strings.xml2
-rw-r--r--WallpaperPicker/res/values-am/strings.xml2
-rw-r--r--WallpaperPicker/res/values-ar/strings.xml2
-rw-r--r--WallpaperPicker/res/values-az-rAZ/strings.xml2
-rw-r--r--WallpaperPicker/res/values-bg/strings.xml2
-rw-r--r--WallpaperPicker/res/values-bn-rBD/strings.xml2
-rw-r--r--WallpaperPicker/res/values-ca/strings.xml2
-rw-r--r--WallpaperPicker/res/values-cs/strings.xml2
-rw-r--r--WallpaperPicker/res/values-da/strings.xml2
-rw-r--r--WallpaperPicker/res/values-de/strings.xml2
-rw-r--r--WallpaperPicker/res/values-el/strings.xml2
-rw-r--r--WallpaperPicker/res/values-en-rAU/strings.xml2
-rw-r--r--WallpaperPicker/res/values-en-rGB/strings.xml2
-rw-r--r--WallpaperPicker/res/values-en-rIN/strings.xml2
-rw-r--r--WallpaperPicker/res/values-es-rUS/strings.xml2
-rw-r--r--WallpaperPicker/res/values-es/strings.xml2
-rw-r--r--WallpaperPicker/res/values-et-rEE/strings.xml2
-rw-r--r--WallpaperPicker/res/values-eu-rES/strings.xml2
-rw-r--r--WallpaperPicker/res/values-fa/strings.xml2
-rw-r--r--WallpaperPicker/res/values-fi/strings.xml2
-rw-r--r--WallpaperPicker/res/values-fr-rCA/strings.xml2
-rw-r--r--WallpaperPicker/res/values-fr/strings.xml2
-rw-r--r--WallpaperPicker/res/values-gl-rES/strings.xml2
-rw-r--r--WallpaperPicker/res/values-gu-rIN/strings.xml2
-rw-r--r--WallpaperPicker/res/values-hi/strings.xml2
-rw-r--r--WallpaperPicker/res/values-hr/strings.xml2
-rw-r--r--WallpaperPicker/res/values-hu/strings.xml2
-rw-r--r--WallpaperPicker/res/values-hy-rAM/strings.xml2
-rw-r--r--WallpaperPicker/res/values-in/strings.xml2
-rw-r--r--WallpaperPicker/res/values-is-rIS/strings.xml2
-rw-r--r--WallpaperPicker/res/values-it/strings.xml2
-rw-r--r--WallpaperPicker/res/values-iw/strings.xml2
-rw-r--r--WallpaperPicker/res/values-ja/strings.xml2
-rw-r--r--WallpaperPicker/res/values-ka-rGE/strings.xml2
-rw-r--r--WallpaperPicker/res/values-kk-rKZ/strings.xml2
-rw-r--r--WallpaperPicker/res/values-km-rKH/strings.xml2
-rw-r--r--WallpaperPicker/res/values-kn-rIN/strings.xml2
-rw-r--r--WallpaperPicker/res/values-ko/strings.xml2
-rw-r--r--WallpaperPicker/res/values-ky-rKG/strings.xml2
-rw-r--r--WallpaperPicker/res/values-lo-rLA/strings.xml2
-rw-r--r--WallpaperPicker/res/values-lt/strings.xml2
-rw-r--r--WallpaperPicker/res/values-lv/strings.xml2
-rw-r--r--WallpaperPicker/res/values-mk-rMK/strings.xml2
-rw-r--r--WallpaperPicker/res/values-ml-rIN/strings.xml2
-rw-r--r--WallpaperPicker/res/values-mn-rMN/strings.xml2
-rw-r--r--WallpaperPicker/res/values-mr-rIN/strings.xml2
-rw-r--r--WallpaperPicker/res/values-ms-rMY/strings.xml2
-rw-r--r--WallpaperPicker/res/values-my-rMM/strings.xml2
-rw-r--r--WallpaperPicker/res/values-nb/strings.xml2
-rw-r--r--WallpaperPicker/res/values-ne-rNP/strings.xml2
-rw-r--r--WallpaperPicker/res/values-nl/strings.xml2
-rw-r--r--WallpaperPicker/res/values-pa-rIN/strings.xml2
-rw-r--r--WallpaperPicker/res/values-pl/strings.xml2
-rw-r--r--WallpaperPicker/res/values-pt-rPT/strings.xml2
-rw-r--r--WallpaperPicker/res/values-pt/strings.xml2
-rw-r--r--WallpaperPicker/res/values-ro/strings.xml2
-rw-r--r--WallpaperPicker/res/values-ru/strings.xml2
-rw-r--r--WallpaperPicker/res/values-si-rLK/strings.xml2
-rw-r--r--WallpaperPicker/res/values-sk/strings.xml2
-rw-r--r--WallpaperPicker/res/values-sl/strings.xml2
-rw-r--r--WallpaperPicker/res/values-sq-rAL/strings.xml2
-rw-r--r--WallpaperPicker/res/values-sr/strings.xml2
-rw-r--r--WallpaperPicker/res/values-sv/strings.xml2
-rw-r--r--WallpaperPicker/res/values-sw/strings.xml2
-rw-r--r--WallpaperPicker/res/values-sw720dp-v19/styles.xml2
-rw-r--r--WallpaperPicker/res/values-sw720dp/dimens.xml28
-rw-r--r--WallpaperPicker/res/values-sw720dp/styles.xml2
-rw-r--r--WallpaperPicker/res/values-ta-rIN/strings.xml2
-rw-r--r--WallpaperPicker/res/values-te-rIN/strings.xml2
-rw-r--r--WallpaperPicker/res/values-th/strings.xml2
-rw-r--r--WallpaperPicker/res/values-tl/strings.xml2
-rw-r--r--WallpaperPicker/res/values-tr/strings.xml2
-rw-r--r--WallpaperPicker/res/values-uk/strings.xml2
-rw-r--r--WallpaperPicker/res/values-ur-rPK/strings.xml2
-rw-r--r--WallpaperPicker/res/values-uz-rUZ/strings.xml2
-rw-r--r--WallpaperPicker/res/values-v21/styles.xml36
-rw-r--r--WallpaperPicker/res/values-vi/strings.xml2
-rw-r--r--WallpaperPicker/res/values-zh-rCN/strings.xml2
-rw-r--r--WallpaperPicker/res/values-zh-rHK/strings.xml2
-rw-r--r--WallpaperPicker/res/values-zh-rTW/strings.xml2
-rw-r--r--WallpaperPicker/res/values-zu/strings.xml2
-rw-r--r--WallpaperPicker/res/values/config.xml1
-rw-r--r--WallpaperPicker/res/values/strings.xml2
-rw-r--r--WallpaperPicker/res/values/styles.xml3
-rw-r--r--WallpaperPicker/src/android/util/Pools.java165
-rw-r--r--WallpaperPicker/src/com/android/gallery3d/common/BitmapCropTask.java405
-rw-r--r--WallpaperPicker/src/com/android/gallery3d/common/BitmapUtils.java253
-rw-r--r--WallpaperPicker/src/com/android/gallery3d/common/Utils.java271
-rw-r--r--WallpaperPicker/src/com/android/gallery3d/exif/ExifInterface.java6
-rw-r--r--WallpaperPicker/src/com/android/gallery3d/glrenderer/BasicTexture.java1
-rw-r--r--WallpaperPicker/src/com/android/gallery3d/glrenderer/BitmapTexture.java4
-rw-r--r--WallpaperPicker/src/com/android/gallery3d/glrenderer/GLES20Canvas.java3
-rw-r--r--WallpaperPicker/src/com/android/gallery3d/glrenderer/GLPaint.java4
-rw-r--r--WallpaperPicker/src/com/android/gallery3d/glrenderer/IntArray.java (renamed from WallpaperPicker/src/com/android/gallery3d/util/IntArray.java)2
-rw-r--r--WallpaperPicker/src/com/android/gallery3d/glrenderer/UploadedTexture.java9
-rw-r--r--WallpaperPicker/src/com/android/launcher3/CropView.java5
-rw-r--r--WallpaperPicker/src/com/android/launcher3/LauncherWallpaperPickerActivity.java (renamed from src/com/android/launcher3/LauncherWallpaperPickerActivity.java)13
-rw-r--r--WallpaperPicker/src/com/android/launcher3/LiveWallpaperListAdapter.java15
-rw-r--r--WallpaperPicker/src/com/android/launcher3/SavedWallpaperImages.java5
-rw-r--r--WallpaperPicker/src/com/android/launcher3/ThirdPartyWallpaperPickerListAdapter.java11
-rw-r--r--WallpaperPicker/src/com/android/launcher3/WallpaperCropActivity.java793
-rw-r--r--WallpaperPicker/src/com/android/launcher3/WallpaperPickerActivity.java391
-rw-r--r--WallpaperPicker/src/com/android/launcher3/WallpaperRootView.java39
-rw-r--r--WallpaperPicker/src/com/android/launcher3/base/BaseActivity.java21
-rw-r--r--WallpaperPicker/src/com/android/photos/BitmapRegionTileSource.java182
-rw-r--r--WallpaperPicker/src/com/android/photos/views/BlockingGLTextureView.java438
-rw-r--r--WallpaperPicker/src/com/android/photos/views/TiledImageRenderer.java27
-rw-r--r--WallpaperPicker/src/com/android/photos/views/TiledImageView.java124
-rw-r--r--proguard.flags54
-rw-r--r--protos/backup.proto28
-rw-r--r--res/drawable-hdpi/apps_customize_bg.pngbin69 -> 0 bytes
-rw-r--r--res/drawable-hdpi/bg_appwidget_error.9.pngbin1285 -> 0 bytes
-rw-r--r--res/drawable-hdpi/home_press.9.pngbin153 -> 0 bytes
-rwxr-xr-xres/drawable-hdpi/ic_arrow_back_grey.pngbin0 -> 190 bytes
-rw-r--r--res/drawable-hdpi/ic_home_all_apps_holo_dark.pngbin1292 -> 0 bytes
-rw-r--r--res/drawable-hdpi/ic_info_launcher.pngbin0 -> 2727 bytes
-rw-r--r--res/drawable-hdpi/ic_launcher_clear_active_holo.pngbin1181 -> 0 bytes
-rw-r--r--res/drawable-hdpi/ic_launcher_clear_normal_holo.pngbin1003 -> 0 bytes
-rw-r--r--res/drawable-hdpi/ic_launcher_info_active_holo.pngbin4714 -> 0 bytes
-rw-r--r--res/drawable-hdpi/ic_launcher_info_normal_holo.pngbin2692 -> 0 bytes
-rw-r--r--res/drawable-hdpi/ic_launcher_market_holo.pngbin1644 -> 0 bytes
-rw-r--r--res/drawable-hdpi/ic_launcher_trashcan_active_holo.pngbin2657 -> 0 bytes
-rw-r--r--res/drawable-hdpi/ic_launcher_trashcan_normal_holo.pngbin1750 -> 0 bytes
-rw-r--r--res/drawable-hdpi/ic_pageindicator_current.pngbin1038 -> 1038 bytes
-rw-r--r--res/drawable-hdpi/ic_pageindicator_current_folder.pngbin0 -> 610 bytes
-rw-r--r--res/drawable-hdpi/ic_pageindicator_default.pngbin895 -> 895 bytes
-rw-r--r--res/drawable-hdpi/ic_pageindicator_default_folder.pngbin0 -> 529 bytes
-rw-r--r--res/drawable-hdpi/ic_remove_launcher.pngbin0 -> 1610 bytes
-rwxr-xr-xres/drawable-hdpi/ic_search_grey.pngbin0 -> 743 bytes
-rw-r--r--res/drawable-hdpi/ic_uninstall_launcher.pngbin0 -> 1194 bytes
-rw-r--r--res/drawable-hdpi/ic_widget_resize_handle.pngbin0 -> 1492 bytes
-rw-r--r--res/drawable-hdpi/on_boarding_welcome.pngbin22423 -> 0 bytes
-rw-r--r--res/drawable-hdpi/overscroll_glow_left.9.pngbin858 -> 0 bytes
-rw-r--r--res/drawable-hdpi/overscroll_glow_right.9.pngbin856 -> 0 bytes
-rw-r--r--res/drawable-hdpi/paged_view_indicator.9.pngbin637 -> 0 bytes
-rw-r--r--res/drawable-hdpi/portal_container_holo.9.pngbin1384 -> 0 bytes
-rw-r--r--res/drawable-hdpi/portal_ring_inner.pngbin0 -> 4386 bytes
-rw-r--r--res/drawable-hdpi/portal_ring_inner_holo.pngbin4429 -> 0 bytes
-rw-r--r--res/drawable-hdpi/portal_ring_inner_nolip.pngbin0 -> 4107 bytes
-rw-r--r--res/drawable-hdpi/portal_ring_inner_nolip_holo.pngbin4118 -> 0 bytes
-rw-r--r--res/drawable-hdpi/portal_ring_outer.pngbin0 -> 7887 bytes
-rw-r--r--res/drawable-hdpi/portal_ring_outer_holo.pngbin7658 -> 0 bytes
-rw-r--r--res/drawable-hdpi/portal_ring_rest.pngbin2646 -> 2794 bytes
-rw-r--r--res/drawable-hdpi/quantum_panel.9.pngbin744 -> 0 bytes
-rw-r--r--res/drawable-hdpi/quantum_panel_bitmap.9.pngbin0 -> 608 bytes
-rw-r--r--res/drawable-hdpi/quantum_panel_dark.9.pngbin646 -> 0 bytes
-rw-r--r--res/drawable-hdpi/quantum_panel_dark_bitmap.9.pngbin0 -> 629 bytes
-rw-r--r--res/drawable-hdpi/widget_resize_frame.9.pngbin0 -> 405 bytes
-rw-r--r--res/drawable-hdpi/widget_resize_frame_holo.9.pngbin880 -> 0 bytes
-rw-r--r--res/drawable-hdpi/widget_resize_handle_bottom.pngbin1080 -> 0 bytes
-rw-r--r--res/drawable-hdpi/widget_resize_handle_left.pngbin1097 -> 0 bytes
-rw-r--r--res/drawable-hdpi/widget_resize_handle_right.pngbin1085 -> 0 bytes
-rw-r--r--res/drawable-hdpi/widget_resize_handle_top.pngbin1085 -> 0 bytes
-rw-r--r--res/drawable-hdpi/widget_resize_shadow.9.pngbin0 -> 527 bytes
-rw-r--r--res/drawable-ldrtl/container_fastscroll_popup_bg.xml27
-rw-r--r--res/drawable-mdpi/apps_customize_bg.pngbin69 -> 0 bytes
-rw-r--r--res/drawable-mdpi/bg_appwidget_error.9.pngbin794 -> 0 bytes
-rw-r--r--res/drawable-mdpi/home_press.9.pngbin129 -> 0 bytes
-rwxr-xr-xres/drawable-mdpi/ic_arrow_back_grey.pngbin0 -> 151 bytes
-rw-r--r--res/drawable-mdpi/ic_home_all_apps_holo_dark.pngbin889 -> 0 bytes
-rw-r--r--res/drawable-mdpi/ic_info_launcher.pngbin0 -> 1603 bytes
-rw-r--r--res/drawable-mdpi/ic_launcher_clear_active_holo.pngbin949 -> 0 bytes
-rw-r--r--res/drawable-mdpi/ic_launcher_clear_normal_holo.pngbin802 -> 0 bytes
-rw-r--r--res/drawable-mdpi/ic_launcher_info_active_holo.pngbin2736 -> 0 bytes
-rw-r--r--res/drawable-mdpi/ic_launcher_info_normal_holo.pngbin1518 -> 0 bytes
-rw-r--r--res/drawable-mdpi/ic_launcher_market_holo.pngbin1124 -> 0 bytes
-rw-r--r--res/drawable-mdpi/ic_launcher_trashcan_active_holo.pngbin1783 -> 0 bytes
-rw-r--r--res/drawable-mdpi/ic_launcher_trashcan_normal_holo.pngbin1109 -> 0 bytes
-rw-r--r--res/drawable-mdpi/ic_pageindicator_current.pngbin704 -> 704 bytes
-rw-r--r--res/drawable-mdpi/ic_pageindicator_current_folder.pngbin0 -> 484 bytes
-rw-r--r--res/drawable-mdpi/ic_pageindicator_default.pngbin694 -> 694 bytes
-rw-r--r--res/drawable-mdpi/ic_pageindicator_default_folder.pngbin0 -> 482 bytes
-rw-r--r--res/drawable-mdpi/ic_remove_launcher.pngbin0 -> 1087 bytes
-rwxr-xr-xres/drawable-mdpi/ic_search_grey.pngbin0 -> 497 bytes
-rw-r--r--res/drawable-mdpi/ic_setting_icn.pngbin1718 -> 0 bytes
-rw-r--r--res/drawable-mdpi/ic_uninstall_launcher.pngbin0 -> 932 bytes
-rw-r--r--res/drawable-mdpi/ic_widget_resize_handle.pngbin0 -> 896 bytes
-rw-r--r--res/drawable-mdpi/on_boarding_welcome.pngbin15325 -> 0 bytes
-rw-r--r--res/drawable-mdpi/overscroll_glow_left.9.pngbin552 -> 0 bytes
-rw-r--r--res/drawable-mdpi/overscroll_glow_right.9.pngbin525 -> 0 bytes
-rw-r--r--res/drawable-mdpi/paged_view_indicator.9.pngbin264 -> 0 bytes
-rw-r--r--res/drawable-mdpi/portal_container_holo.9.pngbin843 -> 0 bytes
-rw-r--r--res/drawable-mdpi/portal_ring_inner.pngbin0 -> 2641 bytes
-rw-r--r--res/drawable-mdpi/portal_ring_inner_holo.pngbin2779 -> 0 bytes
-rw-r--r--res/drawable-mdpi/portal_ring_inner_nolip.pngbin0 -> 2545 bytes
-rw-r--r--res/drawable-mdpi/portal_ring_inner_nolip_holo.pngbin2632 -> 0 bytes
-rw-r--r--res/drawable-mdpi/portal_ring_outer.pngbin0 -> 4704 bytes
-rw-r--r--res/drawable-mdpi/portal_ring_outer_holo.pngbin4798 -> 0 bytes
-rw-r--r--res/drawable-mdpi/portal_ring_rest.pngbin1633 -> 1675 bytes
-rw-r--r--res/drawable-mdpi/quantum_panel.9.pngbin476 -> 0 bytes
-rw-r--r--res/drawable-mdpi/quantum_panel_bitmap.9.pngbin0 -> 436 bytes
-rw-r--r--res/drawable-mdpi/quantum_panel_dark.9.pngbin449 -> 0 bytes
-rw-r--r--res/drawable-mdpi/quantum_panel_dark_bitmap.9.pngbin0 -> 445 bytes
-rw-r--r--res/drawable-mdpi/widget_resize_frame.9.pngbin0 -> 304 bytes
-rw-r--r--res/drawable-mdpi/widget_resize_frame_holo.9.pngbin619 -> 0 bytes
-rw-r--r--res/drawable-mdpi/widget_resize_handle_bottom.pngbin745 -> 0 bytes
-rw-r--r--res/drawable-mdpi/widget_resize_handle_left.pngbin762 -> 0 bytes
-rw-r--r--res/drawable-mdpi/widget_resize_handle_right.pngbin772 -> 0 bytes
-rw-r--r--res/drawable-mdpi/widget_resize_handle_top.pngbin750 -> 0 bytes
-rw-r--r--res/drawable-mdpi/widget_resize_shadow.9.pngbin0 -> 367 bytes
-rw-r--r--res/drawable-v21/quantum_panel.xml22
-rw-r--r--res/drawable-v21/quantum_panel_dark.xml22
-rw-r--r--res/drawable-xhdpi/apps_customize_bg.pngbin244 -> 0 bytes
-rw-r--r--res/drawable-xhdpi/bg_appwidget_error.9.pngbin2387 -> 0 bytes
-rw-r--r--res/drawable-xhdpi/home_press.9.pngbin206 -> 0 bytes
-rwxr-xr-xres/drawable-xhdpi/ic_arrow_back_grey.pngbin0 -> 234 bytes
-rw-r--r--res/drawable-xhdpi/ic_home_all_apps_holo_dark.pngbin1569 -> 0 bytes
-rw-r--r--res/drawable-xhdpi/ic_info_launcher.pngbin0 -> 3777 bytes
-rw-r--r--res/drawable-xhdpi/ic_launcher_clear_active_holo.pngbin1595 -> 0 bytes
-rw-r--r--res/drawable-xhdpi/ic_launcher_clear_normal_holo.pngbin1392 -> 0 bytes
-rw-r--r--res/drawable-xhdpi/ic_launcher_info_active_holo.pngbin6841 -> 0 bytes
-rw-r--r--res/drawable-xhdpi/ic_launcher_info_normal_holo.pngbin3837 -> 0 bytes
-rw-r--r--res/drawable-xhdpi/ic_launcher_market_holo.pngbin2187 -> 0 bytes
-rw-r--r--res/drawable-xhdpi/ic_launcher_trashcan_active_holo.pngbin3431 -> 0 bytes
-rw-r--r--res/drawable-xhdpi/ic_launcher_trashcan_normal_holo.pngbin2240 -> 0 bytes
-rw-r--r--res/drawable-xhdpi/ic_pageindicator_current.pngbin1414 -> 1414 bytes
-rw-r--r--res/drawable-xhdpi/ic_pageindicator_current_folder.pngbin0 -> 782 bytes
-rw-r--r--res/drawable-xhdpi/ic_pageindicator_default.pngbin1168 -> 1168 bytes
-rw-r--r--res/drawable-xhdpi/ic_pageindicator_default_folder.pngbin0 -> 644 bytes
-rw-r--r--res/drawable-xhdpi/ic_remove_launcher.pngbin0 -> 1724 bytes
-rwxr-xr-xres/drawable-xhdpi/ic_search_grey.pngbin0 -> 972 bytes
-rw-r--r--res/drawable-xhdpi/ic_uninstall_launcher.pngbin0 -> 1456 bytes
-rw-r--r--res/drawable-xhdpi/ic_widget_resize_handle.pngbin0 -> 2144 bytes
-rw-r--r--res/drawable-xhdpi/on_boarding_welcome.pngbin34253 -> 0 bytes
-rw-r--r--res/drawable-xhdpi/overscroll_glow_left.9.pngbin1249 -> 0 bytes
-rw-r--r--res/drawable-xhdpi/overscroll_glow_right.9.pngbin1248 -> 0 bytes
-rw-r--r--res/drawable-xhdpi/paged_view_indicator.9.pngbin897 -> 0 bytes
-rw-r--r--res/drawable-xhdpi/portal_container_holo.9.pngbin2130 -> 0 bytes
-rw-r--r--res/drawable-xhdpi/portal_ring_inner.pngbin0 -> 5983 bytes
-rw-r--r--res/drawable-xhdpi/portal_ring_inner_holo.pngbin6711 -> 0 bytes
-rw-r--r--res/drawable-xhdpi/portal_ring_inner_nolip.pngbin0 -> 5569 bytes
-rw-r--r--res/drawable-xhdpi/portal_ring_inner_nolip_holo.pngbin6191 -> 0 bytes
-rw-r--r--res/drawable-xhdpi/portal_ring_outer.pngbin0 -> 10394 bytes
-rw-r--r--res/drawable-xhdpi/portal_ring_outer_holo.pngbin11037 -> 0 bytes
-rw-r--r--res/drawable-xhdpi/portal_ring_rest.pngbin3939 -> 3754 bytes
-rw-r--r--res/drawable-xhdpi/quantum_panel.9.pngbin928 -> 0 bytes
-rw-r--r--res/drawable-xhdpi/quantum_panel_bitmap.9.pngbin0 -> 843 bytes
-rw-r--r--res/drawable-xhdpi/quantum_panel_dark.9.pngbin894 -> 0 bytes
-rw-r--r--res/drawable-xhdpi/quantum_panel_dark_bitmap.9.pngbin0 -> 842 bytes
-rw-r--r--res/drawable-xhdpi/widget_resize_frame.9.pngbin0 -> 494 bytes
-rw-r--r--res/drawable-xhdpi/widget_resize_frame_holo.9.pngbin1323 -> 0 bytes
-rw-r--r--res/drawable-xhdpi/widget_resize_handle_bottom.pngbin1434 -> 0 bytes
-rw-r--r--res/drawable-xhdpi/widget_resize_handle_left.pngbin1467 -> 0 bytes
-rw-r--r--res/drawable-xhdpi/widget_resize_handle_right.pngbin1483 -> 0 bytes
-rw-r--r--res/drawable-xhdpi/widget_resize_handle_top.pngbin1463 -> 0 bytes
-rw-r--r--res/drawable-xhdpi/widget_resize_shadow.9.pngbin0 -> 669 bytes
-rw-r--r--res/drawable-xxhdpi/apps_customize_bg.pngbin244 -> 0 bytes
-rw-r--r--res/drawable-xxhdpi/arrow_dashed.pngbin25263 -> 0 bytes
-rw-r--r--res/drawable-xxhdpi/default_widget_preview_holo.9.pngbin1342 -> 0 bytes
-rw-r--r--res/drawable-xxhdpi/hotseat_bg_panel.9.pngbin1126 -> 0 bytes
-rw-r--r--res/drawable-xxhdpi/hotseat_scrubber_holo.9.pngbin1088 -> 0 bytes
-rw-r--r--res/drawable-xxhdpi/hotseat_track_holo.9.pngbin1213 -> 0 bytes
-rwxr-xr-xres/drawable-xxhdpi/ic_arrow_back_grey.pngbin0 -> 308 bytes
-rw-r--r--res/drawable-xxhdpi/ic_home_all_apps_holo_dark.pngbin3300 -> 0 bytes
-rw-r--r--res/drawable-xxhdpi/ic_home_google_logo_normal_holo.pngbin13630 -> 0 bytes
-rw-r--r--res/drawable-xxhdpi/ic_home_google_logo_pressed_holo.pngbin20843 -> 0 bytes
-rw-r--r--res/drawable-xxhdpi/ic_home_search_pressed_holo.pngbin7909 -> 0 bytes
-rw-r--r--res/drawable-xxhdpi/ic_home_voice_search_pressed_holo.pngbin5445 -> 0 bytes
-rw-r--r--res/drawable-xxhdpi/ic_info_launcher.pngbin0 -> 6343 bytes
-rw-r--r--res/drawable-xxhdpi/ic_launcher_clear_active_holo.pngbin2357 -> 0 bytes
-rw-r--r--res/drawable-xxhdpi/ic_launcher_clear_normal_holo.pngbin2738 -> 0 bytes
-rw-r--r--res/drawable-xxhdpi/ic_launcher_info_active_holo.pngbin8022 -> 0 bytes
-rw-r--r--res/drawable-xxhdpi/ic_launcher_info_normal_holo.pngbin7833 -> 0 bytes
-rw-r--r--res/drawable-xxhdpi/ic_launcher_trashcan_active_holo.pngbin4493 -> 0 bytes
-rw-r--r--res/drawable-xxhdpi/ic_launcher_trashcan_normal_holo.pngbin4522 -> 0 bytes
-rw-r--r--res/drawable-xxhdpi/ic_pageindicator_current.pngbin2105 -> 2105 bytes
-rw-r--r--res/drawable-xxhdpi/ic_pageindicator_current_folder.pngbin0 -> 1023 bytes
-rw-r--r--res/drawable-xxhdpi/ic_pageindicator_default.pngbin1634 -> 1634 bytes
-rw-r--r--res/drawable-xxhdpi/ic_pageindicator_default_folder.pngbin0 -> 832 bytes
-rw-r--r--res/drawable-xxhdpi/ic_qs_remote_display.pngbin1715 -> 0 bytes
-rw-r--r--res/drawable-xxhdpi/ic_qs_remote_display_connected.pngbin1718 -> 0 bytes
-rw-r--r--res/drawable-xxhdpi/ic_remove_launcher.pngbin0 -> 2892 bytes
-rwxr-xr-xres/drawable-xxhdpi/ic_search_grey.pngbin0 -> 1473 bytes
-rw-r--r--res/drawable-xxhdpi/ic_uninstall_launcher.pngbin0 -> 2045 bytes
-rw-r--r--res/drawable-xxhdpi/ic_widget_resize_handle.pngbin0 -> 2928 bytes
-rw-r--r--res/drawable-xxhdpi/overscroll_glow_left.9.pngbin4562 -> 0 bytes
-rw-r--r--res/drawable-xxhdpi/overscroll_glow_right.9.pngbin2738 -> 0 bytes
-rw-r--r--res/drawable-xxhdpi/portal_container_holo.9.pngbin4096 -> 0 bytes
-rw-r--r--res/drawable-xxhdpi/portal_ring_inner.pngbin0 -> 9918 bytes
-rw-r--r--res/drawable-xxhdpi/portal_ring_inner_holo.pngbin10046 -> 0 bytes
-rw-r--r--res/drawable-xxhdpi/portal_ring_inner_nolip.png (renamed from res/drawable-xxhdpi/portal_ring_inner_nolip_holo.png)bin9127 -> 9127 bytes
-rw-r--r--res/drawable-xxhdpi/portal_ring_outer.pngbin0 -> 19200 bytes
-rw-r--r--res/drawable-xxhdpi/portal_ring_outer_holo.pngbin16576 -> 0 bytes
-rw-r--r--res/drawable-xxhdpi/quantum_panel.9.pngbin1439 -> 0 bytes
-rw-r--r--res/drawable-xxhdpi/quantum_panel_bitmap.9.pngbin0 -> 1323 bytes
-rw-r--r--res/drawable-xxhdpi/quantum_panel_dark.9.pngbin1366 -> 0 bytes
-rw-r--r--res/drawable-xxhdpi/quantum_panel_dark_bitmap.9.pngbin0 -> 1332 bytes
-rw-r--r--res/drawable-xxhdpi/widget_resize_frame.9.pngbin0 -> 626 bytes
-rw-r--r--res/drawable-xxhdpi/widget_resize_frame_holo.9.pngbin4396 -> 0 bytes
-rw-r--r--res/drawable-xxhdpi/widget_resize_handle_bottom.pngbin4470 -> 0 bytes
-rw-r--r--res/drawable-xxhdpi/widget_resize_handle_left.pngbin4428 -> 0 bytes
-rw-r--r--res/drawable-xxhdpi/widget_resize_handle_right.pngbin4438 -> 0 bytes
-rw-r--r--res/drawable-xxhdpi/widget_resize_handle_top.pngbin4473 -> 0 bytes
-rw-r--r--res/drawable-xxhdpi/widget_resize_shadow.9.pngbin0 -> 975 bytes
-rwxr-xr-xres/drawable-xxxhdpi/ic_arrow_back_grey.pngbin0 -> 359 bytes
-rw-r--r--res/drawable-xxxhdpi/ic_info_launcher.pngbin0 -> 5724 bytes
-rw-r--r--res/drawable-xxxhdpi/ic_remove_launcher.pngbin0 -> 3210 bytes
-rwxr-xr-xres/drawable-xxxhdpi/ic_search_grey.pngbin0 -> 1996 bytes
-rw-r--r--res/drawable-xxxhdpi/ic_uninstall_launcher.pngbin0 -> 2445 bytes
-rw-r--r--res/drawable-xxxhdpi/ic_widget_resize_handle.pngbin0 -> 2930 bytes
-rw-r--r--res/drawable-xxxhdpi/portal_ring_inner.pngbin0 -> 13024 bytes
-rw-r--r--res/drawable-xxxhdpi/portal_ring_inner_nolip.pngbin0 -> 12202 bytes
-rw-r--r--res/drawable-xxxhdpi/portal_ring_outer.pngbin0 -> 23360 bytes
-rw-r--r--res/drawable-xxxhdpi/portal_ring_rest.pngbin0 -> 8628 bytes
-rw-r--r--res/drawable-xxxhdpi/quantum_panel_bitmap.9.pngbin0 -> 2546 bytes
-rw-r--r--res/drawable-xxxhdpi/quantum_panel_dark_bitmap.9.pngbin0 -> 2531 bytes
-rw-r--r--res/drawable-xxxhdpi/widget_resize_frame.9.pngbin0 -> 1569 bytes
-rw-r--r--res/drawable-xxxhdpi/widget_resize_shadow.9.pngbin0 -> 2058 bytes
-rw-r--r--res/drawable/all_apps_search_bg.xml20
-rw-r--r--res/drawable/bg_screenpanel.xml (renamed from res/drawable/info_target_selector.xml)12
-rw-r--r--res/drawable/container_fastscroll_popup_bg.xml27
-rw-r--r--res/drawable/quantum_panel.xml (renamed from WallpaperPicker/res/values-sw600dp/config.xml)8
-rw-r--r--res/drawable/quantum_panel_dark.xml (renamed from res/values-sw340dp-port/config.xml)8
-rw-r--r--res/drawable/quantum_panel_shape.xml22
-rw-r--r--res/drawable/quantum_panel_shape_dark.xml (renamed from res/layout/apps_customize_application.xml)15
-rw-r--r--res/drawable/remove_target_selector.xml24
-rw-r--r--res/drawable/uninstall_target_selector.xml24
-rw-r--r--res/drawable/widgets_row_divider.xml (renamed from res/values-land/config.xml)12
-rw-r--r--res/layout-land/launcher.xml16
-rw-r--r--res/layout-land/migration_cling.xml1
-rw-r--r--res/layout-port/launcher.xml13
-rw-r--r--res/layout-port/migration_cling.xml1
-rw-r--r--res/layout-sw720dp/launcher.xml17
-rw-r--r--res/layout/all_apps.xml57
-rw-r--r--res/layout/all_apps_button.xml2
-rw-r--r--res/layout/all_apps_container.xml38
-rw-r--r--res/layout/all_apps_empty_search.xml (renamed from res/layout/add_list_item.xml)27
-rw-r--r--res/layout/all_apps_icon.xml29
-rw-r--r--res/layout/all_apps_prediction_bar_icon.xml29
-rw-r--r--res/layout/all_apps_search_bar.xml72
-rw-r--r--res/layout/app_icon.xml (renamed from res/layout/application.xml)2
-rw-r--r--res/layout/apps_customize_pane.xml62
-rw-r--r--res/layout/apps_customize_progressbar.xml22
-rw-r--r--res/layout/apps_customize_widget.xml105
-rw-r--r--res/layout/appwidget_error.xml13
-rw-r--r--res/layout/dummy_widget.xml35
-rw-r--r--res/layout/folder_application.xml2
-rw-r--r--res/layout/folder_icon.xml4
-rw-r--r--res/layout/page_indicator_marker.xml4
-rw-r--r--res/layout/rename_folder.xml42
-rw-r--r--res/layout/search_drop_target_bar.xml19
-rw-r--r--res/layout/user_folder.xml98
-rw-r--r--res/layout/widget_cell.xml74
-rw-r--r--res/layout/widgets_list_row_view.xml67
-rw-r--r--res/layout/widgets_view.xml51
-rw-r--r--res/mipmap-xxhdpi/on_boarding_welcome.pngbin50862 -> 0 bytes
-rw-r--r--res/values-af/strings.xml81
-rw-r--r--res/values-am/strings.xml81
-rw-r--r--res/values-ar/strings.xml81
-rw-r--r--res/values-az-rAZ/strings.xml81
-rw-r--r--res/values-be/strings.xml6
-rw-r--r--res/values-bg/strings.xml81
-rw-r--r--res/values-bn-rBD/strings.xml81
-rw-r--r--res/values-ca/strings.xml81
-rw-r--r--res/values-cs/strings.xml81
-rw-r--r--res/values-da/strings.xml81
-rw-r--r--res/values-de/strings.xml81
-rw-r--r--res/values-el/strings.xml81
-rw-r--r--res/values-en-rAU/strings.xml81
-rw-r--r--res/values-en-rGB/strings.xml81
-rw-r--r--res/values-en-rIN/strings.xml81
-rw-r--r--res/values-es-rUS/strings.xml81
-rw-r--r--res/values-es/strings.xml81
-rw-r--r--res/values-et-rEE/strings.xml81
-rw-r--r--res/values-et/strings.xml61
-rw-r--r--res/values-eu-rES/strings.xml81
-rw-r--r--res/values-fa/strings.xml81
-rw-r--r--res/values-fi/strings.xml81
-rw-r--r--res/values-fr-rCA/strings.xml81
-rw-r--r--res/values-fr/strings.xml81
-rw-r--r--res/values-gl-rES/strings.xml81
-rw-r--r--res/values-gu-rIN/strings.xml85
-rw-r--r--res/values-hi/strings.xml81
-rw-r--r--res/values-hr/strings.xml81
-rw-r--r--res/values-hu/strings.xml81
-rw-r--r--res/values-hy-rAM/strings.xml81
-rw-r--r--res/values-in/strings.xml81
-rw-r--r--res/values-is-rIS/strings.xml81
-rw-r--r--res/values-it/strings.xml81
-rw-r--r--res/values-iw/strings.xml81
-rw-r--r--res/values-ja/strings.xml81
-rw-r--r--res/values-ka-rGE/strings.xml81
-rw-r--r--res/values-kk-rKZ/strings.xml81
-rw-r--r--res/values-km-rKH/strings.xml81
-rw-r--r--res/values-kn-rIN/strings.xml81
-rw-r--r--res/values-ko/strings.xml81
-rw-r--r--res/values-ky-rKG/strings.xml81
-rw-r--r--res/values-land/dimens.xml5
-rw-r--r--res/values-land/styles.xml2
-rw-r--r--res/values-lo-rLA/strings.xml81
-rw-r--r--res/values-lt/strings.xml81
-rw-r--r--res/values-lv/strings.xml81
-rw-r--r--res/values-mk-rMK/strings.xml81
-rw-r--r--res/values-ml-rIN/strings.xml81
-rw-r--r--res/values-mn-rMN/strings.xml81
-rw-r--r--res/values-mr-rIN/strings.xml81
-rw-r--r--res/values-ms-rMY/strings.xml81
-rw-r--r--res/values-ms/strings.xml61
-rw-r--r--res/values-my-rMM/strings.xml81
-rw-r--r--res/values-nb/strings.xml81
-rw-r--r--res/values-ne-rNP/strings.xml83
-rw-r--r--res/values-nl/strings.xml81
-rw-r--r--res/values-pa-rIN/strings.xml81
-rw-r--r--res/values-pl/strings.xml81
-rw-r--r--res/values-port/dimens.xml21
-rw-r--r--res/values-pt-rPT/strings.xml81
-rw-r--r--res/values-pt/strings.xml81
-rw-r--r--res/values-rm/strings.xml2
-rw-r--r--res/values-ro/strings.xml81
-rw-r--r--res/values-ru/strings.xml81
-rw-r--r--res/values-si-rLK/strings.xml81
-rw-r--r--res/values-sk/strings.xml81
-rw-r--r--res/values-sl/strings.xml81
-rw-r--r--res/values-sq-rAL/strings.xml81
-rw-r--r--res/values-sr/strings.xml81
-rw-r--r--res/values-sv/strings.xml81
-rw-r--r--res/values-sw/strings.xml81
-rw-r--r--res/values-sw600dp/config.xml4
-rw-r--r--res/values-sw600dp/dimens.xml12
-rw-r--r--res/values-sw600dp/styles.xml21
-rw-r--r--res/values-sw720dp-land/dimens.xml4
-rw-r--r--res/values-sw720dp/config.xml9
-rw-r--r--res/values-sw720dp/dimens.xml9
-rw-r--r--res/values-sw720dp/styles.xml2
-rw-r--r--res/values-ta-rIN/strings.xml83
-rw-r--r--res/values-te-rIN/strings.xml81
-rw-r--r--res/values-th/strings.xml81
-rw-r--r--res/values-tl/strings.xml81
-rw-r--r--res/values-tr/strings.xml81
-rw-r--r--res/values-uk/strings.xml81
-rw-r--r--res/values-ur-rPK/strings.xml81
-rw-r--r--res/values-uz-rUZ/strings.xml81
-rw-r--r--res/values-v17/styles.xml6
-rw-r--r--res/values-vi/strings.xml81
-rw-r--r--res/values-zh-rCN/strings.xml81
-rw-r--r--res/values-zh-rHK/strings.xml81
-rw-r--r--res/values-zh-rTW/strings.xml81
-rw-r--r--res/values-zu/strings.xml81
-rw-r--r--res/values/attrs.xml45
-rw-r--r--res/values/colors.xml28
-rw-r--r--res/values/config.xml56
-rw-r--r--res/values/dimens.xml99
-rw-r--r--res/values/strings.xml227
-rw-r--r--res/values/styles.xml26
-rw-r--r--res/xml/app_target_browser.xml23
-rw-r--r--res/xml/app_target_camera.xml (renamed from res/anim/fade_out_fast.xml)12
-rw-r--r--res/xml/app_target_email.xml (renamed from res/anim/fade_in_fast.xml)12
-rw-r--r--res/xml/app_target_gallery.xml23
-rw-r--r--res/xml/app_target_messenger.xml26
-rw-r--r--res/xml/app_target_phone.xml24
-rw-r--r--res/xml/launcher_preferences.xml26
-rw-r--r--res/xml/update_workspace.xml49
-rw-r--r--src/com/android/launcher3/AllAppsList.java22
-rw-r--r--src/com/android/launcher3/AppInfo.java39
-rw-r--r--src/com/android/launcher3/AppWidgetResizeFrame.java133
-rw-r--r--src/com/android/launcher3/AppWidgetsRestoredReceiver.java5
-rw-r--r--src/com/android/launcher3/AppsCustomizeCellLayout.java71
-rw-r--r--src/com/android/launcher3/AppsCustomizePagedView.java1567
-rw-r--r--src/com/android/launcher3/AppsCustomizeTabHost.java220
-rw-r--r--src/com/android/launcher3/AutoInstallsLayout.java81
-rw-r--r--src/com/android/launcher3/BaseContainerView.java137
-rw-r--r--src/com/android/launcher3/BaseRecyclerView.java285
-rw-r--r--src/com/android/launcher3/BaseRecyclerViewFastScrollBar.java235
-rw-r--r--src/com/android/launcher3/BaseRecyclerViewFastScrollPopup.java160
-rw-r--r--src/com/android/launcher3/BubbleTextView.java346
-rw-r--r--src/com/android/launcher3/ButtonDropTarget.java225
-rw-r--r--src/com/android/launcher3/CellLayout.java733
-rw-r--r--src/com/android/launcher3/CheckLongPressHelper.java32
-rw-r--r--src/com/android/launcher3/ClickShadowView.java112
-rw-r--r--src/com/android/launcher3/CommonAppTypeParser.java153
-rw-r--r--src/com/android/launcher3/CustomAppWidget.java14
-rw-r--r--src/com/android/launcher3/DefaultLayoutParser.java46
-rw-r--r--src/com/android/launcher3/DeferredHandler.java51
-rw-r--r--src/com/android/launcher3/DeleteDropTarget.java506
-rw-r--r--src/com/android/launcher3/DeviceProfile.java704
-rw-r--r--src/com/android/launcher3/DragController.java117
-rw-r--r--src/com/android/launcher3/DragLayer.java151
-rw-r--r--src/com/android/launcher3/DragSource.java2
-rw-r--r--src/com/android/launcher3/DragView.java88
-rw-r--r--src/com/android/launcher3/DropTarget.java65
-rw-r--r--src/com/android/launcher3/DummyWidget.java50
-rw-r--r--src/com/android/launcher3/DynamicGrid.java109
-rw-r--r--src/com/android/launcher3/FastBitmapDrawable.java4
-rw-r--r--src/com/android/launcher3/FastBitmapView.java58
-rw-r--r--src/com/android/launcher3/FirstFrameAnimatorHelper.java4
-rw-r--r--src/com/android/launcher3/FocusHelper.java927
-rw-r--r--src/com/android/launcher3/FocusIndicatorView.java52
-rw-r--r--src/com/android/launcher3/FocusOnlyTabWidget.java86
-rw-r--r--src/com/android/launcher3/Folder.java1018
-rw-r--r--src/com/android/launcher3/FolderAutoScrollHelper.java59
-rw-r--r--src/com/android/launcher3/FolderIcon.java53
-rw-r--r--src/com/android/launcher3/FolderInfo.java46
-rw-r--r--src/com/android/launcher3/FolderPagedView.java678
-rw-r--r--src/com/android/launcher3/HolographicOutlineHelper.java110
-rw-r--r--src/com/android/launcher3/Hotseat.java189
-rw-r--r--src/com/android/launcher3/IconCache.java798
-rw-r--r--src/com/android/launcher3/InfoDropTarget.java99
-rw-r--r--src/com/android/launcher3/Insettable.java4
-rw-r--r--src/com/android/launcher3/InstallShortcutReceiver.java108
-rw-r--r--src/com/android/launcher3/InterruptibleInOutAnimator.java4
-rw-r--r--src/com/android/launcher3/InvariantDeviceProfile.java303
-rw-r--r--src/com/android/launcher3/ItemInfo.java47
-rw-r--r--src/com/android/launcher3/Launcher.java2082
-rw-r--r--src/com/android/launcher3/LauncherAnimUtils.java13
-rw-r--r--src/com/android/launcher3/LauncherAppState.java193
-rw-r--r--src/com/android/launcher3/LauncherAppWidgetHost.java55
-rw-r--r--src/com/android/launcher3/LauncherAppWidgetHostView.java36
-rw-r--r--src/com/android/launcher3/LauncherAppWidgetInfo.java16
-rw-r--r--src/com/android/launcher3/LauncherAppWidgetProviderInfo.java113
-rw-r--r--src/com/android/launcher3/LauncherBackupAgentHelper.java10
-rw-r--r--src/com/android/launcher3/LauncherBackupHelper.java379
-rw-r--r--src/com/android/launcher3/LauncherCallbacks.java19
-rw-r--r--src/com/android/launcher3/LauncherClings.java14
-rw-r--r--src/com/android/launcher3/LauncherFiles.java22
-rw-r--r--src/com/android/launcher3/LauncherModel.java1922
-rw-r--r--src/com/android/launcher3/LauncherProvider.java1133
-rw-r--r--src/com/android/launcher3/LauncherProviderChangeListener.java4
-rw-r--r--src/com/android/launcher3/LauncherScroller.java5
-rw-r--r--src/com/android/launcher3/LauncherSettings.java133
-rw-r--r--src/com/android/launcher3/LauncherStateTransitionAnimation.java762
-rw-r--r--src/com/android/launcher3/LauncherTransitionable.java (renamed from src/com/android/launcher3/LauncherApplication.java)27
-rw-r--r--src/com/android/launcher3/MemoryTracker.java2
-rw-r--r--src/com/android/launcher3/PackageChangedReceiver.java21
-rw-r--r--src/com/android/launcher3/PagedView.java1137
-rw-r--r--src/com/android/launcher3/PagedViewCellLayout.java492
-rw-r--r--src/com/android/launcher3/PagedViewCellLayoutChildren.java161
-rw-r--r--src/com/android/launcher3/PagedViewGridLayout.java121
-rw-r--r--src/com/android/launcher3/PagedViewWidget.java262
-rw-r--r--src/com/android/launcher3/PagedViewWidgetImageView.java49
-rw-r--r--src/com/android/launcher3/PagedViewWithDraggableItems.java174
-rw-r--r--src/com/android/launcher3/Partner.java50
-rw-r--r--src/com/android/launcher3/PendingAddItemInfo.java87
-rw-r--r--src/com/android/launcher3/PendingAppWidgetHostView.java18
-rw-r--r--src/com/android/launcher3/PreloadIconDrawable.java5
-rw-r--r--src/com/android/launcher3/SearchDropTargetBar.java143
-rw-r--r--src/com/android/launcher3/SettingsActivity.java76
-rw-r--r--src/com/android/launcher3/ShortcutAndWidgetContainer.java21
-rw-r--r--src/com/android/launcher3/ShortcutInfo.java62
-rw-r--r--src/com/android/launcher3/SmoothPagedView.java185
-rw-r--r--src/com/android/launcher3/Stats.java216
-rw-r--r--src/com/android/launcher3/StylusEventHelper.java84
-rw-r--r--src/com/android/launcher3/UninstallDropTarget.java132
-rw-r--r--src/com/android/launcher3/UninstallShortcutReceiver.java131
-rw-r--r--src/com/android/launcher3/UserInitializeReceiver.java32
-rw-r--r--src/com/android/launcher3/Utilities.java273
-rw-r--r--src/com/android/launcher3/WeightWatcher.java6
-rw-r--r--src/com/android/launcher3/WidgetPreviewLoader.java1112
-rw-r--r--src/com/android/launcher3/Workspace.java1463
-rw-r--r--src/com/android/launcher3/WorkspaceStateTransitionAnimation.java587
-rw-r--r--src/com/android/launcher3/accessibility/DragAndDropAccessibilityDelegate.java136
-rw-r--r--src/com/android/launcher3/accessibility/FolderAccessibilityHelper.java56
-rw-r--r--src/com/android/launcher3/accessibility/LauncherAccessibilityDelegate.java434
-rw-r--r--src/com/android/launcher3/accessibility/OverviewScreenAccessibilityDelegate.java95
-rw-r--r--src/com/android/launcher3/accessibility/WorkspaceAccessibilityHelper.java166
-rw-r--r--src/com/android/launcher3/allapps/AllAppsContainerView.java638
-rw-r--r--src/com/android/launcher3/allapps/AllAppsGridAdapter.java453
-rw-r--r--src/com/android/launcher3/allapps/AllAppsRecyclerView.java327
-rw-r--r--src/com/android/launcher3/allapps/AllAppsRecyclerViewContainerView.java72
-rw-r--r--src/com/android/launcher3/allapps/AllAppsSearchBarController.java100
-rw-r--r--src/com/android/launcher3/allapps/AllAppsSearchEditView.java65
-rw-r--r--src/com/android/launcher3/allapps/AlphabeticalAppsList.java590
-rw-r--r--src/com/android/launcher3/allapps/DefaultAppSearchAlgorithm.java94
-rw-r--r--src/com/android/launcher3/allapps/DefaultAppSearchController.java269
-rw-r--r--src/com/android/launcher3/compat/AlphabeticIndexCompat.java170
-rw-r--r--src/com/android/launcher3/compat/AppWidgetManagerCompat.java10
-rw-r--r--src/com/android/launcher3/compat/AppWidgetManagerCompatV16.java14
-rw-r--r--src/com/android/launcher3/compat/AppWidgetManagerCompatVL.java27
-rw-r--r--src/com/android/launcher3/compat/LauncherActivityInfoCompat.java9
-rw-r--r--src/com/android/launcher3/compat/LauncherActivityInfoCompatV16.java45
-rw-r--r--src/com/android/launcher3/compat/LauncherActivityInfoCompatVL.java4
-rw-r--r--src/com/android/launcher3/compat/LauncherAppsCompatV16.java6
-rw-r--r--src/com/android/launcher3/compat/LauncherAppsCompatVL.java4
-rw-r--r--src/com/android/launcher3/compat/PackageInstallerCompat.java17
-rw-r--r--src/com/android/launcher3/compat/PackageInstallerCompatV16.java151
-rw-r--r--src/com/android/launcher3/compat/PackageInstallerCompatVL.java152
-rw-r--r--src/com/android/launcher3/compat/UserHandleCompat.java5
-rw-r--r--src/com/android/launcher3/compat/UserManagerCompat.java1
-rw-r--r--src/com/android/launcher3/compat/UserManagerCompatV16.java5
-rw-r--r--src/com/android/launcher3/compat/UserManagerCompatV17.java8
-rw-r--r--src/com/android/launcher3/compat/UserManagerCompatVL.java25
-rw-r--r--src/com/android/launcher3/config/ProviderConfig.java2
-rw-r--r--src/com/android/launcher3/model/AbstractUserComparator.java67
-rw-r--r--src/com/android/launcher3/model/AppNameComparator.java101
-rw-r--r--src/com/android/launcher3/model/PackageItemInfo.java65
-rw-r--r--src/com/android/launcher3/model/WidgetsAndShortcutNameComparator.java68
-rw-r--r--src/com/android/launcher3/model/WidgetsModel.java170
-rw-r--r--src/com/android/launcher3/testing/LauncherExtension.java (renamed from src/com/android/launcher3/LauncherExtension.java)37
-rw-r--r--src/com/android/launcher3/util/ComponentKey.java81
-rw-r--r--src/com/android/launcher3/util/CursorIconInfo.java70
-rw-r--r--src/com/android/launcher3/util/FlingAnimation.java104
-rw-r--r--src/com/android/launcher3/util/FocusLogic.java507
-rw-r--r--src/com/android/launcher3/util/LauncherEdgeEffect.java365
-rw-r--r--src/com/android/launcher3/util/LongArrayMap.java65
-rw-r--r--src/com/android/launcher3/util/ManagedProfileHeuristic.java350
-rw-r--r--src/com/android/launcher3/util/RevealOutlineProvider.java49
-rw-r--r--src/com/android/launcher3/util/Thunk.java43
-rw-r--r--src/com/android/launcher3/util/UiThreadCircularReveal.java57
-rw-r--r--src/com/android/launcher3/util/WallpaperUtils.java123
-rw-r--r--src/com/android/launcher3/widget/PendingAddShortcutInfo.java44
-rw-r--r--src/com/android/launcher3/widget/PendingAddWidgetInfo.java75
-rw-r--r--src/com/android/launcher3/widget/WidgetCell.java230
-rw-r--r--src/com/android/launcher3/widget/WidgetHostViewLoader.java155
-rw-r--r--src/com/android/launcher3/widget/WidgetImageView.java97
-rw-r--r--src/com/android/launcher3/widget/WidgetsContainerView.java370
-rw-r--r--src/com/android/launcher3/widget/WidgetsListAdapter.java215
-rw-r--r--src/com/android/launcher3/widget/WidgetsRecyclerView.java158
-rw-r--r--src/com/android/launcher3/widget/WidgetsRowViewHolder.java (renamed from src/com/android/launcher3/LauncherAnimatorUpdateListener.java)28
-rw-r--r--tests/Android.mk27
-rw-r--r--tests/AndroidManifest.xml (renamed from tests/stress/AndroidManifest.xml)6
-rw-r--r--tests/res/values/string.xml21
-rw-r--r--tests/src/com/android/launcher3/InvariantDeviceProfileTest.java123
-rw-r--r--tests/src/com/android/launcher3/util/FocusLogicTest.java60
-rw-r--r--tests/stress/Android.mk31
-rw-r--r--tests/stress/src/com/android/launcher3/stress/LauncherRotationStressTest.java63
-rw-r--r--util/com/android/launcher3/DecoderRing.java3
630 files changed, 23677 insertions, 21563 deletions
diff --git a/.gitignore b/.gitignore
index f830c66eb..aea5d6102 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,10 @@
db_files
+*.iml
+.project
+.classpath
+.project.properties
+gen/
+tests/stress/gen/
+WallpaperPicker/gen/
+WallpaperPicker/.project.properties
+bin/
diff --git a/Android.mk b/Android.mk
index 2a406e76d..134cfb5b0 100644
--- a/Android.mk
+++ b/Android.mk
@@ -23,28 +23,23 @@ include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := optional
-LOCAL_STATIC_JAVA_LIBRARIES := android-support-v13
-
LOCAL_SRC_FILES := $(call all-java-files-under, src) \
$(call all-java-files-under, WallpaperPicker/src) \
- $(call all-renderscript-files-under, src) \
$(call all-proto-files-under, protos)
LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/WallpaperPicker/res $(LOCAL_PATH)/res
-
-LOCAL_AAPT_FLAGS := --auto-add-overlay
+LOCAL_PROGUARD_FLAG_FILES := proguard.flags
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-v4 android-support-v7-recyclerview
LOCAL_PROTOC_OPTIMIZE_TYPE := nano
LOCAL_PROTOC_FLAGS := --proto_path=$(LOCAL_PATH)/protos/
+LOCAL_AAPT_FLAGS := --auto-add-overlay
-LOCAL_SDK_VERSION := 21
-
+LOCAL_SDK_VERSION := current
LOCAL_PACKAGE_NAME := Launcher3
#LOCAL_CERTIFICATE := shared
LOCAL_OVERRIDES_PACKAGES := Home Launcher2
-LOCAL_PROGUARD_FLAG_FILES := proguard.flags
-
include $(BUILD_PACKAGE)
@@ -83,4 +78,6 @@ $(LOCAL_BUILT_MODULE): $(LOCAL_PATH)/util/etc/launcher_protoutil | $(ACP)
$(copy-file-to-new-target)
$(hide) chmod 755 $@
+INTERNAL_DALVIK_MODULES += $(LOCAL_INSTALLED_MODULE)
+
include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index fb7ac3fab..1fb8e8d01 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -29,12 +29,6 @@
android:label="@string/permlab_install_shortcut"
android:description="@string/permdesc_install_shortcut" />
<permission
- android:name="com.android.launcher.permission.UNINSTALL_SHORTCUT"
- android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
- android:protectionLevel="dangerous"
- android:label="@string/permlab_uninstall_shortcut"
- android:description="@string/permdesc_uninstall_shortcut"/>
- <permission
android:name="com.android.launcher3.permission.READ_SETTINGS"
android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
android:protectionLevel="normal"
@@ -71,7 +65,6 @@
<uses-permission android:name="com.android.launcher3.permission.RECEIVE_FIRST_LOAD_BROADCAST" />
<application
- android:name="com.android.launcher3.LauncherApplication"
android:allowBackup="@bool/enable_backup"
android:backupAgent="com.android.launcher3.LauncherBackupAgentHelper"
android:hardwareAccelerated="true"
@@ -89,6 +82,8 @@
android:theme="@style/Theme"
android:windowSoftInputMode="adjustPan"
android:screenOrientation="nosensor"
+ android:resumeWhilePausing="true"
+ android:taskAffinity=""
android:enabled="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
@@ -98,8 +93,10 @@
</intent-filter>
</activity>
+ <!-- ENABLE_FOR_TESTING
+
<activity
- android:name="com.android.launcher3.LauncherExtension"
+ android:name="com.android.launcher3.testing.LauncherExtension"
android:launchMode="singleTask"
android:clearTaskOnLaunch="true"
android:stateNotNeeded="true"
@@ -115,6 +112,8 @@
</intent-filter>
</activity>
+ -->
+
<activity
android:name="com.android.launcher3.ToggleWeightWatcher"
android:label="@string/toggle_weight_watcher"
@@ -128,7 +127,7 @@
</activity>
<activity
- android:name="com.android.launcher3.LauncherWallpaperPickerActivity"
+ android:name="com.android.launcher3.WallpaperPickerActivity"
android:theme="@style/Theme.WallpaperPicker"
android:label="@string/pick_wallpaper"
android:icon="@mipmap/ic_launcher_wallpaper"
@@ -154,6 +153,13 @@
</intent-filter>
</activity>
+ <activity
+ android:name="com.android.launcher3.SettingsActivity"
+ android:label="@string/settings_button_text"
+ android:autoRemoveFromRecents="true"
+ android:process=":settings_process">
+ </activity>
+
<!-- Debugging tools -->
<activity
android:name="com.android.launcher3.MemoryDumpActivity"
@@ -191,15 +197,6 @@
</intent-filter>
</receiver>
- <!-- Intent received used to uninstall shortcuts from other applications -->
- <receiver
- android:name="com.android.launcher3.UninstallShortcutReceiver"
- android:permission="com.android.launcher.permission.UNINSTALL_SHORTCUT">
- <intent-filter>
- <action android:name="com.android.launcher.action.UNINSTALL_SHORTCUT" />
- </intent-filter>
- </receiver>
-
<!-- Intent received used to initialize a restored widget -->
<receiver android:name="com.android.launcher3.AppWidgetsRestoredReceiver" >
<intent-filter>
@@ -207,24 +204,6 @@
</intent-filter>
</receiver>
- <!-- New user initialization; set up initial wallpaper -->
- <receiver
- android:name="com.android.launcher3.UserInitializeReceiver"
- android:exported="false">
- <intent-filter>
- <action android:name="android.intent.action.USER_INITIALIZE" />
- </intent-filter>
- </receiver>
-
- <receiver android:name="com.android.launcher3.PackageChangedReceiver" >
- <intent-filter>
- <action android:name="android.intent.action.PACKAGE_CHANGED"/>
- <action android:name="android.intent.action.PACKAGE_REPLACED"/>
- <action android:name="android.intent.action.PACKAGE_REMOVED"/>
- <data android:scheme="package"></data>
- </intent-filter>
- </receiver>
-
<receiver android:name="com.android.launcher3.StartupReceiver" >
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
diff --git a/WallpaperPicker/AndroidManifest.xml b/WallpaperPicker/AndroidManifest.xml
index 86a94d078..cb1457bdc 100644
--- a/WallpaperPicker/AndroidManifest.xml
+++ b/WallpaperPicker/AndroidManifest.xml
@@ -5,6 +5,6 @@
android:versionName="1.0"
>
- <uses-sdk android:minSdkVersion="15" android:targetSdkVersion="19" />
-
+ <uses-sdk android:minSdkVersion="16" android:targetSdkVersion="21" />
+ <application/>
</manifest>
diff --git a/WallpaperPicker/res/drawable-hdpi/ic_images.png b/WallpaperPicker/res/drawable-hdpi/ic_images.png
index 0003c6c65..15e511c89 100644
--- a/WallpaperPicker/res/drawable-hdpi/ic_images.png
+++ b/WallpaperPicker/res/drawable-hdpi/ic_images.png
Binary files differ
diff --git a/WallpaperPicker/res/drawable-mdpi/ic_images.png b/WallpaperPicker/res/drawable-mdpi/ic_images.png
index aabc1237a..c4a2229e9 100644
--- a/WallpaperPicker/res/drawable-mdpi/ic_images.png
+++ b/WallpaperPicker/res/drawable-mdpi/ic_images.png
Binary files differ
diff --git a/WallpaperPicker/res/drawable-xhdpi/ic_images.png b/WallpaperPicker/res/drawable-xhdpi/ic_images.png
index 3f21faf8f..497479291 100644
--- a/WallpaperPicker/res/drawable-xhdpi/ic_images.png
+++ b/WallpaperPicker/res/drawable-xhdpi/ic_images.png
Binary files differ
diff --git a/WallpaperPicker/res/drawable-xxhdpi/ic_images.png b/WallpaperPicker/res/drawable-xxhdpi/ic_images.png
index d00db9a00..c8b9f757a 100644
--- a/WallpaperPicker/res/drawable-xxhdpi/ic_images.png
+++ b/WallpaperPicker/res/drawable-xxhdpi/ic_images.png
Binary files differ
diff --git a/WallpaperPicker/res/drawable-xxxhdpi/ic_images.png b/WallpaperPicker/res/drawable-xxxhdpi/ic_images.png
new file mode 100644
index 000000000..a19002e47
--- /dev/null
+++ b/WallpaperPicker/res/drawable-xxxhdpi/ic_images.png
Binary files differ
diff --git a/WallpaperPicker/res/layout/wallpaper_cropper.xml b/WallpaperPicker/res/layout/wallpaper_cropper.xml
index abb860898..ffe8df0fb 100644
--- a/WallpaperPicker/res/layout/wallpaper_cropper.xml
+++ b/WallpaperPicker/res/layout/wallpaper_cropper.xml
@@ -19,7 +19,6 @@
-->
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/wallpaper_root"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.android.launcher3.CropView
@@ -28,7 +27,7 @@
android:layout_height="match_parent" />
<ProgressBar
android:id="@+id/loading"
- style="@android:style/Widget.Holo.ProgressBar.Large"
+ style="?android:attr/progressBarStyleLarge"
android:visibility="invisible"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
diff --git a/WallpaperPicker/res/layout/wallpaper_picker.xml b/WallpaperPicker/res/layout/wallpaper_picker.xml
index c36493d2f..0b970b09f 100644
--- a/WallpaperPicker/res/layout/wallpaper_picker.xml
+++ b/WallpaperPicker/res/layout/wallpaper_picker.xml
@@ -18,60 +18,74 @@
*/
-->
-<com.android.launcher3.WallpaperRootView
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/wallpaper_root"
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:launcher="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
- android:layout_height="match_parent">
+ android:layout_height="match_parent" >
+
<com.android.launcher3.CropView
android:id="@+id/cropView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
+
<ProgressBar
android:id="@+id/loading"
- style="@android:style/Widget.Holo.ProgressBar.Large"
- android:visibility="invisible"
+ style="?android:attr/progressBarStyleLarge"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_centerInParent="true"
+ android:layout_gravity="center"
android:indeterminate="true"
android:indeterminateOnly="true"
- android:background="@android:color/transparent" />
+ android:visibility="invisible" />
+
<LinearLayout
android:id="@+id/wallpaper_strip"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_alignParentBottom="true"
+ android:layout_gravity="bottom"
+ android:fitsSystemWindows="true"
android:orientation="vertical" >
+
<View
android:layout_width="match_parent"
android:layout_height="2dp"
android:background="@drawable/tile_shadow_top" />
+
<HorizontalScrollView
android:id="@+id/wallpaper_scroll_container"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
- <LinearLayout android:id="@+id/master_wallpaper_list"
+
+ <LinearLayout
+ android:id="@+id/master_wallpaper_list"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal" >
- <LinearLayout android:id="@+id/wallpaper_list"
+
+ <LinearLayout
+ android:id="@+id/wallpaper_list"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal" />
- <LinearLayout android:id="@+id/live_wallpaper_list"
+
+ <LinearLayout
+ android:id="@+id/live_wallpaper_list"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal" />
- <LinearLayout android:id="@+id/third_party_wallpaper_list"
+
+ <LinearLayout
+ android:id="@+id/third_party_wallpaper_list"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal" />
</LinearLayout>
</HorizontalScrollView>
+
<View
android:layout_width="match_parent"
android:layout_height="2dp"
android:background="@drawable/tile_shadow_bottom" />
</LinearLayout>
-</com.android.launcher3.WallpaperRootView>
+
+</FrameLayout> \ No newline at end of file
diff --git a/WallpaperPicker/res/layout/wallpaper_picker_image_picker_item.xml b/WallpaperPicker/res/layout/wallpaper_picker_image_picker_item.xml
index ae3c43d8e..dc6524486 100644
--- a/WallpaperPicker/res/layout/wallpaper_picker_image_picker_item.xml
+++ b/WallpaperPicker/res/layout/wallpaper_picker_image_picker_item.xml
@@ -20,7 +20,6 @@
android:layout_height="@dimen/wallpaperThumbnailHeight"
android:focusable="true"
android:clickable="true"
- android:background="@drawable/wallpaper_tile_fg"
android:foreground="@drawable/wallpaper_tile_fg">
<ImageView
android:id="@+id/wallpaper_image"
diff --git a/WallpaperPicker/res/layout/wallpaper_picker_item.xml b/WallpaperPicker/res/layout/wallpaper_picker_item.xml
index 0ac8f97fb..3f57fcdbd 100644
--- a/WallpaperPicker/res/layout/wallpaper_picker_item.xml
+++ b/WallpaperPicker/res/layout/wallpaper_picker_item.xml
@@ -20,7 +20,6 @@
android:layout_height="@dimen/wallpaperThumbnailHeight"
android:focusable="true"
android:clickable="true"
- android:background="@drawable/wallpaper_tile_fg"
android:foreground="@drawable/wallpaper_tile_fg">
<ImageView
android:id="@+id/wallpaper_image"
diff --git a/WallpaperPicker/res/layout/wallpaper_picker_live_wallpaper_item.xml b/WallpaperPicker/res/layout/wallpaper_picker_live_wallpaper_item.xml
index 29fdb1b82..2b152fce2 100644
--- a/WallpaperPicker/res/layout/wallpaper_picker_live_wallpaper_item.xml
+++ b/WallpaperPicker/res/layout/wallpaper_picker_live_wallpaper_item.xml
@@ -20,7 +20,6 @@
android:layout_height="@dimen/wallpaperThumbnailHeight"
android:focusable="true"
android:clickable="true"
- android:background="@drawable/wallpaper_tile_fg"
android:foreground="@drawable/wallpaper_tile_fg">
<ImageView
android:id="@+id/wallpaper_image"
diff --git a/WallpaperPicker/res/layout/wallpaper_picker_third_party_item.xml b/WallpaperPicker/res/layout/wallpaper_picker_third_party_item.xml
index 68661bc00..a7e3a0c79 100644
--- a/WallpaperPicker/res/layout/wallpaper_picker_third_party_item.xml
+++ b/WallpaperPicker/res/layout/wallpaper_picker_third_party_item.xml
@@ -20,7 +20,6 @@
android:layout_height="@dimen/wallpaperThumbnailHeight"
android:focusable="true"
android:clickable="true"
- android:background="@drawable/wallpaper_tile_fg"
android:foreground="@drawable/wallpaper_tile_fg">
<ImageView
android:id="@+id/wallpaper_image"
diff --git a/WallpaperPicker/res/values-af/strings.xml b/WallpaperPicker/res/values-af/strings.xml
index c17d26be0..eb816402a 100644
--- a/WallpaperPicker/res/values-af/strings.xml
+++ b/WallpaperPicker/res/values-af/strings.xml
@@ -30,7 +30,7 @@
<string name="wallpaper_accessibility_name" msgid="4093221025304876354">"Muurpapier %1$d van %2$d"</string>
<string name="announce_selection" msgid="123723511662250539">"Het <xliff:g id="LABEL">%1$s</xliff:g> gekies"</string>
<string name="wallpaper_delete" msgid="1459353972739215344">"Vee uit"</string>
- <string name="pick_image" msgid="6704438906027442697">"Kies prent"</string>
+ <string name="pick_image" msgid="3189640419551368385">"My foto\'s"</string>
<string name="pick_wallpaper" msgid="4628969645948454559">"Muurpapiere"</string>
<string name="crop_wallpaper" msgid="4882870800623585836">"Snoei muurpapier"</string>
</resources>
diff --git a/WallpaperPicker/res/values-am/strings.xml b/WallpaperPicker/res/values-am/strings.xml
index 59c3bf733..7e793856e 100644
--- a/WallpaperPicker/res/values-am/strings.xml
+++ b/WallpaperPicker/res/values-am/strings.xml
@@ -30,7 +30,7 @@
<string name="wallpaper_accessibility_name" msgid="4093221025304876354">"ልጣፍ %1$d የ%2$d"</string>
<string name="announce_selection" msgid="123723511662250539">"<xliff:g id="LABEL">%1$s</xliff:g> ተመርጧል"</string>
<string name="wallpaper_delete" msgid="1459353972739215344">"ሰርዝ"</string>
- <string name="pick_image" msgid="6704438906027442697">"ምስል ይምረጡ"</string>
+ <string name="pick_image" msgid="3189640419551368385">"የእኔ ፎቶዎች"</string>
<string name="pick_wallpaper" msgid="4628969645948454559">"የግድግዳ ወረቀቶች"</string>
<string name="crop_wallpaper" msgid="4882870800623585836">"ልጣፍ ይከርክሙ"</string>
</resources>
diff --git a/WallpaperPicker/res/values-ar/strings.xml b/WallpaperPicker/res/values-ar/strings.xml
index 2075cc875..84fa104db 100644
--- a/WallpaperPicker/res/values-ar/strings.xml
+++ b/WallpaperPicker/res/values-ar/strings.xml
@@ -30,7 +30,7 @@
<string name="wallpaper_accessibility_name" msgid="4093221025304876354">"‏الخلفية %1$d من %2$d"</string>
<string name="announce_selection" msgid="123723511662250539">"تم تحديد <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="wallpaper_delete" msgid="1459353972739215344">"حذف"</string>
- <string name="pick_image" msgid="6704438906027442697">"اختيار صورة"</string>
+ <string name="pick_image" msgid="3189640419551368385">"صوري"</string>
<string name="pick_wallpaper" msgid="4628969645948454559">"الخلفيات"</string>
<string name="crop_wallpaper" msgid="4882870800623585836">"اقتصاص الخلفية"</string>
</resources>
diff --git a/WallpaperPicker/res/values-az-rAZ/strings.xml b/WallpaperPicker/res/values-az-rAZ/strings.xml
index f9d1fcced..883673dd6 100644
--- a/WallpaperPicker/res/values-az-rAZ/strings.xml
+++ b/WallpaperPicker/res/values-az-rAZ/strings.xml
@@ -30,7 +30,7 @@
<string name="wallpaper_accessibility_name" msgid="4093221025304876354">"Divar kağızı %1$d of %2$d"</string>
<string name="announce_selection" msgid="123723511662250539">"<xliff:g id="LABEL">%1$s</xliff:g> seçilib"</string>
<string name="wallpaper_delete" msgid="1459353972739215344">"Sil"</string>
- <string name="pick_image" msgid="6704438906027442697">"Şəkil seçin"</string>
+ <string name="pick_image" msgid="3189640419551368385">"Fotolarım"</string>
<string name="pick_wallpaper" msgid="4628969645948454559">"Divar kağızları"</string>
<string name="crop_wallpaper" msgid="4882870800623585836">"Divar kağızını kəsin"</string>
</resources>
diff --git a/WallpaperPicker/res/values-bg/strings.xml b/WallpaperPicker/res/values-bg/strings.xml
index ce4fc651b..60ae3022f 100644
--- a/WallpaperPicker/res/values-bg/strings.xml
+++ b/WallpaperPicker/res/values-bg/strings.xml
@@ -30,7 +30,7 @@
<string name="wallpaper_accessibility_name" msgid="4093221025304876354">"Тапет %1$d от %2$d"</string>
<string name="announce_selection" msgid="123723511662250539">"Избрахте <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="wallpaper_delete" msgid="1459353972739215344">"Изтриване"</string>
- <string name="pick_image" msgid="6704438906027442697">"Избиране на изображение"</string>
+ <string name="pick_image" msgid="3189640419551368385">"Моите снимки"</string>
<string name="pick_wallpaper" msgid="4628969645948454559">"Тапети"</string>
<string name="crop_wallpaper" msgid="4882870800623585836">"Подрязване на тапета"</string>
</resources>
diff --git a/WallpaperPicker/res/values-bn-rBD/strings.xml b/WallpaperPicker/res/values-bn-rBD/strings.xml
index a4fccb208..74d7e57bd 100644
--- a/WallpaperPicker/res/values-bn-rBD/strings.xml
+++ b/WallpaperPicker/res/values-bn-rBD/strings.xml
@@ -30,7 +30,7 @@
<string name="wallpaper_accessibility_name" msgid="4093221025304876354">"%2$dটির মধ্যে %1$dটি ওয়ালপেপার"</string>
<string name="announce_selection" msgid="123723511662250539">"<xliff:g id="LABEL">%1$s</xliff:g> নির্বাচন করা হয়েছে"</string>
<string name="wallpaper_delete" msgid="1459353972739215344">"মুছুন"</string>
- <string name="pick_image" msgid="6704438906027442697">"চিত্র বাছুন"</string>
+ <string name="pick_image" msgid="3189640419551368385">"আমার ফটো"</string>
<string name="pick_wallpaper" msgid="4628969645948454559">"ওয়ালপেপারগুলি"</string>
<string name="crop_wallpaper" msgid="4882870800623585836">"ওয়ালপেপার কাটছাঁট করুন"</string>
</resources>
diff --git a/WallpaperPicker/res/values-ca/strings.xml b/WallpaperPicker/res/values-ca/strings.xml
index 89de81c30..cbec76250 100644
--- a/WallpaperPicker/res/values-ca/strings.xml
+++ b/WallpaperPicker/res/values-ca/strings.xml
@@ -30,7 +30,7 @@
<string name="wallpaper_accessibility_name" msgid="4093221025304876354">"Fons de pantalla %1$d de %2$d"</string>
<string name="announce_selection" msgid="123723511662250539">"S\'ha seleccionat <xliff:g id="LABEL">%1$s</xliff:g>."</string>
<string name="wallpaper_delete" msgid="1459353972739215344">"Suprimeix"</string>
- <string name="pick_image" msgid="6704438906027442697">"Tria una imatge"</string>
+ <string name="pick_image" msgid="3189640419551368385">"Les meves fotos"</string>
<string name="pick_wallpaper" msgid="4628969645948454559">"Fons de pantalla"</string>
<string name="crop_wallpaper" msgid="4882870800623585836">"Retallar fons de pantalla"</string>
</resources>
diff --git a/WallpaperPicker/res/values-cs/strings.xml b/WallpaperPicker/res/values-cs/strings.xml
index a07b9eda2..da0758e0a 100644
--- a/WallpaperPicker/res/values-cs/strings.xml
+++ b/WallpaperPicker/res/values-cs/strings.xml
@@ -30,7 +30,7 @@
<string name="wallpaper_accessibility_name" msgid="4093221025304876354">"Tapeta %1$d z %2$d"</string>
<string name="announce_selection" msgid="123723511662250539">"Vybrána položka <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="wallpaper_delete" msgid="1459353972739215344">"Smazat"</string>
- <string name="pick_image" msgid="6704438906027442697">"Vybrat obrázek"</string>
+ <string name="pick_image" msgid="3189640419551368385">"Moje fotografie"</string>
<string name="pick_wallpaper" msgid="4628969645948454559">"Tapety"</string>
<string name="crop_wallpaper" msgid="4882870800623585836">"Oříznutí tapety"</string>
</resources>
diff --git a/WallpaperPicker/res/values-da/strings.xml b/WallpaperPicker/res/values-da/strings.xml
index 5b233e1d0..12c0fe87e 100644
--- a/WallpaperPicker/res/values-da/strings.xml
+++ b/WallpaperPicker/res/values-da/strings.xml
@@ -30,7 +30,7 @@
<string name="wallpaper_accessibility_name" msgid="4093221025304876354">"Baggrund %1$d af %2$d"</string>
<string name="announce_selection" msgid="123723511662250539">"<xliff:g id="LABEL">%1$s</xliff:g> blev valgt"</string>
<string name="wallpaper_delete" msgid="1459353972739215344">"Slet"</string>
- <string name="pick_image" msgid="6704438906027442697">"Vælg et billede"</string>
+ <string name="pick_image" msgid="3189640419551368385">"Mine billeder"</string>
<string name="pick_wallpaper" msgid="4628969645948454559">"Baggrunde"</string>
<string name="crop_wallpaper" msgid="4882870800623585836">"Beskær baggrunden"</string>
</resources>
diff --git a/WallpaperPicker/res/values-de/strings.xml b/WallpaperPicker/res/values-de/strings.xml
index 11c1cac6a..3171b3f3a 100644
--- a/WallpaperPicker/res/values-de/strings.xml
+++ b/WallpaperPicker/res/values-de/strings.xml
@@ -30,7 +30,7 @@
<string name="wallpaper_accessibility_name" msgid="4093221025304876354">"Hintergrund %1$d von %2$d"</string>
<string name="announce_selection" msgid="123723511662250539">"<xliff:g id="LABEL">%1$s</xliff:g> ausgewählt"</string>
<string name="wallpaper_delete" msgid="1459353972739215344">"Löschen"</string>
- <string name="pick_image" msgid="6704438906027442697">"Bild auswählen"</string>
+ <string name="pick_image" msgid="3189640419551368385">"Meine Fotos"</string>
<string name="pick_wallpaper" msgid="4628969645948454559">"Hintergründe"</string>
<string name="crop_wallpaper" msgid="4882870800623585836">"Hintergrund zuschneiden"</string>
</resources>
diff --git a/WallpaperPicker/res/values-el/strings.xml b/WallpaperPicker/res/values-el/strings.xml
index 8e1e78fb9..2988beced 100644
--- a/WallpaperPicker/res/values-el/strings.xml
+++ b/WallpaperPicker/res/values-el/strings.xml
@@ -30,7 +30,7 @@
<string name="wallpaper_accessibility_name" msgid="4093221025304876354">"Ταπετσαρία %1$d από %2$d"</string>
<string name="announce_selection" msgid="123723511662250539">"Επιλέχθηκε το <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="wallpaper_delete" msgid="1459353972739215344">"Διαγραφή"</string>
- <string name="pick_image" msgid="6704438906027442697">"Επιλογή εικόνας"</string>
+ <string name="pick_image" msgid="3189640419551368385">"Οι φωτογραφίες μου"</string>
<string name="pick_wallpaper" msgid="4628969645948454559">"Ταπετσαρίες"</string>
<string name="crop_wallpaper" msgid="4882870800623585836">"Περικοπή ταπετσαρίας"</string>
</resources>
diff --git a/WallpaperPicker/res/values-en-rAU/strings.xml b/WallpaperPicker/res/values-en-rAU/strings.xml
index c057c0cb3..30450ee81 100644
--- a/WallpaperPicker/res/values-en-rAU/strings.xml
+++ b/WallpaperPicker/res/values-en-rAU/strings.xml
@@ -30,7 +30,7 @@
<string name="wallpaper_accessibility_name" msgid="4093221025304876354">"Wallpaper %1$d of %2$d"</string>
<string name="announce_selection" msgid="123723511662250539">"Selected <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="wallpaper_delete" msgid="1459353972739215344">"Delete"</string>
- <string name="pick_image" msgid="6704438906027442697">"Pick image"</string>
+ <string name="pick_image" msgid="3189640419551368385">"My photos"</string>
<string name="pick_wallpaper" msgid="4628969645948454559">"Wallpapers"</string>
<string name="crop_wallpaper" msgid="4882870800623585836">"Crop wallpaper"</string>
</resources>
diff --git a/WallpaperPicker/res/values-en-rGB/strings.xml b/WallpaperPicker/res/values-en-rGB/strings.xml
index c057c0cb3..30450ee81 100644
--- a/WallpaperPicker/res/values-en-rGB/strings.xml
+++ b/WallpaperPicker/res/values-en-rGB/strings.xml
@@ -30,7 +30,7 @@
<string name="wallpaper_accessibility_name" msgid="4093221025304876354">"Wallpaper %1$d of %2$d"</string>
<string name="announce_selection" msgid="123723511662250539">"Selected <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="wallpaper_delete" msgid="1459353972739215344">"Delete"</string>
- <string name="pick_image" msgid="6704438906027442697">"Pick image"</string>
+ <string name="pick_image" msgid="3189640419551368385">"My photos"</string>
<string name="pick_wallpaper" msgid="4628969645948454559">"Wallpapers"</string>
<string name="crop_wallpaper" msgid="4882870800623585836">"Crop wallpaper"</string>
</resources>
diff --git a/WallpaperPicker/res/values-en-rIN/strings.xml b/WallpaperPicker/res/values-en-rIN/strings.xml
index c057c0cb3..30450ee81 100644
--- a/WallpaperPicker/res/values-en-rIN/strings.xml
+++ b/WallpaperPicker/res/values-en-rIN/strings.xml
@@ -30,7 +30,7 @@
<string name="wallpaper_accessibility_name" msgid="4093221025304876354">"Wallpaper %1$d of %2$d"</string>
<string name="announce_selection" msgid="123723511662250539">"Selected <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="wallpaper_delete" msgid="1459353972739215344">"Delete"</string>
- <string name="pick_image" msgid="6704438906027442697">"Pick image"</string>
+ <string name="pick_image" msgid="3189640419551368385">"My photos"</string>
<string name="pick_wallpaper" msgid="4628969645948454559">"Wallpapers"</string>
<string name="crop_wallpaper" msgid="4882870800623585836">"Crop wallpaper"</string>
</resources>
diff --git a/WallpaperPicker/res/values-es-rUS/strings.xml b/WallpaperPicker/res/values-es-rUS/strings.xml
index 768385b9e..c18ecb233 100644
--- a/WallpaperPicker/res/values-es-rUS/strings.xml
+++ b/WallpaperPicker/res/values-es-rUS/strings.xml
@@ -30,7 +30,7 @@
<string name="wallpaper_accessibility_name" msgid="4093221025304876354">"Fondo de pantalla %1$d de %2$d"</string>
<string name="announce_selection" msgid="123723511662250539">"<xliff:g id="LABEL">%1$s</xliff:g> seleccionado"</string>
<string name="wallpaper_delete" msgid="1459353972739215344">"Eliminar"</string>
- <string name="pick_image" msgid="6704438906027442697">"Elegir imagen"</string>
+ <string name="pick_image" msgid="3189640419551368385">"Mis fotos"</string>
<string name="pick_wallpaper" msgid="4628969645948454559">"Fondos de pantalla"</string>
<string name="crop_wallpaper" msgid="4882870800623585836">"Recortar fondo de pantalla"</string>
</resources>
diff --git a/WallpaperPicker/res/values-es/strings.xml b/WallpaperPicker/res/values-es/strings.xml
index 702b6d413..b7221af2a 100644
--- a/WallpaperPicker/res/values-es/strings.xml
+++ b/WallpaperPicker/res/values-es/strings.xml
@@ -30,7 +30,7 @@
<string name="wallpaper_accessibility_name" msgid="4093221025304876354">"Fondo de pantalla %1$d de %2$d"</string>
<string name="announce_selection" msgid="123723511662250539">"<xliff:g id="LABEL">%1$s</xliff:g> seleccionado"</string>
<string name="wallpaper_delete" msgid="1459353972739215344">"Eliminar"</string>
- <string name="pick_image" msgid="6704438906027442697">"Seleccionar imagen"</string>
+ <string name="pick_image" msgid="3189640419551368385">"Mis fotos"</string>
<string name="pick_wallpaper" msgid="4628969645948454559">"Fondos de pantalla"</string>
<string name="crop_wallpaper" msgid="4882870800623585836">"Recortar fondo de pantalla"</string>
</resources>
diff --git a/WallpaperPicker/res/values-et-rEE/strings.xml b/WallpaperPicker/res/values-et-rEE/strings.xml
index c09e223d9..571a0ffbd 100644
--- a/WallpaperPicker/res/values-et-rEE/strings.xml
+++ b/WallpaperPicker/res/values-et-rEE/strings.xml
@@ -30,7 +30,7 @@
<string name="wallpaper_accessibility_name" msgid="4093221025304876354">"%1$d/%2$d taustapildist"</string>
<string name="announce_selection" msgid="123723511662250539">"Valitud on <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="wallpaper_delete" msgid="1459353972739215344">"Kustuta"</string>
- <string name="pick_image" msgid="6704438906027442697">"Vali kujutis"</string>
+ <string name="pick_image" msgid="3189640419551368385">"Minu fotod"</string>
<string name="pick_wallpaper" msgid="4628969645948454559">"Taustapildid"</string>
<string name="crop_wallpaper" msgid="4882870800623585836">"Taustapildi kärpimine"</string>
</resources>
diff --git a/WallpaperPicker/res/values-eu-rES/strings.xml b/WallpaperPicker/res/values-eu-rES/strings.xml
index 327550d52..45bf7a106 100644
--- a/WallpaperPicker/res/values-eu-rES/strings.xml
+++ b/WallpaperPicker/res/values-eu-rES/strings.xml
@@ -30,7 +30,7 @@
<string name="wallpaper_accessibility_name" msgid="4093221025304876354">"%1$d/%2$d horma-papera"</string>
<string name="announce_selection" msgid="123723511662250539">"<xliff:g id="LABEL">%1$s</xliff:g> hautatu da"</string>
<string name="wallpaper_delete" msgid="1459353972739215344">"Ezabatu"</string>
- <string name="pick_image" msgid="6704438906027442697">"Hautatu irudia"</string>
+ <string name="pick_image" msgid="3189640419551368385">"Nire argazkiak"</string>
<string name="pick_wallpaper" msgid="4628969645948454559">"Horma-paperak"</string>
<string name="crop_wallpaper" msgid="4882870800623585836">"Ebaki horma-papera"</string>
</resources>
diff --git a/WallpaperPicker/res/values-fa/strings.xml b/WallpaperPicker/res/values-fa/strings.xml
index e1d26a868..469ec1263 100644
--- a/WallpaperPicker/res/values-fa/strings.xml
+++ b/WallpaperPicker/res/values-fa/strings.xml
@@ -30,7 +30,7 @@
<string name="wallpaper_accessibility_name" msgid="4093221025304876354">"‏کاغذدیواری %1$d از %2$d"</string>
<string name="announce_selection" msgid="123723511662250539">"<xliff:g id="LABEL">%1$s</xliff:g> انتخاب شد"</string>
<string name="wallpaper_delete" msgid="1459353972739215344">"حذف"</string>
- <string name="pick_image" msgid="6704438906027442697">"انتخاب تصویر"</string>
+ <string name="pick_image" msgid="3189640419551368385">"عکس‌های من"</string>
<string name="pick_wallpaper" msgid="4628969645948454559">"کاغذدیواری‌ها"</string>
<string name="crop_wallpaper" msgid="4882870800623585836">"برش کاغذدیواری"</string>
</resources>
diff --git a/WallpaperPicker/res/values-fi/strings.xml b/WallpaperPicker/res/values-fi/strings.xml
index 0fa4b7bcf..c82d3e0ed 100644
--- a/WallpaperPicker/res/values-fi/strings.xml
+++ b/WallpaperPicker/res/values-fi/strings.xml
@@ -30,7 +30,7 @@
<string name="wallpaper_accessibility_name" msgid="4093221025304876354">"Taustakuva %1$d/%2$d"</string>
<string name="announce_selection" msgid="123723511662250539">"Valittu: <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="wallpaper_delete" msgid="1459353972739215344">"Poista"</string>
- <string name="pick_image" msgid="6704438906027442697">"Valitse kuva"</string>
+ <string name="pick_image" msgid="3189640419551368385">"Omat valokuvat"</string>
<string name="pick_wallpaper" msgid="4628969645948454559">"Taustakuvat"</string>
<string name="crop_wallpaper" msgid="4882870800623585836">"Rajaa taustakuva"</string>
</resources>
diff --git a/WallpaperPicker/res/values-fr-rCA/strings.xml b/WallpaperPicker/res/values-fr-rCA/strings.xml
index e95670678..92568966e 100644
--- a/WallpaperPicker/res/values-fr-rCA/strings.xml
+++ b/WallpaperPicker/res/values-fr-rCA/strings.xml
@@ -30,7 +30,7 @@
<string name="wallpaper_accessibility_name" msgid="4093221025304876354">"Fond d\'écran %1$d de %2$d"</string>
<string name="announce_selection" msgid="123723511662250539">"Sélection : <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="wallpaper_delete" msgid="1459353972739215344">"Supprimer"</string>
- <string name="pick_image" msgid="6704438906027442697">"Choisir une image"</string>
+ <string name="pick_image" msgid="3189640419551368385">"Mes photos"</string>
<string name="pick_wallpaper" msgid="4628969645948454559">"Fonds d\'écran"</string>
<string name="crop_wallpaper" msgid="4882870800623585836">"Rogner le fond d\'écran"</string>
</resources>
diff --git a/WallpaperPicker/res/values-fr/strings.xml b/WallpaperPicker/res/values-fr/strings.xml
index 37846e0f5..479a7e430 100644
--- a/WallpaperPicker/res/values-fr/strings.xml
+++ b/WallpaperPicker/res/values-fr/strings.xml
@@ -30,7 +30,7 @@
<string name="wallpaper_accessibility_name" msgid="4093221025304876354">"Fond d\'écran %1$d sur %2$d"</string>
<string name="announce_selection" msgid="123723511662250539">"<xliff:g id="LABEL">%1$s</xliff:g> sélectionné"</string>
<string name="wallpaper_delete" msgid="1459353972739215344">"Supprimer"</string>
- <string name="pick_image" msgid="6704438906027442697">"Sélectionner une image"</string>
+ <string name="pick_image" msgid="3189640419551368385">"Mes photos"</string>
<string name="pick_wallpaper" msgid="4628969645948454559">"Fonds d\'écran"</string>
<string name="crop_wallpaper" msgid="4882870800623585836">"Recadrer le fond d\'écran"</string>
</resources>
diff --git a/WallpaperPicker/res/values-gl-rES/strings.xml b/WallpaperPicker/res/values-gl-rES/strings.xml
index 9f1fd5014..0396b2f62 100644
--- a/WallpaperPicker/res/values-gl-rES/strings.xml
+++ b/WallpaperPicker/res/values-gl-rES/strings.xml
@@ -30,7 +30,7 @@
<string name="wallpaper_accessibility_name" msgid="4093221025304876354">"Fondo de pantalla %1$d de %2$d"</string>
<string name="announce_selection" msgid="123723511662250539">"Seleccionaches <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="wallpaper_delete" msgid="1459353972739215344">"Eliminar"</string>
- <string name="pick_image" msgid="6704438906027442697">"Escoller imaxe"</string>
+ <string name="pick_image" msgid="3189640419551368385">"As miñas fotos"</string>
<string name="pick_wallpaper" msgid="4628969645948454559">"Fondos de pantalla"</string>
<string name="crop_wallpaper" msgid="4882870800623585836">"Recortar fondo de pantalla"</string>
</resources>
diff --git a/WallpaperPicker/res/values-gu-rIN/strings.xml b/WallpaperPicker/res/values-gu-rIN/strings.xml
index acee01cfc..e201d523f 100644
--- a/WallpaperPicker/res/values-gu-rIN/strings.xml
+++ b/WallpaperPicker/res/values-gu-rIN/strings.xml
@@ -30,7 +30,7 @@
<string name="wallpaper_accessibility_name" msgid="4093221025304876354">"%2$d માંથી %1$d વૉલપેપર"</string>
<string name="announce_selection" msgid="123723511662250539">"<xliff:g id="LABEL">%1$s</xliff:g> પસંદ કર્યો"</string>
<string name="wallpaper_delete" msgid="1459353972739215344">"કાઢી નાખો"</string>
- <string name="pick_image" msgid="6704438906027442697">"છબી ચૂંટો"</string>
+ <string name="pick_image" msgid="3189640419551368385">"મારા ફોટા"</string>
<string name="pick_wallpaper" msgid="4628969645948454559">"વૉલપેપર્સ"</string>
<string name="crop_wallpaper" msgid="4882870800623585836">"વૉલપેપર કાપો"</string>
</resources>
diff --git a/WallpaperPicker/res/values-hi/strings.xml b/WallpaperPicker/res/values-hi/strings.xml
index fcb252eb5..60834e103 100644
--- a/WallpaperPicker/res/values-hi/strings.xml
+++ b/WallpaperPicker/res/values-hi/strings.xml
@@ -30,7 +30,7 @@
<string name="wallpaper_accessibility_name" msgid="4093221025304876354">"वॉलपेपर %2$d में से %1$d"</string>
<string name="announce_selection" msgid="123723511662250539">"चयनित <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="wallpaper_delete" msgid="1459353972739215344">"हटाएं"</string>
- <string name="pick_image" msgid="6704438906027442697">"चित्र चुनें"</string>
+ <string name="pick_image" msgid="3189640419551368385">"मेरी फ़ोटो"</string>
<string name="pick_wallpaper" msgid="4628969645948454559">"वॉलपेपर"</string>
<string name="crop_wallpaper" msgid="4882870800623585836">"वॉलपेपर काटें"</string>
</resources>
diff --git a/WallpaperPicker/res/values-hr/strings.xml b/WallpaperPicker/res/values-hr/strings.xml
index 3d79e8f0c..9ed702c5a 100644
--- a/WallpaperPicker/res/values-hr/strings.xml
+++ b/WallpaperPicker/res/values-hr/strings.xml
@@ -30,7 +30,7 @@
<string name="wallpaper_accessibility_name" msgid="4093221025304876354">"%1$d. pozadinska slika od %2$d"</string>
<string name="announce_selection" msgid="123723511662250539">"Odabrana je <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="wallpaper_delete" msgid="1459353972739215344">"Izbriši"</string>
- <string name="pick_image" msgid="6704438906027442697">"Odaberi sliku"</string>
+ <string name="pick_image" msgid="3189640419551368385">"Moje fotografije"</string>
<string name="pick_wallpaper" msgid="4628969645948454559">"Pozadine"</string>
<string name="crop_wallpaper" msgid="4882870800623585836">"Obrezivanje pozadinske slike"</string>
</resources>
diff --git a/WallpaperPicker/res/values-hu/strings.xml b/WallpaperPicker/res/values-hu/strings.xml
index 703aa12eb..d8b08fdfd 100644
--- a/WallpaperPicker/res/values-hu/strings.xml
+++ b/WallpaperPicker/res/values-hu/strings.xml
@@ -30,7 +30,7 @@
<string name="wallpaper_accessibility_name" msgid="4093221025304876354">"%1$d/%2$d. háttérkép"</string>
<string name="announce_selection" msgid="123723511662250539">"<xliff:g id="LABEL">%1$s</xliff:g> kiválasztva"</string>
<string name="wallpaper_delete" msgid="1459353972739215344">"Törlés"</string>
- <string name="pick_image" msgid="6704438906027442697">"Kép kiválasztása"</string>
+ <string name="pick_image" msgid="3189640419551368385">"Saját fotók"</string>
<string name="pick_wallpaper" msgid="4628969645948454559">"Háttérképek"</string>
<string name="crop_wallpaper" msgid="4882870800623585836">"Háttérkép körbevágása"</string>
</resources>
diff --git a/WallpaperPicker/res/values-hy-rAM/strings.xml b/WallpaperPicker/res/values-hy-rAM/strings.xml
index f3891dd35..027b841a7 100644
--- a/WallpaperPicker/res/values-hy-rAM/strings.xml
+++ b/WallpaperPicker/res/values-hy-rAM/strings.xml
@@ -30,7 +30,7 @@
<string name="wallpaper_accessibility_name" msgid="4093221025304876354">"%1$d պաստառ՝ %2$d-ից"</string>
<string name="announce_selection" msgid="123723511662250539">"Ընտրված է <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="wallpaper_delete" msgid="1459353972739215344">"Ջնջել"</string>
- <string name="pick_image" msgid="6704438906027442697">"Ընտրել պատկեր"</string>
+ <string name="pick_image" msgid="3189640419551368385">"Իմ լուսանկարները"</string>
<string name="pick_wallpaper" msgid="4628969645948454559">"Պաստառներ"</string>
<string name="crop_wallpaper" msgid="4882870800623585836">"Եզրատել պաստառը"</string>
</resources>
diff --git a/WallpaperPicker/res/values-in/strings.xml b/WallpaperPicker/res/values-in/strings.xml
index f216cf343..91554522f 100644
--- a/WallpaperPicker/res/values-in/strings.xml
+++ b/WallpaperPicker/res/values-in/strings.xml
@@ -30,7 +30,7 @@
<string name="wallpaper_accessibility_name" msgid="4093221025304876354">"Wallpaper %1$d dari %2$d"</string>
<string name="announce_selection" msgid="123723511662250539">"<xliff:g id="LABEL">%1$s</xliff:g> terpilih"</string>
<string name="wallpaper_delete" msgid="1459353972739215344">"Hapus"</string>
- <string name="pick_image" msgid="6704438906027442697">"Pilih gambar"</string>
+ <string name="pick_image" msgid="3189640419551368385">"Foto saya"</string>
<string name="pick_wallpaper" msgid="4628969645948454559">"Wallpaper"</string>
<string name="crop_wallpaper" msgid="4882870800623585836">"Pangkas wallpaper"</string>
</resources>
diff --git a/WallpaperPicker/res/values-is-rIS/strings.xml b/WallpaperPicker/res/values-is-rIS/strings.xml
index 6d5d680cf..69e6cd498 100644
--- a/WallpaperPicker/res/values-is-rIS/strings.xml
+++ b/WallpaperPicker/res/values-is-rIS/strings.xml
@@ -30,7 +30,7 @@
<string name="wallpaper_accessibility_name" msgid="4093221025304876354">"Veggfóður %1$d af %2$d"</string>
<string name="announce_selection" msgid="123723511662250539">"<xliff:g id="LABEL">%1$s</xliff:g> valið"</string>
<string name="wallpaper_delete" msgid="1459353972739215344">"Eyða"</string>
- <string name="pick_image" msgid="6704438906027442697">"Velja mynd"</string>
+ <string name="pick_image" msgid="3189640419551368385">"Myndirnar mínar"</string>
<string name="pick_wallpaper" msgid="4628969645948454559">"Veggfóður"</string>
<string name="crop_wallpaper" msgid="4882870800623585836">"Skera veggfóður"</string>
</resources>
diff --git a/WallpaperPicker/res/values-it/strings.xml b/WallpaperPicker/res/values-it/strings.xml
index c29946f85..f4d38d14e 100644
--- a/WallpaperPicker/res/values-it/strings.xml
+++ b/WallpaperPicker/res/values-it/strings.xml
@@ -30,7 +30,7 @@
<string name="wallpaper_accessibility_name" msgid="4093221025304876354">"Sfondo %1$d di %2$d"</string>
<string name="announce_selection" msgid="123723511662250539">"Elemento selezionato: <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="wallpaper_delete" msgid="1459353972739215344">"Elimina"</string>
- <string name="pick_image" msgid="6704438906027442697">"Scegli l\'immagine"</string>
+ <string name="pick_image" msgid="3189640419551368385">"Le mie foto"</string>
<string name="pick_wallpaper" msgid="4628969645948454559">"Sfondi"</string>
<string name="crop_wallpaper" msgid="4882870800623585836">"Ritaglia sfondo"</string>
</resources>
diff --git a/WallpaperPicker/res/values-iw/strings.xml b/WallpaperPicker/res/values-iw/strings.xml
index ddc96e92c..e29f2372f 100644
--- a/WallpaperPicker/res/values-iw/strings.xml
+++ b/WallpaperPicker/res/values-iw/strings.xml
@@ -30,7 +30,7 @@
<string name="wallpaper_accessibility_name" msgid="4093221025304876354">"‏טפט %1$d מתוך %2$d"</string>
<string name="announce_selection" msgid="123723511662250539">"בחרת <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="wallpaper_delete" msgid="1459353972739215344">"מחק"</string>
- <string name="pick_image" msgid="6704438906027442697">"בחר תמונה"</string>
+ <string name="pick_image" msgid="3189640419551368385">"התמונות שלי"</string>
<string name="pick_wallpaper" msgid="4628969645948454559">"טפטים"</string>
<string name="crop_wallpaper" msgid="4882870800623585836">"חתוך את הטפט"</string>
</resources>
diff --git a/WallpaperPicker/res/values-ja/strings.xml b/WallpaperPicker/res/values-ja/strings.xml
index 80b094453..e86026bf9 100644
--- a/WallpaperPicker/res/values-ja/strings.xml
+++ b/WallpaperPicker/res/values-ja/strings.xml
@@ -30,7 +30,7 @@
<string name="wallpaper_accessibility_name" msgid="4093221025304876354">"壁紙: %1$d/%2$d"</string>
<string name="announce_selection" msgid="123723511662250539">"選択: <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="wallpaper_delete" msgid="1459353972739215344">"削除"</string>
- <string name="pick_image" msgid="6704438906027442697">"画像を選択"</string>
+ <string name="pick_image" msgid="3189640419551368385">"マイフォト"</string>
<string name="pick_wallpaper" msgid="4628969645948454559">"壁紙"</string>
<string name="crop_wallpaper" msgid="4882870800623585836">"壁紙のトリミング"</string>
</resources>
diff --git a/WallpaperPicker/res/values-ka-rGE/strings.xml b/WallpaperPicker/res/values-ka-rGE/strings.xml
index 2f59712d8..1ae10214a 100644
--- a/WallpaperPicker/res/values-ka-rGE/strings.xml
+++ b/WallpaperPicker/res/values-ka-rGE/strings.xml
@@ -30,7 +30,7 @@
<string name="wallpaper_accessibility_name" msgid="4093221025304876354">"ფონი %1$d %2$d-დან"</string>
<string name="announce_selection" msgid="123723511662250539">"არჩეული <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="wallpaper_delete" msgid="1459353972739215344">"წაშლა"</string>
- <string name="pick_image" msgid="6704438906027442697">"სურათის ამორჩევა"</string>
+ <string name="pick_image" msgid="3189640419551368385">"ჩემი ფოტოები"</string>
<string name="pick_wallpaper" msgid="4628969645948454559">"ფონები"</string>
<string name="crop_wallpaper" msgid="4882870800623585836">"ფონის ჩამოჭრა"</string>
</resources>
diff --git a/WallpaperPicker/res/values-kk-rKZ/strings.xml b/WallpaperPicker/res/values-kk-rKZ/strings.xml
index dcf372cf5..a10e27318 100644
--- a/WallpaperPicker/res/values-kk-rKZ/strings.xml
+++ b/WallpaperPicker/res/values-kk-rKZ/strings.xml
@@ -30,7 +30,7 @@
<string name="wallpaper_accessibility_name" msgid="4093221025304876354">"%1$d артқы фон, барлығы %2$d"</string>
<string name="announce_selection" msgid="123723511662250539">"<xliff:g id="LABEL">%1$s</xliff:g> таңдалған"</string>
<string name="wallpaper_delete" msgid="1459353972739215344">"Жою"</string>
- <string name="pick_image" msgid="6704438906027442697">"Суретті таңдау"</string>
+ <string name="pick_image" msgid="3189640419551368385">"Менің фотосуреттерім"</string>
<string name="pick_wallpaper" msgid="4628969645948454559">"Артқы фондар"</string>
<string name="crop_wallpaper" msgid="4882870800623585836">"Артқы фонды кесу"</string>
</resources>
diff --git a/WallpaperPicker/res/values-km-rKH/strings.xml b/WallpaperPicker/res/values-km-rKH/strings.xml
index 41722355f..2a605e86a 100644
--- a/WallpaperPicker/res/values-km-rKH/strings.xml
+++ b/WallpaperPicker/res/values-km-rKH/strings.xml
@@ -30,7 +30,7 @@
<string name="wallpaper_accessibility_name" msgid="4093221025304876354">"ផ្ទាំង​រូបភាព %1$d នៃ %2$d"</string>
<string name="announce_selection" msgid="123723511662250539">"បាន​ជ្រើស <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="wallpaper_delete" msgid="1459353972739215344">"លុប"</string>
- <string name="pick_image" msgid="6704438906027442697">"ជ្រើស​យក​រូបភាព"</string>
+ <string name="pick_image" msgid="3189640419551368385">"រូបថតរបស់ខ្ញុំ"</string>
<string name="pick_wallpaper" msgid="4628969645948454559">"ផ្ទាំង​រូបភាព"</string>
<string name="crop_wallpaper" msgid="4882870800623585836">"ច្រឹប​ផ្ទាំង​រូបភាព"</string>
</resources>
diff --git a/WallpaperPicker/res/values-kn-rIN/strings.xml b/WallpaperPicker/res/values-kn-rIN/strings.xml
index 89203bf1c..b69bda529 100644
--- a/WallpaperPicker/res/values-kn-rIN/strings.xml
+++ b/WallpaperPicker/res/values-kn-rIN/strings.xml
@@ -30,7 +30,7 @@
<string name="wallpaper_accessibility_name" msgid="4093221025304876354">"%2$d ರಲ್ಲಿ %1$d ವಾಲ್‌ಪೇಪರ್‌"</string>
<string name="announce_selection" msgid="123723511662250539">"<xliff:g id="LABEL">%1$s</xliff:g> ಆಯ್ಕೆ ಮಾಡಲಾಗಿದೆ"</string>
<string name="wallpaper_delete" msgid="1459353972739215344">"ಅಳಿಸು"</string>
- <string name="pick_image" msgid="6704438906027442697">"ಚಿತ್ರವನ್ನು ಆರಿಸಿ"</string>
+ <string name="pick_image" msgid="3189640419551368385">"ನನ್ನ ಫೋಟೋಗಳು"</string>
<string name="pick_wallpaper" msgid="4628969645948454559">"ವಾಲ್‌ಪೇಪರ್‌ಗಳು"</string>
<string name="crop_wallpaper" msgid="4882870800623585836">"ವಾಲ್‌ಪೇಪರ್‌ ಕತ್ತರಿಸಿ"</string>
</resources>
diff --git a/WallpaperPicker/res/values-ko/strings.xml b/WallpaperPicker/res/values-ko/strings.xml
index a5a85b773..30e7cfa23 100644
--- a/WallpaperPicker/res/values-ko/strings.xml
+++ b/WallpaperPicker/res/values-ko/strings.xml
@@ -30,7 +30,7 @@
<string name="wallpaper_accessibility_name" msgid="4093221025304876354">"배경화면 %1$d/%2$d"</string>
<string name="announce_selection" msgid="123723511662250539">"<xliff:g id="LABEL">%1$s</xliff:g> 선택함"</string>
<string name="wallpaper_delete" msgid="1459353972739215344">"삭제"</string>
- <string name="pick_image" msgid="6704438906027442697">"이미지 선택"</string>
+ <string name="pick_image" msgid="3189640419551368385">"내 사진"</string>
<string name="pick_wallpaper" msgid="4628969645948454559">"배경화면"</string>
<string name="crop_wallpaper" msgid="4882870800623585836">"배경화면 잘라내기"</string>
</resources>
diff --git a/WallpaperPicker/res/values-ky-rKG/strings.xml b/WallpaperPicker/res/values-ky-rKG/strings.xml
index 696b3ee17..f1ebf095d 100644
--- a/WallpaperPicker/res/values-ky-rKG/strings.xml
+++ b/WallpaperPicker/res/values-ky-rKG/strings.xml
@@ -30,7 +30,7 @@
<string name="wallpaper_accessibility_name" msgid="4093221025304876354">"%2$d ичинен %1$d тушкагаз"</string>
<string name="announce_selection" msgid="123723511662250539">"<xliff:g id="LABEL">%1$s</xliff:g> тандалды"</string>
<string name="wallpaper_delete" msgid="1459353972739215344">"Жок кылуу"</string>
- <string name="pick_image" msgid="6704438906027442697">"Сүрөт тандоо"</string>
+ <string name="pick_image" msgid="3189640419551368385">"Менин сүрөттөрүм"</string>
<string name="pick_wallpaper" msgid="4628969645948454559">"Тушкагаздар"</string>
<string name="crop_wallpaper" msgid="4882870800623585836">"Тушкагазды тегиздөө"</string>
</resources>
diff --git a/WallpaperPicker/res/values-lo-rLA/strings.xml b/WallpaperPicker/res/values-lo-rLA/strings.xml
index e46859111..e32cafb7d 100644
--- a/WallpaperPicker/res/values-lo-rLA/strings.xml
+++ b/WallpaperPicker/res/values-lo-rLA/strings.xml
@@ -30,7 +30,7 @@
<string name="wallpaper_accessibility_name" msgid="4093221025304876354">"ພາບພື້ນຫຼັງ %1$d ໃນ %2$d"</string>
<string name="announce_selection" msgid="123723511662250539">"ເລືອກ <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="wallpaper_delete" msgid="1459353972739215344">"ລຶບ"</string>
- <string name="pick_image" msgid="6704438906027442697">"ເລືອກ​ຮູບ​ພາບ"</string>
+ <string name="pick_image" msgid="3189640419551368385">"ຮູບຂອງຂ້ອຍ"</string>
<string name="pick_wallpaper" msgid="4628969645948454559">"ພາບພື້ນຫຼັງ"</string>
<string name="crop_wallpaper" msgid="4882870800623585836">"ຕັດພາບພື້ນຫຼັງ"</string>
</resources>
diff --git a/WallpaperPicker/res/values-lt/strings.xml b/WallpaperPicker/res/values-lt/strings.xml
index 86035b883..c442e3a5a 100644
--- a/WallpaperPicker/res/values-lt/strings.xml
+++ b/WallpaperPicker/res/values-lt/strings.xml
@@ -30,7 +30,7 @@
<string name="wallpaper_accessibility_name" msgid="4093221025304876354">"%1$d ekrano fonas iš %2$d"</string>
<string name="announce_selection" msgid="123723511662250539">"Pasirinkta: <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="wallpaper_delete" msgid="1459353972739215344">"Ištrinti"</string>
- <string name="pick_image" msgid="6704438906027442697">"Pasirinkti vaizdą"</string>
+ <string name="pick_image" msgid="3189640419551368385">"Mano nuotraukos"</string>
<string name="pick_wallpaper" msgid="4628969645948454559">"Ekrano fonai"</string>
<string name="crop_wallpaper" msgid="4882870800623585836">"Apkirpti ekrano foną"</string>
</resources>
diff --git a/WallpaperPicker/res/values-lv/strings.xml b/WallpaperPicker/res/values-lv/strings.xml
index 02e5cfb22..d05a17547 100644
--- a/WallpaperPicker/res/values-lv/strings.xml
+++ b/WallpaperPicker/res/values-lv/strings.xml
@@ -30,7 +30,7 @@
<string name="wallpaper_accessibility_name" msgid="4093221025304876354">"%1$d. fona tapete no %2$d"</string>
<string name="announce_selection" msgid="123723511662250539">"Atlasīta: <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="wallpaper_delete" msgid="1459353972739215344">"Dzēst"</string>
- <string name="pick_image" msgid="6704438906027442697">"Izvēlēties attēlu"</string>
+ <string name="pick_image" msgid="3189640419551368385">"Mani fotoattēli"</string>
<string name="pick_wallpaper" msgid="4628969645948454559">"Fona tapetes"</string>
<string name="crop_wallpaper" msgid="4882870800623585836">"Apgriezt fona tapeti"</string>
</resources>
diff --git a/WallpaperPicker/res/values-mk-rMK/strings.xml b/WallpaperPicker/res/values-mk-rMK/strings.xml
index b1919ccd4..f9e0963ed 100644
--- a/WallpaperPicker/res/values-mk-rMK/strings.xml
+++ b/WallpaperPicker/res/values-mk-rMK/strings.xml
@@ -30,7 +30,7 @@
<string name="wallpaper_accessibility_name" msgid="4093221025304876354">"Тапет %1$d од %2$d"</string>
<string name="announce_selection" msgid="123723511662250539">"Избран <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="wallpaper_delete" msgid="1459353972739215344">"Избриши"</string>
- <string name="pick_image" msgid="6704438906027442697">"Избери слика"</string>
+ <string name="pick_image" msgid="3189640419551368385">"Моите фотографии"</string>
<string name="pick_wallpaper" msgid="4628969645948454559">"Тапети"</string>
<string name="crop_wallpaper" msgid="4882870800623585836">"Исечи тапет"</string>
</resources>
diff --git a/WallpaperPicker/res/values-ml-rIN/strings.xml b/WallpaperPicker/res/values-ml-rIN/strings.xml
index 0b6a4c108..6be771c0e 100644
--- a/WallpaperPicker/res/values-ml-rIN/strings.xml
+++ b/WallpaperPicker/res/values-ml-rIN/strings.xml
@@ -30,7 +30,7 @@
<string name="wallpaper_accessibility_name" msgid="4093221025304876354">"%1$d / %2$d വാൾപേപ്പർ"</string>
<string name="announce_selection" msgid="123723511662250539">"<xliff:g id="LABEL">%1$s</xliff:g> തിരഞ്ഞെടുത്തു"</string>
<string name="wallpaper_delete" msgid="1459353972739215344">"ഇല്ലാതാക്കുക"</string>
- <string name="pick_image" msgid="6704438906027442697">"ചിത്രം തിരഞ്ഞെടുക്കുക"</string>
+ <string name="pick_image" msgid="3189640419551368385">"എന്റെ ഫോട്ടോകൾ"</string>
<string name="pick_wallpaper" msgid="4628969645948454559">"വാൾപേപ്പറുകൾ"</string>
<string name="crop_wallpaper" msgid="4882870800623585836">"വാൾപേപ്പറിന്റെ വലുപ്പം മാറ്റൽ"</string>
</resources>
diff --git a/WallpaperPicker/res/values-mn-rMN/strings.xml b/WallpaperPicker/res/values-mn-rMN/strings.xml
index 71ff9e0f7..b88da5a96 100644
--- a/WallpaperPicker/res/values-mn-rMN/strings.xml
+++ b/WallpaperPicker/res/values-mn-rMN/strings.xml
@@ -30,7 +30,7 @@
<string name="wallpaper_accessibility_name" msgid="4093221025304876354">"%2$d ханын цаасны %1$d нь"</string>
<string name="announce_selection" msgid="123723511662250539">"<xliff:g id="LABEL">%1$s</xliff:g> сонгогдсон"</string>
<string name="wallpaper_delete" msgid="1459353972739215344">"Устгах"</string>
- <string name="pick_image" msgid="6704438906027442697">"Зураг сонгох"</string>
+ <string name="pick_image" msgid="3189640419551368385">"Миний зураг"</string>
<string name="pick_wallpaper" msgid="4628969645948454559">"Ханын зураг"</string>
<string name="crop_wallpaper" msgid="4882870800623585836">"Ханын зургийг тайрах"</string>
</resources>
diff --git a/WallpaperPicker/res/values-mr-rIN/strings.xml b/WallpaperPicker/res/values-mr-rIN/strings.xml
index 33cfaa148..128b21c1c 100644
--- a/WallpaperPicker/res/values-mr-rIN/strings.xml
+++ b/WallpaperPicker/res/values-mr-rIN/strings.xml
@@ -30,7 +30,7 @@
<string name="wallpaper_accessibility_name" msgid="4093221025304876354">"%2$d पैकी %1$d वॉलपेपर"</string>
<string name="announce_selection" msgid="123723511662250539">"<xliff:g id="LABEL">%1$s</xliff:g> निवडले"</string>
<string name="wallpaper_delete" msgid="1459353972739215344">"हटवा"</string>
- <string name="pick_image" msgid="6704438906027442697">"प्रतिमा निवडा"</string>
+ <string name="pick_image" msgid="3189640419551368385">"माझे फोटो"</string>
<string name="pick_wallpaper" msgid="4628969645948454559">"वॉलपेपर"</string>
<string name="crop_wallpaper" msgid="4882870800623585836">"वॉलपेपर कापा"</string>
</resources>
diff --git a/WallpaperPicker/res/values-ms-rMY/strings.xml b/WallpaperPicker/res/values-ms-rMY/strings.xml
index 950f4d0e1..9d824e4fa 100644
--- a/WallpaperPicker/res/values-ms-rMY/strings.xml
+++ b/WallpaperPicker/res/values-ms-rMY/strings.xml
@@ -30,7 +30,7 @@
<string name="wallpaper_accessibility_name" msgid="4093221025304876354">"Kertas dinding %1$d daripada %2$d"</string>
<string name="announce_selection" msgid="123723511662250539">"Memilih <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="wallpaper_delete" msgid="1459353972739215344">"Padam"</string>
- <string name="pick_image" msgid="6704438906027442697">"Pilih imej"</string>
+ <string name="pick_image" msgid="3189640419551368385">"Foto saya"</string>
<string name="pick_wallpaper" msgid="4628969645948454559">"Kertas dinding"</string>
<string name="crop_wallpaper" msgid="4882870800623585836">"Pangkas kertas dinding"</string>
</resources>
diff --git a/WallpaperPicker/res/values-my-rMM/strings.xml b/WallpaperPicker/res/values-my-rMM/strings.xml
index 4d5ac47df..233611431 100644
--- a/WallpaperPicker/res/values-my-rMM/strings.xml
+++ b/WallpaperPicker/res/values-my-rMM/strings.xml
@@ -30,7 +30,7 @@
<string name="wallpaper_accessibility_name" msgid="4093221025304876354">"နောက်ခံ %1$d မှ %2$d"</string>
<string name="announce_selection" msgid="123723511662250539">"ရွေးချယ်ထားသော <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="wallpaper_delete" msgid="1459353972739215344">"ဖျက်ပါ"</string>
- <string name="pick_image" msgid="6704438906027442697">"ပုံ ရွေးပါ"</string>
+ <string name="pick_image" msgid="3189640419551368385">"ကျွန်ုပ်၏ ဓာတ်ပုံများ"</string>
<string name="pick_wallpaper" msgid="4628969645948454559">"နောက်ခံများ"</string>
<string name="crop_wallpaper" msgid="4882870800623585836">"နောက်ခံအား ဖြတ်ခြင်း"</string>
</resources>
diff --git a/WallpaperPicker/res/values-nb/strings.xml b/WallpaperPicker/res/values-nb/strings.xml
index 3589e4bc8..9ae0b989a 100644
--- a/WallpaperPicker/res/values-nb/strings.xml
+++ b/WallpaperPicker/res/values-nb/strings.xml
@@ -30,7 +30,7 @@
<string name="wallpaper_accessibility_name" msgid="4093221025304876354">"Bakgrunn %1$d av %2$d"</string>
<string name="announce_selection" msgid="123723511662250539">"Valgt <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="wallpaper_delete" msgid="1459353972739215344">"Slett"</string>
- <string name="pick_image" msgid="6704438906027442697">"Velg bilde"</string>
+ <string name="pick_image" msgid="3189640419551368385">"Mine bilder"</string>
<string name="pick_wallpaper" msgid="4628969645948454559">"Bakgrunner"</string>
<string name="crop_wallpaper" msgid="4882870800623585836">"Beskjær bakgrunnen"</string>
</resources>
diff --git a/WallpaperPicker/res/values-ne-rNP/strings.xml b/WallpaperPicker/res/values-ne-rNP/strings.xml
index 221fa9438..5bca8d809 100644
--- a/WallpaperPicker/res/values-ne-rNP/strings.xml
+++ b/WallpaperPicker/res/values-ne-rNP/strings.xml
@@ -30,7 +30,7 @@
<string name="wallpaper_accessibility_name" msgid="4093221025304876354">"%2$d को %1$d वालपेपर"</string>
<string name="announce_selection" msgid="123723511662250539">"चयन गरिएको <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="wallpaper_delete" msgid="1459353972739215344">"मेट्नुहोस्"</string>
- <string name="pick_image" msgid="6704438906027442697">"तस्बिर छान्नुहोस्"</string>
+ <string name="pick_image" msgid="3189640419551368385">"मेरा तस्बिरहरू"</string>
<string name="pick_wallpaper" msgid="4628969645948454559">"वालपेपरहरु"</string>
<string name="crop_wallpaper" msgid="4882870800623585836">"वालपेपर काँटछाट गर्नुहोस्"</string>
</resources>
diff --git a/WallpaperPicker/res/values-nl/strings.xml b/WallpaperPicker/res/values-nl/strings.xml
index 7dd4f22b0..a86f0f651 100644
--- a/WallpaperPicker/res/values-nl/strings.xml
+++ b/WallpaperPicker/res/values-nl/strings.xml
@@ -30,7 +30,7 @@
<string name="wallpaper_accessibility_name" msgid="4093221025304876354">"Achtergrond %1$d van %2$d"</string>
<string name="announce_selection" msgid="123723511662250539">"<xliff:g id="LABEL">%1$s</xliff:g> is geselecteerd"</string>
<string name="wallpaper_delete" msgid="1459353972739215344">"Verwijderen"</string>
- <string name="pick_image" msgid="6704438906027442697">"Afbeelding kiezen"</string>
+ <string name="pick_image" msgid="3189640419551368385">"Mijn foto\'s"</string>
<string name="pick_wallpaper" msgid="4628969645948454559">"Achtergronden"</string>
<string name="crop_wallpaper" msgid="4882870800623585836">"Achtergrond bijsnijden"</string>
</resources>
diff --git a/WallpaperPicker/res/values-pa-rIN/strings.xml b/WallpaperPicker/res/values-pa-rIN/strings.xml
index 3be7bf802..e4225e02d 100644
--- a/WallpaperPicker/res/values-pa-rIN/strings.xml
+++ b/WallpaperPicker/res/values-pa-rIN/strings.xml
@@ -30,7 +30,7 @@
<string name="wallpaper_accessibility_name" msgid="4093221025304876354">"ਵਾਲਪੇਪਰ %2$d ਦਾ %1$d"</string>
<string name="announce_selection" msgid="123723511662250539">"<xliff:g id="LABEL">%1$s</xliff:g> ਚੁਣਿਆ ਗਿਆ"</string>
<string name="wallpaper_delete" msgid="1459353972739215344">"ਮਿਟਾਓ"</string>
- <string name="pick_image" msgid="6704438906027442697">"ਚਿੱਤਰ ਚੁਣੋ"</string>
+ <string name="pick_image" msgid="3189640419551368385">"ਮੇਰੀਆਂ ਫੋਟੋਆਂ"</string>
<string name="pick_wallpaper" msgid="4628969645948454559">"ਵਾਲਪੇਪਰ"</string>
<string name="crop_wallpaper" msgid="4882870800623585836">"ਵਾਲਪੇਪਰ ਕੱਟੋ"</string>
</resources>
diff --git a/WallpaperPicker/res/values-pl/strings.xml b/WallpaperPicker/res/values-pl/strings.xml
index bcdbb3dc7..cd52082d6 100644
--- a/WallpaperPicker/res/values-pl/strings.xml
+++ b/WallpaperPicker/res/values-pl/strings.xml
@@ -30,7 +30,7 @@
<string name="wallpaper_accessibility_name" msgid="4093221025304876354">"Tapeta %1$d z %2$d"</string>
<string name="announce_selection" msgid="123723511662250539">"Wybrano <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="wallpaper_delete" msgid="1459353972739215344">"Usuń"</string>
- <string name="pick_image" msgid="6704438906027442697">"Wybierz obraz"</string>
+ <string name="pick_image" msgid="3189640419551368385">"Moje zdjęcia"</string>
<string name="pick_wallpaper" msgid="4628969645948454559">"Tapety"</string>
<string name="crop_wallpaper" msgid="4882870800623585836">"Przytnij tapetę"</string>
</resources>
diff --git a/WallpaperPicker/res/values-pt-rPT/strings.xml b/WallpaperPicker/res/values-pt-rPT/strings.xml
index 83492327f..82aa4694a 100644
--- a/WallpaperPicker/res/values-pt-rPT/strings.xml
+++ b/WallpaperPicker/res/values-pt-rPT/strings.xml
@@ -30,7 +30,7 @@
<string name="wallpaper_accessibility_name" msgid="4093221025304876354">"Imagem de fundo %1$d de %2$d"</string>
<string name="announce_selection" msgid="123723511662250539">"<xliff:g id="LABEL">%1$s</xliff:g> selecionada"</string>
<string name="wallpaper_delete" msgid="1459353972739215344">"Eliminar"</string>
- <string name="pick_image" msgid="6704438906027442697">"Escolher imagem"</string>
+ <string name="pick_image" msgid="3189640419551368385">"As minhas fotos"</string>
<string name="pick_wallpaper" msgid="4628969645948454559">"Imagens de fundo"</string>
<string name="crop_wallpaper" msgid="4882870800623585836">"Recortar imagem de fundo"</string>
</resources>
diff --git a/WallpaperPicker/res/values-pt/strings.xml b/WallpaperPicker/res/values-pt/strings.xml
index 2332fcbd1..74ff3106c 100644
--- a/WallpaperPicker/res/values-pt/strings.xml
+++ b/WallpaperPicker/res/values-pt/strings.xml
@@ -30,7 +30,7 @@
<string name="wallpaper_accessibility_name" msgid="4093221025304876354">"Plano de fundo %1$d de %2$d"</string>
<string name="announce_selection" msgid="123723511662250539">"<xliff:g id="LABEL">%1$s</xliff:g> selecionado"</string>
<string name="wallpaper_delete" msgid="1459353972739215344">"Excluir"</string>
- <string name="pick_image" msgid="6704438906027442697">"Escolher imagem"</string>
+ <string name="pick_image" msgid="3189640419551368385">"Minhas fotos"</string>
<string name="pick_wallpaper" msgid="4628969645948454559">"Planos de fundo"</string>
<string name="crop_wallpaper" msgid="4882870800623585836">"Cortar plano de fundo"</string>
</resources>
diff --git a/WallpaperPicker/res/values-ro/strings.xml b/WallpaperPicker/res/values-ro/strings.xml
index 8ee1a5a39..6281b80fc 100644
--- a/WallpaperPicker/res/values-ro/strings.xml
+++ b/WallpaperPicker/res/values-ro/strings.xml
@@ -30,7 +30,7 @@
<string name="wallpaper_accessibility_name" msgid="4093221025304876354">"Imaginea de fundal %1$d din %2$d"</string>
<string name="announce_selection" msgid="123723511662250539">"S-a selectat <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="wallpaper_delete" msgid="1459353972739215344">"Ștergeți"</string>
- <string name="pick_image" msgid="6704438906027442697">"Alegeți imaginea"</string>
+ <string name="pick_image" msgid="3189640419551368385">"Fotografiile mele"</string>
<string name="pick_wallpaper" msgid="4628969645948454559">"Imagini de fundal"</string>
<string name="crop_wallpaper" msgid="4882870800623585836">"Decupați imaginea de fundal"</string>
</resources>
diff --git a/WallpaperPicker/res/values-ru/strings.xml b/WallpaperPicker/res/values-ru/strings.xml
index ff43ce8f6..959205a33 100644
--- a/WallpaperPicker/res/values-ru/strings.xml
+++ b/WallpaperPicker/res/values-ru/strings.xml
@@ -30,7 +30,7 @@
<string name="wallpaper_accessibility_name" msgid="4093221025304876354">"Обои %1$d из %2$d"</string>
<string name="announce_selection" msgid="123723511662250539">"Выбран элемент \"<xliff:g id="LABEL">%1$s</xliff:g>\""</string>
<string name="wallpaper_delete" msgid="1459353972739215344">"Удалить"</string>
- <string name="pick_image" msgid="6704438906027442697">"Выбрать обои"</string>
+ <string name="pick_image" msgid="3189640419551368385">"Мои фото"</string>
<string name="pick_wallpaper" msgid="4628969645948454559">"Обои"</string>
<string name="crop_wallpaper" msgid="4882870800623585836">"Кадрировать обои"</string>
</resources>
diff --git a/WallpaperPicker/res/values-si-rLK/strings.xml b/WallpaperPicker/res/values-si-rLK/strings.xml
index d175724fd..37ce1fc52 100644
--- a/WallpaperPicker/res/values-si-rLK/strings.xml
+++ b/WallpaperPicker/res/values-si-rLK/strings.xml
@@ -32,7 +32,7 @@
<skip />
<string name="announce_selection" msgid="123723511662250539">"තෝරාගත්තේ <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="wallpaper_delete" msgid="1459353972739215344">"මකන්න"</string>
- <string name="pick_image" msgid="6704438906027442697">"පින්තූරයක් තෝරන්න"</string>
+ <string name="pick_image" msgid="3189640419551368385">"මගේ ඡායාරූප"</string>
<string name="pick_wallpaper" msgid="4628969645948454559">"වෝල්පේපර"</string>
<string name="crop_wallpaper" msgid="4882870800623585836">"වෝල්පේපරය කප්පාදු කිරීම"</string>
</resources>
diff --git a/WallpaperPicker/res/values-sk/strings.xml b/WallpaperPicker/res/values-sk/strings.xml
index 33477a124..9d38de437 100644
--- a/WallpaperPicker/res/values-sk/strings.xml
+++ b/WallpaperPicker/res/values-sk/strings.xml
@@ -30,7 +30,7 @@
<string name="wallpaper_accessibility_name" msgid="4093221025304876354">"Tapeta %1$d z %2$d"</string>
<string name="announce_selection" msgid="123723511662250539">"Vybratá položka <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="wallpaper_delete" msgid="1459353972739215344">"Odstrániť"</string>
- <string name="pick_image" msgid="6704438906027442697">"Vybrať obrázok"</string>
+ <string name="pick_image" msgid="3189640419551368385">"Moje fotky"</string>
<string name="pick_wallpaper" msgid="4628969645948454559">"Tapety"</string>
<string name="crop_wallpaper" msgid="4882870800623585836">"Orezanie tapety"</string>
</resources>
diff --git a/WallpaperPicker/res/values-sl/strings.xml b/WallpaperPicker/res/values-sl/strings.xml
index 06a508a8c..e776cc7d5 100644
--- a/WallpaperPicker/res/values-sl/strings.xml
+++ b/WallpaperPicker/res/values-sl/strings.xml
@@ -30,7 +30,7 @@
<string name="wallpaper_accessibility_name" msgid="4093221025304876354">"%1$d. ozadje od %2$d"</string>
<string name="announce_selection" msgid="123723511662250539">"Izbrano: <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="wallpaper_delete" msgid="1459353972739215344">"Izbriši"</string>
- <string name="pick_image" msgid="6704438906027442697">"Izberi sliko"</string>
+ <string name="pick_image" msgid="3189640419551368385">"Moje fotografije"</string>
<string name="pick_wallpaper" msgid="4628969645948454559">"Ozadja"</string>
<string name="crop_wallpaper" msgid="4882870800623585836">"Obrezovanje ozadja"</string>
</resources>
diff --git a/WallpaperPicker/res/values-sq-rAL/strings.xml b/WallpaperPicker/res/values-sq-rAL/strings.xml
index f21b7ef83..8a9983b4b 100644
--- a/WallpaperPicker/res/values-sq-rAL/strings.xml
+++ b/WallpaperPicker/res/values-sq-rAL/strings.xml
@@ -30,7 +30,7 @@
<string name="wallpaper_accessibility_name" msgid="4093221025304876354">"Imazhi i sfondit: %1$d nga gjithsej %2$d"</string>
<string name="announce_selection" msgid="123723511662250539">"<xliff:g id="LABEL">%1$s</xliff:g> u përzgjodh"</string>
<string name="wallpaper_delete" msgid="1459353972739215344">"Fshi"</string>
- <string name="pick_image" msgid="6704438906027442697">"Zgjidh imazhin"</string>
+ <string name="pick_image" msgid="3189640419551368385">"Fotografitë e mia"</string>
<string name="pick_wallpaper" msgid="4628969645948454559">"Imazhet e sfondit"</string>
<string name="crop_wallpaper" msgid="4882870800623585836">"Prit imazhin e sfondit"</string>
</resources>
diff --git a/WallpaperPicker/res/values-sr/strings.xml b/WallpaperPicker/res/values-sr/strings.xml
index fdfaaf60f..c37bc060f 100644
--- a/WallpaperPicker/res/values-sr/strings.xml
+++ b/WallpaperPicker/res/values-sr/strings.xml
@@ -30,7 +30,7 @@
<string name="wallpaper_accessibility_name" msgid="4093221025304876354">"Позадина %1$d од %2$d"</string>
<string name="announce_selection" msgid="123723511662250539">"Изабрана је <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="wallpaper_delete" msgid="1459353972739215344">"Избриши"</string>
- <string name="pick_image" msgid="6704438906027442697">"Изабери слику"</string>
+ <string name="pick_image" msgid="3189640419551368385">"Моје фотографије"</string>
<string name="pick_wallpaper" msgid="4628969645948454559">"Позадине"</string>
<string name="crop_wallpaper" msgid="4882870800623585836">"Опсеци позадину"</string>
</resources>
diff --git a/WallpaperPicker/res/values-sv/strings.xml b/WallpaperPicker/res/values-sv/strings.xml
index 57db3a64d..044508b4d 100644
--- a/WallpaperPicker/res/values-sv/strings.xml
+++ b/WallpaperPicker/res/values-sv/strings.xml
@@ -30,7 +30,7 @@
<string name="wallpaper_accessibility_name" msgid="4093221025304876354">"Bakgrund %1$d av %2$d"</string>
<string name="announce_selection" msgid="123723511662250539">"<xliff:g id="LABEL">%1$s</xliff:g> har valts"</string>
<string name="wallpaper_delete" msgid="1459353972739215344">"Ta bort"</string>
- <string name="pick_image" msgid="6704438906027442697">"Välj bild"</string>
+ <string name="pick_image" msgid="3189640419551368385">"Mina foton"</string>
<string name="pick_wallpaper" msgid="4628969645948454559">"Bakgrunder"</string>
<string name="crop_wallpaper" msgid="4882870800623585836">"Beskär bakgrund"</string>
</resources>
diff --git a/WallpaperPicker/res/values-sw/strings.xml b/WallpaperPicker/res/values-sw/strings.xml
index edea3de5b..367912aab 100644
--- a/WallpaperPicker/res/values-sw/strings.xml
+++ b/WallpaperPicker/res/values-sw/strings.xml
@@ -30,7 +30,7 @@
<string name="wallpaper_accessibility_name" msgid="4093221025304876354">"Mandhari %1$d ya %2$d"</string>
<string name="announce_selection" msgid="123723511662250539">"<xliff:g id="LABEL">%1$s</xliff:g> iliyochaguliwa"</string>
<string name="wallpaper_delete" msgid="1459353972739215344">"Futa"</string>
- <string name="pick_image" msgid="6704438906027442697">"Chagua picha"</string>
+ <string name="pick_image" msgid="3189640419551368385">"Picha zangu"</string>
<string name="pick_wallpaper" msgid="4628969645948454559">"Mandhari"</string>
<string name="crop_wallpaper" msgid="4882870800623585836">"Punguza mandhari"</string>
</resources>
diff --git a/WallpaperPicker/res/values-sw720dp-v19/styles.xml b/WallpaperPicker/res/values-sw720dp-v19/styles.xml
index 91078517d..d8dab223a 100644
--- a/WallpaperPicker/res/values-sw720dp-v19/styles.xml
+++ b/WallpaperPicker/res/values-sw720dp-v19/styles.xml
@@ -18,7 +18,7 @@
-->
<resources>
- <style name="Theme" parent="android:Theme.Holo.Wallpaper.NoTitleBar">
+ <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>
diff --git a/WallpaperPicker/res/values-sw720dp/dimens.xml b/WallpaperPicker/res/values-sw720dp/dimens.xml
deleted file mode 100644
index 9ae155b3c..000000000
--- a/WallpaperPicker/res/values-sw720dp/dimens.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2011 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<resources>
- <dimen name="app_icon_size">72dp</dimen>
-
-<!-- QSB -->
- <dimen name="toolbar_button_vertical_padding">8dip</dimen>
- <dimen name="toolbar_button_horizontal_padding">8dip</dimen>
-
- <!-- When dragging items on the workspace, the number of dps by which the position of
- the drag view should be offset from the position of the original view. -->
- <dimen name="dragViewOffsetX">0dp</dimen>
- <dimen name="dragViewOffsetY">0dp</dimen>
-</resources>
diff --git a/WallpaperPicker/res/values-sw720dp/styles.xml b/WallpaperPicker/res/values-sw720dp/styles.xml
index b48909087..12f8884f1 100644
--- a/WallpaperPicker/res/values-sw720dp/styles.xml
+++ b/WallpaperPicker/res/values-sw720dp/styles.xml
@@ -18,7 +18,7 @@
-->
<resources>
- <style name="Theme" parent="android:Theme.Holo.Wallpaper.NoTitleBar">
+ <style name="Theme" parent="@android:style/Theme.DeviceDefault.Wallpaper.NoTitleBar">
<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 2b984271a..7284da8ae 100644
--- a/WallpaperPicker/res/values-ta-rIN/strings.xml
+++ b/WallpaperPicker/res/values-ta-rIN/strings.xml
@@ -30,7 +30,7 @@
<string name="wallpaper_accessibility_name" msgid="4093221025304876354">"வால்பேப்பர் %1$d / %2$d"</string>
<string name="announce_selection" msgid="123723511662250539">"<xliff:g id="LABEL">%1$s</xliff:g> தேர்ந்தெடுக்கப்பட்டது"</string>
<string name="wallpaper_delete" msgid="1459353972739215344">"நீக்கு"</string>
- <string name="pick_image" msgid="6704438906027442697">"படத்தைத் தேர்வுசெய்க"</string>
+ <string name="pick_image" msgid="3189640419551368385">"எனது படங்கள்"</string>
<string name="pick_wallpaper" msgid="4628969645948454559">"வால்பேப்பர்கள்"</string>
<string name="crop_wallpaper" msgid="4882870800623585836">"வால்பேப்பரைச் செதுக்கு"</string>
</resources>
diff --git a/WallpaperPicker/res/values-te-rIN/strings.xml b/WallpaperPicker/res/values-te-rIN/strings.xml
index c26f84e28..4c5ad2f08 100644
--- a/WallpaperPicker/res/values-te-rIN/strings.xml
+++ b/WallpaperPicker/res/values-te-rIN/strings.xml
@@ -30,7 +30,7 @@
<string name="wallpaper_accessibility_name" msgid="4093221025304876354">"%2$dలో %1$dవ వాల్‌పేపర్"</string>
<string name="announce_selection" msgid="123723511662250539">"<xliff:g id="LABEL">%1$s</xliff:g> ఎంచుకోబడింది"</string>
<string name="wallpaper_delete" msgid="1459353972739215344">"తొలగించు"</string>
- <string name="pick_image" msgid="6704438906027442697">"చిత్రాన్ని ఎంచుకోండి"</string>
+ <string name="pick_image" msgid="3189640419551368385">"నా ఫోటోలు"</string>
<string name="pick_wallpaper" msgid="4628969645948454559">"వాల్‌పేపర్‌లు"</string>
<string name="crop_wallpaper" msgid="4882870800623585836">"వాల్‌పేపర్‌ను కత్తిరించండి"</string>
</resources>
diff --git a/WallpaperPicker/res/values-th/strings.xml b/WallpaperPicker/res/values-th/strings.xml
index 6b4c23536..b3d7a8bc7 100644
--- a/WallpaperPicker/res/values-th/strings.xml
+++ b/WallpaperPicker/res/values-th/strings.xml
@@ -30,7 +30,7 @@
<string name="wallpaper_accessibility_name" msgid="4093221025304876354">"วอลเปเปอร์ %1$d จาก %2$d"</string>
<string name="announce_selection" msgid="123723511662250539">"เลือก <xliff:g id="LABEL">%1$s</xliff:g> แล้ว"</string>
<string name="wallpaper_delete" msgid="1459353972739215344">"ลบ"</string>
- <string name="pick_image" msgid="6704438906027442697">"เลือกรูปภาพ"</string>
+ <string name="pick_image" msgid="3189640419551368385">"รูปภาพของฉัน"</string>
<string name="pick_wallpaper" msgid="4628969645948454559">"วอลเปเปอร์"</string>
<string name="crop_wallpaper" msgid="4882870800623585836">"ครอบตัดวอลเปเปอร์"</string>
</resources>
diff --git a/WallpaperPicker/res/values-tl/strings.xml b/WallpaperPicker/res/values-tl/strings.xml
index c9fe338d4..db8f4d542 100644
--- a/WallpaperPicker/res/values-tl/strings.xml
+++ b/WallpaperPicker/res/values-tl/strings.xml
@@ -30,7 +30,7 @@
<string name="wallpaper_accessibility_name" msgid="4093221025304876354">"Wallpaper %1$d ng %2$d"</string>
<string name="announce_selection" msgid="123723511662250539">"Napili ang <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="wallpaper_delete" msgid="1459353972739215344">"Tanggalin"</string>
- <string name="pick_image" msgid="6704438906027442697">"Pumili ng larawan"</string>
+ <string name="pick_image" msgid="3189640419551368385">"Aking mga larawan"</string>
<string name="pick_wallpaper" msgid="4628969645948454559">"Mga Wallpaper"</string>
<string name="crop_wallpaper" msgid="4882870800623585836">"I-crop ang wallpaper"</string>
</resources>
diff --git a/WallpaperPicker/res/values-tr/strings.xml b/WallpaperPicker/res/values-tr/strings.xml
index 3d03c6be8..d1e57edbb 100644
--- a/WallpaperPicker/res/values-tr/strings.xml
+++ b/WallpaperPicker/res/values-tr/strings.xml
@@ -30,7 +30,7 @@
<string name="wallpaper_accessibility_name" msgid="4093221025304876354">"%2$d duvar kağıdı arasından duvar kağıdı %1$d"</string>
<string name="announce_selection" msgid="123723511662250539">"<xliff:g id="LABEL">%1$s</xliff:g> seçildi"</string>
<string name="wallpaper_delete" msgid="1459353972739215344">"Sil"</string>
- <string name="pick_image" msgid="6704438906027442697">"Resim seç"</string>
+ <string name="pick_image" msgid="3189640419551368385">"Fotoğraflarım"</string>
<string name="pick_wallpaper" msgid="4628969645948454559">"Duvar kağıtları"</string>
<string name="crop_wallpaper" msgid="4882870800623585836">"Duvar kağıdını kırp"</string>
</resources>
diff --git a/WallpaperPicker/res/values-uk/strings.xml b/WallpaperPicker/res/values-uk/strings.xml
index 076c88238..756e7cf09 100644
--- a/WallpaperPicker/res/values-uk/strings.xml
+++ b/WallpaperPicker/res/values-uk/strings.xml
@@ -30,7 +30,7 @@
<string name="wallpaper_accessibility_name" msgid="4093221025304876354">"Фоновий малюнок %1$d з %2$d"</string>
<string name="announce_selection" msgid="123723511662250539">"Вибрано <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="wallpaper_delete" msgid="1459353972739215344">"Видалити"</string>
- <string name="pick_image" msgid="6704438906027442697">"Вибрати зображення"</string>
+ <string name="pick_image" msgid="3189640419551368385">"Мої фото"</string>
<string name="pick_wallpaper" msgid="4628969645948454559">"Фонові малюнки"</string>
<string name="crop_wallpaper" msgid="4882870800623585836">"Обрізати фоновий малюнок"</string>
</resources>
diff --git a/WallpaperPicker/res/values-ur-rPK/strings.xml b/WallpaperPicker/res/values-ur-rPK/strings.xml
index 7b12d4239..86d8163d9 100644
--- a/WallpaperPicker/res/values-ur-rPK/strings.xml
+++ b/WallpaperPicker/res/values-ur-rPK/strings.xml
@@ -30,7 +30,7 @@
<string name="wallpaper_accessibility_name" msgid="4093221025304876354">"‏وال پیپر ‎%1$d از ‎%2$d"</string>
<string name="announce_selection" msgid="123723511662250539">"<xliff:g id="LABEL">%1$s</xliff:g> کو منتخب کیا گیا"</string>
<string name="wallpaper_delete" msgid="1459353972739215344">"حذف کریں"</string>
- <string name="pick_image" msgid="6704438906027442697">"تصویر منتخب کریں"</string>
+ <string name="pick_image" msgid="3189640419551368385">"میری تصاویر"</string>
<string name="pick_wallpaper" msgid="4628969645948454559">"وال پیپرز"</string>
<string name="crop_wallpaper" msgid="4882870800623585836">"وال پیپر کو تراشیں"</string>
</resources>
diff --git a/WallpaperPicker/res/values-uz-rUZ/strings.xml b/WallpaperPicker/res/values-uz-rUZ/strings.xml
index 807d6b4ae..97d3938ae 100644
--- a/WallpaperPicker/res/values-uz-rUZ/strings.xml
+++ b/WallpaperPicker/res/values-uz-rUZ/strings.xml
@@ -30,7 +30,7 @@
<string name="wallpaper_accessibility_name" msgid="4093221025304876354">"Fon rasmi %2$ddan %1$d"</string>
<string name="announce_selection" msgid="123723511662250539">"<xliff:g id="LABEL">%1$s</xliff:g> tanlandi"</string>
<string name="wallpaper_delete" msgid="1459353972739215344">"O‘chirish"</string>
- <string name="pick_image" msgid="6704438906027442697">"Rasm tanlang"</string>
+ <string name="pick_image" msgid="3189640419551368385">"Mening rasmlarim"</string>
<string name="pick_wallpaper" msgid="4628969645948454559">"Fon rasmlari"</string>
<string name="crop_wallpaper" msgid="4882870800623585836">"Fon rasmini kesish"</string>
</resources>
diff --git a/WallpaperPicker/res/values-v21/styles.xml b/WallpaperPicker/res/values-v21/styles.xml
new file mode 100644
index 000000000..582ab8fed
--- /dev/null
+++ b/WallpaperPicker/res/values-v21/styles.xml
@@ -0,0 +1,36 @@
+<?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.
+*/
+-->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <style name="WallpaperCropperActionBar" parent="@android:style/Widget.DeviceDefault.ActionBar">
+ <item name="android:displayOptions">showCustom</item>
+ <item name="android:background">#88000000</item>
+ <item name="android:contentInsetEnd">0dp</item>
+ <item name="android:contentInsetLeft">0dp</item>
+ <item name="android:contentInsetRight">0dp</item>
+ <item name="android:contentInsetStart">0dp</item>
+ </style>
+
+ <style name="ActionBarSetWallpaperStyle" parent="@android:style/Widget.DeviceDefault.ActionButton">
+ <item name="android:textColor">#ffffffff</item>
+ <item name="android:background">?android:attr/selectableItemBackgroundBorderless</item>
+ </style>
+
+</resources> \ No newline at end of file
diff --git a/WallpaperPicker/res/values-vi/strings.xml b/WallpaperPicker/res/values-vi/strings.xml
index d1efbe989..ae00d585c 100644
--- a/WallpaperPicker/res/values-vi/strings.xml
+++ b/WallpaperPicker/res/values-vi/strings.xml
@@ -30,7 +30,7 @@
<string name="wallpaper_accessibility_name" msgid="4093221025304876354">"Hình nền %1$d / %2$d"</string>
<string name="announce_selection" msgid="123723511662250539">"<xliff:g id="LABEL">%1$s</xliff:g> được chọn"</string>
<string name="wallpaper_delete" msgid="1459353972739215344">"Xóa"</string>
- <string name="pick_image" msgid="6704438906027442697">"Chọn hình ảnh"</string>
+ <string name="pick_image" msgid="3189640419551368385">"Ảnh của tôi"</string>
<string name="pick_wallpaper" msgid="4628969645948454559">"Hình nền"</string>
<string name="crop_wallpaper" msgid="4882870800623585836">"Cắt hình nền"</string>
</resources>
diff --git a/WallpaperPicker/res/values-zh-rCN/strings.xml b/WallpaperPicker/res/values-zh-rCN/strings.xml
index 1def9ed41..8bd5342eb 100644
--- a/WallpaperPicker/res/values-zh-rCN/strings.xml
+++ b/WallpaperPicker/res/values-zh-rCN/strings.xml
@@ -30,7 +30,7 @@
<string name="wallpaper_accessibility_name" msgid="4093221025304876354">"第%1$d张壁纸,共%2$d张"</string>
<string name="announce_selection" msgid="123723511662250539">"已选择<xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="wallpaper_delete" msgid="1459353972739215344">"删除"</string>
- <string name="pick_image" msgid="6704438906027442697">"选择图片"</string>
+ <string name="pick_image" msgid="3189640419551368385">"我的照片"</string>
<string name="pick_wallpaper" msgid="4628969645948454559">"壁纸"</string>
<string name="crop_wallpaper" msgid="4882870800623585836">"剪裁壁纸"</string>
</resources>
diff --git a/WallpaperPicker/res/values-zh-rHK/strings.xml b/WallpaperPicker/res/values-zh-rHK/strings.xml
index 66ba0af18..e51d60afa 100644
--- a/WallpaperPicker/res/values-zh-rHK/strings.xml
+++ b/WallpaperPicker/res/values-zh-rHK/strings.xml
@@ -30,7 +30,7 @@
<string name="wallpaper_accessibility_name" msgid="4093221025304876354">"第 %1$d 張桌布,共 %2$d 張"</string>
<string name="announce_selection" msgid="123723511662250539">"已選取<xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="wallpaper_delete" msgid="1459353972739215344">"刪除"</string>
- <string name="pick_image" msgid="6704438906027442697">"選擇圖片"</string>
+ <string name="pick_image" msgid="3189640419551368385">"我的相片"</string>
<string name="pick_wallpaper" msgid="4628969645948454559">"桌布"</string>
<string name="crop_wallpaper" msgid="4882870800623585836">"裁剪桌布"</string>
</resources>
diff --git a/WallpaperPicker/res/values-zh-rTW/strings.xml b/WallpaperPicker/res/values-zh-rTW/strings.xml
index 418497608..c12350af0 100644
--- a/WallpaperPicker/res/values-zh-rTW/strings.xml
+++ b/WallpaperPicker/res/values-zh-rTW/strings.xml
@@ -30,7 +30,7 @@
<string name="wallpaper_accessibility_name" msgid="4093221025304876354">"第 %1$d 張桌布,共 %2$d 張"</string>
<string name="announce_selection" msgid="123723511662250539">"已選取<xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="wallpaper_delete" msgid="1459353972739215344">"刪除"</string>
- <string name="pick_image" msgid="6704438906027442697">"選擇圖片"</string>
+ <string name="pick_image" msgid="3189640419551368385">"我的相片"</string>
<string name="pick_wallpaper" msgid="4628969645948454559">"桌布"</string>
<string name="crop_wallpaper" msgid="4882870800623585836">"裁剪桌布"</string>
</resources>
diff --git a/WallpaperPicker/res/values-zu/strings.xml b/WallpaperPicker/res/values-zu/strings.xml
index c7d3f33d1..537b2f3ca 100644
--- a/WallpaperPicker/res/values-zu/strings.xml
+++ b/WallpaperPicker/res/values-zu/strings.xml
@@ -30,7 +30,7 @@
<string name="wallpaper_accessibility_name" msgid="4093221025304876354">"Isithombe sangemuva esingu-%1$d kwezingu-%2$d"</string>
<string name="announce_selection" msgid="123723511662250539">"I-<xliff:g id="LABEL">%1$s</xliff:g> ekhethiwe"</string>
<string name="wallpaper_delete" msgid="1459353972739215344">"Susa"</string>
- <string name="pick_image" msgid="6704438906027442697">"Khetha isithombe"</string>
+ <string name="pick_image" msgid="3189640419551368385">"Izithombe zami"</string>
<string name="pick_wallpaper" msgid="4628969645948454559">"Izithombe zangemuva"</string>
<string name="crop_wallpaper" msgid="4882870800623585836">"Nqampuna isithombe sangemuva"</string>
</resources>
diff --git a/WallpaperPicker/res/values/config.xml b/WallpaperPicker/res/values/config.xml
index 71580b5b0..2f5174ce6 100644
--- a/WallpaperPicker/res/values/config.xml
+++ b/WallpaperPicker/res/values/config.xml
@@ -14,7 +14,6 @@
limitations under the License.
-->
<resources>
- <bool name="allow_rotation">false</bool>
<!-- Specifies whether to expand the cropped area on both sides (rather
than just to one side) -->
<bool name="center_crop">false</bool>
diff --git a/WallpaperPicker/res/values/strings.xml b/WallpaperPicker/res/values/strings.xml
index 1ee3513f9..72b1e15df 100644
--- a/WallpaperPicker/res/values/strings.xml
+++ b/WallpaperPicker/res/values/strings.xml
@@ -45,7 +45,7 @@
<!-- Label on button to delete wallpaper(s) -->
<string name="wallpaper_delete">Delete</string>
<!-- Label on button in Wallpaper Picker to pick an image -->
- <string name="pick_image">Pick image</string>
+ <string name="pick_image">My photos</string>
<!-- Option in "Select wallpaper from" dialog box -->
<string name="pick_wallpaper">Wallpapers</string>
<!-- Title of activity for cropping wallpapers -->
diff --git a/WallpaperPicker/res/values/styles.xml b/WallpaperPicker/res/values/styles.xml
index f4008f159..74aeab903 100644
--- a/WallpaperPicker/res/values/styles.xml
+++ b/WallpaperPicker/res/values/styles.xml
@@ -17,7 +17,7 @@
*/
-->
-<resources>
+<resources xmlns:android="http://schemas.android.com/apk/res/android">
<style name="Theme.WallpaperCropper" parent="@android:style/Theme.DeviceDefault">
<item name="android:actionBarStyle">@style/WallpaperCropperActionBar</item>
<item name="android:windowFullscreen">true</item>
@@ -40,5 +40,6 @@
<style name="ActionBarSetWallpaperStyle" parent="@android:style/Widget.DeviceDefault.ActionButton">
<item name="android:textColor">#ffffffff</item>
+ <item name="android:background">?android:attr/selectableItemBackground</item>
</style>
</resources>
diff --git a/WallpaperPicker/src/android/util/Pools.java b/WallpaperPicker/src/android/util/Pools.java
deleted file mode 100644
index 40bab1eae..000000000
--- a/WallpaperPicker/src/android/util/Pools.java
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.util;
-
-/**
- * Helper class for crating pools of objects. An example use looks like this:
- * <pre>
- * public class MyPooledClass {
- *
- * private static final SynchronizedPool<MyPooledClass> sPool =
- * new SynchronizedPool<MyPooledClass>(10);
- *
- * public static MyPooledClass obtain() {
- * MyPooledClass instance = sPool.acquire();
- * return (instance != null) ? instance : new MyPooledClass();
- * }
- *
- * public void recycle() {
- * // Clear state if needed.
- * sPool.release(this);
- * }
- *
- * . . .
- * }
- * </pre>
- *
- * @hide
- */
-public final class Pools {
-
- /**
- * Interface for managing a pool of objects.
- *
- * @param <T> The pooled type.
- */
- public static interface Pool<T> {
-
- /**
- * @return An instance from the pool if such, null otherwise.
- */
- public T acquire();
-
- /**
- * Release an instance to the pool.
- *
- * @param instance The instance to release.
- * @return Whether the instance was put in the pool.
- *
- * @throws IllegalStateException If the instance is already in the pool.
- */
- public boolean release(T instance);
- }
-
- private Pools() {
- /* do nothing - hiding constructor */
- }
-
- /**
- * Simple (non-synchronized) pool of objects.
- *
- * @param <T> The pooled type.
- */
- public static class SimplePool<T> implements Pool<T> {
- private final Object[] mPool;
-
- private int mPoolSize;
-
- /**
- * Creates a new instance.
- *
- * @param maxPoolSize The max pool size.
- *
- * @throws IllegalArgumentException If the max pool size is less than zero.
- */
- public SimplePool(int maxPoolSize) {
- if (maxPoolSize <= 0) {
- throw new IllegalArgumentException("The max pool size must be > 0");
- }
- mPool = new Object[maxPoolSize];
- }
-
- @Override
- @SuppressWarnings("unchecked")
- public T acquire() {
- if (mPoolSize > 0) {
- final int lastPooledIndex = mPoolSize - 1;
- T instance = (T) mPool[lastPooledIndex];
- mPool[lastPooledIndex] = null;
- mPoolSize--;
- return instance;
- }
- return null;
- }
-
- @Override
- public boolean release(T instance) {
- if (isInPool(instance)) {
- throw new IllegalStateException("Already in the pool!");
- }
- if (mPoolSize < mPool.length) {
- mPool[mPoolSize] = instance;
- mPoolSize++;
- return true;
- }
- return false;
- }
-
- private boolean isInPool(T instance) {
- for (int i = 0; i < mPoolSize; i++) {
- if (mPool[i] == instance) {
- return true;
- }
- }
- return false;
- }
- }
-
- /**
- * Synchronized) pool of objects.
- *
- * @param <T> The pooled type.
- */
- public static class SynchronizedPool<T> extends SimplePool<T> {
- private final Object mLock = new Object();
-
- /**
- * Creates a new instance.
- *
- * @param maxPoolSize The max pool size.
- *
- * @throws IllegalArgumentException If the max pool size is less than zero.
- */
- public SynchronizedPool(int maxPoolSize) {
- super(maxPoolSize);
- }
-
- @Override
- public T acquire() {
- synchronized (mLock) {
- return super.acquire();
- }
- }
-
- @Override
- public boolean release(T element) {
- synchronized (mLock) {
- return super.release(element);
- }
- }
- }
-} \ No newline at end of file
diff --git a/WallpaperPicker/src/com/android/gallery3d/common/BitmapCropTask.java b/WallpaperPicker/src/com/android/gallery3d/common/BitmapCropTask.java
new file mode 100644
index 000000000..45118bf45
--- /dev/null
+++ b/WallpaperPicker/src/com/android/gallery3d/common/BitmapCropTask.java
@@ -0,0 +1,405 @@
+/**
+ * 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.gallery3d.common;
+
+import android.app.WallpaperManager;
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.Bitmap.CompressFormat;
+import android.graphics.BitmapFactory;
+import android.graphics.BitmapRegionDecoder;
+import android.graphics.Canvas;
+import android.graphics.Matrix;
+import android.graphics.Paint;
+import android.graphics.Point;
+import android.graphics.Rect;
+import android.graphics.RectF;
+import android.net.Uri;
+import android.os.AsyncTask;
+import android.util.Log;
+
+import java.io.BufferedInputStream;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+
+public class BitmapCropTask extends AsyncTask<Void, Void, Boolean> {
+
+ public interface OnBitmapCroppedHandler {
+ public void onBitmapCropped(byte[] imageBytes);
+ }
+
+ private static final int DEFAULT_COMPRESS_QUALITY = 90;
+ private static final String LOGTAG = "BitmapCropTask";
+
+ Uri mInUri = null;
+ Context mContext;
+ String mInFilePath;
+ byte[] mInImageBytes;
+ int mInResId = 0;
+ RectF mCropBounds = null;
+ int mOutWidth, mOutHeight;
+ int mRotation;
+ boolean mSetWallpaper;
+ boolean mSaveCroppedBitmap;
+ Bitmap mCroppedBitmap;
+ Runnable mOnEndRunnable;
+ Resources mResources;
+ BitmapCropTask.OnBitmapCroppedHandler mOnBitmapCroppedHandler;
+ boolean mNoCrop;
+
+ public BitmapCropTask(Context c, String filePath,
+ RectF cropBounds, int rotation, int outWidth, int outHeight,
+ boolean setWallpaper, boolean saveCroppedBitmap, Runnable onEndRunnable) {
+ mContext = c;
+ mInFilePath = filePath;
+ init(cropBounds, rotation,
+ outWidth, outHeight, setWallpaper, saveCroppedBitmap, onEndRunnable);
+ }
+
+ public BitmapCropTask(byte[] imageBytes,
+ RectF cropBounds, int rotation, int outWidth, int outHeight,
+ boolean setWallpaper, boolean saveCroppedBitmap, Runnable onEndRunnable) {
+ mInImageBytes = imageBytes;
+ init(cropBounds, rotation,
+ outWidth, outHeight, setWallpaper, saveCroppedBitmap, onEndRunnable);
+ }
+
+ public BitmapCropTask(Context c, Uri inUri,
+ RectF cropBounds, int rotation, int outWidth, int outHeight,
+ boolean setWallpaper, boolean saveCroppedBitmap, Runnable onEndRunnable) {
+ mContext = c;
+ mInUri = inUri;
+ init(cropBounds, rotation,
+ outWidth, outHeight, setWallpaper, saveCroppedBitmap, onEndRunnable);
+ }
+
+ public BitmapCropTask(Context c, Resources res, int inResId,
+ RectF cropBounds, int rotation, int outWidth, int outHeight,
+ boolean setWallpaper, boolean saveCroppedBitmap, Runnable onEndRunnable) {
+ mContext = c;
+ mInResId = inResId;
+ mResources = res;
+ init(cropBounds, rotation,
+ outWidth, outHeight, setWallpaper, saveCroppedBitmap, onEndRunnable);
+ }
+
+ private void init(RectF cropBounds, int rotation, int outWidth, int outHeight,
+ boolean setWallpaper, boolean saveCroppedBitmap, Runnable onEndRunnable) {
+ mCropBounds = cropBounds;
+ mRotation = rotation;
+ mOutWidth = outWidth;
+ mOutHeight = outHeight;
+ mSetWallpaper = setWallpaper;
+ mSaveCroppedBitmap = saveCroppedBitmap;
+ mOnEndRunnable = onEndRunnable;
+ }
+
+ public void setOnBitmapCropped(BitmapCropTask.OnBitmapCroppedHandler handler) {
+ mOnBitmapCroppedHandler = handler;
+ }
+
+ public void setNoCrop(boolean value) {
+ mNoCrop = value;
+ }
+
+ public void setOnEndRunnable(Runnable onEndRunnable) {
+ mOnEndRunnable = onEndRunnable;
+ }
+
+ // Helper to setup input stream
+ private InputStream regenerateInputStream() {
+ if (mInUri == null && mInResId == 0 && mInFilePath == null && mInImageBytes == null) {
+ Log.w(LOGTAG, "cannot read original file, no input URI, resource ID, or " +
+ "image byte array given");
+ } else {
+ try {
+ if (mInUri != null) {
+ return new BufferedInputStream(
+ mContext.getContentResolver().openInputStream(mInUri));
+ } else if (mInFilePath != null) {
+ return mContext.openFileInput(mInFilePath);
+ } else if (mInImageBytes != null) {
+ return new BufferedInputStream(new ByteArrayInputStream(mInImageBytes));
+ } else {
+ return new BufferedInputStream(mResources.openRawResource(mInResId));
+ }
+ } catch (FileNotFoundException e) {
+ Log.w(LOGTAG, "cannot read file: " + mInUri.toString(), e);
+ }
+ }
+ return null;
+ }
+
+ public Point getImageBounds() {
+ InputStream is = regenerateInputStream();
+ if (is != null) {
+ BitmapFactory.Options options = new BitmapFactory.Options();
+ options.inJustDecodeBounds = true;
+ BitmapFactory.decodeStream(is, null, options);
+ Utils.closeSilently(is);
+ if (options.outWidth != 0 && options.outHeight != 0) {
+ return new Point(options.outWidth, options.outHeight);
+ }
+ }
+ return null;
+ }
+
+ public void setCropBounds(RectF cropBounds) {
+ mCropBounds = cropBounds;
+ }
+
+ public Bitmap getCroppedBitmap() {
+ return mCroppedBitmap;
+ }
+ public boolean cropBitmap() {
+ boolean failure = false;
+
+
+ WallpaperManager wallpaperManager = null;
+ if (mSetWallpaper) {
+ wallpaperManager = WallpaperManager.getInstance(mContext.getApplicationContext());
+ }
+
+
+ if (mSetWallpaper && mNoCrop) {
+ try {
+ InputStream is = regenerateInputStream();
+ if (is != null) {
+ wallpaperManager.setStream(is);
+ Utils.closeSilently(is);
+ }
+ } catch (IOException e) {
+ Log.w(LOGTAG, "cannot write stream to wallpaper", e);
+ failure = true;
+ }
+ return !failure;
+ } else {
+ // Find crop bounds (scaled to original image size)
+ Rect roundedTrueCrop = new Rect();
+ Matrix rotateMatrix = new Matrix();
+ Matrix inverseRotateMatrix = new Matrix();
+
+ Point bounds = getImageBounds();
+ if (mRotation > 0) {
+ rotateMatrix.setRotate(mRotation);
+ inverseRotateMatrix.setRotate(-mRotation);
+
+ mCropBounds.roundOut(roundedTrueCrop);
+ mCropBounds = new RectF(roundedTrueCrop);
+
+ if (bounds == null) {
+ Log.w(LOGTAG, "cannot get bounds for image");
+ failure = true;
+ return false;
+ }
+
+ float[] rotatedBounds = new float[] { bounds.x, bounds.y };
+ rotateMatrix.mapPoints(rotatedBounds);
+ rotatedBounds[0] = Math.abs(rotatedBounds[0]);
+ rotatedBounds[1] = Math.abs(rotatedBounds[1]);
+
+ mCropBounds.offset(-rotatedBounds[0]/2, -rotatedBounds[1]/2);
+ inverseRotateMatrix.mapRect(mCropBounds);
+ mCropBounds.offset(bounds.x/2, bounds.y/2);
+
+ }
+
+ mCropBounds.roundOut(roundedTrueCrop);
+
+ if (roundedTrueCrop.width() <= 0 || roundedTrueCrop.height() <= 0) {
+ Log.w(LOGTAG, "crop has bad values for full size image");
+ failure = true;
+ return false;
+ }
+
+ // See how much we're reducing the size of the image
+ int scaleDownSampleSize = Math.max(1, Math.min(roundedTrueCrop.width() / mOutWidth,
+ roundedTrueCrop.height() / mOutHeight));
+ // Attempt to open a region decoder
+ BitmapRegionDecoder decoder = null;
+ InputStream is = null;
+ try {
+ is = regenerateInputStream();
+ if (is == null) {
+ Log.w(LOGTAG, "cannot get input stream for uri=" + mInUri.toString());
+ failure = true;
+ return false;
+ }
+ decoder = BitmapRegionDecoder.newInstance(is, false);
+ Utils.closeSilently(is);
+ } catch (IOException e) {
+ Log.w(LOGTAG, "cannot open region decoder for file: " + mInUri.toString(), e);
+ } finally {
+ Utils.closeSilently(is);
+ is = null;
+ }
+
+ Bitmap crop = null;
+ if (decoder != null) {
+ // Do region decoding to get crop bitmap
+ BitmapFactory.Options options = new BitmapFactory.Options();
+ if (scaleDownSampleSize > 1) {
+ options.inSampleSize = scaleDownSampleSize;
+ }
+ crop = decoder.decodeRegion(roundedTrueCrop, options);
+ decoder.recycle();
+ }
+
+ if (crop == null) {
+ // BitmapRegionDecoder has failed, try to crop in-memory
+ is = regenerateInputStream();
+ Bitmap fullSize = null;
+ if (is != null) {
+ BitmapFactory.Options options = new BitmapFactory.Options();
+ if (scaleDownSampleSize > 1) {
+ options.inSampleSize = scaleDownSampleSize;
+ }
+ fullSize = BitmapFactory.decodeStream(is, null, options);
+ Utils.closeSilently(is);
+ }
+ if (fullSize != null) {
+ // Find out the true sample size that was used by the decoder
+ scaleDownSampleSize = bounds.x / fullSize.getWidth();
+ mCropBounds.left /= scaleDownSampleSize;
+ mCropBounds.top /= scaleDownSampleSize;
+ mCropBounds.bottom /= scaleDownSampleSize;
+ mCropBounds.right /= scaleDownSampleSize;
+ mCropBounds.roundOut(roundedTrueCrop);
+
+ // Adjust values to account for issues related to rounding
+ if (roundedTrueCrop.width() > fullSize.getWidth()) {
+ // Adjust the width
+ 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;
+ }
+ 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;
+ }
+
+ crop = Bitmap.createBitmap(fullSize, roundedTrueCrop.left,
+ roundedTrueCrop.top, roundedTrueCrop.width(),
+ roundedTrueCrop.height());
+ }
+ }
+
+ if (crop == null) {
+ Log.w(LOGTAG, "cannot decode file: " + mInUri.toString());
+ failure = true;
+ return false;
+ }
+ if (mOutWidth > 0 && mOutHeight > 0 || mRotation > 0) {
+ float[] dimsAfter = new float[] { crop.getWidth(), crop.getHeight() };
+ rotateMatrix.mapPoints(dimsAfter);
+ dimsAfter[0] = Math.abs(dimsAfter[0]);
+ dimsAfter[1] = Math.abs(dimsAfter[1]);
+
+ if (!(mOutWidth > 0 && mOutHeight > 0)) {
+ mOutWidth = Math.round(dimsAfter[0]);
+ mOutHeight = Math.round(dimsAfter[1]);
+ }
+
+ RectF cropRect = new RectF(0, 0, dimsAfter[0], dimsAfter[1]);
+ RectF returnRect = new RectF(0, 0, mOutWidth, mOutHeight);
+
+ Matrix m = new Matrix();
+ if (mRotation == 0) {
+ m.setRectToRect(cropRect, returnRect, Matrix.ScaleToFit.FILL);
+ } else {
+ Matrix m1 = new Matrix();
+ m1.setTranslate(-crop.getWidth() / 2f, -crop.getHeight() / 2f);
+ Matrix m2 = new Matrix();
+ m2.setRotate(mRotation);
+ Matrix m3 = new Matrix();
+ m3.setTranslate(dimsAfter[0] / 2f, dimsAfter[1] / 2f);
+ Matrix m4 = new Matrix();
+ m4.setRectToRect(cropRect, returnRect, Matrix.ScaleToFit.FILL);
+
+ Matrix c1 = new Matrix();
+ c1.setConcat(m2, m1);
+ Matrix c2 = new Matrix();
+ c2.setConcat(m4, m3);
+ m.setConcat(c2, c1);
+ }
+
+ Bitmap tmp = Bitmap.createBitmap((int) returnRect.width(),
+ (int) returnRect.height(), Bitmap.Config.ARGB_8888);
+ if (tmp != null) {
+ Canvas c = new Canvas(tmp);
+ Paint p = new Paint();
+ p.setFilterBitmap(true);
+ c.drawBitmap(crop, m, p);
+ crop = tmp;
+ }
+ }
+
+ if (mSaveCroppedBitmap) {
+ mCroppedBitmap = crop;
+ }
+
+ // Compress to byte array
+ ByteArrayOutputStream tmpOut = new ByteArrayOutputStream(2048);
+ if (crop.compress(CompressFormat.JPEG, DEFAULT_COMPRESS_QUALITY, tmpOut)) {
+ // If we need to set to the wallpaper, set it
+ if (mSetWallpaper && wallpaperManager != null) {
+ try {
+ byte[] outByteArray = tmpOut.toByteArray();
+ wallpaperManager.setStream(new ByteArrayInputStream(outByteArray));
+ if (mOnBitmapCroppedHandler != null) {
+ mOnBitmapCroppedHandler.onBitmapCropped(outByteArray);
+ }
+ } catch (IOException e) {
+ Log.w(LOGTAG, "cannot write stream to wallpaper", e);
+ failure = true;
+ }
+ }
+ } else {
+ Log.w(LOGTAG, "cannot compress bitmap");
+ failure = true;
+ }
+ }
+ return !failure; // True if any of the operations failed
+ }
+
+ @Override
+ protected Boolean doInBackground(Void... params) {
+ return cropBitmap();
+ }
+
+ @Override
+ protected void onPostExecute(Boolean result) {
+ if (mOnEndRunnable != null) {
+ mOnEndRunnable.run();
+ }
+ }
+} \ No newline at end of file
diff --git a/WallpaperPicker/src/com/android/gallery3d/common/BitmapUtils.java b/WallpaperPicker/src/com/android/gallery3d/common/BitmapUtils.java
index a671ed2b9..9ac5c1bf7 100644
--- a/WallpaperPicker/src/com/android/gallery3d/common/BitmapUtils.java
+++ b/WallpaperPicker/src/com/android/gallery3d/common/BitmapUtils.java
@@ -16,87 +16,24 @@
package com.android.gallery3d.common;
-import android.graphics.Bitmap;
-import android.graphics.Bitmap.CompressFormat;
-import android.graphics.BitmapFactory;
-import android.graphics.Canvas;
-import android.graphics.Matrix;
-import android.graphics.Paint;
-import android.os.Build;
-import android.util.FloatMath;
+import android.content.Context;
+import android.content.res.Resources;
+import android.net.Uri;
import android.util.Log;
-import java.io.ByteArrayOutputStream;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
+import com.android.gallery3d.exif.ExifInterface;
-public class BitmapUtils {
- private static final String TAG = "BitmapUtils";
- private static final int DEFAULT_JPEG_QUALITY = 90;
- public static final int UNCONSTRAINED = -1;
-
- private BitmapUtils(){}
-
- /*
- * Compute the sample size as a function of minSideLength
- * and maxNumOfPixels.
- * minSideLength is used to specify that minimal width or height of a
- * bitmap.
- * maxNumOfPixels is used to specify the maximal size in pixels that is
- * tolerable in terms of memory usage.
- *
- * The function returns a sample size based on the constraints.
- * Both size and minSideLength can be passed in as UNCONSTRAINED,
- * which indicates no care of the corresponding constraint.
- * The functions prefers returning a sample size that
- * generates a smaller bitmap, unless minSideLength = UNCONSTRAINED.
- *
- * Also, the function rounds up the sample size to a power of 2 or multiple
- * of 8 because BitmapFactory only honors sample size this way.
- * For example, BitmapFactory downsamples an image by 2 even though the
- * request is 3. So we round up the sample size to avoid OOM.
- */
- public static int computeSampleSize(int width, int height,
- int minSideLength, int maxNumOfPixels) {
- int initialSize = computeInitialSampleSize(
- width, height, minSideLength, maxNumOfPixels);
-
- return initialSize <= 8
- ? Utils.nextPowerOf2(initialSize)
- : (initialSize + 7) / 8 * 8;
- }
-
- private static int computeInitialSampleSize(int w, int h,
- int minSideLength, int maxNumOfPixels) {
- if (maxNumOfPixels == UNCONSTRAINED
- && minSideLength == UNCONSTRAINED) return 1;
-
- int lowerBound = (maxNumOfPixels == UNCONSTRAINED) ? 1 :
- (int) FloatMath.ceil(FloatMath.sqrt((float) (w * h) / maxNumOfPixels));
-
- if (minSideLength == UNCONSTRAINED) {
- return lowerBound;
- } else {
- int sampleSize = Math.min(w / minSideLength, h / minSideLength);
- return Math.max(sampleSize, lowerBound);
- }
- }
+import java.io.BufferedInputStream;
+import java.io.IOException;
+import java.io.InputStream;
- // This computes a sample size which makes the longer side at least
- // minSideLength long. If that's not possible, return 1.
- public static int computeSampleSizeLarger(int w, int h,
- int minSideLength) {
- int initialSize = Math.max(w / minSideLength, h / minSideLength);
- if (initialSize <= 1) return 1;
+public class BitmapUtils {
- return initialSize <= 8
- ? Utils.prevPowerOf2(initialSize)
- : initialSize / 8 * 8;
- }
+ private static final String TAG = "BitmapUtils";
// Find the min x that 1 / x >= scale
public static int computeSampleSizeLarger(float scale) {
- int initialSize = (int) FloatMath.floor(1f / scale);
+ int initialSize = (int) Math.floor(1f / scale);
if (initialSize <= 1) return 1;
return initialSize <= 8
@@ -104,157 +41,41 @@ public class BitmapUtils {
: initialSize / 8 * 8;
}
- // Find the max x that 1 / x <= scale.
- public static int computeSampleSize(float scale) {
- Utils.assertTrue(scale > 0);
- int initialSize = Math.max(1, (int) FloatMath.ceil(1 / scale));
- return initialSize <= 8
- ? Utils.nextPowerOf2(initialSize)
- : (initialSize + 7) / 8 * 8;
- }
-
- public static Bitmap resizeBitmapByScale(
- Bitmap bitmap, float scale, boolean recycle) {
- int width = Math.round(bitmap.getWidth() * scale);
- int height = Math.round(bitmap.getHeight() * scale);
- if (width == bitmap.getWidth()
- && height == bitmap.getHeight()) return bitmap;
- Bitmap target = Bitmap.createBitmap(width, height, getConfig(bitmap));
- Canvas canvas = new Canvas(target);
- canvas.scale(scale, scale);
- Paint paint = new Paint(Paint.FILTER_BITMAP_FLAG | Paint.DITHER_FLAG);
- canvas.drawBitmap(bitmap, 0, 0, paint);
- if (recycle) bitmap.recycle();
- return target;
+ public static int getRotationFromExif(Context context, Uri uri) {
+ return BitmapUtils.getRotationFromExifHelper(null, 0, context, uri);
}
- private static Bitmap.Config getConfig(Bitmap bitmap) {
- Bitmap.Config config = bitmap.getConfig();
- if (config == null) {
- config = Bitmap.Config.ARGB_8888;
- }
- return config;
+ public static int getRotationFromExif(Resources res, int resId) {
+ return BitmapUtils.getRotationFromExifHelper(res, resId, null, null);
}
- public static Bitmap resizeDownBySideLength(
- Bitmap bitmap, int maxLength, boolean recycle) {
- int srcWidth = bitmap.getWidth();
- int srcHeight = bitmap.getHeight();
- float scale = Math.min(
- (float) maxLength / srcWidth, (float) maxLength / srcHeight);
- if (scale >= 1.0f) return bitmap;
- return resizeBitmapByScale(bitmap, scale, recycle);
- }
-
- public static Bitmap resizeAndCropCenter(Bitmap bitmap, int size, boolean recycle) {
- int w = bitmap.getWidth();
- int h = bitmap.getHeight();
- if (w == size && h == size) return bitmap;
-
- // scale the image so that the shorter side equals to the target;
- // the longer side will be center-cropped.
- float scale = (float) size / Math.min(w, h);
-
- Bitmap target = Bitmap.createBitmap(size, size, getConfig(bitmap));
- int width = Math.round(scale * bitmap.getWidth());
- int height = Math.round(scale * bitmap.getHeight());
- Canvas canvas = new Canvas(target);
- canvas.translate((size - width) / 2f, (size - height) / 2f);
- canvas.scale(scale, scale);
- Paint paint = new Paint(Paint.FILTER_BITMAP_FLAG | Paint.DITHER_FLAG);
- canvas.drawBitmap(bitmap, 0, 0, paint);
- if (recycle) bitmap.recycle();
- return target;
- }
-
- public static void recycleSilently(Bitmap bitmap) {
- if (bitmap == null) return;
- try {
- bitmap.recycle();
- } catch (Throwable t) {
- Log.w(TAG, "unable recycle bitmap", t);
- }
- }
-
- public static Bitmap rotateBitmap(Bitmap source, int rotation, boolean recycle) {
- if (rotation == 0) return source;
- int w = source.getWidth();
- int h = source.getHeight();
- Matrix m = new Matrix();
- m.postRotate(rotation);
- Bitmap bitmap = Bitmap.createBitmap(source, 0, 0, w, h, m, true);
- if (recycle) source.recycle();
- return bitmap;
- }
-
- public static Bitmap createVideoThumbnail(String filePath) {
- // MediaMetadataRetriever is available on API Level 8
- // but is hidden until API Level 10
- Class<?> clazz = null;
- Object instance = null;
+ private static int getRotationFromExifHelper(Resources res, int resId, Context context, Uri uri) {
+ ExifInterface ei = new ExifInterface();
+ InputStream is = null;
+ BufferedInputStream bis = null;
try {
- clazz = Class.forName("android.media.MediaMetadataRetriever");
- instance = clazz.newInstance();
-
- Method method = clazz.getMethod("setDataSource", String.class);
- method.invoke(instance, filePath);
-
- // The method name changes between API Level 9 and 10.
- if (Build.VERSION.SDK_INT <= 9) {
- return (Bitmap) clazz.getMethod("captureFrame").invoke(instance);
+ if (uri != null) {
+ is = context.getContentResolver().openInputStream(uri);
+ bis = new BufferedInputStream(is);
+ ei.readExif(bis);
} else {
- byte[] data = (byte[]) clazz.getMethod("getEmbeddedPicture").invoke(instance);
- if (data != null) {
- Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
- if (bitmap != null) return bitmap;
- }
- return (Bitmap) clazz.getMethod("getFrameAtTime").invoke(instance);
+ is = res.openRawResource(resId);
+ bis = new BufferedInputStream(is);
+ ei.readExif(bis);
}
- } catch (IllegalArgumentException ex) {
- // Assume this is a corrupt video file
- } catch (RuntimeException ex) {
- // Assume this is a corrupt video file.
- } catch (InstantiationException e) {
- Log.e(TAG, "createVideoThumbnail", e);
- } catch (InvocationTargetException e) {
- Log.e(TAG, "createVideoThumbnail", e);
- } catch (ClassNotFoundException e) {
- Log.e(TAG, "createVideoThumbnail", e);
- } catch (NoSuchMethodException e) {
- Log.e(TAG, "createVideoThumbnail", e);
- } catch (IllegalAccessException e) {
- Log.e(TAG, "createVideoThumbnail", e);
- } finally {
- try {
- if (instance != null) {
- clazz.getMethod("release").invoke(instance);
- }
- } catch (Exception ignored) {
+ Integer ori = ei.getTagIntValue(ExifInterface.TAG_ORIENTATION);
+ if (ori != null) {
+ return ExifInterface.getRotationForOrientationValue(ori.shortValue());
}
+ } catch (IOException e) {
+ Log.w(TAG, "Getting exif data failed", e);
+ } catch (NullPointerException e) {
+ // Sometimes the ExifInterface has an internal NPE if Exif data isn't valid
+ Log.w(TAG, "Getting exif data failed", e);
+ } finally {
+ Utils.closeSilently(bis);
+ Utils.closeSilently(is);
}
- return null;
- }
-
- public static byte[] compressToBytes(Bitmap bitmap) {
- return compressToBytes(bitmap, DEFAULT_JPEG_QUALITY);
- }
-
- public static byte[] compressToBytes(Bitmap bitmap, int quality) {
- ByteArrayOutputStream baos = new ByteArrayOutputStream(65536);
- bitmap.compress(CompressFormat.JPEG, quality, baos);
- return baos.toByteArray();
- }
-
- public static boolean isSupportedByRegionDecoder(String mimeType) {
- if (mimeType == null) return false;
- mimeType = mimeType.toLowerCase();
- return mimeType.startsWith("image/") &&
- (!mimeType.equals("image/gif") && !mimeType.endsWith("bmp"));
- }
-
- public static boolean isRotationSupported(String mimeType) {
- if (mimeType == null) return false;
- mimeType = mimeType.toLowerCase();
- return mimeType.equals("image/jpeg");
+ return 0;
}
}
diff --git a/WallpaperPicker/src/com/android/gallery3d/common/Utils.java b/WallpaperPicker/src/com/android/gallery3d/common/Utils.java
index 614a081c8..8466c22cb 100644
--- a/WallpaperPicker/src/com/android/gallery3d/common/Utils.java
+++ b/WallpaperPicker/src/com/android/gallery3d/common/Utils.java
@@ -16,32 +16,16 @@
package com.android.gallery3d.common;
-import android.content.Context;
-import android.content.pm.PackageInfo;
-import android.content.pm.PackageManager.NameNotFoundException;
import android.database.Cursor;
-import android.os.Build;
+import android.graphics.RectF;
import android.os.ParcelFileDescriptor;
-import android.text.TextUtils;
import android.util.Log;
import java.io.Closeable;
import java.io.IOException;
-import java.io.InterruptedIOException;
public class Utils {
private static final String TAG = "Utils";
- private static final String DEBUG_TAG = "GalleryDebug";
-
- private static final long POLY64REV = 0x95AC9329AC4BC9B5L;
- private static final long INITIALCRC = 0xFFFFFFFFFFFFFFFFL;
-
- private static long[] sCrcTable = new long[256];
-
- private static final boolean IS_DEBUG_BUILD =
- Build.TYPE.equals("eng") || Build.TYPE.equals("userdebug");
-
- private static final String MASK_STRING = "********************************";
// Throws AssertionError if the input is false.
public static void assertTrue(boolean cond) {
@@ -50,28 +34,6 @@ public class Utils {
}
}
- // Throws AssertionError with the message. We had a method having the form
- // assertTrue(boolean cond, String message, Object ... args);
- // However a call to that method will cause memory allocation even if the
- // condition is false (due to autoboxing generated by "Object ... args"),
- // so we don't use that anymore.
- public static void fail(String message, Object ... args) {
- throw new AssertionError(
- args.length == 0 ? message : String.format(message, args));
- }
-
- // Throws NullPointerException if the input is null.
- public static <T> T checkNotNull(T object) {
- if (object == null) throw new NullPointerException();
- return object;
- }
-
- // Returns true if two input Object are both null or equal
- // to each other.
- public static boolean equals(Object a, Object b) {
- return (a == b) || (a == null ? false : a.equals(b));
- }
-
// Returns the next power of two.
// Returns the input if it is already power of 2.
// Throws IllegalArgumentException if the input is <= 0 or
@@ -102,87 +64,6 @@ public class Utils {
return x;
}
- // Returns the input value x clamped to the range [min, max].
- public static float clamp(float x, float min, float max) {
- if (x > max) return max;
- if (x < min) return min;
- return x;
- }
-
- // Returns the input value x clamped to the range [min, max].
- public static long clamp(long x, long min, long max) {
- if (x > max) return max;
- if (x < min) return min;
- return x;
- }
-
- public static boolean isOpaque(int color) {
- return color >>> 24 == 0xFF;
- }
-
- public static void swap(int[] array, int i, int j) {
- int temp = array[i];
- array[i] = array[j];
- array[j] = temp;
- }
-
- /**
- * A function thats returns a 64-bit crc for string
- *
- * @param in input string
- * @return a 64-bit crc value
- */
- public static final long crc64Long(String in) {
- if (in == null || in.length() == 0) {
- return 0;
- }
- return crc64Long(getBytes(in));
- }
-
- static {
- // http://bioinf.cs.ucl.ac.uk/downloads/crc64/crc64.c
- long part;
- for (int i = 0; i < 256; i++) {
- part = i;
- for (int j = 0; j < 8; j++) {
- long x = ((int) part & 1) != 0 ? POLY64REV : 0;
- part = (part >> 1) ^ x;
- }
- sCrcTable[i] = part;
- }
- }
-
- public static final long crc64Long(byte[] buffer) {
- long crc = INITIALCRC;
- for (int k = 0, n = buffer.length; k < n; ++k) {
- crc = sCrcTable[(((int) crc) ^ buffer[k]) & 0xff] ^ (crc >> 8);
- }
- return crc;
- }
-
- public static byte[] getBytes(String in) {
- byte[] result = new byte[in.length() * 2];
- int output = 0;
- for (char ch : in.toCharArray()) {
- result[output++] = (byte) (ch & 0xFF);
- result[output++] = (byte) (ch >> 8);
- }
- return result;
- }
-
- public static void closeSilently(Closeable c) {
- if (c == null) return;
- try {
- c.close();
- } catch (IOException t) {
- Log.w(TAG, "close fail ", t);
- }
- }
-
- public static int compare(long a, long b) {
- return a < b ? -1 : a == b ? 0 : 1;
- }
-
public static int ceilLog2(float value) {
int i;
for (i = 0; i < 31; i++) {
@@ -199,6 +80,15 @@ public class Utils {
return i - 1;
}
+ public static void closeSilently(Closeable c) {
+ if (c == null) return;
+ try {
+ c.close();
+ } catch (IOException t) {
+ Log.w(TAG, "close fail ", t);
+ }
+ }
+
public static void closeSilently(ParcelFileDescriptor fd) {
try {
if (fd != null) fd.close();
@@ -215,126 +105,25 @@ public class Utils {
}
}
- public static float interpolateAngle(
- float source, float target, float progress) {
- // interpolate the angle from source to target
- // We make the difference in the range of [-179, 180], this is the
- // shortest path to change source to target.
- float diff = target - source;
- if (diff < 0) diff += 360f;
- if (diff > 180) diff -= 360f;
-
- float result = source + diff * progress;
- return result < 0 ? result + 360f : result;
- }
-
- public static float interpolateScale(
- float source, float target, float progress) {
- return source + progress * (target - source);
- }
-
- public static String ensureNotNull(String value) {
- return value == null ? "" : value;
- }
-
- public static float parseFloatSafely(String content, float defaultValue) {
- if (content == null) return defaultValue;
- try {
- return Float.parseFloat(content);
- } catch (NumberFormatException e) {
- return defaultValue;
- }
- }
-
- public static int parseIntSafely(String content, int defaultValue) {
- if (content == null) return defaultValue;
- try {
- return Integer.parseInt(content);
- } catch (NumberFormatException e) {
- return defaultValue;
- }
- }
-
- public static boolean isNullOrEmpty(String exifMake) {
- return TextUtils.isEmpty(exifMake);
- }
-
- public static void waitWithoutInterrupt(Object object) {
- try {
- object.wait();
- } catch (InterruptedException e) {
- Log.w(TAG, "unexpected interrupt: " + object);
- }
- }
-
- public static boolean handleInterrruptedException(Throwable e) {
- // A helper to deal with the interrupt exception
- // If an interrupt detected, we will setup the bit again.
- if (e instanceof InterruptedIOException
- || e instanceof InterruptedException) {
- Thread.currentThread().interrupt();
- return true;
- }
- return false;
- }
-
- /**
- * @return String with special XML characters escaped.
- */
- public static String escapeXml(String s) {
- StringBuilder sb = new StringBuilder();
- for (int i = 0, len = s.length(); i < len; ++i) {
- char c = s.charAt(i);
- switch (c) {
- case '<': sb.append("&lt;"); break;
- case '>': sb.append("&gt;"); break;
- case '\"': sb.append("&quot;"); break;
- case '\'': sb.append("&#039;"); break;
- case '&': sb.append("&amp;"); break;
- default: sb.append(c);
- }
- }
- return sb.toString();
- }
-
- public static String getUserAgent(Context context) {
- PackageInfo packageInfo;
- try {
- packageInfo = context.getPackageManager().getPackageInfo(context.getPackageName(), 0);
- } catch (NameNotFoundException e) {
- throw new IllegalStateException("getPackageInfo failed");
- }
- return String.format("%s/%s; %s/%s/%s/%s; %s/%s/%s",
- packageInfo.packageName,
- packageInfo.versionName,
- Build.BRAND,
- Build.DEVICE,
- Build.MODEL,
- Build.ID,
- Build.VERSION.SDK_INT,
- Build.VERSION.RELEASE,
- Build.VERSION.INCREMENTAL);
- }
-
- public static String[] copyOf(String[] source, int newSize) {
- String[] result = new String[newSize];
- newSize = Math.min(source.length, newSize);
- System.arraycopy(source, 0, result, 0, newSize);
- return result;
- }
-
- // Mask information for debugging only. It returns <code>info.toString()</code> directly
- // for debugging build (i.e., 'eng' and 'userdebug') and returns a mask ("****")
- // in release build to protect the information (e.g. for privacy issue).
- public static String maskDebugInfo(Object info) {
- if (info == null) return null;
- String s = info.toString();
- int length = Math.min(s.length(), MASK_STRING.length());
- return IS_DEBUG_BUILD ? s : MASK_STRING.substring(0, length);
- }
-
- // This method should be ONLY used for debugging.
- public static void debug(String message, Object ... args) {
- Log.v(DEBUG_TAG, String.format(message, args));
+ public static RectF getMaxCropRect(
+ int inWidth, int inHeight, int outWidth, int outHeight, boolean leftAligned) {
+ RectF cropRect = new RectF();
+ // Get a crop rect that will fit this
+ if (inWidth / (float) inHeight > outWidth / (float) outHeight) {
+ cropRect.top = 0;
+ cropRect.bottom = inHeight;
+ cropRect.left = (inWidth - (outWidth / (float) outHeight) * inHeight) / 2;
+ cropRect.right = inWidth - cropRect.left;
+ if (leftAligned) {
+ cropRect.right -= cropRect.left;
+ cropRect.left = 0;
+ }
+ } else {
+ cropRect.left = 0;
+ cropRect.right = inWidth;
+ cropRect.top = (inHeight - (outHeight / (float) outWidth) * inWidth) / 2;
+ cropRect.bottom = inHeight - cropRect.top;
+ }
+ return cropRect;
}
}
diff --git a/WallpaperPicker/src/com/android/gallery3d/exif/ExifInterface.java b/WallpaperPicker/src/com/android/gallery3d/exif/ExifInterface.java
index a1cf0fc85..9247e879f 100644
--- a/WallpaperPicker/src/com/android/gallery3d/exif/ExifInterface.java
+++ b/WallpaperPicker/src/com/android/gallery3d/exif/ExifInterface.java
@@ -1247,7 +1247,7 @@ public class ExifInterface {
if (l == null || l.length <= 0) {
return null;
}
- return new Long(l[0]);
+ return Long.valueOf(l[0]);
}
/**
@@ -1266,7 +1266,7 @@ public class ExifInterface {
if (l == null || l.length <= 0) {
return null;
}
- return new Integer(l[0]);
+ return Integer.valueOf(l[0]);
}
/**
@@ -1285,7 +1285,7 @@ public class ExifInterface {
if (l == null || l.length <= 0) {
return null;
}
- return new Byte(l[0]);
+ return Byte.valueOf(l[0]);
}
/**
diff --git a/WallpaperPicker/src/com/android/gallery3d/glrenderer/BasicTexture.java b/WallpaperPicker/src/com/android/gallery3d/glrenderer/BasicTexture.java
index 2e77b903f..0f3efb727 100644
--- a/WallpaperPicker/src/com/android/gallery3d/glrenderer/BasicTexture.java
+++ b/WallpaperPicker/src/com/android/gallery3d/glrenderer/BasicTexture.java
@@ -27,7 +27,6 @@ import java.util.WeakHashMap;
// If a BasicTexture is loaded into GL memory, it has a GL texture id.
public abstract class BasicTexture implements Texture {
- @SuppressWarnings("unused")
private static final String TAG = "BasicTexture";
protected static final int UNSPECIFIED = -1;
diff --git a/WallpaperPicker/src/com/android/gallery3d/glrenderer/BitmapTexture.java b/WallpaperPicker/src/com/android/gallery3d/glrenderer/BitmapTexture.java
index 100b0b3b9..f8b01cb42 100644
--- a/WallpaperPicker/src/com/android/gallery3d/glrenderer/BitmapTexture.java
+++ b/WallpaperPicker/src/com/android/gallery3d/glrenderer/BitmapTexture.java
@@ -18,7 +18,7 @@ package com.android.gallery3d.glrenderer;
import android.graphics.Bitmap;
-import junit.framework.Assert;
+import com.android.gallery3d.common.Utils;
// BitmapTexture is a texture whose content is specified by a fixed Bitmap.
//
@@ -34,7 +34,7 @@ public class BitmapTexture extends UploadedTexture {
public BitmapTexture(Bitmap bitmap, boolean hasBorder) {
super(hasBorder);
- Assert.assertTrue(bitmap != null && !bitmap.isRecycled());
+ Utils.assertTrue(bitmap != null && !bitmap.isRecycled());
mContentBitmap = bitmap;
}
diff --git a/WallpaperPicker/src/com/android/gallery3d/glrenderer/GLES20Canvas.java b/WallpaperPicker/src/com/android/gallery3d/glrenderer/GLES20Canvas.java
index 4ead1315e..933260b48 100644
--- a/WallpaperPicker/src/com/android/gallery3d/glrenderer/GLES20Canvas.java
+++ b/WallpaperPicker/src/com/android/gallery3d/glrenderer/GLES20Canvas.java
@@ -23,8 +23,6 @@ import android.opengl.GLUtils;
import android.opengl.Matrix;
import android.util.Log;
-import com.android.gallery3d.util.IntArray;
-
import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
@@ -698,6 +696,7 @@ public class GLES20Canvas implements GLCanvas {
}
private void prepareTexture(BasicTexture texture, int program, ShaderParameter[] params) {
+ deleteRecycledResources();
GLES20.glUseProgram(program);
checkError();
enableBlending(!texture.isOpaque() || getAlpha() < OPAQUE_ALPHA);
diff --git a/WallpaperPicker/src/com/android/gallery3d/glrenderer/GLPaint.java b/WallpaperPicker/src/com/android/gallery3d/glrenderer/GLPaint.java
index 16b220690..b26e9ab29 100644
--- a/WallpaperPicker/src/com/android/gallery3d/glrenderer/GLPaint.java
+++ b/WallpaperPicker/src/com/android/gallery3d/glrenderer/GLPaint.java
@@ -16,7 +16,7 @@
package com.android.gallery3d.glrenderer;
-import junit.framework.Assert;
+import com.android.gallery3d.common.Utils;
public class GLPaint {
private float mLineWidth = 1f;
@@ -31,7 +31,7 @@ public class GLPaint {
}
public void setLineWidth(float width) {
- Assert.assertTrue(width >= 0);
+ Utils.assertTrue(width >= 0);
mLineWidth = width;
}
diff --git a/WallpaperPicker/src/com/android/gallery3d/util/IntArray.java b/WallpaperPicker/src/com/android/gallery3d/glrenderer/IntArray.java
index 2c4dc2c83..f123624d6 100644
--- a/WallpaperPicker/src/com/android/gallery3d/util/IntArray.java
+++ b/WallpaperPicker/src/com/android/gallery3d/glrenderer/IntArray.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.gallery3d.util;
+package com.android.gallery3d.glrenderer;
public class IntArray {
private static final int INIT_CAPACITY = 8;
diff --git a/WallpaperPicker/src/com/android/gallery3d/glrenderer/UploadedTexture.java b/WallpaperPicker/src/com/android/gallery3d/glrenderer/UploadedTexture.java
index f41a979b7..8075bf868 100644
--- a/WallpaperPicker/src/com/android/gallery3d/glrenderer/UploadedTexture.java
+++ b/WallpaperPicker/src/com/android/gallery3d/glrenderer/UploadedTexture.java
@@ -20,7 +20,8 @@ import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.opengl.GLUtils;
-import junit.framework.Assert;
+import com.android.gallery3d.common.Utils;
+import com.android.launcher3.util.Thunk;
import java.util.HashMap;
@@ -82,7 +83,7 @@ public abstract class UploadedTexture extends BasicTexture {
return mIsUploading;
}
- private static class BorderKey implements Cloneable {
+ @Thunk static class BorderKey implements Cloneable {
public boolean vertical;
public Config config;
public int length;
@@ -144,7 +145,7 @@ public abstract class UploadedTexture extends BasicTexture {
}
private void freeBitmap() {
- Assert.assertTrue(mBitmap != null);
+ Utils.assertTrue(mBitmap != null);
onFreeBitmap(mBitmap);
mBitmap = null;
}
@@ -219,7 +220,7 @@ public abstract class UploadedTexture extends BasicTexture {
int texWidth = getTextureWidth();
int texHeight = getTextureHeight();
- Assert.assertTrue(bWidth <= texWidth && bHeight <= texHeight);
+ Utils.assertTrue(bWidth <= texWidth && bHeight <= texHeight);
// Upload the bitmap to a new texture.
mId = canvas.getGLId().generateTexture();
diff --git a/WallpaperPicker/src/com/android/launcher3/CropView.java b/WallpaperPicker/src/com/android/launcher3/CropView.java
index 578b8eafd..50f779add 100644
--- a/WallpaperPicker/src/com/android/launcher3/CropView.java
+++ b/WallpaperPicker/src/com/android/launcher3/CropView.java
@@ -21,7 +21,6 @@ import android.graphics.Matrix;
import android.graphics.Point;
import android.graphics.RectF;
import android.util.AttributeSet;
-import android.util.FloatMath;
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;
import android.view.ScaleGestureDetector.OnScaleGestureListener;
@@ -300,12 +299,12 @@ public class CropView extends TiledImageView implements OnScaleGestureListener {
adjustment[0] = (edges.right - getWidth()) / scale;
}
if (edges.top > 0) {
- adjustment[1] = FloatMath.ceil(edges.top / scale);
+ adjustment[1] = (float) Math.ceil(edges.top / scale);
} else if (edges.bottom < getHeight()) {
adjustment[1] = (edges.bottom - getHeight()) / scale;
}
for (int dim = 0; dim <= 1; dim++) {
- if (coef[dim] > 0) adjustment[dim] = FloatMath.ceil(adjustment[dim]);
+ if (coef[dim] > 0) adjustment[dim] = (float) Math.ceil(adjustment[dim]);
}
mInverseRotateMatrix.mapPoints(adjustment);
diff --git a/src/com/android/launcher3/LauncherWallpaperPickerActivity.java b/WallpaperPicker/src/com/android/launcher3/LauncherWallpaperPickerActivity.java
index 10fe013ee..091c05462 100644
--- a/src/com/android/launcher3/LauncherWallpaperPickerActivity.java
+++ b/WallpaperPicker/src/com/android/launcher3/LauncherWallpaperPickerActivity.java
@@ -16,15 +16,6 @@
package com.android.launcher3;
-import android.content.Intent;
-
+// TODO: Remove this class
public class LauncherWallpaperPickerActivity extends WallpaperPickerActivity {
- @Override
- public void startActivityForResultSafely(Intent intent, int requestCode) {
- Utilities.startActivityForResultSafely(this, intent, requestCode);
- }
- @Override
- public boolean enableRotation() {
- return Utilities.isRotationEnabled(this);
- }
-}
+} \ No newline at end of file
diff --git a/WallpaperPicker/src/com/android/launcher3/LiveWallpaperListAdapter.java b/WallpaperPicker/src/com/android/launcher3/LiveWallpaperListAdapter.java
index 88f4461bf..b53fce119 100644
--- a/WallpaperPicker/src/com/android/launcher3/LiveWallpaperListAdapter.java
+++ b/WallpaperPicker/src/com/android/launcher3/LiveWallpaperListAdapter.java
@@ -30,11 +30,12 @@ import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
-import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.ListAdapter;
import android.widget.TextView;
+import com.android.launcher3.util.Thunk;
+
import org.xmlpull.v1.XmlPullParserException;
import java.io.IOException;
@@ -50,7 +51,7 @@ public class LiveWallpaperListAdapter extends BaseAdapter implements ListAdapter
private final LayoutInflater mInflater;
private final PackageManager mPackageManager;
- private List<LiveWallpaperTile> mWallpapers;
+ @Thunk List<LiveWallpaperTile> mWallpapers;
@SuppressWarnings("unchecked")
public LiveWallpaperListAdapter(Context context) {
@@ -90,8 +91,6 @@ public class LiveWallpaperListAdapter extends BaseAdapter implements ListAdapter
view = convertView;
}
- WallpaperPickerActivity.setWallpaperItemPaddingToZero((FrameLayout) view);
-
LiveWallpaperTile wallpaperInfo = mWallpapers.get(position);
wallpaperInfo.setView(view);
ImageView image = (ImageView) view.findViewById(R.id.wallpaper_image);
@@ -111,8 +110,8 @@ public class LiveWallpaperListAdapter extends BaseAdapter implements ListAdapter
}
public static class LiveWallpaperTile extends WallpaperPickerActivity.WallpaperTileInfo {
- private Drawable mThumbnail;
- private WallpaperInfo mInfo;
+ @Thunk Drawable mThumbnail;
+ @Thunk WallpaperInfo mInfo;
public LiveWallpaperTile(Drawable thumbnail, WallpaperInfo info, Intent intent) {
mThumbnail = thumbnail;
mInfo = info;
@@ -122,8 +121,8 @@ public class LiveWallpaperListAdapter extends BaseAdapter implements ListAdapter
Intent preview = new Intent(WallpaperManager.ACTION_CHANGE_LIVE_WALLPAPER);
preview.putExtra(WallpaperManager.EXTRA_LIVE_WALLPAPER_COMPONENT,
mInfo.getComponent());
- a.onLiveWallpaperPickerLaunch(mInfo);
- a.startActivityForResultSafely(preview, WallpaperPickerActivity.PICK_LIVE_WALLPAPER);
+ a.startActivityForResultSafely(preview,
+ WallpaperPickerActivity.PICK_WALLPAPER_THIRD_PARTY_ACTIVITY);
}
}
diff --git a/WallpaperPicker/src/com/android/launcher3/SavedWallpaperImages.java b/WallpaperPicker/src/com/android/launcher3/SavedWallpaperImages.java
index 9f92bc105..64b0ac466 100644
--- a/WallpaperPicker/src/com/android/launcher3/SavedWallpaperImages.java
+++ b/WallpaperPicker/src/com/android/launcher3/SavedWallpaperImages.java
@@ -16,7 +16,6 @@
package com.android.launcher3;
-import android.app.Activity;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
@@ -60,13 +59,13 @@ public class SavedWallpaperImages extends BaseAdapter implements ListAdapter {
}
}
- public SavedWallpaperImages(Activity context) {
+ public SavedWallpaperImages(Context context) {
// We used to store the saved images in the cache directory, but that meant they'd get
// deleted sometimes-- move them to the data directory
ImageDb.moveFromCacheDirectoryIfNecessary(context);
mDb = new ImageDb(context);
mContext = context;
- mLayoutInflater = context.getLayoutInflater();
+ mLayoutInflater = LayoutInflater.from(context);
}
public void loadThumbnailsAndImageIdList() {
diff --git a/WallpaperPicker/src/com/android/launcher3/ThirdPartyWallpaperPickerListAdapter.java b/WallpaperPicker/src/com/android/launcher3/ThirdPartyWallpaperPickerListAdapter.java
index 7a4d48ca9..f46da53ec 100644
--- a/WallpaperPicker/src/com/android/launcher3/ThirdPartyWallpaperPickerListAdapter.java
+++ b/WallpaperPicker/src/com/android/launcher3/ThirdPartyWallpaperPickerListAdapter.java
@@ -28,16 +28,15 @@ import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
-import android.widget.FrameLayout;
import android.widget.ListAdapter;
import android.widget.TextView;
+import com.android.launcher3.util.Thunk;
+
import java.util.ArrayList;
import java.util.List;
public class ThirdPartyWallpaperPickerListAdapter extends BaseAdapter implements ListAdapter {
- private static final String LOG_TAG = "LiveWallpaperListAdapter";
-
private final LayoutInflater mInflater;
private final PackageManager mPackageManager;
private final int mIconSize;
@@ -46,7 +45,7 @@ public class ThirdPartyWallpaperPickerListAdapter extends BaseAdapter implements
new ArrayList<ThirdPartyWallpaperTile>();
public static class ThirdPartyWallpaperTile extends WallpaperPickerActivity.WallpaperTileInfo {
- private ResolveInfo mResolveInfo;
+ @Thunk ResolveInfo mResolveInfo;
public ThirdPartyWallpaperTile(ResolveInfo resolveInfo) {
mResolveInfo = resolveInfo;
}
@@ -62,7 +61,7 @@ public class ThirdPartyWallpaperPickerListAdapter extends BaseAdapter implements
}
public ThirdPartyWallpaperPickerListAdapter(Context context) {
- mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+ mInflater = LayoutInflater.from(context);
mPackageManager = context.getPackageManager();
mIconSize = context.getResources().getDimensionPixelSize(R.dimen.wallpaperItemIconSize);
final PackageManager pm = mPackageManager;
@@ -126,8 +125,6 @@ public class ThirdPartyWallpaperPickerListAdapter extends BaseAdapter implements
view = convertView;
}
- WallpaperPickerActivity.setWallpaperItemPaddingToZero((FrameLayout) view);
-
ResolveInfo info = mThirdPartyWallpaperPickers.get(position).mResolveInfo;
TextView label = (TextView) view.findViewById(R.id.wallpaper_item_label);
label.setText(info.loadLabel(mPackageManager));
diff --git a/WallpaperPicker/src/com/android/launcher3/WallpaperCropActivity.java b/WallpaperPicker/src/com/android/launcher3/WallpaperCropActivity.java
index fa8ec64c2..f2bb50944 100644
--- a/WallpaperPicker/src/com/android/launcher3/WallpaperCropActivity.java
+++ b/WallpaperPicker/src/com/android/launcher3/WallpaperCropActivity.java
@@ -16,6 +16,7 @@
package com.android.launcher3;
+import android.annotation.TargetApi;
import android.app.ActionBar;
import android.app.Activity;
import android.app.WallpaperManager;
@@ -25,42 +26,41 @@ import android.content.SharedPreferences;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Bitmap;
-import android.graphics.Bitmap.CompressFormat;
-import android.graphics.BitmapFactory;
-import android.graphics.BitmapRegionDecoder;
-import android.graphics.Canvas;
import android.graphics.Matrix;
-import android.graphics.Paint;
import android.graphics.Point;
-import android.graphics.Rect;
import android.graphics.RectF;
import android.net.Uri;
-import android.os.AsyncTask;
+import android.os.Build;
import android.os.Bundle;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.Message;
import android.util.Log;
import android.view.Display;
import android.view.View;
-import android.view.WindowManager;
import android.widget.Toast;
+import com.android.gallery3d.common.BitmapCropTask;
+import com.android.gallery3d.common.BitmapUtils;
import com.android.gallery3d.common.Utils;
-import com.android.gallery3d.exif.ExifInterface;
+import com.android.launcher3.base.BaseActivity;
+import com.android.launcher3.util.Thunk;
+import com.android.launcher3.util.WallpaperUtils;
import com.android.photos.BitmapRegionTileSource;
import com.android.photos.BitmapRegionTileSource.BitmapSource;
+import com.android.photos.BitmapRegionTileSource.BitmapSource.InBitmapProvider;
+import com.android.photos.views.TiledImageRenderer.TileSource;
-import java.io.BufferedInputStream;
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.InputStream;
+import java.util.Collections;
+import java.util.Set;
+import java.util.WeakHashMap;
-public class WallpaperCropActivity extends Activity {
+public class WallpaperCropActivity extends BaseActivity implements Handler.Callback {
private static final String LOGTAG = "Launcher3.CropActivity";
- protected static final String WALLPAPER_WIDTH_KEY = "wallpaper.width";
- protected static final String WALLPAPER_HEIGHT_KEY = "wallpaper.height";
- private static final int DEFAULT_COMPRESS_QUALITY = 90;
+ protected static final String WALLPAPER_WIDTH_KEY = WallpaperUtils.WALLPAPER_WIDTH_KEY;
+ protected static final String WALLPAPER_HEIGHT_KEY = WallpaperUtils.WALLPAPER_HEIGHT_KEY;
+
/**
* The maximum bitmap size we allow to be returned through the intent.
* Intents have a maximum of 1MB in total size. However, the Bitmap seems to
@@ -69,17 +69,31 @@ public class WallpaperCropActivity extends Activity {
* array instead of a Bitmap instance to avoid overhead.
*/
public static final int MAX_BMAP_IN_INTENT = 750000;
- private static final float WALLPAPER_SCREENS_SPAN = 2f;
+ public static final float WALLPAPER_SCREENS_SPAN = WallpaperUtils.WALLPAPER_SCREENS_SPAN;
- protected static Point sDefaultWallpaperSize;
+ private static final int MSG_LOAD_IMAGE = 1;
protected CropView mCropView;
+ protected View mProgressView;
protected Uri mUri;
protected View mSetWallpaperButton;
+ private HandlerThread mLoaderThread;
+ private Handler mLoaderHandler;
+ @Thunk LoadRequest mCurrentLoadRequest;
+ private byte[] mTempStorageForDecoding = new byte[16 * 1024];
+ // A weak-set of reusable bitmaps
+ @Thunk Set<Bitmap> mReusableBitmaps =
+ Collections.newSetFromMap(new WeakHashMap<Bitmap, Boolean>());
+
@Override
- protected void onCreate(Bundle savedInstanceState) {
+ public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
+
+ mLoaderThread = new HandlerThread("wallpaper_loader");
+ mLoaderThread.start();
+ mLoaderHandler = new Handler(mLoaderThread.getLooper(), this);
+
init();
if (!enableRotation()) {
setRequestedOrientation(Configuration.ORIENTATION_PORTRAIT);
@@ -90,6 +104,7 @@ public class WallpaperCropActivity extends Activity {
setContentView(R.layout.wallpaper_cropper);
mCropView = (CropView) findViewById(R.id.cropView);
+ mProgressView = findViewById(R.id.loading);
Intent cropIntent = getIntent();
final Uri imageUri = cropIntent.getData();
@@ -116,13 +131,12 @@ public class WallpaperCropActivity extends Activity {
// Load image in background
final BitmapRegionTileSource.UriBitmapSource bitmapSource =
- new BitmapRegionTileSource.UriBitmapSource(this, imageUri, 1024);
+ new BitmapRegionTileSource.UriBitmapSource(getContext(), imageUri);
mSetWallpaperButton.setEnabled(false);
Runnable onLoad = new Runnable() {
public void run() {
if (bitmapSource.getLoadingState() != BitmapSource.State.LOADED) {
- Toast.makeText(WallpaperCropActivity.this,
- getString(R.string.wallpaper_load_fail),
+ Toast.makeText(getContext(), R.string.wallpaper_load_fail,
Toast.LENGTH_LONG).show();
finish();
} else {
@@ -130,188 +144,163 @@ public class WallpaperCropActivity extends Activity {
}
}
};
- setCropViewTileSource(bitmapSource, true, false, onLoad);
+ setCropViewTileSource(bitmapSource, true, false, null, onLoad);
}
@Override
- protected void onDestroy() {
+ public void onDestroy() {
if (mCropView != null) {
mCropView.destroy();
}
+ if (mLoaderThread != null) {
+ mLoaderThread.quit();
+ }
super.onDestroy();
}
- public void setCropViewTileSource(
- final BitmapRegionTileSource.BitmapSource bitmapSource, final boolean touchEnabled,
- final boolean moveToLeft, final Runnable postExecute) {
- final Context context = WallpaperCropActivity.this;
- final View progressView = findViewById(R.id.loading);
- final AsyncTask<Void, Void, Void> loadBitmapTask = new AsyncTask<Void, Void, Void>() {
- protected Void doInBackground(Void...args) {
- if (!isCancelled()) {
- try {
- bitmapSource.loadInBackground();
- } catch (SecurityException securityException) {
- if (isDestroyed()) {
- // Temporarily granted permissions are revoked when the activity
- // finishes, potentially resulting in a SecurityException here.
- // Even though {@link #isDestroyed} might also return true in different
- // situations where the configuration changes, we are fine with
- // catching these cases here as well.
- cancel(false);
- } else {
- // otherwise it had a different cause and we throw it further
- throw securityException;
+ /**
+ * This is called on {@link #mLoaderThread}
+ */
+ @Override
+ public boolean handleMessage(Message msg) {
+ if (msg.what == MSG_LOAD_IMAGE) {
+ final LoadRequest req = (LoadRequest) msg.obj;
+ try {
+ req.src.loadInBackground(new InBitmapProvider() {
+
+ @Override
+ public Bitmap forPixelCount(int count) {
+ Bitmap bitmapToReuse = null;
+ // Find the smallest bitmap that satisfies the pixel count limit
+ synchronized (mReusableBitmaps) {
+ int currentBitmapSize = Integer.MAX_VALUE;
+ for (Bitmap b : mReusableBitmaps) {
+ int bitmapSize = b.getWidth() * b.getHeight();
+ if ((bitmapSize >= count) && (bitmapSize < currentBitmapSize)) {
+ bitmapToReuse = b;
+ currentBitmapSize = bitmapSize;
+ }
+ }
+
+ if (bitmapToReuse != null) {
+ mReusableBitmaps.remove(bitmapToReuse);
+ }
}
+ return bitmapToReuse;
}
+ });
+ } catch (SecurityException securityException) {
+ if (isActivityDestroyed()) {
+ // Temporarily granted permissions are revoked when the activity
+ // finishes, potentially resulting in a SecurityException here.
+ // Even though {@link #isDestroyed} might also return true in different
+ // situations where the configuration changes, we are fine with
+ // catching these cases here as well.
+ return true;
+ } else {
+ // otherwise it had a different cause and we throw it further
+ throw securityException;
}
- return null;
}
- protected void onPostExecute(Void arg) {
- if (!isCancelled()) {
- progressView.setVisibility(View.INVISIBLE);
- if (bitmapSource.getLoadingState() == BitmapSource.State.LOADED) {
- mCropView.setTileSource(
- new BitmapRegionTileSource(context, bitmapSource), null);
- mCropView.setTouchEnabled(touchEnabled);
- if (moveToLeft) {
- mCropView.moveToLeft();
- }
+
+ req.result = new BitmapRegionTileSource(getContext(), req.src, mTempStorageForDecoding);
+ runOnUiThread(new Runnable() {
+
+ @Override
+ public void run() {
+ if (req == mCurrentLoadRequest) {
+ onLoadRequestComplete(req,
+ req.src.getLoadingState() == BitmapSource.State.LOADED);
+ } else {
+ addReusableBitmap(req.result);
}
}
- if (postExecute != null) {
- postExecute.run();
- }
- }
- };
- // We don't want to show the spinner every time we load an image, because that would be
- // annoying; instead, only start showing the spinner if loading the image has taken
- // longer than 1 sec (ie 1000 ms)
- progressView.postDelayed(new Runnable() {
- public void run() {
- if (loadBitmapTask.getStatus() != AsyncTask.Status.FINISHED) {
- progressView.setVisibility(View.VISIBLE);
- }
- }
- }, 1000);
- loadBitmapTask.execute();
- }
-
- public boolean enableRotation() {
- return getResources().getBoolean(R.bool.allow_rotation);
+ });
+ return true;
+ }
+ return false;
}
- public static String getSharedPreferencesKey() {
- return LauncherFiles.WALLPAPER_CROP_PREFERENCES_KEY;
+ @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
+ protected boolean isActivityDestroyed() {
+ return (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1)
+ && isDestroyed();
}
- // As a ratio of screen height, the total distance we want the parallax effect to span
- // horizontally
- private static float wallpaperTravelToScreenWidthRatio(int width, int height) {
- float aspectRatio = width / (float) height;
-
- // At an aspect ratio of 16/10, the wallpaper parallax effect should span 1.5 * screen width
- // At an aspect ratio of 10/16, the wallpaper parallax effect should span 1.2 * screen width
- // We will use these two data points to extrapolate how much the wallpaper parallax effect
- // to span (ie travel) at any aspect ratio:
-
- final float ASPECT_RATIO_LANDSCAPE = 16/10f;
- final float ASPECT_RATIO_PORTRAIT = 10/16f;
- final float WALLPAPER_WIDTH_TO_SCREEN_RATIO_LANDSCAPE = 1.5f;
- final float WALLPAPER_WIDTH_TO_SCREEN_RATIO_PORTRAIT = 1.2f;
-
- // To find out the desired width at different aspect ratios, we use the following two
- // formulas, where the coefficient on x is the aspect ratio (width/height):
- // (16/10)x + y = 1.5
- // (10/16)x + y = 1.2
- // We solve for x and y and end up with a final formula:
- final float x =
- (WALLPAPER_WIDTH_TO_SCREEN_RATIO_LANDSCAPE - WALLPAPER_WIDTH_TO_SCREEN_RATIO_PORTRAIT) /
- (ASPECT_RATIO_LANDSCAPE - ASPECT_RATIO_PORTRAIT);
- final float y = WALLPAPER_WIDTH_TO_SCREEN_RATIO_PORTRAIT - x * ASPECT_RATIO_PORTRAIT;
- return x * aspectRatio + y;
+ @Thunk void addReusableBitmap(TileSource src) {
+ synchronized (mReusableBitmaps) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT
+ && src instanceof BitmapRegionTileSource) {
+ Bitmap preview = ((BitmapRegionTileSource) src).getBitmap();
+ if (preview != null && preview.isMutable()) {
+ mReusableBitmaps.add(preview);
+ }
+ }
+ }
}
- static protected Point getDefaultWallpaperSize(Resources res, WindowManager windowManager) {
- if (sDefaultWallpaperSize == null) {
- Point minDims = new Point();
- Point maxDims = new Point();
- windowManager.getDefaultDisplay().getCurrentSizeRange(minDims, maxDims);
-
- int maxDim = Math.max(maxDims.x, maxDims.y);
- int minDim = Math.max(minDims.x, minDims.y);
-
- if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR1) {
- Point realSize = new Point();
- windowManager.getDefaultDisplay().getRealSize(realSize);
- maxDim = Math.max(realSize.x, realSize.y);
- minDim = Math.min(realSize.x, realSize.y);
+ protected void onLoadRequestComplete(LoadRequest req, boolean success) {
+ mCurrentLoadRequest = null;
+ if (success) {
+ TileSource oldSrc = mCropView.getTileSource();
+ mCropView.setTileSource(req.result, null);
+ mCropView.setTouchEnabled(req.touchEnabled);
+ if (req.moveToLeft) {
+ mCropView.moveToLeft();
+ }
+ if (req.scaleProvider != null) {
+ mCropView.setScale(req.scaleProvider.getScale(req.result));
}
- // We need to ensure that there is enough extra space in the wallpaper
- // for the intended parallax effects
- final int defaultWidth, defaultHeight;
- if (isScreenLarge(res)) {
- defaultWidth = (int) (maxDim * wallpaperTravelToScreenWidthRatio(maxDim, minDim));
- defaultHeight = maxDim;
- } else {
- defaultWidth = Math.max((int) (minDim * WALLPAPER_SCREENS_SPAN), maxDim);
- defaultHeight = maxDim;
+ // Free last image
+ if (oldSrc != null) {
+ // Call yield instead of recycle, as we only want to free GL resource.
+ // We can still reuse the bitmap for decoding any other image.
+ oldSrc.getPreview().yield();
}
- sDefaultWallpaperSize = new Point(defaultWidth, defaultHeight);
+ addReusableBitmap(oldSrc);
}
- return sDefaultWallpaperSize;
+ if (req.postExecute != null) {
+ req.postExecute.run();
+ }
+ mProgressView.setVisibility(View.GONE);
}
- public static int getRotationFromExif(String path) {
- return getRotationFromExifHelper(path, null, 0, null, null);
- }
+ public final void setCropViewTileSource(BitmapSource bitmapSource, boolean touchEnabled,
+ boolean moveToLeft, CropViewScaleProvider scaleProvider, Runnable postExecute) {
+ final LoadRequest req = new LoadRequest();
+ req.moveToLeft = moveToLeft;
+ req.src = bitmapSource;
+ req.touchEnabled = touchEnabled;
+ req.postExecute = postExecute;
+ req.scaleProvider = scaleProvider;
+ mCurrentLoadRequest = req;
- public static int getRotationFromExif(Context context, Uri uri) {
- return getRotationFromExifHelper(null, null, 0, context, uri);
- }
+ // Remove any pending requests
+ mLoaderHandler.removeMessages(MSG_LOAD_IMAGE);
+ Message.obtain(mLoaderHandler, MSG_LOAD_IMAGE, req).sendToTarget();
- public static int getRotationFromExif(Resources res, int resId) {
- return getRotationFromExifHelper(null, res, resId, null, null);
+ // We don't want to show the spinner every time we load an image, because that would be
+ // annoying; instead, only start showing the spinner if loading the image has taken
+ // longer than 1 sec (ie 1000 ms)
+ mProgressView.postDelayed(new Runnable() {
+ public void run() {
+ if (mCurrentLoadRequest == req) {
+ mProgressView.setVisibility(View.VISIBLE);
+ }
+ }
+ }, 1000);
}
- private static int getRotationFromExifHelper(
- String path, Resources res, int resId, Context context, Uri uri) {
- ExifInterface ei = new ExifInterface();
- InputStream is = null;
- BufferedInputStream bis = null;
- try {
- if (path != null) {
- ei.readExif(path);
- } else if (uri != null) {
- is = context.getContentResolver().openInputStream(uri);
- bis = new BufferedInputStream(is);
- ei.readExif(bis);
- } else {
- is = res.openRawResource(resId);
- bis = new BufferedInputStream(is);
- ei.readExif(bis);
- }
- Integer ori = ei.getTagIntValue(ExifInterface.TAG_ORIENTATION);
- if (ori != null) {
- return ExifInterface.getRotationForOrientationValue(ori.shortValue());
- }
- } catch (IOException e) {
- Log.w(LOGTAG, "Getting exif data failed", e);
- } catch (NullPointerException e) {
- // Sometimes the ExifInterface has an internal NPE if Exif data isn't valid
- Log.w(LOGTAG, "Getting exif data failed", e);
- } finally {
- Utils.closeSilently(bis);
- Utils.closeSilently(is);
- }
- return 0;
+
+ public boolean enableRotation() {
+ return getResources().getBoolean(R.bool.allow_rotation);
}
protected void setWallpaper(Uri uri, final boolean finishActivityWhenDone) {
- int rotation = getRotationFromExif(this, uri);
+ int rotation = BitmapUtils.getRotationFromExif(getContext(), uri);
BitmapCropTask cropTask = new BitmapCropTask(
- this, uri, null, rotation, 0, 0, true, false, null);
+ getContext(), uri, null, rotation, 0, 0, true, false, null);
final Point bounds = cropTask.getImageBounds();
Runnable onEndCrop = new Runnable() {
public void run() {
@@ -331,11 +320,11 @@ public class WallpaperCropActivity extends Activity {
Resources res, int resId, final boolean finishActivityWhenDone) {
// crop this image and scale it down to the default wallpaper size for
// this device
- int rotation = getRotationFromExif(res, resId);
+ int rotation = BitmapUtils.getRotationFromExif(res, resId);
Point inSize = mCropView.getSourceDimensions();
- Point outSize = getDefaultWallpaperSize(getResources(),
+ Point outSize = WallpaperUtils.getDefaultWallpaperSize(getResources(),
getWindowManager());
- RectF crop = getMaxCropRect(
+ RectF crop = Utils.getMaxCropRect(
inSize.x, inSize.y, outSize.x, outSize.y, false);
Runnable onEndCrop = new Runnable() {
public void run() {
@@ -348,18 +337,14 @@ public class WallpaperCropActivity extends Activity {
}
}
};
- BitmapCropTask cropTask = new BitmapCropTask(this, res, resId,
+ BitmapCropTask cropTask = new BitmapCropTask(getContext(), res, resId,
crop, rotation, outSize.x, outSize.y, true, false, onEndCrop);
cropTask.execute();
}
- private static boolean isScreenLarge(Resources res) {
- Configuration config = res.getConfiguration();
- return config.smallestScreenWidthDp >= 720;
- }
-
+ @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
protected void cropImageAndSetWallpaper(Uri uri,
- OnBitmapCroppedHandler onBitmapCroppedHandler, final boolean finishActivityWhenDone) {
+ BitmapCropTask.OnBitmapCroppedHandler onBitmapCroppedHandler, final boolean finishActivityWhenDone) {
boolean centerCrop = getResources().getBoolean(R.bool.center_crop);
// Get the crop
boolean ltr = mCropView.getLayoutDirection() == View.LAYOUT_DIRECTION_LTR;
@@ -370,7 +355,7 @@ public class WallpaperCropActivity extends Activity {
d.getSize(displaySize);
boolean isPortrait = displaySize.x < displaySize.y;
- Point defaultWallpaperSize = getDefaultWallpaperSize(getResources(),
+ Point defaultWallpaperSize = WallpaperUtils.getDefaultWallpaperSize(getResources(),
getWindowManager());
// Get the crop
RectF cropRect = mCropView.getCrop();
@@ -444,7 +429,7 @@ public class WallpaperCropActivity extends Activity {
}
}
};
- BitmapCropTask cropTask = new BitmapCropTask(this, uri,
+ BitmapCropTask cropTask = new BitmapCropTask(getContext(), uri,
cropRect, cropRotation, outWidth, outHeight, true, false, onEndCrop);
if (onBitmapCroppedHandler != null) {
cropTask.setOnBitmapCropped(onBitmapCroppedHandler);
@@ -452,375 +437,9 @@ public class WallpaperCropActivity extends Activity {
cropTask.execute();
}
- public interface OnBitmapCroppedHandler {
- public void onBitmapCropped(byte[] imageBytes);
- }
-
- protected static class BitmapCropTask extends AsyncTask<Void, Void, Boolean> {
- Uri mInUri = null;
- Context mContext;
- String mInFilePath;
- byte[] mInImageBytes;
- int mInResId = 0;
- RectF mCropBounds = null;
- int mOutWidth, mOutHeight;
- int mRotation;
- String mOutputFormat = "jpg"; // for now
- boolean mSetWallpaper;
- boolean mSaveCroppedBitmap;
- Bitmap mCroppedBitmap;
- Runnable mOnEndRunnable;
- Resources mResources;
- OnBitmapCroppedHandler mOnBitmapCroppedHandler;
- boolean mNoCrop;
-
- public BitmapCropTask(Context c, String filePath,
- RectF cropBounds, int rotation, int outWidth, int outHeight,
- boolean setWallpaper, boolean saveCroppedBitmap, Runnable onEndRunnable) {
- mContext = c;
- mInFilePath = filePath;
- init(cropBounds, rotation,
- outWidth, outHeight, setWallpaper, saveCroppedBitmap, onEndRunnable);
- }
-
- public BitmapCropTask(byte[] imageBytes,
- RectF cropBounds, int rotation, int outWidth, int outHeight,
- boolean setWallpaper, boolean saveCroppedBitmap, Runnable onEndRunnable) {
- mInImageBytes = imageBytes;
- init(cropBounds, rotation,
- outWidth, outHeight, setWallpaper, saveCroppedBitmap, onEndRunnable);
- }
-
- public BitmapCropTask(Context c, Uri inUri,
- RectF cropBounds, int rotation, int outWidth, int outHeight,
- boolean setWallpaper, boolean saveCroppedBitmap, Runnable onEndRunnable) {
- mContext = c;
- mInUri = inUri;
- init(cropBounds, rotation,
- outWidth, outHeight, setWallpaper, saveCroppedBitmap, onEndRunnable);
- }
-
- public BitmapCropTask(Context c, Resources res, int inResId,
- RectF cropBounds, int rotation, int outWidth, int outHeight,
- boolean setWallpaper, boolean saveCroppedBitmap, Runnable onEndRunnable) {
- mContext = c;
- mInResId = inResId;
- mResources = res;
- init(cropBounds, rotation,
- outWidth, outHeight, setWallpaper, saveCroppedBitmap, onEndRunnable);
- }
-
- private void init(RectF cropBounds, int rotation, int outWidth, int outHeight,
- boolean setWallpaper, boolean saveCroppedBitmap, Runnable onEndRunnable) {
- mCropBounds = cropBounds;
- mRotation = rotation;
- mOutWidth = outWidth;
- mOutHeight = outHeight;
- mSetWallpaper = setWallpaper;
- mSaveCroppedBitmap = saveCroppedBitmap;
- mOnEndRunnable = onEndRunnable;
- }
-
- public void setOnBitmapCropped(OnBitmapCroppedHandler handler) {
- mOnBitmapCroppedHandler = handler;
- }
-
- public void setNoCrop(boolean value) {
- mNoCrop = value;
- }
-
- public void setOnEndRunnable(Runnable onEndRunnable) {
- mOnEndRunnable = onEndRunnable;
- }
-
- // Helper to setup input stream
- private InputStream regenerateInputStream() {
- if (mInUri == null && mInResId == 0 && mInFilePath == null && mInImageBytes == null) {
- Log.w(LOGTAG, "cannot read original file, no input URI, resource ID, or " +
- "image byte array given");
- } else {
- try {
- if (mInUri != null) {
- return new BufferedInputStream(
- mContext.getContentResolver().openInputStream(mInUri));
- } else if (mInFilePath != null) {
- return mContext.openFileInput(mInFilePath);
- } else if (mInImageBytes != null) {
- return new BufferedInputStream(new ByteArrayInputStream(mInImageBytes));
- } else {
- return new BufferedInputStream(mResources.openRawResource(mInResId));
- }
- } catch (FileNotFoundException e) {
- Log.w(LOGTAG, "cannot read file: " + mInUri.toString(), e);
- }
- }
- return null;
- }
-
- public Point getImageBounds() {
- InputStream is = regenerateInputStream();
- if (is != null) {
- BitmapFactory.Options options = new BitmapFactory.Options();
- options.inJustDecodeBounds = true;
- BitmapFactory.decodeStream(is, null, options);
- Utils.closeSilently(is);
- if (options.outWidth != 0 && options.outHeight != 0) {
- return new Point(options.outWidth, options.outHeight);
- }
- }
- return null;
- }
-
- public void setCropBounds(RectF cropBounds) {
- mCropBounds = cropBounds;
- }
-
- public Bitmap getCroppedBitmap() {
- return mCroppedBitmap;
- }
- public boolean cropBitmap() {
- boolean failure = false;
-
-
- WallpaperManager wallpaperManager = null;
- if (mSetWallpaper) {
- wallpaperManager = WallpaperManager.getInstance(mContext.getApplicationContext());
- }
-
-
- if (mSetWallpaper && mNoCrop) {
- try {
- InputStream is = regenerateInputStream();
- if (is != null) {
- wallpaperManager.setStream(is);
- Utils.closeSilently(is);
- }
- } catch (IOException e) {
- Log.w(LOGTAG, "cannot write stream to wallpaper", e);
- failure = true;
- }
- return !failure;
- } else {
- // Find crop bounds (scaled to original image size)
- Rect roundedTrueCrop = new Rect();
- Matrix rotateMatrix = new Matrix();
- Matrix inverseRotateMatrix = new Matrix();
-
- Point bounds = getImageBounds();
- if (mRotation > 0) {
- rotateMatrix.setRotate(mRotation);
- inverseRotateMatrix.setRotate(-mRotation);
-
- mCropBounds.roundOut(roundedTrueCrop);
- mCropBounds = new RectF(roundedTrueCrop);
-
- if (bounds == null) {
- Log.w(LOGTAG, "cannot get bounds for image");
- failure = true;
- return false;
- }
-
- float[] rotatedBounds = new float[] { bounds.x, bounds.y };
- rotateMatrix.mapPoints(rotatedBounds);
- rotatedBounds[0] = Math.abs(rotatedBounds[0]);
- rotatedBounds[1] = Math.abs(rotatedBounds[1]);
-
- mCropBounds.offset(-rotatedBounds[0]/2, -rotatedBounds[1]/2);
- inverseRotateMatrix.mapRect(mCropBounds);
- mCropBounds.offset(bounds.x/2, bounds.y/2);
-
- }
-
- mCropBounds.roundOut(roundedTrueCrop);
-
- if (roundedTrueCrop.width() <= 0 || roundedTrueCrop.height() <= 0) {
- Log.w(LOGTAG, "crop has bad values for full size image");
- failure = true;
- return false;
- }
-
- // See how much we're reducing the size of the image
- int scaleDownSampleSize = Math.max(1, Math.min(roundedTrueCrop.width() / mOutWidth,
- roundedTrueCrop.height() / mOutHeight));
- // Attempt to open a region decoder
- BitmapRegionDecoder decoder = null;
- InputStream is = null;
- try {
- is = regenerateInputStream();
- if (is == null) {
- Log.w(LOGTAG, "cannot get input stream for uri=" + mInUri.toString());
- failure = true;
- return false;
- }
- decoder = BitmapRegionDecoder.newInstance(is, false);
- Utils.closeSilently(is);
- } catch (IOException e) {
- Log.w(LOGTAG, "cannot open region decoder for file: " + mInUri.toString(), e);
- } finally {
- Utils.closeSilently(is);
- is = null;
- }
-
- Bitmap crop = null;
- if (decoder != null) {
- // Do region decoding to get crop bitmap
- BitmapFactory.Options options = new BitmapFactory.Options();
- if (scaleDownSampleSize > 1) {
- options.inSampleSize = scaleDownSampleSize;
- }
- crop = decoder.decodeRegion(roundedTrueCrop, options);
- decoder.recycle();
- }
-
- if (crop == null) {
- // BitmapRegionDecoder has failed, try to crop in-memory
- is = regenerateInputStream();
- Bitmap fullSize = null;
- if (is != null) {
- BitmapFactory.Options options = new BitmapFactory.Options();
- if (scaleDownSampleSize > 1) {
- options.inSampleSize = scaleDownSampleSize;
- }
- fullSize = BitmapFactory.decodeStream(is, null, options);
- Utils.closeSilently(is);
- }
- if (fullSize != null) {
- // Find out the true sample size that was used by the decoder
- scaleDownSampleSize = bounds.x / fullSize.getWidth();
- mCropBounds.left /= scaleDownSampleSize;
- mCropBounds.top /= scaleDownSampleSize;
- mCropBounds.bottom /= scaleDownSampleSize;
- mCropBounds.right /= scaleDownSampleSize;
- mCropBounds.roundOut(roundedTrueCrop);
-
- // Adjust values to account for issues related to rounding
- if (roundedTrueCrop.width() > fullSize.getWidth()) {
- // Adjust the width
- 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;
- }
- 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;
- }
-
- crop = Bitmap.createBitmap(fullSize, roundedTrueCrop.left,
- roundedTrueCrop.top, roundedTrueCrop.width(),
- roundedTrueCrop.height());
- }
- }
-
- if (crop == null) {
- Log.w(LOGTAG, "cannot decode file: " + mInUri.toString());
- failure = true;
- return false;
- }
- if (mOutWidth > 0 && mOutHeight > 0 || mRotation > 0) {
- float[] dimsAfter = new float[] { crop.getWidth(), crop.getHeight() };
- rotateMatrix.mapPoints(dimsAfter);
- dimsAfter[0] = Math.abs(dimsAfter[0]);
- dimsAfter[1] = Math.abs(dimsAfter[1]);
-
- if (!(mOutWidth > 0 && mOutHeight > 0)) {
- mOutWidth = Math.round(dimsAfter[0]);
- mOutHeight = Math.round(dimsAfter[1]);
- }
-
- RectF cropRect = new RectF(0, 0, dimsAfter[0], dimsAfter[1]);
- RectF returnRect = new RectF(0, 0, mOutWidth, mOutHeight);
-
- Matrix m = new Matrix();
- if (mRotation == 0) {
- m.setRectToRect(cropRect, returnRect, Matrix.ScaleToFit.FILL);
- } else {
- Matrix m1 = new Matrix();
- m1.setTranslate(-crop.getWidth() / 2f, -crop.getHeight() / 2f);
- Matrix m2 = new Matrix();
- m2.setRotate(mRotation);
- Matrix m3 = new Matrix();
- m3.setTranslate(dimsAfter[0] / 2f, dimsAfter[1] / 2f);
- Matrix m4 = new Matrix();
- m4.setRectToRect(cropRect, returnRect, Matrix.ScaleToFit.FILL);
-
- Matrix c1 = new Matrix();
- c1.setConcat(m2, m1);
- Matrix c2 = new Matrix();
- c2.setConcat(m4, m3);
- m.setConcat(c2, c1);
- }
-
- Bitmap tmp = Bitmap.createBitmap((int) returnRect.width(),
- (int) returnRect.height(), Bitmap.Config.ARGB_8888);
- if (tmp != null) {
- Canvas c = new Canvas(tmp);
- Paint p = new Paint();
- p.setFilterBitmap(true);
- c.drawBitmap(crop, m, p);
- crop = tmp;
- }
- }
-
- if (mSaveCroppedBitmap) {
- mCroppedBitmap = crop;
- }
-
- // Get output compression format
- CompressFormat cf =
- convertExtensionToCompressFormat(getFileExtension(mOutputFormat));
-
- // Compress to byte array
- ByteArrayOutputStream tmpOut = new ByteArrayOutputStream(2048);
- if (crop.compress(cf, DEFAULT_COMPRESS_QUALITY, tmpOut)) {
- // If we need to set to the wallpaper, set it
- if (mSetWallpaper && wallpaperManager != null) {
- try {
- byte[] outByteArray = tmpOut.toByteArray();
- wallpaperManager.setStream(new ByteArrayInputStream(outByteArray));
- if (mOnBitmapCroppedHandler != null) {
- mOnBitmapCroppedHandler.onBitmapCropped(outByteArray);
- }
- } catch (IOException e) {
- Log.w(LOGTAG, "cannot write stream to wallpaper", e);
- failure = true;
- }
- }
- } else {
- Log.w(LOGTAG, "cannot compress bitmap");
- failure = true;
- }
- }
- return !failure; // True if any of the operations failed
- }
-
- @Override
- protected Boolean doInBackground(Void... params) {
- return cropBitmap();
- }
-
- @Override
- protected void onPostExecute(Boolean result) {
- if (mOnEndRunnable != null) {
- mOnEndRunnable.run();
- }
- }
- }
-
protected void updateWallpaperDimensions(int width, int height) {
- String spKey = getSharedPreferencesKey();
- SharedPreferences sp = getSharedPreferences(spKey, Context.MODE_MULTI_PROCESS);
+ String spKey = LauncherFiles.WALLPAPER_CROP_PREFERENCES_KEY;
+ SharedPreferences sp = getContext().getSharedPreferences(spKey, Context.MODE_MULTI_PROCESS);
SharedPreferences.Editor editor = sp.edit();
if (width != 0 && height != 0) {
editor.putInt(WALLPAPER_WIDTH_KEY, width);
@@ -830,69 +449,21 @@ public class WallpaperCropActivity extends Activity {
editor.remove(WALLPAPER_HEIGHT_KEY);
}
editor.commit();
-
- suggestWallpaperDimension(getResources(),
- sp, getWindowManager(), WallpaperManager.getInstance(this), true);
- }
-
- static public void suggestWallpaperDimension(Resources res,
- final SharedPreferences sharedPrefs,
- WindowManager windowManager,
- final WallpaperManager wallpaperManager, boolean fallBackToDefaults) {
- final Point defaultWallpaperSize = getDefaultWallpaperSize(res, windowManager);
- // If we have saved a wallpaper width/height, use that instead
-
- int savedWidth = sharedPrefs.getInt(WALLPAPER_WIDTH_KEY, -1);
- int savedHeight = sharedPrefs.getInt(WALLPAPER_HEIGHT_KEY, -1);
-
- if (savedWidth == -1 || savedHeight == -1) {
- if (!fallBackToDefaults) {
- return;
- } else {
- savedWidth = defaultWallpaperSize.x;
- savedHeight = defaultWallpaperSize.y;
- }
- }
-
- if (savedWidth != wallpaperManager.getDesiredMinimumWidth() ||
- savedHeight != wallpaperManager.getDesiredMinimumHeight()) {
- wallpaperManager.suggestDesiredDimensions(savedWidth, savedHeight);
- }
+ WallpaperUtils.suggestWallpaperDimension(getResources(),
+ sp, getWindowManager(), WallpaperManager.getInstance(getContext()), true);
}
- protected static RectF getMaxCropRect(
- int inWidth, int inHeight, int outWidth, int outHeight, boolean leftAligned) {
- RectF cropRect = new RectF();
- // Get a crop rect that will fit this
- if (inWidth / (float) inHeight > outWidth / (float) outHeight) {
- cropRect.top = 0;
- cropRect.bottom = inHeight;
- cropRect.left = (inWidth - (outWidth / (float) outHeight) * inHeight) / 2;
- cropRect.right = inWidth - cropRect.left;
- if (leftAligned) {
- cropRect.right -= cropRect.left;
- cropRect.left = 0;
- }
- } else {
- cropRect.left = 0;
- cropRect.right = inWidth;
- cropRect.top = (inHeight - (outHeight / (float) outWidth) * inWidth) / 2;
- cropRect.bottom = inHeight - cropRect.top;
- }
- return cropRect;
- }
+ static class LoadRequest {
+ BitmapSource src;
+ boolean touchEnabled;
+ boolean moveToLeft;
+ Runnable postExecute;
+ CropViewScaleProvider scaleProvider;
- protected static CompressFormat convertExtensionToCompressFormat(String extension) {
- return extension.equals("png") ? CompressFormat.PNG : CompressFormat.JPEG;
+ TileSource result;
}
- protected static String getFileExtension(String requestFormat) {
- String outputFormat = (requestFormat == null)
- ? "jpg"
- : requestFormat;
- outputFormat = outputFormat.toLowerCase();
- return (outputFormat.equals("png") || outputFormat.equals("gif"))
- ? "png" // We don't support gif compression.
- : "jpg";
+ interface CropViewScaleProvider {
+ float getScale(TileSource src);
}
}
diff --git a/WallpaperPicker/src/com/android/launcher3/WallpaperPickerActivity.java b/WallpaperPicker/src/com/android/launcher3/WallpaperPickerActivity.java
index 09e096396..88dc3e22b 100644
--- a/WallpaperPicker/src/com/android/launcher3/WallpaperPickerActivity.java
+++ b/WallpaperPicker/src/com/android/launcher3/WallpaperPickerActivity.java
@@ -16,11 +16,11 @@
package com.android.launcher3;
+import android.Manifest.permission;
import android.animation.LayoutTransition;
import android.annotation.TargetApi;
import android.app.ActionBar;
import android.app.Activity;
-import android.app.WallpaperInfo;
import android.app.WallpaperManager;
import android.content.Context;
import android.content.Intent;
@@ -35,15 +35,15 @@ import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Point;
import android.graphics.PorterDuff;
-import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
-import android.graphics.drawable.LevelListDrawable;
+import android.Manifest;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
+import android.os.Process;
import android.provider.MediaStore;
import android.util.Log;
import android.util.Pair;
@@ -52,6 +52,7 @@ import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
+import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnLayoutChangeListener;
@@ -70,8 +71,14 @@ import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.Toast;
+import com.android.gallery3d.common.BitmapCropTask;
+import com.android.gallery3d.common.BitmapUtils;
+import com.android.gallery3d.common.Utils;
+import com.android.launcher3.util.Thunk;
+import com.android.launcher3.util.WallpaperUtils;
import com.android.photos.BitmapRegionTileSource;
import com.android.photos.BitmapRegionTileSource.BitmapSource;
+import com.android.photos.views.TiledImageRenderer.TileSource;
import java.io.File;
import java.io.FileOutputStream;
@@ -83,28 +90,25 @@ public class WallpaperPickerActivity extends WallpaperCropActivity {
public static final int IMAGE_PICK = 5;
public static final int PICK_WALLPAPER_THIRD_PARTY_ACTIVITY = 6;
- public static final int PICK_LIVE_WALLPAPER = 7;
private static final String TEMP_WALLPAPER_TILES = "TEMP_WALLPAPER_TILES";
private static final String SELECTED_INDEX = "SELECTED_INDEX";
private static final int FLAG_POST_DELAY_MILLIS = 200;
- private View mSelectedTile;
- private boolean mIgnoreNextTap;
- private OnClickListener mThumbnailOnClickListener;
+ @Thunk View mSelectedTile;
+ @Thunk boolean mIgnoreNextTap;
+ @Thunk OnClickListener mThumbnailOnClickListener;
- private LinearLayout mWallpapersView;
- private View mWallpaperStrip;
+ @Thunk LinearLayout mWallpapersView;
+ @Thunk HorizontalScrollView mWallpaperScrollContainer;
- private ActionMode.Callback mActionModeCallback;
- private ActionMode mActionMode;
+ @Thunk ActionMode.Callback mActionModeCallback;
+ @Thunk ActionMode mActionMode;
- private View.OnLongClickListener mLongClickListener;
+ @Thunk View.OnLongClickListener mLongClickListener;
ArrayList<Uri> mTempWallpaperTiles = new ArrayList<Uri>();
private SavedWallpaperImages mSavedImages;
- private WallpaperInfo mLiveWallpaperInfoOnPickerLaunch;
- private int mSelectedIndex = -1;
- private WallpaperInfo mLastClickedLiveWallpaperInfo;
+ @Thunk int mSelectedIndex = -1;
public static abstract class WallpaperTileInfo {
protected View mView;
@@ -136,45 +140,36 @@ public class WallpaperPickerActivity extends WallpaperCropActivity {
public static class UriWallpaperInfo extends WallpaperTileInfo {
private Uri mUri;
- private boolean mFirstClick = true;
- private BitmapRegionTileSource.UriBitmapSource mBitmapSource;
public UriWallpaperInfo(Uri uri) {
mUri = uri;
}
@Override
public void onClick(final WallpaperPickerActivity a) {
- final Runnable onLoad;
- if (!mFirstClick) {
- onLoad = null;
- } else {
- mFirstClick = false;
- a.mSetWallpaperButton.setEnabled(false);
- onLoad = new Runnable() {
- public void run() {
- if (mBitmapSource != null &&
- mBitmapSource.getLoadingState() == BitmapSource.State.LOADED) {
- a.selectTile(mView);
- a.mSetWallpaperButton.setEnabled(true);
- } else {
- ViewGroup parent = (ViewGroup) mView.getParent();
- if (parent != null) {
- parent.removeView(mView);
- Toast.makeText(a,
- a.getString(R.string.image_load_fail),
- Toast.LENGTH_SHORT).show();
- }
+ a.setWallpaperButtonEnabled(false);
+ final BitmapRegionTileSource.UriBitmapSource bitmapSource =
+ new BitmapRegionTileSource.UriBitmapSource(a.getContext(), mUri);
+ a.setCropViewTileSource(bitmapSource, true, false, null, new Runnable() {
+
+ @Override
+ public void run() {
+ if (bitmapSource.getLoadingState() == BitmapSource.State.LOADED) {
+ a.selectTile(mView);
+ a.setWallpaperButtonEnabled(true);
+ } else {
+ ViewGroup parent = (ViewGroup) mView.getParent();
+ if (parent != null) {
+ parent.removeView(mView);
+ Toast.makeText(a.getContext(), R.string.image_load_fail,
+ Toast.LENGTH_SHORT).show();
}
}
- };
- }
- mBitmapSource = new BitmapRegionTileSource.UriBitmapSource(
- a, mUri, BitmapRegionTileSource.MAX_PREVIEW_SIZE);
- a.setCropViewTileSource(mBitmapSource, true, false, onLoad);
+ }
+ });
}
@Override
public void onSave(final WallpaperPickerActivity a) {
boolean finishActivityWhenDone = true;
- OnBitmapCroppedHandler h = new OnBitmapCroppedHandler() {
+ BitmapCropTask.OnBitmapCroppedHandler h = new BitmapCropTask.OnBitmapCroppedHandler() {
public void onBitmapCropped(byte[] imageBytes) {
Point thumbSize = getDefaultThumbnailSize(a.getResources());
// rotation is set to 0 since imageBytes has already been correctly rotated
@@ -203,10 +198,19 @@ public class WallpaperPickerActivity extends WallpaperCropActivity {
mThumb = thumb;
}
@Override
- public void onClick(WallpaperPickerActivity a) {
- BitmapRegionTileSource.UriBitmapSource bitmapSource =
- new BitmapRegionTileSource.UriBitmapSource(a, Uri.fromFile(mFile), 1024);
- a.setCropViewTileSource(bitmapSource, false, true, null);
+ public void onClick(final WallpaperPickerActivity a) {
+ a.setWallpaperButtonEnabled(false);
+ final BitmapRegionTileSource.UriBitmapSource bitmapSource =
+ new BitmapRegionTileSource.UriBitmapSource(a.getContext(), Uri.fromFile(mFile));
+ a.setCropViewTileSource(bitmapSource, false, true, null, new Runnable() {
+
+ @Override
+ public void run() {
+ if (bitmapSource.getLoadingState() == BitmapSource.State.LOADED) {
+ a.setWallpaperButtonEnabled(true);
+ }
+ }
+ });
}
@Override
public void onSave(WallpaperPickerActivity a) {
@@ -232,22 +236,30 @@ public class WallpaperPickerActivity extends WallpaperCropActivity {
mThumb = thumb;
}
@Override
- public void onClick(WallpaperPickerActivity a) {
- BitmapRegionTileSource.ResourceBitmapSource bitmapSource =
- new BitmapRegionTileSource.ResourceBitmapSource(
- mResources, mResId, BitmapRegionTileSource.MAX_PREVIEW_SIZE);
- bitmapSource.loadInBackground();
- BitmapRegionTileSource source = new BitmapRegionTileSource(a, bitmapSource);
- CropView v = a.getCropView();
- v.setTileSource(source, null);
- Point wallpaperSize = WallpaperCropActivity.getDefaultWallpaperSize(
- a.getResources(), a.getWindowManager());
- RectF crop = WallpaperCropActivity.getMaxCropRect(
- source.getImageWidth(), source.getImageHeight(),
- wallpaperSize.x, wallpaperSize.y, false);
- v.setScale(wallpaperSize.x / crop.width());
- v.setTouchEnabled(false);
- a.setSystemWallpaperVisiblity(false);
+ public void onClick(final WallpaperPickerActivity a) {
+ a.setWallpaperButtonEnabled(false);
+ final BitmapRegionTileSource.ResourceBitmapSource bitmapSource =
+ new BitmapRegionTileSource.ResourceBitmapSource(mResources, mResId);
+ a.setCropViewTileSource(bitmapSource, false, false, new CropViewScaleProvider() {
+
+ @Override
+ public float getScale(TileSource src) {
+ Point wallpaperSize = WallpaperUtils.getDefaultWallpaperSize(
+ a.getResources(), a.getWindowManager());
+ RectF crop = Utils.getMaxCropRect(
+ src.getImageWidth(), src.getImageHeight(),
+ wallpaperSize.x, wallpaperSize.y, false);
+ return wallpaperSize.x / crop.width();
+ }
+ }, new Runnable() {
+
+ @Override
+ public void run() {
+ if (bitmapSource.getLoadingState() == BitmapSource.State.LOADED) {
+ a.setWallpaperButtonEnabled(true);
+ }
+ }
+ });
}
@Override
public void onSave(WallpaperPickerActivity a) {
@@ -272,27 +284,33 @@ public class WallpaperPickerActivity extends WallpaperCropActivity {
@Override
public void onClick(WallpaperPickerActivity a) {
CropView c = a.getCropView();
-
- Drawable defaultWallpaper = WallpaperManager.getInstance(a).getBuiltInDrawable(
- c.getWidth(), c.getHeight(), false, 0.5f, 0.5f);
-
+ Drawable defaultWallpaper = WallpaperManager.getInstance(a.getContext())
+ .getBuiltInDrawable(c.getWidth(), c.getHeight(), false, 0.5f, 0.5f);
if (defaultWallpaper == null) {
Log.w(TAG, "Null default wallpaper encountered.");
c.setTileSource(null, null);
return;
}
- c.setTileSource(
- new DrawableTileSource(a, defaultWallpaper, DrawableTileSource.MAX_PREVIEW_SIZE), null);
- c.setScale(1f);
- c.setTouchEnabled(false);
- a.setSystemWallpaperVisiblity(false);
+ LoadRequest req = new LoadRequest();
+ req.moveToLeft = false;
+ req.touchEnabled = false;
+ req.scaleProvider = new CropViewScaleProvider() {
+
+ @Override
+ public float getScale(TileSource src) {
+ return 1f;
+ }
+ };
+ req.result = new DrawableTileSource(a.getContext(),
+ defaultWallpaper, DrawableTileSource.MAX_PREVIEW_SIZE);
+ a.onLoadRequestComplete(req, true);
}
@Override
public void onSave(WallpaperPickerActivity a) {
try {
- WallpaperManager.getInstance(a).clear();
- a.setResult(RESULT_OK);
+ WallpaperManager.getInstance(a.getContext()).clear();
+ a.setResult(Activity.RESULT_OK);
} catch (IOException e) {
Log.w("Setting wallpaper to default threw exception", e);
}
@@ -308,10 +326,6 @@ public class WallpaperPickerActivity extends WallpaperCropActivity {
}
}
- public void setWallpaperStripYOffset(float offset) {
- mWallpaperStrip.setPadding(0, 0, 0, (int) offset);
- }
-
/**
* shows the system wallpaper behind the window and hides the {@link
* #mCropView} if visible
@@ -338,7 +352,7 @@ public class WallpaperPickerActivity extends WallpaperCropActivity {
}, FLAG_POST_DELAY_MILLIS);
}
- private void changeWallpaperFlags(boolean visible) {
+ @Thunk void changeWallpaperFlags(boolean visible) {
int desiredWallpaperFlag = visible ? WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER : 0;
int currentWallpaperFlag = getWindow().getAttributes().flags
& WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
@@ -349,24 +363,11 @@ public class WallpaperPickerActivity extends WallpaperCropActivity {
}
@Override
- public void setCropViewTileSource(BitmapSource bitmapSource,
- boolean touchEnabled,
- boolean moveToLeft,
- final Runnable postExecute) {
- // we also want to show our own wallpaper instead of the one in the background
- Runnable showPostExecuteRunnable = new Runnable() {
- @Override
- public void run() {
- if(postExecute != null) {
- postExecute.run();
- }
- setSystemWallpaperVisiblity(false);
- }
- };
- super.setCropViewTileSource(bitmapSource,
- touchEnabled,
- moveToLeft,
- showPostExecuteRunnable);
+ protected void onLoadRequestComplete(LoadRequest req, boolean success) {
+ super.onLoadRequestComplete(req, success);
+ if (success) {
+ setSystemWallpaperVisiblity(false);
+ }
}
// called by onCreate; this is subclassed to overwrite WallpaperCropActivity
@@ -376,7 +377,8 @@ public class WallpaperPickerActivity extends WallpaperCropActivity {
mCropView = (CropView) findViewById(R.id.cropView);
mCropView.setVisibility(View.INVISIBLE);
- mWallpaperStrip = findViewById(R.id.wallpaper_strip);
+ mProgressView = findViewById(R.id.loading);
+ mWallpaperScrollContainer = (HorizontalScrollView) findViewById(R.id.wallpaper_scroll_container);
mCropView.setTouchCallback(new CropView.TouchCallback() {
ViewPropertyAnimator mAnim;
@Override
@@ -384,15 +386,15 @@ public class WallpaperPickerActivity extends WallpaperCropActivity {
if (mAnim != null) {
mAnim.cancel();
}
- if (mWallpaperStrip.getAlpha() == 1f) {
+ if (mWallpaperScrollContainer.getAlpha() == 1f) {
mIgnoreNextTap = true;
}
- mAnim = mWallpaperStrip.animate();
+ mAnim = mWallpaperScrollContainer.animate();
mAnim.alpha(0f)
.setDuration(150)
.withEndAction(new Runnable() {
public void run() {
- mWallpaperStrip.setVisibility(View.INVISIBLE);
+ mWallpaperScrollContainer.setVisibility(View.INVISIBLE);
}
});
mAnim.setInterpolator(new AccelerateInterpolator(0.75f));
@@ -410,8 +412,8 @@ public class WallpaperPickerActivity extends WallpaperCropActivity {
if (mAnim != null) {
mAnim.cancel();
}
- mWallpaperStrip.setVisibility(View.VISIBLE);
- mAnim = mWallpaperStrip.animate();
+ mWallpaperScrollContainer.setVisibility(View.VISIBLE);
+ mAnim = mWallpaperScrollContainer.animate();
mAnim.alpha(1f)
.setDuration(150)
.setInterpolator(new DecelerateInterpolator(0.75f));
@@ -429,7 +431,7 @@ public class WallpaperPickerActivity extends WallpaperCropActivity {
}
return;
}
- mSetWallpaperButton.setEnabled(true);
+ setWallpaperButtonEnabled(true);
WallpaperTileInfo info = (WallpaperTileInfo) v.getTag();
if (info.isSelectable() && v.getVisibility() == View.VISIBLE) {
selectTile(v);
@@ -460,18 +462,18 @@ public class WallpaperPickerActivity extends WallpaperCropActivity {
// Populate the built-in wallpapers
ArrayList<WallpaperTileInfo> wallpapers = findBundledWallpapers();
mWallpapersView = (LinearLayout) findViewById(R.id.wallpaper_list);
- SimpleWallpapersAdapter ia = new SimpleWallpapersAdapter(this, wallpapers);
+ SimpleWallpapersAdapter ia = new SimpleWallpapersAdapter(getContext(), wallpapers);
populateWallpapersFromAdapter(mWallpapersView, ia, false);
// Populate the saved wallpapers
- mSavedImages = new SavedWallpaperImages(this);
+ mSavedImages = new SavedWallpaperImages(getContext());
mSavedImages.loadThumbnailsAndImageIdList();
populateWallpapersFromAdapter(mWallpapersView, mSavedImages, true);
// Populate the live wallpapers
final LinearLayout liveWallpapersView =
(LinearLayout) findViewById(R.id.live_wallpaper_list);
- final LiveWallpaperListAdapter a = new LiveWallpaperListAdapter(this);
+ final LiveWallpaperListAdapter a = new LiveWallpaperListAdapter(getContext());
a.registerDataSetObserver(new DataSetObserver() {
public void onChanged() {
liveWallpapersView.removeAllViews();
@@ -485,14 +487,13 @@ public class WallpaperPickerActivity extends WallpaperCropActivity {
final LinearLayout thirdPartyWallpapersView =
(LinearLayout) findViewById(R.id.third_party_wallpaper_list);
final ThirdPartyWallpaperPickerListAdapter ta =
- new ThirdPartyWallpaperPickerListAdapter(this);
+ new ThirdPartyWallpaperPickerListAdapter(getContext());
populateWallpapersFromAdapter(thirdPartyWallpapersView, ta, false);
// Add a tile for the Gallery
LinearLayout masterWallpaperList = (LinearLayout) findViewById(R.id.master_wallpaper_list);
FrameLayout pickImageTile = (FrameLayout) getLayoutInflater().
inflate(R.layout.wallpaper_picker_image_picker_item, masterWallpaperList, false);
- setWallpaperItemPaddingToZero(pickImageTile);
masterWallpaperList.addView(pickImageTile, 0);
// Make its background the last photo taken on external storage
@@ -500,10 +501,9 @@ public class WallpaperPickerActivity extends WallpaperCropActivity {
if (lastPhoto != null) {
ImageView galleryThumbnailBg =
(ImageView) pickImageTile.findViewById(R.id.wallpaper_image);
- galleryThumbnailBg.setImageBitmap(getThumbnailOfLastPhoto());
+ galleryThumbnailBg.setImageBitmap(lastPhoto);
int colorOverlay = getResources().getColor(R.color.wallpaper_picker_translucent_gray);
galleryThumbnailBg.setColorFilter(colorOverlay, PorterDuff.Mode.SRC_ATOP);
-
}
PickImageInfo pickImageInfo = new PickImageInfo();
@@ -650,7 +650,11 @@ public class WallpaperPickerActivity extends WallpaperCropActivity {
};
}
- private void selectTile(View v) {
+ public void setWallpaperButtonEnabled(boolean enabled) {
+ mSetWallpaperButton.setEnabled(enabled);
+ }
+
+ @Thunk void selectTile(View v) {
if (mSelectedTile != null) {
mSelectedTile.setSelected(false);
mSelectedTile = null;
@@ -661,28 +665,35 @@ public class WallpaperPickerActivity extends WallpaperCropActivity {
// TODO: Remove this once the accessibility framework and
// services have better support for selection state.
v.announceForAccessibility(
- getString(R.string.announce_selection, v.getContentDescription()));
+ getContext().getString(R.string.announce_selection, v.getContentDescription()));
}
- private void initializeScrollForRtl() {
- final HorizontalScrollView scroll =
- (HorizontalScrollView) findViewById(R.id.wallpaper_scroll_container);
-
- if (scroll.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL) {
- final ViewTreeObserver observer = scroll.getViewTreeObserver();
+ @Thunk void initializeScrollForRtl() {
+ if (Utilities.isRtl(getResources())) {
+ final ViewTreeObserver observer = mWallpaperScrollContainer.getViewTreeObserver();
observer.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
public void onGlobalLayout() {
LinearLayout masterWallpaperList =
(LinearLayout) findViewById(R.id.master_wallpaper_list);
- scroll.scrollTo(masterWallpaperList.getWidth(), 0);
- scroll.getViewTreeObserver().removeOnGlobalLayoutListener(this);
+ mWallpaperScrollContainer.scrollTo(masterWallpaperList.getWidth(), 0);
+ mWallpaperScrollContainer.getViewTreeObserver().removeOnGlobalLayoutListener(this);
}
});
}
}
protected Bitmap getThumbnailOfLastPhoto() {
- Cursor cursor = MediaStore.Images.Media.query(getContentResolver(),
+ boolean canReadExternalStorage = getActivity().checkPermission(
+ Manifest.permission.READ_EXTERNAL_STORAGE, Process.myPid(), Process.myUid()) ==
+ PackageManager.PERMISSION_GRANTED;
+
+ if (!canReadExternalStorage) {
+ // MediaStore.Images.Media.EXTERNAL_CONTENT_URI requires
+ // the READ_EXTERNAL_STORAGE permission
+ return null;
+ }
+
+ Cursor cursor = MediaStore.Images.Media.query(getContext().getContentResolver(),
MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
new String[] { MediaStore.Images.ImageColumns._ID,
MediaStore.Images.ImageColumns.DATE_TAKEN},
@@ -692,7 +703,7 @@ public class WallpaperPickerActivity extends WallpaperCropActivity {
if (cursor != null) {
if (cursor.moveToNext()) {
int id = cursor.getInt(0);
- thumb = MediaStore.Images.Thumbnails.getThumbnail(getContentResolver(),
+ thumb = MediaStore.Images.Thumbnails.getThumbnail(getContext().getContentResolver(),
id, MediaStore.Images.Thumbnails.MINI_KIND, null);
}
cursor.close();
@@ -700,16 +711,16 @@ public class WallpaperPickerActivity extends WallpaperCropActivity {
return thumb;
}
- protected void onStop() {
+ public void onStop() {
super.onStop();
- mWallpaperStrip = findViewById(R.id.wallpaper_strip);
- if (mWallpaperStrip.getAlpha() < 1f) {
- mWallpaperStrip.setAlpha(1f);
- mWallpaperStrip.setVisibility(View.VISIBLE);
+ mWallpaperScrollContainer = (HorizontalScrollView) findViewById(R.id.wallpaper_scroll_container);
+ if (mWallpaperScrollContainer.getAlpha() < 1f) {
+ mWallpaperScrollContainer.setAlpha(1f);
+ mWallpaperScrollContainer.setVisibility(View.VISIBLE);
}
}
- protected void onSaveInstanceState(Bundle outState) {
+ public void onSaveInstanceState(Bundle outState) {
outState.putParcelableArrayList(TEMP_WALLPAPER_TILES, mTempWallpaperTiles);
outState.putInt(SELECTED_INDEX, mSelectedIndex);
}
@@ -722,7 +733,7 @@ public class WallpaperPickerActivity extends WallpaperCropActivity {
mSelectedIndex = savedInstanceState.getInt(SELECTED_INDEX, -1);
}
- private void populateWallpapersFromAdapter(ViewGroup parent, BaseAdapter adapter,
+ @Thunk void populateWallpapersFromAdapter(ViewGroup parent, BaseAdapter adapter,
boolean addLongPressHandler) {
for (int i = 0; i < adapter.getCount(); i++) {
FrameLayout thumbnail = (FrameLayout) adapter.getView(i, null, parent);
@@ -737,7 +748,7 @@ public class WallpaperPickerActivity extends WallpaperCropActivity {
}
}
- private void updateTileIndices() {
+ @Thunk void updateTileIndices() {
LinearLayout masterWallpaperList = (LinearLayout) findViewById(R.id.master_wallpaper_list);
final int childCount = masterWallpaperList.getChildCount();
final Resources res = getResources();
@@ -778,13 +789,13 @@ public class WallpaperPickerActivity extends WallpaperCropActivity {
}
}
- private static Point getDefaultThumbnailSize(Resources res) {
+ @Thunk static Point getDefaultThumbnailSize(Resources res) {
return new Point(res.getDimensionPixelSize(R.dimen.wallpaperThumbnailWidth),
res.getDimensionPixelSize(R.dimen.wallpaperThumbnailHeight));
}
- private static Bitmap createThumbnail(Point size, Context context, Uri uri, byte[] imageBytes,
+ @Thunk static Bitmap createThumbnail(Point size, Context context, Uri uri, byte[] imageBytes,
Resources res, int resId, int rotation, boolean leftAligned) {
int width = size.x;
int height = size.y;
@@ -812,7 +823,7 @@ public class WallpaperPickerActivity extends WallpaperCropActivity {
rotatedBounds[0] = Math.abs(rotatedBounds[0]);
rotatedBounds[1] = Math.abs(rotatedBounds[1]);
- RectF cropRect = WallpaperCropActivity.getMaxCropRect(
+ RectF cropRect = Utils.getMaxCropRect(
(int) rotatedBounds[0], (int) rotatedBounds[1], width, height, leftAligned);
cropTask.setCropBounds(cropRect);
@@ -829,20 +840,19 @@ public class WallpaperPickerActivity extends WallpaperCropActivity {
final FrameLayout pickedImageThumbnail = (FrameLayout) getLayoutInflater().
inflate(R.layout.wallpaper_picker_item, mWallpapersView, false);
pickedImageThumbnail.setVisibility(View.GONE);
- setWallpaperItemPaddingToZero(pickedImageThumbnail);
mWallpapersView.addView(pickedImageThumbnail, 0);
// Load the thumbnail
final ImageView image = (ImageView) pickedImageThumbnail.findViewById(R.id.wallpaper_image);
final Point defaultSize = getDefaultThumbnailSize(this.getResources());
- final Context context = this;
+ final Context context = getContext();
new AsyncTask<Void, Bitmap, Bitmap>() {
protected Bitmap doInBackground(Void...args) {
try {
- int rotation = WallpaperCropActivity.getRotationFromExif(context, uri);
+ int rotation = BitmapUtils.getRotationFromExif(context, uri);
return createThumbnail(defaultSize, context, uri, null, null, 0, rotation, false);
} catch (SecurityException securityException) {
- if (isDestroyed()) {
+ if (isActivityDestroyed()) {
// Temporarily granted permissions are revoked when the activity
// finishes, potentially resulting in a SecurityException here.
// Even though {@link #isDestroyed} might also return true in different
@@ -879,45 +889,35 @@ public class WallpaperPickerActivity extends WallpaperCropActivity {
}
}
- protected void onActivityResult(int requestCode, int resultCode, Intent data) {
- if (requestCode == IMAGE_PICK && resultCode == RESULT_OK) {
+ public void onActivityResult(int requestCode, int resultCode, Intent data) {
+ if (requestCode == IMAGE_PICK && resultCode == Activity.RESULT_OK) {
if (data != null && data.getData() != null) {
Uri uri = data.getData();
addTemporaryWallpaperTile(uri, false);
}
- } else if (requestCode == PICK_WALLPAPER_THIRD_PARTY_ACTIVITY) {
- setResult(RESULT_OK);
+ } else if (requestCode == PICK_WALLPAPER_THIRD_PARTY_ACTIVITY
+ && resultCode == Activity.RESULT_OK) {
+ // Something was set on the third-party activity.
+ setResult(Activity.RESULT_OK);
finish();
- } else if (requestCode == PICK_LIVE_WALLPAPER) {
- WallpaperManager wm = WallpaperManager.getInstance(this);
- final WallpaperInfo oldLiveWallpaper = mLiveWallpaperInfoOnPickerLaunch;
- final WallpaperInfo clickedWallpaper = mLastClickedLiveWallpaperInfo;
- WallpaperInfo newLiveWallpaper = wm.getWallpaperInfo();
- // Try to figure out if a live wallpaper was set;
- if (newLiveWallpaper != null &&
- (oldLiveWallpaper == null
- || !oldLiveWallpaper.getComponent()
- .equals(newLiveWallpaper.getComponent())
- || clickedWallpaper.getComponent()
- .equals(oldLiveWallpaper.getComponent()))) {
- // Return if a live wallpaper was set
- setResult(RESULT_OK);
- finish();
- }
}
}
- static void setWallpaperItemPaddingToZero(FrameLayout frameLayout) {
- frameLayout.setPadding(0, 0, 0, 0);
- frameLayout.setForeground(new ZeroPaddingDrawable(frameLayout.getForeground()));
- }
-
private void addLongPressHandler(View v) {
v.setOnLongClickListener(mLongClickListener);
+
+ // Enable stylus button to also trigger long click.
+ final StylusEventHelper stylusEventHelper = new StylusEventHelper(v);
+ v.setOnTouchListener(new View.OnTouchListener() {
+ @Override
+ public boolean onTouch(View view, MotionEvent event) {
+ return stylusEventHelper.checkAndPerformStylusEvent(event);
+ }
+ });
}
private ArrayList<WallpaperTileInfo> findBundledWallpapers() {
- final PackageManager pm = getPackageManager();
+ final PackageManager pm = getContext().getPackageManager();
final ArrayList<WallpaperTileInfo> bundled = new ArrayList<WallpaperTileInfo>(24);
Partner partner = Partner.get(pm);
@@ -961,7 +961,8 @@ public class WallpaperPickerActivity extends WallpaperCropActivity {
Pair<ApplicationInfo, Integer> r = getWallpaperArrayResourceId();
if (r != null) {
try {
- Resources wallpaperRes = getPackageManager().getResourcesForApplication(r.first);
+ Resources wallpaperRes = getContext().getPackageManager()
+ .getResourcesForApplication(r.first);
addWallpapers(bundled, wallpaperRes, r.first.packageName, r.second);
} catch (PackageManager.NameNotFoundException e) {
}
@@ -984,7 +985,7 @@ public class WallpaperPickerActivity extends WallpaperCropActivity {
try {
f.createNewFile();
FileOutputStream thumbFileStream =
- openFileOutput(f.getName(), Context.MODE_PRIVATE);
+ getContext().openFileOutput(f.getName(), Context.MODE_PRIVATE);
b.compress(Bitmap.CompressFormat.JPEG, 95, thumbFileStream);
thumbFileStream.close();
return true;
@@ -996,17 +997,18 @@ public class WallpaperPickerActivity extends WallpaperCropActivity {
}
private File getDefaultThumbFile() {
- return new File(getFilesDir(), Build.VERSION.SDK_INT
+ return new File(getContext().getFilesDir(), Build.VERSION.SDK_INT
+ "_" + LauncherFiles.DEFAULT_WALLPAPER_THUMBNAIL);
}
private boolean saveDefaultWallpaperThumb(Bitmap b) {
// Delete old thumbnails.
- new File(getFilesDir(), LauncherFiles.DEFAULT_WALLPAPER_THUMBNAIL_OLD).delete();
- new File(getFilesDir(), LauncherFiles.DEFAULT_WALLPAPER_THUMBNAIL).delete();
+ new File(getContext().getFilesDir(), LauncherFiles.DEFAULT_WALLPAPER_THUMBNAIL_OLD).delete();
+ new File(getContext().getFilesDir(), LauncherFiles.DEFAULT_WALLPAPER_THUMBNAIL).delete();
for (int i = Build.VERSION_CODES.JELLY_BEAN; i < Build.VERSION.SDK_INT; i++) {
- new File(getFilesDir(), i + "_" + LauncherFiles.DEFAULT_WALLPAPER_THUMBNAIL).delete();
+ new File(getContext().getFilesDir(), i + "_"
+ + LauncherFiles.DEFAULT_WALLPAPER_THUMBNAIL).delete();
}
return writeImageToFileAsJpeg(getDefaultThumbFile(), b);
}
@@ -1024,9 +1026,9 @@ public class WallpaperPickerActivity extends WallpaperCropActivity {
} else {
Resources res = getResources();
Point defaultThumbSize = getDefaultThumbnailSize(res);
- int rotation = WallpaperCropActivity.getRotationFromExif(res, resId);
+ int rotation = BitmapUtils.getRotationFromExif(res, resId);
thumb = createThumbnail(
- defaultThumbSize, this, null, null, sysRes, resId, rotation, false);
+ defaultThumbSize, getContext(), null, null, sysRes, resId, rotation, false);
if (thumb != null) {
defaultWallpaperExists = saveDefaultWallpaperThumb(thumb);
}
@@ -1048,7 +1050,7 @@ public class WallpaperPickerActivity extends WallpaperCropActivity {
} else {
Resources res = getResources();
Point defaultThumbSize = getDefaultThumbnailSize(res);
- Drawable wallpaperDrawable = WallpaperManager.getInstance(this).getBuiltInDrawable(
+ Drawable wallpaperDrawable = WallpaperManager.getInstance(getContext()).getBuiltInDrawable(
defaultThumbSize.x, defaultThumbSize.y, true, 0.5f, 0.5f);
if (wallpaperDrawable != null) {
thumb = Bitmap.createBitmap(
@@ -1075,7 +1077,7 @@ public class WallpaperPickerActivity extends WallpaperCropActivity {
// package name should be.
final String packageName = getResources().getResourcePackageName(R.array.wallpapers);
try {
- ApplicationInfo info = getPackageManager().getApplicationInfo(packageName, 0);
+ ApplicationInfo info = getContext().getPackageManager().getApplicationInfo(packageName, 0);
return new Pair<ApplicationInfo, Integer>(info, R.array.wallpapers);
} catch (PackageManager.NameNotFoundException e) {
return null;
@@ -1110,31 +1112,12 @@ public class WallpaperPickerActivity extends WallpaperCropActivity {
return mSavedImages;
}
- public void onLiveWallpaperPickerLaunch(WallpaperInfo info) {
- mLastClickedLiveWallpaperInfo = info;
- mLiveWallpaperInfoOnPickerLaunch = WallpaperManager.getInstance(this).getWallpaperInfo();
- }
-
- static class ZeroPaddingDrawable extends LevelListDrawable {
- public ZeroPaddingDrawable(Drawable d) {
- super();
- addLevel(0, 0, d);
- setLevel(0);
- }
-
- @Override
- public boolean getPadding(Rect padding) {
- padding.set(0, 0, 0, 0);
- return true;
- }
- }
-
private static class SimpleWallpapersAdapter extends ArrayAdapter<WallpaperTileInfo> {
private final LayoutInflater mLayoutInflater;
- SimpleWallpapersAdapter(Activity activity, ArrayList<WallpaperTileInfo> wallpapers) {
- super(activity, R.layout.wallpaper_picker_item, wallpapers);
- mLayoutInflater = activity.getLayoutInflater();
+ SimpleWallpapersAdapter(Context context, ArrayList<WallpaperTileInfo> wallpapers) {
+ super(context, R.layout.wallpaper_picker_item, wallpapers);
+ mLayoutInflater = LayoutInflater.from(context);
}
public View getView(int position, View convertView, ViewGroup parent) {
@@ -1156,8 +1139,6 @@ public class WallpaperPickerActivity extends WallpaperCropActivity {
view = convertView;
}
- setWallpaperItemPaddingToZero((FrameLayout) view);
-
ImageView image = (ImageView) view.findViewById(R.id.wallpaper_image);
if (thumb != null) {
@@ -1168,9 +1149,17 @@ public class WallpaperPickerActivity extends WallpaperCropActivity {
return view;
}
- // In Launcher3, we override this with a method that catches exceptions
- // from starting activities; didn't want to copy and paste code into here
public void startActivityForResultSafely(Intent intent, int requestCode) {
- startActivityForResult(intent, requestCode);
+ Utilities.startActivityForResultSafely(getActivity(), intent, requestCode);
+ }
+
+ @Override
+ public boolean enableRotation() {
+ // Check if rotation is enabled for this device.
+ if (Utilities.isRotationAllowedForDevice(getContext()))
+ return true;
+
+ // Check if the user has specifically enabled rotation via preferences.
+ return Utilities.isAllowRotationPrefEnabled(getApplicationContext(), true);
}
}
diff --git a/WallpaperPicker/src/com/android/launcher3/WallpaperRootView.java b/WallpaperPicker/src/com/android/launcher3/WallpaperRootView.java
deleted file mode 100644
index ceaa043a7..000000000
--- a/WallpaperPicker/src/com/android/launcher3/WallpaperRootView.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * 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.
- */
-
-package com.android.launcher3;
-
-import android.content.Context;
-import android.graphics.Rect;
-import android.util.AttributeSet;
-import android.widget.RelativeLayout;
-
-public class WallpaperRootView extends RelativeLayout {
- private final WallpaperPickerActivity a;
- public WallpaperRootView(Context context, AttributeSet attrs) {
- super(context, attrs);
- a = (WallpaperPickerActivity) context;
- }
- public WallpaperRootView(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
- a = (WallpaperPickerActivity) context;
- }
-
- protected boolean fitSystemWindows(Rect insets) {
- a.setWallpaperStripYOffset(insets.bottom);
- return true;
- }
-}
diff --git a/WallpaperPicker/src/com/android/launcher3/base/BaseActivity.java b/WallpaperPicker/src/com/android/launcher3/base/BaseActivity.java
new file mode 100644
index 000000000..f8541188f
--- /dev/null
+++ b/WallpaperPicker/src/com/android/launcher3/base/BaseActivity.java
@@ -0,0 +1,21 @@
+package com.android.launcher3.base;
+
+import android.app.Activity;
+import android.content.Context;
+
+/**
+ * A wrapper over {@link Activity} which allows to override some methods.
+ * The base implementation can change from an Activity to a Fragment (or any other custom
+ * implementation), Callers should not assume that the base class extends Context, instead use
+ * either {@link #getContext} or {@link #getActivity}
+ */
+public class BaseActivity extends Activity {
+
+ public Context getContext() {
+ return this;
+ }
+
+ public Activity getActivity() {
+ return this;
+ }
+}
diff --git a/WallpaperPicker/src/com/android/photos/BitmapRegionTileSource.java b/WallpaperPicker/src/com/android/photos/BitmapRegionTileSource.java
index 66ece4ff6..2d496a5a6 100644
--- a/WallpaperPicker/src/com/android/photos/BitmapRegionTileSource.java
+++ b/WallpaperPicker/src/com/android/photos/BitmapRegionTileSource.java
@@ -20,15 +20,14 @@ import android.annotation.TargetApi;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
-import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory;
import android.graphics.BitmapRegionDecoder;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.net.Uri;
+import android.opengl.GLUtils;
import android.os.Build;
-import android.os.Build.VERSION_CODES;
import android.util.Log;
import com.android.gallery3d.common.BitmapUtils;
@@ -148,24 +147,19 @@ public class BitmapRegionTileSource implements TiledImageRenderer.TileSource {
private static final String TAG = "BitmapRegionTileSource";
- private static final boolean REUSE_BITMAP =
- Build.VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN;
private static final int GL_SIZE_LIMIT = 2048;
// This must be no larger than half the size of the GL_SIZE_LIMIT
// due to decodePreview being allowed to be up to 2x the size of the target
- public static final int MAX_PREVIEW_SIZE = GL_SIZE_LIMIT / 2;
+ private static final int MAX_PREVIEW_SIZE = GL_SIZE_LIMIT / 2;
public static abstract class BitmapSource {
private SimpleBitmapRegionDecoder mDecoder;
private Bitmap mPreview;
- private int mPreviewSize;
private int mRotation;
public enum State { NOT_LOADED, LOADED, ERROR_LOADING };
private State mState = State.NOT_LOADED;
- public BitmapSource(int previewSize) {
- mPreviewSize = previewSize;
- }
- public boolean loadInBackground() {
+
+ public boolean loadInBackground(InBitmapProvider bitmapProvider) {
ExifInterface ei = new ExifInterface();
if (readExif(ei)) {
Integer ori = ei.getTagIntValue(ExifInterface.TAG_ORIENTATION);
@@ -180,18 +174,44 @@ public class BitmapRegionTileSource implements TiledImageRenderer.TileSource {
} else {
int width = mDecoder.getWidth();
int height = mDecoder.getHeight();
- if (mPreviewSize != 0) {
- int previewSize = Math.min(mPreviewSize, MAX_PREVIEW_SIZE);
- BitmapFactory.Options opts = new BitmapFactory.Options();
- opts.inPreferredConfig = Bitmap.Config.ARGB_8888;
- opts.inPreferQualityOverSpeed = true;
-
- float scale = (float) previewSize / Math.max(width, height);
- opts.inSampleSize = BitmapUtils.computeSampleSizeLarger(scale);
- opts.inJustDecodeBounds = false;
+
+ BitmapFactory.Options opts = new BitmapFactory.Options();
+ opts.inPreferredConfig = Bitmap.Config.ARGB_8888;
+ opts.inPreferQualityOverSpeed = true;
+
+ float scale = (float) MAX_PREVIEW_SIZE / Math.max(width, height);
+ opts.inSampleSize = BitmapUtils.computeSampleSizeLarger(scale);
+ opts.inJustDecodeBounds = false;
+ opts.inMutable = true;
+
+ if (bitmapProvider != null) {
+ int expectedPixles = (width / opts.inSampleSize) * (height / opts.inSampleSize);
+ Bitmap reusableBitmap = bitmapProvider.forPixelCount(expectedPixles);
+ if (reusableBitmap != null) {
+ // Try loading with reusable bitmap
+ opts.inBitmap = reusableBitmap;
+ try {
+ mPreview = loadPreviewBitmap(opts);
+ } catch (IllegalArgumentException e) {
+ Log.d(TAG, "Unable to reusage bitmap", e);
+ opts.inBitmap = null;
+ mPreview = null;
+ }
+ }
+ }
+ if (mPreview == null) {
mPreview = loadPreviewBitmap(opts);
}
- mState = State.LOADED;
+
+ // Verify that the bitmap can be used on GL surface
+ try {
+ GLUtils.getInternalFormat(mPreview);
+ GLUtils.getType(mPreview);
+ mState = State.LOADED;
+ } catch (IllegalArgumentException e) {
+ Log.d(TAG, "Image cannot be rendered on a GL surface", e);
+ mState = State.ERROR_LOADING;
+ }
return true;
}
}
@@ -208,10 +228,6 @@ public class BitmapRegionTileSource implements TiledImageRenderer.TileSource {
return mPreview;
}
- public int getPreviewSize() {
- return mPreviewSize;
- }
-
public int getRotation() {
return mRotation;
}
@@ -219,12 +235,15 @@ public class BitmapRegionTileSource implements TiledImageRenderer.TileSource {
public abstract boolean readExif(ExifInterface ei);
public abstract SimpleBitmapRegionDecoder loadBitmapRegionDecoder();
public abstract Bitmap loadPreviewBitmap(BitmapFactory.Options options);
+
+ public interface InBitmapProvider {
+ Bitmap forPixelCount(int count);
+ }
}
public static class FilePathBitmapSource extends BitmapSource {
private String mPath;
- public FilePathBitmapSource(String path, int previewSize) {
- super(previewSize);
+ public FilePathBitmapSource(String path) {
mPath = path;
}
@Override
@@ -258,8 +277,7 @@ public class BitmapRegionTileSource implements TiledImageRenderer.TileSource {
public static class UriBitmapSource extends BitmapSource {
private Context mContext;
private Uri mUri;
- public UriBitmapSource(Context context, Uri uri, int previewSize) {
- super(previewSize);
+ public UriBitmapSource(Context context, Uri uri) {
mContext = context;
mUri = uri;
}
@@ -306,13 +324,13 @@ public class BitmapRegionTileSource implements TiledImageRenderer.TileSource {
Utils.closeSilently(is);
return true;
} catch (FileNotFoundException e) {
- Log.e("BitmapRegionTileSource", "Failed to load URI " + mUri, e);
+ Log.d("BitmapRegionTileSource", "Failed to load URI " + mUri, e);
return false;
} catch (IOException e) {
- Log.e("BitmapRegionTileSource", "Failed to load URI " + mUri, e);
+ Log.d("BitmapRegionTileSource", "Failed to load URI " + mUri, e);
return false;
} catch (NullPointerException e) {
- Log.e("BitmapRegionTileSource", "Failed to read EXIF for URI " + mUri, e);
+ Log.d("BitmapRegionTileSource", "Failed to read EXIF for URI " + mUri, e);
return false;
} finally {
Utils.closeSilently(is);
@@ -323,8 +341,7 @@ public class BitmapRegionTileSource implements TiledImageRenderer.TileSource {
public static class ResourceBitmapSource extends BitmapSource {
private Resources mRes;
private int mResId;
- public ResourceBitmapSource(Resources res, int resId, int previewSize) {
- super(previewSize);
+ public ResourceBitmapSource(Resources res, int resId) {
mRes = res;
mResId = resId;
}
@@ -372,11 +389,9 @@ public class BitmapRegionTileSource implements TiledImageRenderer.TileSource {
// For use only by getTile
private Rect mWantRegion = new Rect();
- private Rect mOverlapRegion = new Rect();
private BitmapFactory.Options mOptions;
- private Canvas mCanvas;
- public BitmapRegionTileSource(Context context, BitmapSource source) {
+ public BitmapRegionTileSource(Context context, BitmapSource source, byte[] tempStorage) {
mTileSize = TiledImageRenderer.suggestedTileSize(context);
mRotation = source.getRotation();
mDecoder = source.getBitmapRegionDecoder();
@@ -386,27 +401,26 @@ public class BitmapRegionTileSource implements TiledImageRenderer.TileSource {
mOptions = new BitmapFactory.Options();
mOptions.inPreferredConfig = Bitmap.Config.ARGB_8888;
mOptions.inPreferQualityOverSpeed = true;
- mOptions.inTempStorage = new byte[16 * 1024];
- int previewSize = source.getPreviewSize();
- if (previewSize != 0) {
- previewSize = Math.min(previewSize, MAX_PREVIEW_SIZE);
- // Although this is the same size as the Bitmap that is likely already
- // loaded, the lifecycle is different and interactions are on a different
- // thread. Thus to simplify, this source will decode its own bitmap.
- Bitmap preview = decodePreview(source, previewSize);
- if (preview.getWidth() <= GL_SIZE_LIMIT && preview.getHeight() <= GL_SIZE_LIMIT) {
+ mOptions.inTempStorage = tempStorage;
+
+ Bitmap preview = source.getPreviewBitmap();
+ if (preview != null &&
+ preview.getWidth() <= GL_SIZE_LIMIT && preview.getHeight() <= GL_SIZE_LIMIT) {
mPreview = new BitmapTexture(preview);
- } else {
- Log.w(TAG, String.format(
- "Failed to create preview of apropriate size! "
- + " in: %dx%d, out: %dx%d",
- mWidth, mHeight,
- preview.getWidth(), preview.getHeight()));
- }
+ } else {
+ Log.w(TAG, String.format(
+ "Failed to create preview of apropriate size! "
+ + " in: %dx%d, out: %dx%d",
+ mWidth, mHeight,
+ preview.getWidth(), preview.getHeight()));
}
}
}
+ public Bitmap getBitmap() {
+ return mPreview instanceof BitmapTexture ? ((BitmapTexture) mPreview).getBitmap() : null;
+ }
+
@Override
public int getTileSize() {
return mTileSize;
@@ -435,10 +449,6 @@ public class BitmapRegionTileSource implements TiledImageRenderer.TileSource {
@Override
public Bitmap getTile(int level, int x, int y, Bitmap bitmap) {
int tileSize = getTileSize();
- if (!REUSE_BITMAP) {
- return getTileWithoutReusingBitmap(level, x, y, tileSize);
- }
-
int t = tileSize << level;
mWantRegion.set(x, y, x + t, y + t);
@@ -462,64 +472,4 @@ public class BitmapRegionTileSource implements TiledImageRenderer.TileSource {
}
return bitmap;
}
-
- private Bitmap getTileWithoutReusingBitmap(
- int level, int x, int y, int tileSize) {
-
- int t = tileSize << level;
- mWantRegion.set(x, y, x + t, y + t);
-
- mOverlapRegion.set(0, 0, mWidth, mHeight);
-
- mOptions.inSampleSize = (1 << level);
- Bitmap bitmap = mDecoder.decodeRegion(mOverlapRegion, mOptions);
-
- if (bitmap == null) {
- Log.w(TAG, "fail in decoding region");
- }
-
- if (mWantRegion.equals(mOverlapRegion)) {
- return bitmap;
- }
-
- Bitmap result = Bitmap.createBitmap(tileSize, tileSize, Config.ARGB_8888);
- if (mCanvas == null) {
- mCanvas = new Canvas();
- }
- mCanvas.setBitmap(result);
- mCanvas.drawBitmap(bitmap,
- (mOverlapRegion.left - mWantRegion.left) >> level,
- (mOverlapRegion.top - mWantRegion.top) >> level, null);
- mCanvas.setBitmap(null);
- return result;
- }
-
- /**
- * Note that the returned bitmap may have a long edge that's longer
- * than the targetSize, but it will always be less than 2x the targetSize
- */
- private Bitmap decodePreview(BitmapSource source, int targetSize) {
- Bitmap result = source.getPreviewBitmap();
- if (result == null) {
- return null;
- }
-
- // We need to resize down if the decoder does not support inSampleSize
- // or didn't support the specified inSampleSize (some decoders only do powers of 2)
- float scale = (float) targetSize / (float) (Math.max(result.getWidth(), result.getHeight()));
-
- if (scale <= 0.5) {
- result = BitmapUtils.resizeBitmapByScale(result, scale, true);
- }
- return ensureGLCompatibleBitmap(result);
- }
-
- private static Bitmap ensureGLCompatibleBitmap(Bitmap bitmap) {
- if (bitmap == null || bitmap.getConfig() != null) {
- return bitmap;
- }
- Bitmap newBitmap = bitmap.copy(Config.ARGB_8888, false);
- bitmap.recycle();
- return newBitmap;
- }
}
diff --git a/WallpaperPicker/src/com/android/photos/views/BlockingGLTextureView.java b/WallpaperPicker/src/com/android/photos/views/BlockingGLTextureView.java
deleted file mode 100644
index 8a0505185..000000000
--- a/WallpaperPicker/src/com/android/photos/views/BlockingGLTextureView.java
+++ /dev/null
@@ -1,438 +0,0 @@
-/*
- * 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.
- */
-
-package com.android.photos.views;
-
-import android.content.Context;
-import android.graphics.SurfaceTexture;
-import android.opengl.GLSurfaceView.Renderer;
-import android.opengl.GLUtils;
-import android.util.Log;
-import android.view.TextureView;
-import android.view.TextureView.SurfaceTextureListener;
-
-import javax.microedition.khronos.egl.EGL10;
-import javax.microedition.khronos.egl.EGLConfig;
-import javax.microedition.khronos.egl.EGLContext;
-import javax.microedition.khronos.egl.EGLDisplay;
-import javax.microedition.khronos.egl.EGLSurface;
-import javax.microedition.khronos.opengles.GL10;
-
-/**
- * A TextureView that supports blocking rendering for synchronous drawing
- */
-public class BlockingGLTextureView extends TextureView
- implements SurfaceTextureListener {
-
- private RenderThread mRenderThread;
-
- public BlockingGLTextureView(Context context) {
- super(context);
- setSurfaceTextureListener(this);
- }
-
- public void setRenderer(Renderer renderer) {
- if (mRenderThread != null) {
- throw new IllegalArgumentException("Renderer already set");
- }
- mRenderThread = new RenderThread(renderer);
- }
-
- public void render() {
- mRenderThread.render();
- }
-
- public void destroy() {
- if (mRenderThread != null) {
- mRenderThread.finish();
- mRenderThread = null;
- }
- }
-
- @Override
- public void onSurfaceTextureAvailable(SurfaceTexture surface, int width,
- int height) {
- mRenderThread.setSurface(surface);
- mRenderThread.setSize(width, height);
- }
-
- @Override
- public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width,
- int height) {
- mRenderThread.setSize(width, height);
- }
-
- @Override
- public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
- if (mRenderThread != null) {
- mRenderThread.setSurface(null);
- }
- return false;
- }
-
- @Override
- public void onSurfaceTextureUpdated(SurfaceTexture surface) {
- }
-
- @Override
- protected void finalize() throws Throwable {
- try {
- destroy();
- } catch (Throwable t) {
- // Ignore
- }
- super.finalize();
- }
-
- /**
- * An EGL helper class.
- */
-
- private static class EglHelper {
- private static final int EGL_CONTEXT_CLIENT_VERSION = 0x3098;
- private static final int EGL_OPENGL_ES2_BIT = 4;
-
- EGL10 mEgl;
- EGLDisplay mEglDisplay;
- EGLSurface mEglSurface;
- EGLConfig mEglConfig;
- EGLContext mEglContext;
-
- private EGLConfig chooseEglConfig() {
- int[] configsCount = new int[1];
- EGLConfig[] configs = new EGLConfig[1];
- int[] configSpec = getConfig();
- if (!mEgl.eglChooseConfig(mEglDisplay, configSpec, configs, 1, configsCount)) {
- throw new IllegalArgumentException("eglChooseConfig failed " +
- GLUtils.getEGLErrorString(mEgl.eglGetError()));
- } else if (configsCount[0] > 0) {
- return configs[0];
- }
- return null;
- }
-
- private static int[] getConfig() {
- return new int[] {
- EGL10.EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
- EGL10.EGL_RED_SIZE, 8,
- EGL10.EGL_GREEN_SIZE, 8,
- EGL10.EGL_BLUE_SIZE, 8,
- EGL10.EGL_ALPHA_SIZE, 8,
- EGL10.EGL_DEPTH_SIZE, 0,
- EGL10.EGL_STENCIL_SIZE, 0,
- EGL10.EGL_NONE
- };
- }
-
- EGLContext createContext(EGL10 egl, EGLDisplay eglDisplay, EGLConfig eglConfig) {
- int[] attribList = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL10.EGL_NONE };
- return egl.eglCreateContext(eglDisplay, eglConfig, EGL10.EGL_NO_CONTEXT, attribList);
- }
-
- /**
- * Initialize EGL for a given configuration spec.
- */
- public void start() {
- /*
- * Get an EGL instance
- */
- mEgl = (EGL10) EGLContext.getEGL();
-
- /*
- * Get to the default display.
- */
- mEglDisplay = mEgl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
-
- if (mEglDisplay == EGL10.EGL_NO_DISPLAY) {
- throw new RuntimeException("eglGetDisplay failed");
- }
-
- /*
- * We can now initialize EGL for that display
- */
- int[] version = new int[2];
- if (!mEgl.eglInitialize(mEglDisplay, version)) {
- throw new RuntimeException("eglInitialize failed");
- }
- mEglConfig = chooseEglConfig();
-
- /*
- * Create an EGL context. We want to do this as rarely as we can, because an
- * EGL context is a somewhat heavy object.
- */
- mEglContext = createContext(mEgl, mEglDisplay, mEglConfig);
-
- if (mEglContext == null || mEglContext == EGL10.EGL_NO_CONTEXT) {
- mEglContext = null;
- throwEglException("createContext");
- }
-
- mEglSurface = null;
- }
-
- /**
- * Create an egl surface for the current SurfaceTexture surface. If a surface
- * already exists, destroy it before creating the new surface.
- *
- * @return true if the surface was created successfully.
- */
- public boolean createSurface(SurfaceTexture surface) {
- /*
- * Check preconditions.
- */
- if (mEgl == null) {
- throw new RuntimeException("egl not initialized");
- }
- if (mEglDisplay == null) {
- throw new RuntimeException("eglDisplay not initialized");
- }
- if (mEglConfig == null) {
- throw new RuntimeException("mEglConfig not initialized");
- }
-
- /*
- * The window size has changed, so we need to create a new
- * surface.
- */
- destroySurfaceImp();
-
- /*
- * Create an EGL surface we can render into.
- */
- if (surface != null) {
- mEglSurface = mEgl.eglCreateWindowSurface(mEglDisplay, mEglConfig, surface, null);
- } else {
- mEglSurface = null;
- }
-
- if (mEglSurface == null || mEglSurface == EGL10.EGL_NO_SURFACE) {
- int error = mEgl.eglGetError();
- if (error == EGL10.EGL_BAD_NATIVE_WINDOW) {
- Log.e("EglHelper", "createWindowSurface returned EGL_BAD_NATIVE_WINDOW.");
- }
- return false;
- }
-
- /*
- * Before we can issue GL commands, we need to make sure
- * the context is current and bound to a surface.
- */
- if (!mEgl.eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext)) {
- /*
- * Could not make the context current, probably because the underlying
- * SurfaceView surface has been destroyed.
- */
- logEglErrorAsWarning("EGLHelper", "eglMakeCurrent", mEgl.eglGetError());
- return false;
- }
-
- return true;
- }
-
- /**
- * Create a GL object for the current EGL context.
- */
- public GL10 createGL() {
- return (GL10) mEglContext.getGL();
- }
-
- /**
- * Display the current render surface.
- * @return the EGL error code from eglSwapBuffers.
- */
- public int swap() {
- if (!mEgl.eglSwapBuffers(mEglDisplay, mEglSurface)) {
- return mEgl.eglGetError();
- }
- return EGL10.EGL_SUCCESS;
- }
-
- public void destroySurface() {
- destroySurfaceImp();
- }
-
- private void destroySurfaceImp() {
- if (mEglSurface != null && mEglSurface != EGL10.EGL_NO_SURFACE) {
- mEgl.eglMakeCurrent(mEglDisplay, EGL10.EGL_NO_SURFACE,
- EGL10.EGL_NO_SURFACE,
- EGL10.EGL_NO_CONTEXT);
- mEgl.eglDestroySurface(mEglDisplay, mEglSurface);
- mEglSurface = null;
- }
- }
-
- public void finish() {
- if (mEglContext != null) {
- mEgl.eglDestroyContext(mEglDisplay, mEglContext);
- mEglContext = null;
- }
- if (mEglDisplay != null) {
- mEgl.eglTerminate(mEglDisplay);
- mEglDisplay = null;
- }
- }
-
- private void throwEglException(String function) {
- throwEglException(function, mEgl.eglGetError());
- }
-
- public static void throwEglException(String function, int error) {
- String message = formatEglError(function, error);
- throw new RuntimeException(message);
- }
-
- public static void logEglErrorAsWarning(String tag, String function, int error) {
- Log.w(tag, formatEglError(function, error));
- }
-
- public static String formatEglError(String function, int error) {
- return function + " failed: " + error;
- }
-
- }
-
- private static class RenderThread extends Thread {
- private static final int INVALID = -1;
- private static final int RENDER = 1;
- private static final int CHANGE_SURFACE = 2;
- private static final int RESIZE_SURFACE = 3;
- private static final int FINISH = 4;
-
- private EglHelper mEglHelper = new EglHelper();
-
- private Object mLock = new Object();
- private int mExecMsgId = INVALID;
- private SurfaceTexture mSurface;
- private Renderer mRenderer;
- private int mWidth, mHeight;
-
- private boolean mFinished = false;
- private GL10 mGL;
-
- public RenderThread(Renderer renderer) {
- super("RenderThread");
- mRenderer = renderer;
- start();
- }
-
- private void checkRenderer() {
- if (mRenderer == null) {
- throw new IllegalArgumentException("Renderer is null!");
- }
- }
-
- private void checkSurface() {
- if (mSurface == null) {
- throw new IllegalArgumentException("surface is null!");
- }
- }
-
- public void setSurface(SurfaceTexture surface) {
- // If the surface is null we're being torn down, don't need a
- // renderer then
- if (surface != null) {
- checkRenderer();
- }
- mSurface = surface;
- exec(CHANGE_SURFACE);
- }
-
- public void setSize(int width, int height) {
- checkRenderer();
- checkSurface();
- mWidth = width;
- mHeight = height;
- exec(RESIZE_SURFACE);
- }
-
- public void render() {
- checkRenderer();
- if (mSurface != null) {
- exec(RENDER);
- mSurface.updateTexImage();
- }
- }
-
- public void finish() {
- mSurface = null;
- exec(FINISH);
- try {
- join();
- } catch (InterruptedException e) {
- // Ignore
- }
- }
-
- private void exec(int msgid) {
- synchronized (mLock) {
- if (mExecMsgId != INVALID) {
- throw new IllegalArgumentException(
- "Message already set - multithreaded access?");
- }
- mExecMsgId = msgid;
- mLock.notify();
- try {
- mLock.wait();
- } catch (InterruptedException e) {
- // Ignore
- }
- }
- }
-
- private void handleMessageLocked(int what) {
- switch (what) {
- case CHANGE_SURFACE:
- if (mEglHelper.createSurface(mSurface)) {
- mGL = mEglHelper.createGL();
- mRenderer.onSurfaceCreated(mGL, mEglHelper.mEglConfig);
- }
- break;
- case RESIZE_SURFACE:
- mRenderer.onSurfaceChanged(mGL, mWidth, mHeight);
- break;
- case RENDER:
- mRenderer.onDrawFrame(mGL);
- mEglHelper.swap();
- break;
- case FINISH:
- mEglHelper.destroySurface();
- mEglHelper.finish();
- mFinished = true;
- break;
- }
- }
-
- @Override
- public void run() {
- synchronized (mLock) {
- mEglHelper.start();
- while (!mFinished) {
- while (mExecMsgId == INVALID) {
- try {
- mLock.wait();
- } catch (InterruptedException e) {
- // Ignore
- }
- }
- handleMessageLocked(mExecMsgId);
- mExecMsgId = INVALID;
- mLock.notify();
- }
- mExecMsgId = FINISH;
- }
- }
- }
-}
diff --git a/WallpaperPicker/src/com/android/photos/views/TiledImageRenderer.java b/WallpaperPicker/src/com/android/photos/views/TiledImageRenderer.java
index c4e493b34..e57ce70b9 100644
--- a/WallpaperPicker/src/com/android/photos/views/TiledImageRenderer.java
+++ b/WallpaperPicker/src/com/android/photos/views/TiledImageRenderer.java
@@ -20,11 +20,11 @@ import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Rect;
import android.graphics.RectF;
-import android.support.v4.util.LongSparseArray;
+import android.support.v4.util.Pools.Pool;
+import android.support.v4.util.Pools.SynchronizedPool;
import android.util.DisplayMetrics;
import android.util.Log;
-import android.util.Pools.Pool;
-import android.util.Pools.SynchronizedPool;
+import android.util.LongSparseArray;
import android.view.View;
import android.view.WindowManager;
@@ -32,6 +32,7 @@ import com.android.gallery3d.common.Utils;
import com.android.gallery3d.glrenderer.BasicTexture;
import com.android.gallery3d.glrenderer.GLCanvas;
import com.android.gallery3d.glrenderer.UploadedTexture;
+import com.android.launcher3.util.Thunk;
/**
* Handles laying out, decoding, and drawing of tiles in GL
@@ -67,12 +68,12 @@ public class TiledImageRenderer {
private static final int STATE_RECYCLING = 0x20;
private static final int STATE_RECYCLED = 0x40;
- private static Pool<Bitmap> sTilePool = new SynchronizedPool<Bitmap>(64);
+ @Thunk static Pool<Bitmap> sTilePool = new SynchronizedPool<Bitmap>(64);
// TILE_SIZE must be 2^N
- private int mTileSize;
+ @Thunk int mTileSize;
- private TileSource mModel;
+ @Thunk TileSource mModel;
private BasicTexture mPreview;
protected int mLevelCount; // cache the value of mScaledBitmaps.length
@@ -82,7 +83,7 @@ public class TiledImageRenderer {
// half size of the previous one). If the value is in [0, mLevelCount), we
// use the bitmap in mScaledBitmaps[mLevel] for display, otherwise the value
// is mLevelCount
- private int mLevel = 0;
+ @Thunk int mLevel = 0;
private int mOffsetX;
private int mOffsetY;
@@ -96,10 +97,10 @@ public class TiledImageRenderer {
private final LongSparseArray<Tile> mActiveTiles = new LongSparseArray<Tile>();
// The following three queue are guarded by mQueueLock
- private final Object mQueueLock = new Object();
+ @Thunk final Object mQueueLock = new Object();
private final TileQueue mRecycledQueue = new TileQueue();
private final TileQueue mUploadQueue = new TileQueue();
- private final TileQueue mDecodeQueue = new TileQueue();
+ @Thunk final TileQueue mDecodeQueue = new TileQueue();
// The width and height of the full-sized bitmap
protected int mImageWidth = SIZE_UNKNOWN;
@@ -489,7 +490,7 @@ public class TiledImageRenderer {
}
}
- private void decodeTile(Tile tile) {
+ @Thunk void decodeTile(Tile tile) {
synchronized (mQueueLock) {
if (tile.mTileState != STATE_IN_QUEUE) {
return;
@@ -556,7 +557,7 @@ public class TiledImageRenderer {
mActiveTiles.put(key, tile);
}
- private Tile getTile(int x, int y, int level) {
+ @Thunk Tile getTile(int x, int y, int level) {
return mActiveTiles.get(makeTileKey(x, y, level));
}
@@ -748,7 +749,7 @@ public class TiledImageRenderer {
}
}
- private static class TileQueue {
+ @Thunk static class TileQueue {
private Tile mHead;
public Tile pop() {
@@ -786,7 +787,7 @@ public class TiledImageRenderer {
}
}
- private class TileDecoder extends Thread {
+ @Thunk class TileDecoder extends Thread {
public void finishAndWait() {
interrupt();
diff --git a/WallpaperPicker/src/com/android/photos/views/TiledImageView.java b/WallpaperPicker/src/com/android/photos/views/TiledImageView.java
index 94063b027..7e3e1a936 100644
--- a/WallpaperPicker/src/com/android/photos/views/TiledImageView.java
+++ b/WallpaperPicker/src/com/android/photos/views/TiledImageView.java
@@ -16,8 +16,6 @@
package com.android.photos.views;
-import android.annotation.SuppressLint;
-import android.annotation.TargetApi;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
@@ -28,35 +26,26 @@ import android.graphics.Paint.Align;
import android.graphics.RectF;
import android.opengl.GLSurfaceView;
import android.opengl.GLSurfaceView.Renderer;
-import android.os.Build;
import android.util.AttributeSet;
import android.view.Choreographer;
import android.view.Choreographer.FrameCallback;
-import android.view.View;
import android.widget.FrameLayout;
import com.android.gallery3d.glrenderer.BasicTexture;
import com.android.gallery3d.glrenderer.GLES20Canvas;
+import com.android.launcher3.util.Thunk;
import com.android.photos.views.TiledImageRenderer.TileSource;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
/**
- * Shows an image using {@link TiledImageRenderer} using either {@link GLSurfaceView}
- * or {@link BlockingGLTextureView}.
+ * Shows an image using {@link TiledImageRenderer} using either {@link GLSurfaceView}.
*/
public class TiledImageView extends FrameLayout {
- private static final boolean USE_TEXTURE_VIEW = false;
- private static final boolean IS_SUPPORTED =
- Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN;
- private static final boolean USE_CHOREOGRAPHER =
- Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN;
-
- private BlockingGLTextureView mTextureView;
- private GLSurfaceView mGLSurfaceView;
- private boolean mInvalPending = false;
+ @Thunk GLSurfaceView mGLSurfaceView;
+ @Thunk boolean mInvalPending = false;
private FrameCallback mFrameCallback;
protected static class ImageRendererWrapper {
@@ -79,35 +68,19 @@ public class TiledImageView extends FrameLayout {
protected Object mLock = new Object();
protected ImageRendererWrapper mRenderer;
- public static boolean isTilingSupported() {
- return IS_SUPPORTED;
- }
-
public TiledImageView(Context context) {
this(context, null);
}
public TiledImageView(Context context, AttributeSet attrs) {
super(context, attrs);
- if (!IS_SUPPORTED) {
- return;
- }
-
mRenderer = new ImageRendererWrapper();
mRenderer.image = new TiledImageRenderer(this);
- View view;
- if (USE_TEXTURE_VIEW) {
- mTextureView = new BlockingGLTextureView(context);
- mTextureView.setRenderer(new TileRenderer());
- view = mTextureView;
- } else {
- mGLSurfaceView = new GLSurfaceView(context);
- mGLSurfaceView.setEGLContextClientVersion(2);
- mGLSurfaceView.setRenderer(new TileRenderer());
- mGLSurfaceView.setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
- view = mGLSurfaceView;
- }
- addView(view, new LayoutParams(
+ mGLSurfaceView = new GLSurfaceView(context);
+ mGLSurfaceView.setEGLContextClientVersion(2);
+ mGLSurfaceView.setRenderer(new TileRenderer());
+ mGLSurfaceView.setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
+ addView(mGLSurfaceView, new LayoutParams(
LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
//setTileSource(new ColoredTiles());
}
@@ -117,22 +90,11 @@ public class TiledImageView extends FrameLayout {
super.setVisibility(visibility);
// need to update inner view's visibility because it seems like we're causing it to draw
// from {@link #dispatchDraw} or {@link #invalidate} even if we are invisible.
- if (USE_TEXTURE_VIEW) {
- mTextureView.setVisibility(visibility);
- } else {
- mGLSurfaceView.setVisibility(visibility);
- }
+ mGLSurfaceView.setVisibility(visibility);
}
public void destroy() {
- if (!IS_SUPPORTED) {
- return;
- }
- if (USE_TEXTURE_VIEW) {
- mTextureView.destroy();
- } else {
- mGLSurfaceView.queueEvent(mFreeTextures);
- }
+ mGLSurfaceView.queueEvent(mFreeTextures);
}
private Runnable mFreeTextures = new Runnable() {
@@ -144,27 +106,14 @@ public class TiledImageView extends FrameLayout {
};
public void onPause() {
- if (!IS_SUPPORTED) {
- return;
- }
- if (!USE_TEXTURE_VIEW) {
- mGLSurfaceView.onPause();
- }
+ mGLSurfaceView.onPause();
}
public void onResume() {
- if (!IS_SUPPORTED) {
- return;
- }
- if (!USE_TEXTURE_VIEW) {
- mGLSurfaceView.onResume();
- }
+ mGLSurfaceView.onResume();
}
public void setTileSource(TileSource source, Runnable isReadyCallback) {
- if (!IS_SUPPORTED) {
- return;
- }
synchronized (mLock) {
mRenderer.source = source;
mRenderer.isReadyCallback = isReadyCallback;
@@ -177,13 +126,14 @@ public class TiledImageView extends FrameLayout {
invalidate();
}
+ public TileSource getTileSource() {
+ return mRenderer.source;
+ }
+
@Override
protected void onLayout(boolean changed, int left, int top, int right,
int bottom) {
super.onLayout(changed, left, top, right, bottom);
- if (!IS_SUPPORTED) {
- return;
- }
synchronized (mLock) {
updateScaleIfNecessaryLocked(mRenderer);
}
@@ -200,43 +150,10 @@ public class TiledImageView extends FrameLayout {
}
@Override
- protected void dispatchDraw(Canvas canvas) {
- if (!IS_SUPPORTED) {
- return;
- }
- if (USE_TEXTURE_VIEW) {
- mTextureView.render();
- }
- super.dispatchDraw(canvas);
- }
-
- @SuppressLint("NewApi")
- @Override
- public void setTranslationX(float translationX) {
- if (!IS_SUPPORTED) {
- return;
- }
- super.setTranslationX(translationX);
- }
-
- @Override
public void invalidate() {
- if (!IS_SUPPORTED) {
- return;
- }
- if (USE_TEXTURE_VIEW) {
- super.invalidate();
- mTextureView.invalidate();
- } else {
- if (USE_CHOREOGRAPHER) {
- invalOnVsync();
- } else {
- mGLSurfaceView.requestRender();
- }
- }
+ invalOnVsync();
}
- @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
private void invalOnVsync() {
if (!mInvalPending) {
mInvalPending = true;
@@ -255,9 +172,6 @@ public class TiledImageView extends FrameLayout {
private RectF mTempRectF = new RectF();
public void positionFromMatrix(Matrix matrix) {
- if (!IS_SUPPORTED) {
- return;
- }
if (mRenderer.source != null) {
final int rotation = mRenderer.source.getRotation();
final boolean swap = !(rotation % 180 == 0);
@@ -290,7 +204,7 @@ public class TiledImageView extends FrameLayout {
}
}
- private class TileRenderer implements Renderer {
+ @Thunk class TileRenderer implements Renderer {
private GLES20Canvas mCanvas;
diff --git a/proguard.flags b/proguard.flags
index 83a491dfd..6a9d6f345 100644
--- a/proguard.flags
+++ b/proguard.flags
@@ -1,18 +1,22 @@
--keep class com.android.launcher3.Launcher {
- public void previousScreen(android.view.View);
- public void nextScreen(android.view.View);
- public void launchHotSeat(android.view.View);
- public void onClickSearchButton(android.view.View);
- public void onClickVoiceButton(android.view.View);
- public void onClickConfigureButton(android.view.View);
- public void onClickAllAppsButton(android.view.View);
- public void onClickAppMarketButton(android.view.View);
- public void dismissFirstRunCling(android.view.View);
- public void dismissMigrationClingCopyApps(android.view.View);
- public void dismissMigrationClingUseDefault(android.view.View);
- public void dismissMigrationWorkspaceCling(android.view.View);
- public void dismissWorkspaceCling(android.view.View);
- public void dismissAllAppsCling(android.view.View);
+-keep class com.android.launcher3.BaseRecyclerViewFastScrollBar {
+ public void setWidth(int);
+ public int getWidth();
+ public void setTrackAlpha(int);
+ public int getTrackAlpha();
+}
+
+-keep class com.android.launcher3.BaseRecyclerViewFastScrollPopup {
+ public void setAlpha(float);
+ 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();
}
-keep class com.android.launcher3.CellLayout {
@@ -20,7 +24,7 @@
public void setBackgroundAlpha(float);
}
--keep class com.android.launcher3.DragLayer$LayoutParams {
+-keep class com.android.launcher3.CellLayout$LayoutParams {
public void setWidth(int);
public int getWidth();
public void setHeight(int);
@@ -31,7 +35,7 @@
public int getY();
}
--keep class com.android.launcher3.CellLayout$LayoutParams {
+-keep class com.android.launcher3.DragLayer$LayoutParams {
public void setWidth(int);
public int getWidth();
public void setHeight(int);
@@ -42,11 +46,9 @@
public int getY();
}
--keep class com.android.launcher3.Workspace {
- public float getBackgroundAlpha();
- public void setBackgroundAlpha(float);
- public float getChildrenOutlineAlpha();
- public void setChildrenOutlineAlpha(float);
+-keep class com.android.launcher3.FastBitmapDrawable {
+ public int getBrightness();
+ public void setBrightness(int);
}
-keep class com.android.launcher3.MemoryDumpActivity {
@@ -58,7 +60,7 @@
public void setAnimationProgress(float);
}
--keep class com.android.launcher3.FastBitmapDrawable {
- public int getBrightness();
- public void setBrightness(int);
-}
+-keep class com.android.launcher3.Workspace {
+ public float getBackgroundAlpha();
+ public void setBackgroundAlpha(float);
+} \ No newline at end of file
diff --git a/protos/backup.proto b/protos/backup.proto
index 8ae175234..d8d94e8cb 100644
--- a/protos/backup.proto
+++ b/protos/backup.proto
@@ -14,7 +14,9 @@
* limitations under the License.
*/
- package launcher_backup;
+syntax = "proto2";
+
+package launcher_backup;
option java_package = "com.android.launcher3.backup";
option java_outer_classname = "BackupProtos";
@@ -70,6 +72,17 @@ message Journal {
}
message Favorite {
+ // Type of the app, this target represents
+ enum TargetType {
+ TARGET_NONE = 0;
+ TARGET_PHONE = 1;
+ TARGET_MESSENGER = 2;
+ TARGET_EMAIL = 3;
+ TARGET_BROWSER = 4;
+ TARGET_GALLERY = 5;
+ TARGET_CAMERA = 6;
+ }
+
required int64 id = 1;
required int32 itemType = 2;
optional string title = 3;
@@ -88,17 +101,18 @@ message Favorite {
optional string iconPackage = 16;
optional string iconResource = 17;
optional bytes icon = 18;
- }
+ optional TargetType targetType = 19 [default = TARGET_NONE];
+}
message Screen {
required int64 id = 1;
optional int32 rank = 2;
- }
+}
message Resource {
required int32 dpi = 1;
required bytes data = 2;
- }
+}
message Widget {
required string provider = 1;
@@ -106,4 +120,8 @@ message Widget {
optional bool configure = 3;
optional Resource icon = 4;
optional Resource preview = 5;
- }
+
+ // Assume that a widget is resizable upto 2x2 if no data is available
+ optional int32 minSpanX = 6 [default = 2];
+ optional int32 minSpanY = 7 [default = 2];
+}
diff --git a/res/drawable-hdpi/apps_customize_bg.png b/res/drawable-hdpi/apps_customize_bg.png
deleted file mode 100644
index 284746796..000000000
--- a/res/drawable-hdpi/apps_customize_bg.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-hdpi/bg_appwidget_error.9.png b/res/drawable-hdpi/bg_appwidget_error.9.png
deleted file mode 100644
index 4da3195d4..000000000
--- a/res/drawable-hdpi/bg_appwidget_error.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-hdpi/home_press.9.png b/res/drawable-hdpi/home_press.9.png
deleted file mode 100644
index ef07011f8..000000000
--- a/res/drawable-hdpi/home_press.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-hdpi/ic_arrow_back_grey.png b/res/drawable-hdpi/ic_arrow_back_grey.png
new file mode 100755
index 000000000..ccd3900dd
--- /dev/null
+++ b/res/drawable-hdpi/ic_arrow_back_grey.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_home_all_apps_holo_dark.png b/res/drawable-hdpi/ic_home_all_apps_holo_dark.png
deleted file mode 100644
index 1dc02d5e4..000000000
--- a/res/drawable-hdpi/ic_home_all_apps_holo_dark.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-hdpi/ic_info_launcher.png b/res/drawable-hdpi/ic_info_launcher.png
new file mode 100644
index 000000000..ec0cdd18c
--- /dev/null
+++ b/res/drawable-hdpi/ic_info_launcher.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_launcher_clear_active_holo.png b/res/drawable-hdpi/ic_launcher_clear_active_holo.png
deleted file mode 100644
index cdd0052b3..000000000
--- a/res/drawable-hdpi/ic_launcher_clear_active_holo.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-hdpi/ic_launcher_clear_normal_holo.png b/res/drawable-hdpi/ic_launcher_clear_normal_holo.png
deleted file mode 100644
index 84549ff94..000000000
--- a/res/drawable-hdpi/ic_launcher_clear_normal_holo.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-hdpi/ic_launcher_info_active_holo.png b/res/drawable-hdpi/ic_launcher_info_active_holo.png
deleted file mode 100644
index c534e5670..000000000
--- a/res/drawable-hdpi/ic_launcher_info_active_holo.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-hdpi/ic_launcher_info_normal_holo.png b/res/drawable-hdpi/ic_launcher_info_normal_holo.png
deleted file mode 100644
index c9bcd7f37..000000000
--- a/res/drawable-hdpi/ic_launcher_info_normal_holo.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-hdpi/ic_launcher_market_holo.png b/res/drawable-hdpi/ic_launcher_market_holo.png
deleted file mode 100644
index dc7825114..000000000
--- a/res/drawable-hdpi/ic_launcher_market_holo.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-hdpi/ic_launcher_trashcan_active_holo.png b/res/drawable-hdpi/ic_launcher_trashcan_active_holo.png
deleted file mode 100644
index 82b1b5917..000000000
--- a/res/drawable-hdpi/ic_launcher_trashcan_active_holo.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-hdpi/ic_launcher_trashcan_normal_holo.png b/res/drawable-hdpi/ic_launcher_trashcan_normal_holo.png
deleted file mode 100644
index 3fc2e8347..000000000
--- a/res/drawable-hdpi/ic_launcher_trashcan_normal_holo.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-hdpi/ic_pageindicator_current.png b/res/drawable-hdpi/ic_pageindicator_current.png
index 283f44d37..423ca2b45 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
new file mode 100644
index 000000000..43fbb0e79
--- /dev/null
+++ 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 47b998967..83fa73fc6 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
new file mode 100644
index 000000000..55cab1c65
--- /dev/null
+++ 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
new file mode 100644
index 000000000..c0814579a
--- /dev/null
+++ 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
new file mode 100755
index 000000000..f4c5e27d2
--- /dev/null
+++ b/res/drawable-hdpi/ic_search_grey.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_uninstall_launcher.png b/res/drawable-hdpi/ic_uninstall_launcher.png
new file mode 100644
index 000000000..3d8f72644
--- /dev/null
+++ b/res/drawable-hdpi/ic_uninstall_launcher.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_widget_resize_handle.png b/res/drawable-hdpi/ic_widget_resize_handle.png
new file mode 100644
index 000000000..844f3cf09
--- /dev/null
+++ b/res/drawable-hdpi/ic_widget_resize_handle.png
Binary files differ
diff --git a/res/drawable-hdpi/on_boarding_welcome.png b/res/drawable-hdpi/on_boarding_welcome.png
deleted file mode 100644
index 852a0cb13..000000000
--- a/res/drawable-hdpi/on_boarding_welcome.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-hdpi/overscroll_glow_left.9.png b/res/drawable-hdpi/overscroll_glow_left.9.png
deleted file mode 100644
index aaf43c73a..000000000
--- a/res/drawable-hdpi/overscroll_glow_left.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-hdpi/overscroll_glow_right.9.png b/res/drawable-hdpi/overscroll_glow_right.9.png
deleted file mode 100644
index d03486441..000000000
--- a/res/drawable-hdpi/overscroll_glow_right.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-hdpi/paged_view_indicator.9.png b/res/drawable-hdpi/paged_view_indicator.9.png
deleted file mode 100644
index 5b47f4477..000000000
--- a/res/drawable-hdpi/paged_view_indicator.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-hdpi/portal_container_holo.9.png b/res/drawable-hdpi/portal_container_holo.9.png
deleted file mode 100644
index ba8a4a8cd..000000000
--- a/res/drawable-hdpi/portal_container_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-hdpi/portal_ring_inner.png b/res/drawable-hdpi/portal_ring_inner.png
new file mode 100644
index 000000000..c29b4aa64
--- /dev/null
+++ b/res/drawable-hdpi/portal_ring_inner.png
Binary files differ
diff --git a/res/drawable-hdpi/portal_ring_inner_holo.png b/res/drawable-hdpi/portal_ring_inner_holo.png
deleted file mode 100644
index 857a01ec4..000000000
--- a/res/drawable-hdpi/portal_ring_inner_holo.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-hdpi/portal_ring_inner_nolip.png b/res/drawable-hdpi/portal_ring_inner_nolip.png
new file mode 100644
index 000000000..e2f06fe9b
--- /dev/null
+++ b/res/drawable-hdpi/portal_ring_inner_nolip.png
Binary files differ
diff --git a/res/drawable-hdpi/portal_ring_inner_nolip_holo.png b/res/drawable-hdpi/portal_ring_inner_nolip_holo.png
deleted file mode 100644
index 53df36a43..000000000
--- a/res/drawable-hdpi/portal_ring_inner_nolip_holo.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-hdpi/portal_ring_outer.png b/res/drawable-hdpi/portal_ring_outer.png
new file mode 100644
index 000000000..e7b436b7b
--- /dev/null
+++ b/res/drawable-hdpi/portal_ring_outer.png
Binary files differ
diff --git a/res/drawable-hdpi/portal_ring_outer_holo.png b/res/drawable-hdpi/portal_ring_outer_holo.png
deleted file mode 100644
index b711cf350..000000000
--- a/res/drawable-hdpi/portal_ring_outer_holo.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-hdpi/portal_ring_rest.png b/res/drawable-hdpi/portal_ring_rest.png
index 2979b736b..e3b13393e 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.9.png b/res/drawable-hdpi/quantum_panel.9.png
deleted file mode 100644
index b4ac9c0a0..000000000
--- a/res/drawable-hdpi/quantum_panel.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-hdpi/quantum_panel_bitmap.9.png b/res/drawable-hdpi/quantum_panel_bitmap.9.png
new file mode 100644
index 000000000..c3319290f
--- /dev/null
+++ b/res/drawable-hdpi/quantum_panel_bitmap.9.png
Binary files differ
diff --git a/res/drawable-hdpi/quantum_panel_dark.9.png b/res/drawable-hdpi/quantum_panel_dark.9.png
deleted file mode 100644
index abaf23026..000000000
--- a/res/drawable-hdpi/quantum_panel_dark.9.png
+++ /dev/null
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
new file mode 100644
index 000000000..0145d36b7
--- /dev/null
+++ b/res/drawable-hdpi/quantum_panel_dark_bitmap.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
new file mode 100644
index 000000000..b0a740384
--- /dev/null
+++ b/res/drawable-hdpi/widget_resize_frame.9.png
Binary files differ
diff --git a/res/drawable-hdpi/widget_resize_frame_holo.9.png b/res/drawable-hdpi/widget_resize_frame_holo.9.png
deleted file mode 100644
index 2d6fcf51f..000000000
--- a/res/drawable-hdpi/widget_resize_frame_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-hdpi/widget_resize_handle_bottom.png b/res/drawable-hdpi/widget_resize_handle_bottom.png
deleted file mode 100644
index f0afd6172..000000000
--- a/res/drawable-hdpi/widget_resize_handle_bottom.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-hdpi/widget_resize_handle_left.png b/res/drawable-hdpi/widget_resize_handle_left.png
deleted file mode 100644
index 47613b29f..000000000
--- a/res/drawable-hdpi/widget_resize_handle_left.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-hdpi/widget_resize_handle_right.png b/res/drawable-hdpi/widget_resize_handle_right.png
deleted file mode 100644
index acc28be83..000000000
--- a/res/drawable-hdpi/widget_resize_handle_right.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-hdpi/widget_resize_handle_top.png b/res/drawable-hdpi/widget_resize_handle_top.png
deleted file mode 100644
index 2c60be00c..000000000
--- a/res/drawable-hdpi/widget_resize_handle_top.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-hdpi/widget_resize_shadow.9.png b/res/drawable-hdpi/widget_resize_shadow.9.png
new file mode 100644
index 000000000..6e2932dcd
--- /dev/null
+++ b/res/drawable-hdpi/widget_resize_shadow.9.png
Binary files differ
diff --git a/res/drawable-ldrtl/container_fastscroll_popup_bg.xml b/res/drawable-ldrtl/container_fastscroll_popup_bg.xml
new file mode 100644
index 000000000..d79096807
--- /dev/null
+++ b/res/drawable-ldrtl/container_fastscroll_popup_bg.xml
@@ -0,0 +1,27 @@
+<?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.
+-->
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shape="rectangle">
+ <solid android:color="@color/container_fastscroll_thumb_active_color" />
+ <size
+ android:width="64dp"
+ android:height="64dp" />
+ <corners
+ android:topLeftRadius="64dp"
+ android:topRightRadius="64dp"
+ android:bottomRightRadius="64dp" />
+</shape> \ No newline at end of file
diff --git a/res/drawable-mdpi/apps_customize_bg.png b/res/drawable-mdpi/apps_customize_bg.png
deleted file mode 100644
index 284746796..000000000
--- a/res/drawable-mdpi/apps_customize_bg.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/bg_appwidget_error.9.png b/res/drawable-mdpi/bg_appwidget_error.9.png
deleted file mode 100644
index 493c0d454..000000000
--- a/res/drawable-mdpi/bg_appwidget_error.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/home_press.9.png b/res/drawable-mdpi/home_press.9.png
deleted file mode 100644
index 679a1f626..000000000
--- a/res/drawable-mdpi/home_press.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/ic_arrow_back_grey.png b/res/drawable-mdpi/ic_arrow_back_grey.png
new file mode 100755
index 000000000..11996efe3
--- /dev/null
+++ b/res/drawable-mdpi/ic_arrow_back_grey.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_home_all_apps_holo_dark.png b/res/drawable-mdpi/ic_home_all_apps_holo_dark.png
deleted file mode 100644
index 84fa5947d..000000000
--- a/res/drawable-mdpi/ic_home_all_apps_holo_dark.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/ic_info_launcher.png b/res/drawable-mdpi/ic_info_launcher.png
new file mode 100644
index 000000000..c72d0c2a9
--- /dev/null
+++ b/res/drawable-mdpi/ic_info_launcher.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_launcher_clear_active_holo.png b/res/drawable-mdpi/ic_launcher_clear_active_holo.png
deleted file mode 100644
index 2683beaa3..000000000
--- a/res/drawable-mdpi/ic_launcher_clear_active_holo.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/ic_launcher_clear_normal_holo.png b/res/drawable-mdpi/ic_launcher_clear_normal_holo.png
deleted file mode 100644
index 219f3e5cf..000000000
--- a/res/drawable-mdpi/ic_launcher_clear_normal_holo.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/ic_launcher_info_active_holo.png b/res/drawable-mdpi/ic_launcher_info_active_holo.png
deleted file mode 100644
index f84b4a6ba..000000000
--- a/res/drawable-mdpi/ic_launcher_info_active_holo.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/ic_launcher_info_normal_holo.png b/res/drawable-mdpi/ic_launcher_info_normal_holo.png
deleted file mode 100644
index eac578f5c..000000000
--- a/res/drawable-mdpi/ic_launcher_info_normal_holo.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/ic_launcher_market_holo.png b/res/drawable-mdpi/ic_launcher_market_holo.png
deleted file mode 100644
index cacb37484..000000000
--- a/res/drawable-mdpi/ic_launcher_market_holo.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/ic_launcher_trashcan_active_holo.png b/res/drawable-mdpi/ic_launcher_trashcan_active_holo.png
deleted file mode 100644
index 0350e558d..000000000
--- a/res/drawable-mdpi/ic_launcher_trashcan_active_holo.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/ic_launcher_trashcan_normal_holo.png b/res/drawable-mdpi/ic_launcher_trashcan_normal_holo.png
deleted file mode 100644
index 799b62f8b..000000000
--- a/res/drawable-mdpi/ic_launcher_trashcan_normal_holo.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/ic_pageindicator_current.png b/res/drawable-mdpi/ic_pageindicator_current.png
index b41e1bb67..ca889c4d1 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
new file mode 100644
index 000000000..5bbba9140
--- /dev/null
+++ 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 e36c25cf1..34493b155 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
new file mode 100644
index 000000000..0a987a4d0
--- /dev/null
+++ 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
new file mode 100644
index 000000000..4a2c3197e
--- /dev/null
+++ b/res/drawable-mdpi/ic_remove_launcher.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_search_grey.png b/res/drawable-mdpi/ic_search_grey.png
new file mode 100755
index 000000000..e83891c11
--- /dev/null
+++ b/res/drawable-mdpi/ic_search_grey.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_setting_icn.png b/res/drawable-mdpi/ic_setting_icn.png
deleted file mode 100644
index 5c32c54da..000000000
--- a/res/drawable-mdpi/ic_setting_icn.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/ic_uninstall_launcher.png b/res/drawable-mdpi/ic_uninstall_launcher.png
new file mode 100644
index 000000000..af456690c
--- /dev/null
+++ b/res/drawable-mdpi/ic_uninstall_launcher.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_widget_resize_handle.png b/res/drawable-mdpi/ic_widget_resize_handle.png
new file mode 100644
index 000000000..c3b287ff0
--- /dev/null
+++ b/res/drawable-mdpi/ic_widget_resize_handle.png
Binary files differ
diff --git a/res/drawable-mdpi/on_boarding_welcome.png b/res/drawable-mdpi/on_boarding_welcome.png
deleted file mode 100644
index 1d12e8362..000000000
--- a/res/drawable-mdpi/on_boarding_welcome.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/overscroll_glow_left.9.png b/res/drawable-mdpi/overscroll_glow_left.9.png
deleted file mode 100644
index b79cdcdc2..000000000
--- a/res/drawable-mdpi/overscroll_glow_left.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/overscroll_glow_right.9.png b/res/drawable-mdpi/overscroll_glow_right.9.png
deleted file mode 100644
index 1321303e1..000000000
--- a/res/drawable-mdpi/overscroll_glow_right.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/paged_view_indicator.9.png b/res/drawable-mdpi/paged_view_indicator.9.png
deleted file mode 100644
index 647b60f37..000000000
--- a/res/drawable-mdpi/paged_view_indicator.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/portal_container_holo.9.png b/res/drawable-mdpi/portal_container_holo.9.png
deleted file mode 100644
index 1e4afae76..000000000
--- a/res/drawable-mdpi/portal_container_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/portal_ring_inner.png b/res/drawable-mdpi/portal_ring_inner.png
new file mode 100644
index 000000000..99aaa60a9
--- /dev/null
+++ b/res/drawable-mdpi/portal_ring_inner.png
Binary files differ
diff --git a/res/drawable-mdpi/portal_ring_inner_holo.png b/res/drawable-mdpi/portal_ring_inner_holo.png
deleted file mode 100644
index 72e0af8f8..000000000
--- a/res/drawable-mdpi/portal_ring_inner_holo.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/portal_ring_inner_nolip.png b/res/drawable-mdpi/portal_ring_inner_nolip.png
new file mode 100644
index 000000000..f981778f5
--- /dev/null
+++ b/res/drawable-mdpi/portal_ring_inner_nolip.png
Binary files differ
diff --git a/res/drawable-mdpi/portal_ring_inner_nolip_holo.png b/res/drawable-mdpi/portal_ring_inner_nolip_holo.png
deleted file mode 100644
index 483f0ebec..000000000
--- a/res/drawable-mdpi/portal_ring_inner_nolip_holo.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/portal_ring_outer.png b/res/drawable-mdpi/portal_ring_outer.png
new file mode 100644
index 000000000..c98f64b76
--- /dev/null
+++ b/res/drawable-mdpi/portal_ring_outer.png
Binary files differ
diff --git a/res/drawable-mdpi/portal_ring_outer_holo.png b/res/drawable-mdpi/portal_ring_outer_holo.png
deleted file mode 100644
index e9b35f3f3..000000000
--- a/res/drawable-mdpi/portal_ring_outer_holo.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/portal_ring_rest.png b/res/drawable-mdpi/portal_ring_rest.png
index d0a976e55..5c33b424d 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.9.png b/res/drawable-mdpi/quantum_panel.9.png
deleted file mode 100644
index c5a6eb735..000000000
--- a/res/drawable-mdpi/quantum_panel.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/quantum_panel_bitmap.9.png b/res/drawable-mdpi/quantum_panel_bitmap.9.png
new file mode 100644
index 000000000..86be568fd
--- /dev/null
+++ b/res/drawable-mdpi/quantum_panel_bitmap.9.png
Binary files differ
diff --git a/res/drawable-mdpi/quantum_panel_dark.9.png b/res/drawable-mdpi/quantum_panel_dark.9.png
deleted file mode 100644
index 7728a7268..000000000
--- a/res/drawable-mdpi/quantum_panel_dark.9.png
+++ /dev/null
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
new file mode 100644
index 000000000..70429b9fc
--- /dev/null
+++ b/res/drawable-mdpi/quantum_panel_dark_bitmap.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
new file mode 100644
index 000000000..856cec619
--- /dev/null
+++ b/res/drawable-mdpi/widget_resize_frame.9.png
Binary files differ
diff --git a/res/drawable-mdpi/widget_resize_frame_holo.9.png b/res/drawable-mdpi/widget_resize_frame_holo.9.png
deleted file mode 100644
index 028bd6248..000000000
--- a/res/drawable-mdpi/widget_resize_frame_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/widget_resize_handle_bottom.png b/res/drawable-mdpi/widget_resize_handle_bottom.png
deleted file mode 100644
index c838bf405..000000000
--- a/res/drawable-mdpi/widget_resize_handle_bottom.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/widget_resize_handle_left.png b/res/drawable-mdpi/widget_resize_handle_left.png
deleted file mode 100644
index ff0b0d357..000000000
--- a/res/drawable-mdpi/widget_resize_handle_left.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/widget_resize_handle_right.png b/res/drawable-mdpi/widget_resize_handle_right.png
deleted file mode 100644
index fc4808e3a..000000000
--- a/res/drawable-mdpi/widget_resize_handle_right.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/widget_resize_handle_top.png b/res/drawable-mdpi/widget_resize_handle_top.png
deleted file mode 100644
index 3b1df0170..000000000
--- a/res/drawable-mdpi/widget_resize_handle_top.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/widget_resize_shadow.9.png b/res/drawable-mdpi/widget_resize_shadow.9.png
new file mode 100644
index 000000000..02522f344
--- /dev/null
+++ b/res/drawable-mdpi/widget_resize_shadow.9.png
Binary files differ
diff --git a/res/drawable-v21/quantum_panel.xml b/res/drawable-v21/quantum_panel.xml
new file mode 100644
index 000000000..d1c078335
--- /dev/null
+++ b/res/drawable-v21/quantum_panel.xml
@@ -0,0 +1,22 @@
+<?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.
+-->
+<inset xmlns:android="http://schemas.android.com/apk/res/android"
+ android:drawable="@drawable/quantum_panel_shape"
+ android:insetBottom="@dimen/quantum_panel_outer_padding"
+ android:insetLeft="@dimen/quantum_panel_outer_padding"
+ android:insetRight="@dimen/quantum_panel_outer_padding"
+ android:insetTop="@dimen/quantum_panel_outer_padding" />
diff --git a/res/drawable-v21/quantum_panel_dark.xml b/res/drawable-v21/quantum_panel_dark.xml
new file mode 100644
index 000000000..405ad5173
--- /dev/null
+++ b/res/drawable-v21/quantum_panel_dark.xml
@@ -0,0 +1,22 @@
+<?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.
+-->
+<inset xmlns:android="http://schemas.android.com/apk/res/android"
+ android:drawable="@drawable/quantum_panel_shape_dark"
+ android:insetBottom="@dimen/quantum_panel_outer_padding"
+ android:insetLeft="@dimen/quantum_panel_outer_padding"
+ android:insetRight="@dimen/quantum_panel_outer_padding"
+ android:insetTop="@dimen/quantum_panel_outer_padding" />
diff --git a/res/drawable-xhdpi/apps_customize_bg.png b/res/drawable-xhdpi/apps_customize_bg.png
deleted file mode 100644
index a51cc112b..000000000
--- a/res/drawable-xhdpi/apps_customize_bg.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/bg_appwidget_error.9.png b/res/drawable-xhdpi/bg_appwidget_error.9.png
deleted file mode 100644
index b792cc847..000000000
--- a/res/drawable-xhdpi/bg_appwidget_error.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/home_press.9.png b/res/drawable-xhdpi/home_press.9.png
deleted file mode 100644
index d9abfd358..000000000
--- a/res/drawable-xhdpi/home_press.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/ic_arrow_back_grey.png b/res/drawable-xhdpi/ic_arrow_back_grey.png
new file mode 100755
index 000000000..79b9b486c
--- /dev/null
+++ b/res/drawable-xhdpi/ic_arrow_back_grey.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_home_all_apps_holo_dark.png b/res/drawable-xhdpi/ic_home_all_apps_holo_dark.png
deleted file mode 100644
index 81228d402..000000000
--- a/res/drawable-xhdpi/ic_home_all_apps_holo_dark.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/ic_info_launcher.png b/res/drawable-xhdpi/ic_info_launcher.png
new file mode 100644
index 000000000..076b59bf7
--- /dev/null
+++ b/res/drawable-xhdpi/ic_info_launcher.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_launcher_clear_active_holo.png b/res/drawable-xhdpi/ic_launcher_clear_active_holo.png
deleted file mode 100644
index 1a7e53ddb..000000000
--- a/res/drawable-xhdpi/ic_launcher_clear_active_holo.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/ic_launcher_clear_normal_holo.png b/res/drawable-xhdpi/ic_launcher_clear_normal_holo.png
deleted file mode 100644
index d4965d9f8..000000000
--- a/res/drawable-xhdpi/ic_launcher_clear_normal_holo.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/ic_launcher_info_active_holo.png b/res/drawable-xhdpi/ic_launcher_info_active_holo.png
deleted file mode 100644
index b8cdbc4f8..000000000
--- a/res/drawable-xhdpi/ic_launcher_info_active_holo.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/ic_launcher_info_normal_holo.png b/res/drawable-xhdpi/ic_launcher_info_normal_holo.png
deleted file mode 100644
index f503fb82d..000000000
--- a/res/drawable-xhdpi/ic_launcher_info_normal_holo.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/ic_launcher_market_holo.png b/res/drawable-xhdpi/ic_launcher_market_holo.png
deleted file mode 100644
index 958f0de3c..000000000
--- a/res/drawable-xhdpi/ic_launcher_market_holo.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/ic_launcher_trashcan_active_holo.png b/res/drawable-xhdpi/ic_launcher_trashcan_active_holo.png
deleted file mode 100644
index c155274bd..000000000
--- a/res/drawable-xhdpi/ic_launcher_trashcan_active_holo.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/ic_launcher_trashcan_normal_holo.png b/res/drawable-xhdpi/ic_launcher_trashcan_normal_holo.png
deleted file mode 100644
index 2ec7ad9b4..000000000
--- a/res/drawable-xhdpi/ic_launcher_trashcan_normal_holo.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/ic_pageindicator_current.png b/res/drawable-xhdpi/ic_pageindicator_current.png
index 8fa774dee..3054f2f4f 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
new file mode 100644
index 000000000..cd92e9f21
--- /dev/null
+++ 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 8eb5eb08d..38538dcf0 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
new file mode 100644
index 000000000..e7c46e3a1
--- /dev/null
+++ 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
new file mode 100644
index 000000000..de058893a
--- /dev/null
+++ 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
new file mode 100755
index 000000000..bd5fdf444
--- /dev/null
+++ b/res/drawable-xhdpi/ic_search_grey.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_uninstall_launcher.png b/res/drawable-xhdpi/ic_uninstall_launcher.png
new file mode 100644
index 000000000..dd50e88c6
--- /dev/null
+++ b/res/drawable-xhdpi/ic_uninstall_launcher.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_widget_resize_handle.png b/res/drawable-xhdpi/ic_widget_resize_handle.png
new file mode 100644
index 000000000..f445a1c08
--- /dev/null
+++ b/res/drawable-xhdpi/ic_widget_resize_handle.png
Binary files differ
diff --git a/res/drawable-xhdpi/on_boarding_welcome.png b/res/drawable-xhdpi/on_boarding_welcome.png
deleted file mode 100644
index 8c101e0db..000000000
--- a/res/drawable-xhdpi/on_boarding_welcome.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/overscroll_glow_left.9.png b/res/drawable-xhdpi/overscroll_glow_left.9.png
deleted file mode 100644
index 4f248f70b..000000000
--- a/res/drawable-xhdpi/overscroll_glow_left.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/overscroll_glow_right.9.png b/res/drawable-xhdpi/overscroll_glow_right.9.png
deleted file mode 100644
index 818a70db8..000000000
--- a/res/drawable-xhdpi/overscroll_glow_right.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/paged_view_indicator.9.png b/res/drawable-xhdpi/paged_view_indicator.9.png
deleted file mode 100644
index fb8a22820..000000000
--- a/res/drawable-xhdpi/paged_view_indicator.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/portal_container_holo.9.png b/res/drawable-xhdpi/portal_container_holo.9.png
deleted file mode 100644
index cedbdc401..000000000
--- a/res/drawable-xhdpi/portal_container_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/portal_ring_inner.png b/res/drawable-xhdpi/portal_ring_inner.png
new file mode 100644
index 000000000..7b6a8a04e
--- /dev/null
+++ b/res/drawable-xhdpi/portal_ring_inner.png
Binary files differ
diff --git a/res/drawable-xhdpi/portal_ring_inner_holo.png b/res/drawable-xhdpi/portal_ring_inner_holo.png
deleted file mode 100644
index f9acfa284..000000000
--- a/res/drawable-xhdpi/portal_ring_inner_holo.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/portal_ring_inner_nolip.png b/res/drawable-xhdpi/portal_ring_inner_nolip.png
new file mode 100644
index 000000000..4b84436ee
--- /dev/null
+++ b/res/drawable-xhdpi/portal_ring_inner_nolip.png
Binary files differ
diff --git a/res/drawable-xhdpi/portal_ring_inner_nolip_holo.png b/res/drawable-xhdpi/portal_ring_inner_nolip_holo.png
deleted file mode 100644
index eb2cf5f8b..000000000
--- a/res/drawable-xhdpi/portal_ring_inner_nolip_holo.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/portal_ring_outer.png b/res/drawable-xhdpi/portal_ring_outer.png
new file mode 100644
index 000000000..79c188873
--- /dev/null
+++ b/res/drawable-xhdpi/portal_ring_outer.png
Binary files differ
diff --git a/res/drawable-xhdpi/portal_ring_outer_holo.png b/res/drawable-xhdpi/portal_ring_outer_holo.png
deleted file mode 100644
index f32051dcf..000000000
--- a/res/drawable-xhdpi/portal_ring_outer_holo.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/portal_ring_rest.png b/res/drawable-xhdpi/portal_ring_rest.png
index ff0369a26..544a74f9f 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.9.png b/res/drawable-xhdpi/quantum_panel.9.png
deleted file mode 100644
index 1797ad500..000000000
--- a/res/drawable-xhdpi/quantum_panel.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/quantum_panel_bitmap.9.png b/res/drawable-xhdpi/quantum_panel_bitmap.9.png
new file mode 100644
index 000000000..13bdf09ec
--- /dev/null
+++ b/res/drawable-xhdpi/quantum_panel_bitmap.9.png
Binary files differ
diff --git a/res/drawable-xhdpi/quantum_panel_dark.9.png b/res/drawable-xhdpi/quantum_panel_dark.9.png
deleted file mode 100644
index 4c1868b55..000000000
--- a/res/drawable-xhdpi/quantum_panel_dark.9.png
+++ /dev/null
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
new file mode 100644
index 000000000..ac2e423f2
--- /dev/null
+++ b/res/drawable-xhdpi/quantum_panel_dark_bitmap.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
new file mode 100644
index 000000000..bf7cc6b82
--- /dev/null
+++ b/res/drawable-xhdpi/widget_resize_frame.9.png
Binary files differ
diff --git a/res/drawable-xhdpi/widget_resize_frame_holo.9.png b/res/drawable-xhdpi/widget_resize_frame_holo.9.png
deleted file mode 100644
index 76cec606d..000000000
--- a/res/drawable-xhdpi/widget_resize_frame_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/widget_resize_handle_bottom.png b/res/drawable-xhdpi/widget_resize_handle_bottom.png
deleted file mode 100644
index 19437d7dc..000000000
--- a/res/drawable-xhdpi/widget_resize_handle_bottom.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/widget_resize_handle_left.png b/res/drawable-xhdpi/widget_resize_handle_left.png
deleted file mode 100644
index 28c5487ec..000000000
--- a/res/drawable-xhdpi/widget_resize_handle_left.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/widget_resize_handle_right.png b/res/drawable-xhdpi/widget_resize_handle_right.png
deleted file mode 100644
index 4f672a602..000000000
--- a/res/drawable-xhdpi/widget_resize_handle_right.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/widget_resize_handle_top.png b/res/drawable-xhdpi/widget_resize_handle_top.png
deleted file mode 100644
index e866c008c..000000000
--- a/res/drawable-xhdpi/widget_resize_handle_top.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/widget_resize_shadow.9.png b/res/drawable-xhdpi/widget_resize_shadow.9.png
new file mode 100644
index 000000000..96dee7f01
--- /dev/null
+++ b/res/drawable-xhdpi/widget_resize_shadow.9.png
Binary files differ
diff --git a/res/drawable-xxhdpi/apps_customize_bg.png b/res/drawable-xxhdpi/apps_customize_bg.png
deleted file mode 100644
index a51cc112b..000000000
--- a/res/drawable-xxhdpi/apps_customize_bg.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xxhdpi/arrow_dashed.png b/res/drawable-xxhdpi/arrow_dashed.png
deleted file mode 100644
index b64f4d0fe..000000000
--- a/res/drawable-xxhdpi/arrow_dashed.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xxhdpi/default_widget_preview_holo.9.png b/res/drawable-xxhdpi/default_widget_preview_holo.9.png
deleted file mode 100644
index 0f62097a8..000000000
--- a/res/drawable-xxhdpi/default_widget_preview_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xxhdpi/hotseat_bg_panel.9.png b/res/drawable-xxhdpi/hotseat_bg_panel.9.png
deleted file mode 100644
index 40fc076ff..000000000
--- a/res/drawable-xxhdpi/hotseat_bg_panel.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xxhdpi/hotseat_scrubber_holo.9.png b/res/drawable-xxhdpi/hotseat_scrubber_holo.9.png
deleted file mode 100644
index 8a77536be..000000000
--- a/res/drawable-xxhdpi/hotseat_scrubber_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xxhdpi/hotseat_track_holo.9.png b/res/drawable-xxhdpi/hotseat_track_holo.9.png
deleted file mode 100644
index dd2216fb7..000000000
--- a/res/drawable-xxhdpi/hotseat_track_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_arrow_back_grey.png b/res/drawable-xxhdpi/ic_arrow_back_grey.png
new file mode 100755
index 000000000..8e42e091d
--- /dev/null
+++ b/res/drawable-xxhdpi/ic_arrow_back_grey.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_home_all_apps_holo_dark.png b/res/drawable-xxhdpi/ic_home_all_apps_holo_dark.png
deleted file mode 100644
index 0b8e88c16..000000000
--- a/res/drawable-xxhdpi/ic_home_all_apps_holo_dark.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_home_google_logo_normal_holo.png b/res/drawable-xxhdpi/ic_home_google_logo_normal_holo.png
deleted file mode 100644
index a47b2ba99..000000000
--- a/res/drawable-xxhdpi/ic_home_google_logo_normal_holo.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_home_google_logo_pressed_holo.png b/res/drawable-xxhdpi/ic_home_google_logo_pressed_holo.png
deleted file mode 100644
index 75625d120..000000000
--- a/res/drawable-xxhdpi/ic_home_google_logo_pressed_holo.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_home_search_pressed_holo.png b/res/drawable-xxhdpi/ic_home_search_pressed_holo.png
deleted file mode 100644
index 800d99430..000000000
--- a/res/drawable-xxhdpi/ic_home_search_pressed_holo.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_home_voice_search_pressed_holo.png b/res/drawable-xxhdpi/ic_home_voice_search_pressed_holo.png
deleted file mode 100644
index 27a589782..000000000
--- a/res/drawable-xxhdpi/ic_home_voice_search_pressed_holo.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_info_launcher.png b/res/drawable-xxhdpi/ic_info_launcher.png
new file mode 100644
index 000000000..386d09147
--- /dev/null
+++ b/res/drawable-xxhdpi/ic_info_launcher.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_launcher_clear_active_holo.png b/res/drawable-xxhdpi/ic_launcher_clear_active_holo.png
deleted file mode 100644
index 95cf84115..000000000
--- a/res/drawable-xxhdpi/ic_launcher_clear_active_holo.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_launcher_clear_normal_holo.png b/res/drawable-xxhdpi/ic_launcher_clear_normal_holo.png
deleted file mode 100644
index b0f5a2702..000000000
--- a/res/drawable-xxhdpi/ic_launcher_clear_normal_holo.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_launcher_info_active_holo.png b/res/drawable-xxhdpi/ic_launcher_info_active_holo.png
deleted file mode 100644
index 57f332a94..000000000
--- a/res/drawable-xxhdpi/ic_launcher_info_active_holo.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_launcher_info_normal_holo.png b/res/drawable-xxhdpi/ic_launcher_info_normal_holo.png
deleted file mode 100644
index 94f0955d6..000000000
--- a/res/drawable-xxhdpi/ic_launcher_info_normal_holo.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_launcher_trashcan_active_holo.png b/res/drawable-xxhdpi/ic_launcher_trashcan_active_holo.png
deleted file mode 100644
index 3bb098c2b..000000000
--- a/res/drawable-xxhdpi/ic_launcher_trashcan_active_holo.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_launcher_trashcan_normal_holo.png b/res/drawable-xxhdpi/ic_launcher_trashcan_normal_holo.png
deleted file mode 100644
index 550cc5bb8..000000000
--- a/res/drawable-xxhdpi/ic_launcher_trashcan_normal_holo.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_pageindicator_current.png b/res/drawable-xxhdpi/ic_pageindicator_current.png
index 22b290e69..5941c8e4f 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
new file mode 100644
index 000000000..602b89a40
--- /dev/null
+++ 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 e608cae30..3fa9e5fd7 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
new file mode 100644
index 000000000..bbcd7f91e
--- /dev/null
+++ b/res/drawable-xxhdpi/ic_pageindicator_default_folder.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_qs_remote_display.png b/res/drawable-xxhdpi/ic_qs_remote_display.png
deleted file mode 100644
index 25ea9fab2..000000000
--- a/res/drawable-xxhdpi/ic_qs_remote_display.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_qs_remote_display_connected.png b/res/drawable-xxhdpi/ic_qs_remote_display_connected.png
deleted file mode 100644
index 33a8d2d5a..000000000
--- a/res/drawable-xxhdpi/ic_qs_remote_display_connected.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_remove_launcher.png b/res/drawable-xxhdpi/ic_remove_launcher.png
new file mode 100644
index 000000000..7c28bb0bb
--- /dev/null
+++ 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
new file mode 100755
index 000000000..1d5c91361
--- /dev/null
+++ b/res/drawable-xxhdpi/ic_search_grey.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_uninstall_launcher.png b/res/drawable-xxhdpi/ic_uninstall_launcher.png
new file mode 100644
index 000000000..872e82933
--- /dev/null
+++ b/res/drawable-xxhdpi/ic_uninstall_launcher.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_widget_resize_handle.png b/res/drawable-xxhdpi/ic_widget_resize_handle.png
new file mode 100644
index 000000000..144cac996
--- /dev/null
+++ b/res/drawable-xxhdpi/ic_widget_resize_handle.png
Binary files differ
diff --git a/res/drawable-xxhdpi/overscroll_glow_left.9.png b/res/drawable-xxhdpi/overscroll_glow_left.9.png
deleted file mode 100644
index 1a895cdc8..000000000
--- a/res/drawable-xxhdpi/overscroll_glow_left.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xxhdpi/overscroll_glow_right.9.png b/res/drawable-xxhdpi/overscroll_glow_right.9.png
deleted file mode 100644
index 576676145..000000000
--- a/res/drawable-xxhdpi/overscroll_glow_right.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xxhdpi/portal_container_holo.9.png b/res/drawable-xxhdpi/portal_container_holo.9.png
deleted file mode 100644
index 599a076d8..000000000
--- a/res/drawable-xxhdpi/portal_container_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xxhdpi/portal_ring_inner.png b/res/drawable-xxhdpi/portal_ring_inner.png
new file mode 100644
index 000000000..d088a172d
--- /dev/null
+++ b/res/drawable-xxhdpi/portal_ring_inner.png
Binary files differ
diff --git a/res/drawable-xxhdpi/portal_ring_inner_holo.png b/res/drawable-xxhdpi/portal_ring_inner_holo.png
deleted file mode 100644
index 8cd6a5930..000000000
--- a/res/drawable-xxhdpi/portal_ring_inner_holo.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xxhdpi/portal_ring_inner_nolip_holo.png b/res/drawable-xxhdpi/portal_ring_inner_nolip.png
index 0fad65629..0fad65629 100644
--- a/res/drawable-xxhdpi/portal_ring_inner_nolip_holo.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
new file mode 100644
index 000000000..45ac0406c
--- /dev/null
+++ b/res/drawable-xxhdpi/portal_ring_outer.png
Binary files differ
diff --git a/res/drawable-xxhdpi/portal_ring_outer_holo.png b/res/drawable-xxhdpi/portal_ring_outer_holo.png
deleted file mode 100644
index 0aee4f027..000000000
--- a/res/drawable-xxhdpi/portal_ring_outer_holo.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xxhdpi/quantum_panel.9.png b/res/drawable-xxhdpi/quantum_panel.9.png
deleted file mode 100644
index d7ba87416..000000000
--- a/res/drawable-xxhdpi/quantum_panel.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xxhdpi/quantum_panel_bitmap.9.png b/res/drawable-xxhdpi/quantum_panel_bitmap.9.png
new file mode 100644
index 000000000..b44269ea9
--- /dev/null
+++ b/res/drawable-xxhdpi/quantum_panel_bitmap.9.png
Binary files differ
diff --git a/res/drawable-xxhdpi/quantum_panel_dark.9.png b/res/drawable-xxhdpi/quantum_panel_dark.9.png
deleted file mode 100644
index 17ba0f116..000000000
--- a/res/drawable-xxhdpi/quantum_panel_dark.9.png
+++ /dev/null
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
new file mode 100644
index 000000000..7979cf747
--- /dev/null
+++ b/res/drawable-xxhdpi/quantum_panel_dark_bitmap.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
new file mode 100644
index 000000000..7e189d442
--- /dev/null
+++ b/res/drawable-xxhdpi/widget_resize_frame.9.png
Binary files differ
diff --git a/res/drawable-xxhdpi/widget_resize_frame_holo.9.png b/res/drawable-xxhdpi/widget_resize_frame_holo.9.png
deleted file mode 100644
index 1681387a1..000000000
--- a/res/drawable-xxhdpi/widget_resize_frame_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xxhdpi/widget_resize_handle_bottom.png b/res/drawable-xxhdpi/widget_resize_handle_bottom.png
deleted file mode 100644
index d549fcd91..000000000
--- a/res/drawable-xxhdpi/widget_resize_handle_bottom.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xxhdpi/widget_resize_handle_left.png b/res/drawable-xxhdpi/widget_resize_handle_left.png
deleted file mode 100644
index dd56dad15..000000000
--- a/res/drawable-xxhdpi/widget_resize_handle_left.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xxhdpi/widget_resize_handle_right.png b/res/drawable-xxhdpi/widget_resize_handle_right.png
deleted file mode 100644
index 296a1c166..000000000
--- a/res/drawable-xxhdpi/widget_resize_handle_right.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xxhdpi/widget_resize_handle_top.png b/res/drawable-xxhdpi/widget_resize_handle_top.png
deleted file mode 100644
index e86270ad1..000000000
--- a/res/drawable-xxhdpi/widget_resize_handle_top.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xxhdpi/widget_resize_shadow.9.png b/res/drawable-xxhdpi/widget_resize_shadow.9.png
new file mode 100644
index 000000000..41c448bbb
--- /dev/null
+++ b/res/drawable-xxhdpi/widget_resize_shadow.9.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/ic_arrow_back_grey.png b/res/drawable-xxxhdpi/ic_arrow_back_grey.png
new file mode 100755
index 000000000..854a9bd1a
--- /dev/null
+++ 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
new file mode 100644
index 000000000..bf39e5be2
--- /dev/null
+++ 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
new file mode 100644
index 000000000..7043be015
--- /dev/null
+++ 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
new file mode 100755
index 000000000..28519fda6
--- /dev/null
+++ 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
new file mode 100644
index 000000000..77a3302f6
--- /dev/null
+++ 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
new file mode 100644
index 000000000..4bde6b9a6
--- /dev/null
+++ 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
new file mode 100644
index 000000000..34a359997
--- /dev/null
+++ 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
new file mode 100644
index 000000000..8cebb3535
--- /dev/null
+++ 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
new file mode 100644
index 000000000..d2df32267
--- /dev/null
+++ 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
new file mode 100644
index 000000000..11e92eeb6
--- /dev/null
+++ 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
new file mode 100644
index 000000000..bc887fe91
--- /dev/null
+++ 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
new file mode 100644
index 000000000..7cfd6e477
--- /dev/null
+++ 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
new file mode 100644
index 000000000..cb609cef9
--- /dev/null
+++ 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
new file mode 100644
index 000000000..82c8b9c7c
--- /dev/null
+++ b/res/drawable-xxxhdpi/widget_resize_shadow.9.png
Binary files differ
diff --git a/res/drawable/all_apps_search_bg.xml b/res/drawable/all_apps_search_bg.xml
new file mode 100644
index 000000000..a09f88fd4
--- /dev/null
+++ b/res/drawable/all_apps_search_bg.xml
@@ -0,0 +1,20 @@
+<?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.
+-->
+<inset xmlns:android="http://schemas.android.com/apk/res/android"
+ android:drawable="@drawable/quantum_panel"
+ android:insetTop="@dimen/container_bounds_minus_quantum_panel_padding_inset"
+ android:insetBottom="@dimen/container_bounds_minus_quantum_panel_padding_inset" /> \ No newline at end of file
diff --git a/res/drawable/info_target_selector.xml b/res/drawable/bg_screenpanel.xml
index f3a7016c3..cdb71dfa1 100644
--- a/res/drawable/info_target_selector.xml
+++ b/res/drawable/bg_screenpanel.xml
@@ -2,7 +2,7 @@
<!--
/*
**
-** Copyright 2011, The Android Open Source Project
+** Copyright 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.
@@ -18,7 +18,9 @@
*/
-->
-<transition xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:drawable="@drawable/ic_launcher_info_normal_holo" />
- <item android:drawable="@drawable/ic_launcher_info_active_holo" />
-</transition>
+<transition xmlns:android="http://schemas.android.com/apk/res/android" >
+
+ <item android:drawable="@drawable/screenpanel"/>
+ <item android:drawable="@drawable/screenpanel_hover"/>
+
+</transition> \ No newline at end of file
diff --git a/res/drawable/container_fastscroll_popup_bg.xml b/res/drawable/container_fastscroll_popup_bg.xml
new file mode 100644
index 000000000..2ef07ab96
--- /dev/null
+++ b/res/drawable/container_fastscroll_popup_bg.xml
@@ -0,0 +1,27 @@
+<?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.
+-->
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shape="rectangle">
+ <solid android:color="@color/container_fastscroll_thumb_active_color" />
+ <size
+ android:width="64dp"
+ android:height="64dp" />
+ <corners
+ android:topLeftRadius="64dp"
+ android:topRightRadius="64dp"
+ android:bottomLeftRadius="64dp" />
+</shape> \ No newline at end of file
diff --git a/WallpaperPicker/res/values-sw600dp/config.xml b/res/drawable/quantum_panel.xml
index 62342dcc2..1f4fb711b 100644
--- a/WallpaperPicker/res/values-sw600dp/config.xml
+++ b/res/drawable/quantum_panel.xml
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2013 The Android Open Source Project
+<!--
+ 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.
@@ -13,6 +14,5 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<resources>
- <bool name="allow_rotation">true</bool>
-</resources>
+<nine-patch xmlns:android="http://schemas.android.com/apk/res/android"
+ android:src="@drawable/quantum_panel_bitmap" />
diff --git a/res/values-sw340dp-port/config.xml b/res/drawable/quantum_panel_dark.xml
index 5f71077c7..6642e78ac 100644
--- a/res/values-sw340dp-port/config.xml
+++ b/res/drawable/quantum_panel_dark.xml
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2011 The Android Open Source Project
+<!--
+ 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.
@@ -13,6 +14,5 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-
-<resources>
-</resources>
+<nine-patch xmlns:android="http://schemas.android.com/apk/res/android"
+ android:src="@drawable/quantum_panel_dark_bitmap" />
diff --git a/res/drawable/quantum_panel_shape.xml b/res/drawable/quantum_panel_shape.xml
new file mode 100644
index 000000000..108361576
--- /dev/null
+++ b/res/drawable/quantum_panel_shape.xml
@@ -0,0 +1,22 @@
+<?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.
+-->
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shape="rectangle">
+ <solid android:color="@color/quantum_panel_bg_color" />
+ <corners
+ android:radius="2dp" />
+</shape> \ No newline at end of file
diff --git a/res/layout/apps_customize_application.xml b/res/drawable/quantum_panel_shape_dark.xml
index c56cdf3d2..c3821c416 100644
--- a/res/layout/apps_customize_application.xml
+++ b/res/drawable/quantum_panel_shape_dark.xml
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2011 The Android Open Source Project
+<!--
+ 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.
@@ -13,9 +14,9 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-
-<com.android.launcher3.BubbleTextView
- xmlns:android="http://schemas.android.com/apk/res/android"
- style="@style/WorkspaceIcon.AppsCustomize"
- android:id="@+id/application_icon"
- android:focusable="true" />
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shape="rectangle">
+ <solid android:color="@color/quantum_panel_bg_color_dark" />
+ <corners
+ android:radius="2dp" />
+</shape> \ No newline at end of file
diff --git a/res/drawable/remove_target_selector.xml b/res/drawable/remove_target_selector.xml
deleted file mode 100644
index 5e071fbfa..000000000
--- a/res/drawable/remove_target_selector.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2007, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<transition xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:drawable="@drawable/ic_launcher_clear_normal_holo" />
- <item android:drawable="@drawable/ic_launcher_clear_active_holo" />
-</transition>
diff --git a/res/drawable/uninstall_target_selector.xml b/res/drawable/uninstall_target_selector.xml
deleted file mode 100644
index 229942e3a..000000000
--- a/res/drawable/uninstall_target_selector.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2007, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<transition xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:drawable="@drawable/ic_launcher_trashcan_normal_holo" />
- <item android:drawable="@drawable/ic_launcher_trashcan_active_holo" />
-</transition>
diff --git a/res/values-land/config.xml b/res/drawable/widgets_row_divider.xml
index 31115c9cb..bb5b6b55b 100644
--- a/res/values-land/config.xml
+++ b/res/drawable/widgets_row_divider.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2011 The Android Open Source Project
+<!-- 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.
@@ -13,9 +13,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-
-<resources>
-<!-- Workspace -->
- <!-- Whether or not the drop targets drop down as opposed to fade in -->
- <bool name="config_useDropTargetDownTransition">false</bool>
-</resources>
+<shape xmlns:android="http://schemas.android.com/apk/res/android" >
+ <size android:width="@dimen/widget_row_divider" />
+ <solid android:color="@color/quantum_panel_bg_color_dark" />
+</shape>
diff --git a/res/layout-land/launcher.xml b/res/layout-land/launcher.xml
index 6f95bd506..6500ebcd2 100644
--- a/res/layout-land/launcher.xml
+++ b/res/layout-land/launcher.xml
@@ -18,11 +18,9 @@
<com.android.launcher3.LauncherRootView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:launcher="http://schemas.android.com/apk/res-auto"
-
android:id="@+id/launcher"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:background="@drawable/workspace_bg"
android:fitsSystemWindows="true">
<com.android.launcher3.DragLayer
@@ -36,6 +34,7 @@
android:layout_height="52dp" />
<!-- The workspace contains 5 screens of cells -->
+ <!-- DO NOT CHANGE THE ID -->
<com.android.launcher3.Workspace
android:id="@+id/workspace"
android:layout_width="match_parent"
@@ -43,11 +42,12 @@
android:layout_gravity="center"
launcher:defaultScreen="@integer/config_workspaceDefaultScreen" />
+ <!-- DO NOT CHANGE THE ID -->
<include layout="@layout/hotseat"
android:id="@+id/hotseat"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:layout_gravity="end" />
+ android:layout_gravity="right" />
<include
android:id="@+id/search_drop_target_bar"
@@ -57,8 +57,14 @@
android:id="@+id/overview_panel"
android:visibility="gone" />
- <include layout="@layout/apps_customize_pane"
- android:id="@+id/apps_customize_pane"
+ <include layout="@layout/widgets_view"
+ android:id="@+id/widgets_view"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:visibility="invisible" />
+
+ <include layout="@layout/all_apps"
+ android:id="@+id/apps_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="invisible" />
diff --git a/res/layout-land/migration_cling.xml b/res/layout-land/migration_cling.xml
index db93da87a..269c1aee6 100644
--- a/res/layout-land/migration_cling.xml
+++ b/res/layout-land/migration_cling.xml
@@ -46,6 +46,7 @@
android:layout_width="@dimen/cling_migration_content_width"
android:layout_height="wrap_content"
android:layout_marginEnd="@dimen/cling_migration_content_margin"
+ android:layout_marginRight="@dimen/cling_migration_content_margin"
android:orientation="vertical"
android:paddingLeft="24dp"
android:paddingRight="24dp" >
diff --git a/res/layout-port/launcher.xml b/res/layout-port/launcher.xml
index af30a32e5..d0772ee70 100644
--- a/res/layout-port/launcher.xml
+++ b/res/layout-port/launcher.xml
@@ -22,7 +22,6 @@
android:id="@+id/launcher"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:background="@drawable/workspace_bg"
android:fitsSystemWindows="true">
<com.android.launcher3.DragLayer
@@ -36,6 +35,7 @@
android:layout_height="52dp" />
<!-- The workspace contains 5 screens of cells -->
+ <!-- DO NOT CHANGE THE ID -->
<com.android.launcher3.Workspace
android:id="@+id/workspace"
android:layout_width="match_parent"
@@ -44,6 +44,7 @@
launcher:pageIndicator="@+id/page_indicator">
</com.android.launcher3.Workspace>
+ <!-- DO NOT CHANGE THE ID -->
<include layout="@layout/hotseat"
android:id="@+id/hotseat"
android:layout_width="match_parent"
@@ -66,8 +67,14 @@
android:id="@+id/search_drop_target_bar"
layout="@layout/search_drop_target_bar" />
- <include layout="@layout/apps_customize_pane"
- android:id="@+id/apps_customize_pane"
+ <include layout="@layout/widgets_view"
+ android:id="@+id/widgets_view"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:visibility="invisible" />
+
+ <include layout="@layout/all_apps"
+ android:id="@+id/apps_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="invisible" />
diff --git a/res/layout-port/migration_cling.xml b/res/layout-port/migration_cling.xml
index 81689d38b..3f696a216 100644
--- a/res/layout-port/migration_cling.xml
+++ b/res/layout-port/migration_cling.xml
@@ -48,6 +48,7 @@
android:layout_height="wrap_content"
android:layout_below="@+id/ic_cling_migration"
android:layout_marginStart="@dimen/cling_migration_content_margin"
+ android:layout_marginLeft="@dimen/cling_migration_content_margin"
android:orientation="vertical"
android:paddingLeft="24dp"
android:paddingRight="24dp" >
diff --git a/res/layout-sw720dp/launcher.xml b/res/layout-sw720dp/launcher.xml
index 960ccf330..802922ec1 100644
--- a/res/layout-sw720dp/launcher.xml
+++ b/res/layout-sw720dp/launcher.xml
@@ -18,11 +18,9 @@
<com.android.launcher3.LauncherRootView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:launcher="http://schemas.android.com/apk/res-auto"
-
android:id="@+id/launcher"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:background="@drawable/workspace_bg"
android:fitsSystemWindows="true">
<com.android.launcher3.DragLayer
@@ -36,6 +34,7 @@
android:layout_height="52dp" />
<!-- The workspace contains 5 screens of cells -->
+ <!-- DO NOT CHANGE THE ID -->
<com.android.launcher3.Workspace
android:id="@+id/workspace"
android:layout_width="match_parent"
@@ -44,6 +43,7 @@
launcher:pageIndicator="@id/page_indicator">
</com.android.launcher3.Workspace>
+ <!-- DO NOT CHANGE THE ID -->
<include layout="@layout/hotseat"
android:id="@+id/hotseat"
android:layout_width="match_parent"
@@ -59,15 +59,20 @@
<!-- Keep these behind the workspace so that they are not visible when
we go into AllApps -->
- <include
- android:id="@+id/page_indicator"
+ <include android:id="@+id/page_indicator"
layout="@layout/page_indicator"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal" />
- <include layout="@layout/apps_customize_pane"
- android:id="@+id/apps_customize_pane"
+ <include layout="@layout/widgets_view"
+ android:id="@+id/widgets_view"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:visibility="invisible" />
+
+ <include layout="@layout/all_apps"
+ android:id="@+id/apps_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="invisible" />
diff --git a/res/layout/all_apps.xml b/res/layout/all_apps.xml
new file mode 100644
index 000000000..1bf54eefb
--- /dev/null
+++ b/res/layout/all_apps.xml
@@ -0,0 +1,57 @@
+<?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.
+-->
+<!-- The top and bottom paddings are defined in this container, but since we want
+ the list view to span the full width (for touch interception purposes), we
+ will bake the left/right padding into that view's background itself. -->
+<com.android.launcher3.allapps.AllAppsContainerView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/apps_view"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical">
+
+ <!-- Both android:focusable and android:focusableInTouchMode are needed for
+ the view to get focus change events. -->
+ <FrameLayout
+ android:id="@+id/search_box_container"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:focusable="true"
+ android:focusableInTouchMode="true"
+ android:visibility="gone" />
+
+ <FrameLayout
+ android:id="@+id/content"
+ android:layout_width="match_parent"
+ android:layout_height="0dp"
+ android:layout_weight="1">
+ <FrameLayout
+ android:id="@+id/all_apps_reveal"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_gravity="center"
+ android:focusable="false"
+ android:elevation="2dp"
+ android:visibility="invisible" />
+ <include
+ layout="@layout/all_apps_container"
+ android:id="@+id/all_apps_container"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_gravity="center"
+ android:visibility="gone" />
+ </FrameLayout>
+</com.android.launcher3.allapps.AllAppsContainerView> \ No newline at end of file
diff --git a/res/layout/all_apps_button.xml b/res/layout/all_apps_button.xml
index 9d6d82bb2..68cc10932 100644
--- a/res/layout/all_apps_button.xml
+++ b/res/layout/all_apps_button.xml
@@ -15,5 +15,5 @@
-->
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
- style="@style/WorkspaceIcon"
+ style="@style/Icon"
android:focusable="true" />
diff --git a/res/layout/all_apps_container.xml b/res/layout/all_apps_container.xml
new file mode 100644
index 000000000..626edafab
--- /dev/null
+++ b/res/layout/all_apps_container.xml
@@ -0,0 +1,38 @@
+<?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.
+-->
+<!-- Both android:focusable and android:focusableInTouchMode are needed for
+ the view to get focus change events. -->
+<com.android.launcher3.allapps.AllAppsRecyclerViewContainerView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:elevation="15dp"
+ android:focusable="true"
+ android:focusableInTouchMode="true">
+
+ <!-- DO NOT CHANGE THE ID -->
+ <com.android.launcher3.allapps.AllAppsRecyclerView
+ android:id="@+id/apps_list_view"
+ android:theme="@style/Theme.Light.CustomOverscroll"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_gravity="center_horizontal|top"
+ android:clipToPadding="false"
+ android:focusable="true"
+ android:descendantFocusability="afterDescendants" />
+
+</com.android.launcher3.allapps.AllAppsRecyclerViewContainerView> \ No newline at end of file
diff --git a/res/layout/add_list_item.xml b/res/layout/all_apps_empty_search.xml
index e937d7bc1..f60c4a09a 100644
--- a/res/layout/add_list_item.xml
+++ b/res/layout/all_apps_empty_search.xml
@@ -1,25 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2009 The Android Open Source Project
+<!-- 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.
-->
-
-<TextView xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
+<TextView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/empty_text"
+ android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:minHeight="?android:attr/listPreferredItemHeight"
- android:textAppearance="?android:attr/textAppearanceLarge"
- android:gravity="center_vertical"
- android:drawablePadding="14dip"
- android:paddingLeft="15dip"
- android:paddingRight="15dip" />
+ android:gravity="center"
+ android:paddingTop="24dp"
+ android:paddingBottom="24dp"
+ android:paddingRight="@dimen/all_apps_grid_view_start_margin"
+ android:textSize="16sp"
+ android:textColor="#4c4c4c"
+ android:focusable="false" />
+
diff --git a/res/layout/all_apps_icon.xml b/res/layout/all_apps_icon.xml
new file mode 100644
index 000000000..0985e95c0
--- /dev/null
+++ b/res/layout/all_apps_icon.xml
@@ -0,0 +1,29 @@
+<?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.
+-->
+<com.android.launcher3.BubbleTextView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:launcher="http://schemas.android.com/apk/res-auto"
+ style="@style/Icon.AllApps"
+ android:id="@+id/icon"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"
+ android:paddingTop="@dimen/all_apps_icon_top_bottom_padding"
+ android:paddingBottom="@dimen/all_apps_icon_top_bottom_padding"
+ android:focusable="true"
+ android:background="@drawable/focusable_view_bg"
+ launcher:iconDisplay="all_apps" />
+
diff --git a/res/layout/all_apps_prediction_bar_icon.xml b/res/layout/all_apps_prediction_bar_icon.xml
new file mode 100644
index 000000000..341d8ef4f
--- /dev/null
+++ b/res/layout/all_apps_prediction_bar_icon.xml
@@ -0,0 +1,29 @@
+<?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.
+-->
+<com.android.launcher3.BubbleTextView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:launcher="http://schemas.android.com/apk/res-auto"
+ style="@style/Icon.AllApps"
+ android:id="@+id/icon"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"
+ android:paddingTop="@dimen/all_apps_prediction_icon_top_padding"
+ android:paddingBottom="@dimen/all_apps_prediction_icon_bottom_padding"
+ android:focusable="true"
+ android:background="@drawable/focusable_view_bg"
+ launcher:iconDisplay="all_apps" />
+
diff --git a/res/layout/all_apps_search_bar.xml b/res/layout/all_apps_search_bar.xml
new file mode 100644
index 000000000..cf30eac36
--- /dev/null
+++ b/res/layout/all_apps_search_bar.xml
@@ -0,0 +1,72 @@
+<?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.
+-->
+<FrameLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:background="@drawable/all_apps_search_bg" >
+
+ <LinearLayout
+ android:id="@+id/search_container"
+ android:layout_width="match_parent"
+ android:layout_height="@dimen/all_apps_search_bar_height"
+ android:layout_gravity="start|center_vertical"
+ android:orientation="horizontal"
+ android:visibility="invisible" >
+
+ <ImageView
+ android:id="@+id/dismiss_search_button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="4dp"
+ android:layout_marginStart="4dp"
+ android:contentDescription="@string/all_apps_button_label"
+ android:paddingBottom="13dp"
+ android:paddingTop="13dp"
+ android:src="@drawable/ic_arrow_back_grey" />
+
+ <com.android.launcher3.allapps.AllAppsSearchEditView
+ android:id="@+id/search_box_input"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:background="@android:color/transparent"
+ android:focusableInTouchMode="true"
+ android:gravity="fill_horizontal|center_vertical"
+ android:hint="@string/all_apps_search_bar_hint"
+ android:inputType="text|textNoSuggestions|textCapWords"
+ android:imeOptions="actionDone|flagNoExtractUi"
+ android:maxLines="1"
+ android:paddingLeft="8dp"
+ android:scrollHorizontally="true"
+ android:singleLine="true"
+ android:textColor="#4c4c4c"
+ android:textColorHint="#9c9c9c"
+ android:textSize="16sp" />
+ </LinearLayout>
+
+ <ImageView
+ android:id="@+id/search_button"
+ android:layout_width="wrap_content"
+ android:layout_height="@dimen/all_apps_search_bar_height"
+ android:layout_gravity="end|center_vertical"
+ android:layout_marginEnd="4dp"
+ android:layout_marginRight="4dp"
+ android:contentDescription="@string/all_apps_search_bar_hint"
+ android:paddingBottom="13dp"
+ android:paddingTop="13dp"
+ android:src="@drawable/ic_search_grey" />
+</FrameLayout> \ No newline at end of file
diff --git a/res/layout/application.xml b/res/layout/app_icon.xml
index c21dea070..831cee5b0 100644
--- a/res/layout/application.xml
+++ b/res/layout/app_icon.xml
@@ -15,5 +15,5 @@
-->
<com.android.launcher3.BubbleTextView xmlns:android="http://schemas.android.com/apk/res/android"
- style="@style/WorkspaceIcon"
+ style="@style/Icon"
android:focusable="true" />
diff --git a/res/layout/apps_customize_pane.xml b/res/layout/apps_customize_pane.xml
deleted file mode 100644
index e42576ffe..000000000
--- a/res/layout/apps_customize_pane.xml
+++ /dev/null
@@ -1,62 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2011 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<com.android.launcher3.AppsCustomizeTabHost
- xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:launcher="http://schemas.android.com/apk/res-auto"
- android:clipChildren="false">
-
- <LinearLayout
- android:id="@+id/content"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:clipChildren="false"
- android:orientation="vertical">
-
- <FrameLayout
- android:layout_width="match_parent"
- android:layout_height="0dp"
- android:layout_weight="1"
- android:clipChildren="false">
- <FrameLayout
- android:id="@+id/fake_page_container"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:clipChildren="false"
- android:clipToPadding="false">
- <FrameLayout
- android:id="@+id/fake_page"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:visibility="invisible"
- android:clipToPadding="false" />
- </FrameLayout>
- <com.android.launcher3.AppsCustomizePagedView
- android:id="@+id/apps_customize_pane_content"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- launcher:widgetCountX="@integer/apps_customize_widget_cell_count_x"
- launcher:widgetCountY="@integer/apps_customize_widget_cell_count_y"
- launcher:maxGap="@dimen/workspace_max_gap"
- launcher:pageIndicator="@+id/apps_customize_page_indicator" />
- </FrameLayout>
- <include
- android:id="@+id/apps_customize_page_indicator"
- layout="@layout/page_indicator"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="center" />
- </LinearLayout>
-</com.android.launcher3.AppsCustomizeTabHost>
diff --git a/res/layout/apps_customize_progressbar.xml b/res/layout/apps_customize_progressbar.xml
deleted file mode 100644
index 6aa90999c..000000000
--- a/res/layout/apps_customize_progressbar.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2011 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<ProgressBar
- xmlns:android="http://schemas.android.com/apk/res/android"
- style="?android:attr/progressBarStyleLarge"
- android:id="@+id/apps_customize_progress_bar"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="center" />
diff --git a/res/layout/apps_customize_widget.xml b/res/layout/apps_customize_widget.xml
deleted file mode 100644
index a8344e3ff..000000000
--- a/res/layout/apps_customize_widget.xml
+++ /dev/null
@@ -1,105 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2011 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<com.android.launcher3.PagedViewWidget
- xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:launcher="http://schemas.android.com/apk/res-auto"
-
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:layout_weight="1"
- android:orientation="vertical"
-
- android:background="@drawable/focusable_view_bg"
- android:focusable="true">
-
- <LinearLayout
- android:orientation="horizontal"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_weight="1">
- <FrameLayout
- android:id="@+id/left_border"
- android:layout_width="1dp"
- android:layout_height="match_parent"
- android:background="@color/widget_text_panel"
- android:visibility="gone" />
-
- <!-- The preview of the widget or shortcut. -->
- <com.android.launcher3.PagedViewWidgetImageView
- android:id="@+id/widget_preview"
- style="@style/PagedViewWidgetImageView"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:layout_weight="1"
- android:paddingTop="@dimen/app_widget_preview_padding_top"
- android:paddingEnd="@dimen/app_widget_preview_padding_right"
- android:paddingRight="@dimen/app_widget_preview_padding_right"
- android:scaleType="matrix" />
- <FrameLayout
- android:id="@+id/right_border"
- android:layout_width="1dp"
- android:layout_height="match_parent"
- android:background="@color/widget_text_panel"
- android:visibility="gone" />
- </LinearLayout>
-
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:paddingTop="@dimen/app_widget_preview_label_vertical_padding"
- android:paddingBottom="@dimen/app_widget_preview_label_vertical_padding"
- android:paddingLeft="@dimen/app_widget_preview_label_horizontal_padding"
- android:paddingRight="@dimen/app_widget_preview_label_horizontal_padding"
- android:background="@color/widget_text_panel"
- android:orientation="horizontal">
- <!-- The name of the widget. -->
- <TextView
- android:id="@+id/widget_name"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_weight="1"
- android:gravity="start"
- android:singleLine="true"
- android:ellipsize="marquee"
- android:fadingEdge="horizontal"
-
- android:textColor="#FFFFFFFF"
- android:textSize="12sp"
- android:textAlignment="viewStart"
- android:fontFamily="sans-serif-condensed"
- android:shadowRadius="2.0"
- android:shadowColor="#B0000000" />
-
- <!-- The original dimensions of the widget (can't be the same text as above due to different
- style. -->
- <TextView
- android:id="@+id/widget_dims"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="center"
- android:layout_marginStart="5dp"
- android:layout_weight="0"
- android:gravity="start"
-
- android:textColor="#FFFFFFFF"
- android:textSize="12sp"
- android:fontFamily="sans-serif-condensed"
- android:shadowRadius="2.0"
- android:shadowColor="#B0000000" />
- </LinearLayout>
-
-
-</com.android.launcher3.PagedViewWidget>
diff --git a/res/layout/appwidget_error.xml b/res/layout/appwidget_error.xml
index 03d4ae424..708ece4e2 100644
--- a/res/layout/appwidget_error.xml
+++ b/res/layout/appwidget_error.xml
@@ -15,15 +15,12 @@
-->
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:paddingTop="10dip"
- android:paddingBottom="10dip"
- android:paddingLeft="20dip"
- android:paddingRight="20dip"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
android:gravity="center"
- android:background="@drawable/bg_appwidget_error"
+ android:elevation="2dp"
+ android:background="@drawable/quantum_panel_dark"
android:textAppearance="?android:attr/textAppearanceMediumInverse"
- android:textColor="@color/appwidget_error_color"
+ android:textColor="@color/widgets_view_item_text_color"
android:text="@string/gadget_error_text"
/>
diff --git a/res/layout/dummy_widget.xml b/res/layout/dummy_widget.xml
new file mode 100644
index 000000000..a0fa8fc3e
--- /dev/null
+++ b/res/layout/dummy_widget.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="horizontal">
+
+ <FrameLayout
+ android:layout_width="0dp"
+ android:layout_height="match_parent"
+ android:layout_weight="1"
+ android:background="#ffff0000" />
+
+ <FrameLayout
+ android:layout_width="0dp"
+ android:layout_height="match_parent"
+ android:layout_weight="1"
+ android:background="#ff00ff00" />
+
+</LinearLayout> \ No newline at end of file
diff --git a/res/layout/folder_application.xml b/res/layout/folder_application.xml
index b48b61331..4d003313e 100644
--- a/res/layout/folder_application.xml
+++ b/res/layout/folder_application.xml
@@ -15,5 +15,5 @@
-->
<com.android.launcher3.BubbleTextView xmlns:android="http://schemas.android.com/apk/res/android"
- style="@style/WorkspaceIcon.Folder"
+ style="@style/Icon.Folder"
android:focusable="true" />
diff --git a/res/layout/folder_icon.xml b/res/layout/folder_icon.xml
index fd45d7685..237af6890 100644
--- a/res/layout/folder_icon.xml
+++ b/res/layout/folder_icon.xml
@@ -26,9 +26,9 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:antialias="true"
- android:src="@drawable/portal_ring_inner_holo"/>
+ android:src="@drawable/portal_ring_inner"/>
<com.android.launcher3.BubbleTextView
- style="@style/WorkspaceIcon"
+ style="@style/Icon"
android:id="@+id/folder_icon_name"
android:layout_gravity="top"
android:layout_width="match_parent"
diff --git a/res/layout/page_indicator_marker.xml b/res/layout/page_indicator_marker.xml
index 686d27569..564a95811 100644
--- a/res/layout/page_indicator_marker.xml
+++ b/res/layout/page_indicator_marker.xml
@@ -16,8 +16,8 @@
<com.android.launcher3.PageIndicatorMarker
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:launcher="http://schemas.android.com/apk/res-auto"
- android:layout_width="16dp"
- android:layout_height="16dp"
+ android:layout_width="12dp"
+ android:layout_height="12dp"
android:layout_gravity="center_vertical">
<ImageView
android:id="@+id/inactive"
diff --git a/res/layout/rename_folder.xml b/res/layout/rename_folder.xml
deleted file mode 100644
index 21a335c4a..000000000
--- a/res/layout/rename_folder.xml
+++ /dev/null
@@ -1,42 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:padding="20dip"
- android:orientation="vertical">
-
- <TextView
- android:id="@+id/label"
- android:layout_height="wrap_content"
- android:layout_width="wrap_content"
- android:text="@string/rename_folder_label"
- android:gravity="start"
- android:textAppearance="?android:attr/textAppearanceMedium" />
-
- <EditText
- android:id="@+id/folder_name"
- android:layout_height="wrap_content"
- android:layout_width="match_parent"
- android:scrollHorizontally="true"
- android:autoText="false"
- android:capitalize="none"
- android:gravity="fill_horizontal"
- android:maxLength="30"
- android:textAppearance="?android:attr/textAppearanceMedium" />
-
-</LinearLayout>
diff --git a/res/layout/search_drop_target_bar.xml b/res/layout/search_drop_target_bar.xml
index af2d01634..4737ee1bc 100644
--- a/res/layout/search_drop_target_bar.xml
+++ b/res/layout/search_drop_target_bar.xml
@@ -17,8 +17,7 @@
<com.android.launcher3.SearchDropTargetBar xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:focusable="false"
- android:orientation="horizontal" >
+ android:focusable="false" >
<!-- Drag specific targets container -->
@@ -37,8 +36,7 @@
<com.android.launcher3.DeleteDropTarget
android:id="@+id/delete_target_text"
style="@style/DropTargetButton"
- android:drawableStart="@drawable/remove_target_selector"
- android:text="@string/delete_zone_label_workspace" />
+ android:text="@string/delete_target_label" />
</FrameLayout>
<FrameLayout
@@ -50,9 +48,20 @@
<com.android.launcher3.InfoDropTarget
android:id="@+id/info_target_text"
style="@style/DropTargetButton"
- android:drawableStart="@drawable/info_target_selector"
android:text="@string/info_target_label" />
</FrameLayout>
+
+ <FrameLayout
+ style="@style/DropTargetButtonContainer"
+ android:layout_weight="1" >
+
+ <!-- Uninstall target -->
+
+ <com.android.launcher3.UninstallDropTarget
+ android:id="@+id/uninstall_target_text"
+ style="@style/DropTargetButton"
+ android:text="@string/delete_target_uninstall_label" />
+ </FrameLayout>
</LinearLayout>
</com.android.launcher3.SearchDropTargetBar> \ No newline at end of file
diff --git a/res/layout/user_folder.xml b/res/layout/user_folder.xml
index ed8d43e46..ecf7def48 100644
--- a/res/layout/user_folder.xml
+++ b/res/layout/user_folder.xml
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 The Android Open Source Project
+<!--
+ 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.
@@ -13,43 +14,72 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-
-<com.android.launcher3.Folder
- xmlns:android="http://schemas.android.com/apk/res/android"
+<com.android.launcher3.Folder xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:launcher="http://schemas.android.com/apk/res-auto"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:orientation="vertical"
- android:background="@drawable/quantum_panel">
+ android:background="@drawable/quantum_panel"
+ android:elevation="5dp"
+ android:orientation="vertical" >
- <ScrollView
- android:id="@+id/scroll_view"
+ <FrameLayout
+ android:id="@+id/folder_content_wrapper"
android:layout_width="match_parent"
- android:layout_height="match_parent">
- <com.android.launcher3.CellLayout
- android:id="@+id/folder_content"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:cacheColorHint="#ff333333"
- android:hapticFeedbackEnabled="false" />
- </ScrollView>
-
- <com.android.launcher3.FolderEditText
- android:id="@+id/folder_name"
+ android:layout_height="match_parent" >
+
+ <!-- Actual size of the indicator doesn't matter as it is scaled to match the view size -->
+
+ <com.android.launcher3.FocusIndicatorView
+ android:id="@+id/focus_indicator"
+ android:layout_width="20dp"
+ android:layout_height="20dp" />
+
+ <com.android.launcher3.FolderPagedView
+ android:id="@+id/folder_content"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:paddingLeft="4dp"
+ android:paddingRight="4dp"
+ android:paddingTop="8dp"
+ launcher:pageIndicator="@+id/folder_page_indicator" />
+ </FrameLayout>
+
+ <LinearLayout
+ android:id="@+id/folder_footer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_centerHorizontal="true"
- android:paddingTop="@dimen/folder_name_padding"
- android:paddingBottom="@dimen/folder_name_padding"
- android:background="#00000000"
- android:hint="@string/folder_hint_text"
- android:textSize="14sp"
- android:textColor="#ff777777"
- android:textColorHint="#ff808080"
- android:textColorHighlight="#ffCCCCCC"
- android:textCursorDrawable="@null"
- android:gravity="center_horizontal"
- android:singleLine="true"
- android:imeOptions="flagNoExtractUi"
- android:fontFamily="sans-serif-condensed"/>
-</com.android.launcher3.Folder>
+ android:clipChildren="false"
+ android:orientation="horizontal"
+ android:paddingLeft="8dp"
+ android:paddingRight="8dp" >
+
+ <com.android.launcher3.FolderEditText
+ android:id="@+id/folder_name"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:layout_weight="1"
+ android:background="#00000000"
+ android:fontFamily="sans-serif-condensed"
+ android:gravity="center_horizontal"
+ android:hint="@string/folder_hint_text"
+ android:imeOptions="flagNoExtractUi"
+ android:paddingBottom="8dp"
+ android:paddingTop="4dp"
+ android:singleLine="true"
+ android:textColor="#ff777777"
+ android:textColorHighlight="#ffCCCCCC"
+ android:textColorHint="#ff808080"
+ android:textCursorDrawable="@null"
+ android:textSize="14sp" />
+
+ <include
+ android:id="@+id/folder_page_indicator"
+ android:layout_width="wrap_content"
+ android:layout_height="12dp"
+ android:layout_gravity="center_vertical"
+ layout="@layout/page_indicator" />
+
+ </LinearLayout>
+
+</com.android.launcher3.Folder> \ No newline at end of file
diff --git a/res/layout/widget_cell.xml b/res/layout/widget_cell.xml
new file mode 100644
index 000000000..7fefebaec
--- /dev/null
+++ b/res/layout/widget_cell.xml
@@ -0,0 +1,74 @@
+<?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.
+-->
+<com.android.launcher3.widget.WidgetCell
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:launcher="http://schemas.android.com/apk/res-auto"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:orientation="vertical"
+ android:focusable="true"
+ android:background="@color/widgets_cell_color"
+ android:gravity="center_horizontal">
+
+ <LinearLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:paddingTop="@dimen/widget_preview_label_vertical_padding"
+ android:paddingBottom="@dimen/widget_preview_label_vertical_padding"
+ android:paddingLeft="@dimen/widget_preview_label_horizontal_padding"
+ android:paddingRight="@dimen/widget_preview_label_horizontal_padding"
+ android:orientation="horizontal">
+
+ <!-- The name of the widget. -->
+ <TextView
+ android:id="@+id/widget_name"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:ellipsize="end"
+ android:fadingEdge="horizontal"
+ android:fontFamily="sans-serif-condensed"
+ android:gravity="start"
+ android:shadowColor="#B0000000"
+ android:shadowRadius="2.0"
+ android:singleLine="true"
+ android:textColor="@color/widgets_view_item_text_color"
+ android:textSize="14sp" />
+
+ <!-- The original dimensions of the widget (can't be the same text as above due to different
+ style. -->
+ <TextView
+ android:id="@+id/widget_dims"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="5dp"
+ android:layout_marginLeft="5dp"
+ android:textColor="@color/widgets_view_item_text_color"
+ android:textSize="14sp"
+ android:fontFamily="sans-serif-condensed"
+ android:shadowRadius="2.0"
+ android:shadowColor="#B0000000" />
+ </LinearLayout>
+
+ <!-- The image of the widget. This view does not support padding. Any placement adjustment
+ should be done using margins. -->
+ <com.android.launcher3.widget.WidgetImageView
+ android:id="@+id/widget_preview"
+ android:layout_width="match_parent"
+ android:layout_height="0dp"
+ android:layout_weight="1" />
+</com.android.launcher3.widget.WidgetCell> \ No newline at end of file
diff --git a/res/layout/widgets_list_row_view.xml b/res/layout/widgets_list_row_view.xml
new file mode 100644
index 000000000..ced564801
--- /dev/null
+++ b/res/layout/widgets_list_row_view.xml
@@ -0,0 +1,67 @@
+<?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.
+-->
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:launcher="http://schemas.android.com/apk/res-auto"
+ android:id="@+id/widgets_cell_list_container"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:background="@color/widgets_cell_color"
+ android:orientation="vertical"
+ android:focusable="true"
+ android:descendantFocusability="afterDescendants">
+
+ <!-- Section info -->
+
+ <com.android.launcher3.BubbleTextView
+ android:id="@+id/section"
+ android:layout_width="match_parent"
+ android:layout_height="@dimen/widget_section_height"
+ android:background="@color/quantum_panel_bg_color_dark"
+ android:drawablePadding="@dimen/widget_section_horizontal_padding"
+ android:ellipsize="end"
+ android:focusable="true"
+ android:gravity="start|center_vertical"
+ android:importantForAccessibility="no"
+ android:paddingBottom="@dimen/widget_section_vertical_padding"
+ android:paddingLeft="@dimen/widget_section_horizontal_padding"
+ android:paddingRight="@dimen/widget_section_horizontal_padding"
+ android:paddingTop="@dimen/widget_section_vertical_padding"
+ android:singleLine="true"
+ android:textColor="@color/widgets_view_section_text_color"
+ android:textSize="16sp"
+ launcher:customShadows="false"
+ launcher:deferShadowGeneration="true"
+ launcher:iconDisplay="widget_section"
+ launcher:iconSizeOverride="@dimen/widget_section_icon_size"
+ launcher:layoutHorizontal="true" />
+
+ <HorizontalScrollView
+ android:id="@+id/widgets_scroll_container"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:scrollbars="none">
+ <LinearLayout
+ android:id="@+id/widgets_cell_list"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="@dimen/widget_row_padding"
+ android:layout_marginLeft="@dimen/widget_row_padding"
+ android:orientation="horizontal"
+ android:divider="@drawable/widgets_row_divider"
+ android:showDividers="middle"/>
+ </HorizontalScrollView>
+</LinearLayout>
diff --git a/res/layout/widgets_view.xml b/res/layout/widgets_view.xml
new file mode 100644
index 000000000..755634f82
--- /dev/null
+++ b/res/layout/widgets_view.xml
@@ -0,0 +1,51 @@
+<?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.
+-->
+<!-- The top and bottom paddings are defined in this container, but since we want
+ the list view to span the full width (for touch interception purposes), we
+ will bake the left/right padding into that view's background itself. -->
+<com.android.launcher3.widget.WidgetsContainerView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/widgets_view"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical"
+ android:descendantFocusability="afterDescendants">
+
+ <FrameLayout
+ android:id="@+id/content"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+ <FrameLayout
+ android:id="@+id/widgets_reveal_view"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_gravity="center"
+ android:focusable="false"
+ android:elevation="2dp"
+ android:visibility="invisible" />
+
+ <!-- DO NOT CHANGE THE ID -->
+ <com.android.launcher3.widget.WidgetsRecyclerView
+ android:id="@+id/widgets_list_view"
+ android:theme="@style/Theme.Dark.CustomOverscroll"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_gravity="center"
+ android:elevation="15dp"
+ android:visibility="gone" />
+ </FrameLayout>
+
+</com.android.launcher3.widget.WidgetsContainerView> \ No newline at end of file
diff --git a/res/mipmap-xxhdpi/on_boarding_welcome.png b/res/mipmap-xxhdpi/on_boarding_welcome.png
deleted file mode 100644
index 7b11dea0e..000000000
--- a/res/mipmap-xxhdpi/on_boarding_welcome.png
+++ /dev/null
Binary files differ
diff --git a/res/values-af/strings.xml b/res/values-af/strings.xml
index f37f08f3b..700452463 100644
--- a/res/values-af/strings.xml
+++ b/res/values-af/strings.xml
@@ -20,57 +20,27 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="application_name" msgid="5181331383435256801">"Launcher3"</string>
- <string name="home" msgid="7658288663002113681">"Tuis"</string>
- <string name="uid_name" msgid="7820867637514617527">"Android-kernprogramme"</string>
<string name="folder_name" msgid="7371454440695724752"></string>
+ <string name="work_folder_name" msgid="3753320833950115786">"Werk"</string>
<string name="activity_not_found" msgid="8071924732094499514">"Program is nie geïnstalleer nie."</string>
<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="widgets_tab_label" msgid="2921133187116603919">"Legstukke"</string>
- <string name="widget_adder" msgid="3201040140710381657">"Legstukke"</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="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
- <string name="external_drop_widget_error" msgid="3165821058322217155">"Kan nie item op hierdie Tuisskerm laat los nie."</string>
- <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Kies legstuk om te skep"</string>
- <string name="rename_folder_label" msgid="3727762225964550653">"Vouernaam"</string>
- <string name="rename_folder_title" msgid="3771389277707820891">"Hernoem vouer"</string>
- <string name="rename_action" msgid="5559600076028658757">"OK"</string>
- <string name="cancel_action" msgid="7009134900002915310">"Kanselleer"</string>
- <string name="menu_item_add_item" msgid="1264911265836810421">"Voeg by Tuisskerm"</string>
- <string name="group_applications" msgid="3797214114206693605">"Programme"</string>
- <string name="group_shortcuts" msgid="6012256992764410535">"Kortpaaie"</string>
- <string name="group_widgets" msgid="1569030723286851002">"Legstukke"</string>
- <string name="completely_out_of_space" msgid="6106288382070760318">"Niks meer spasie op jou Tuisskerms nie."</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>
+ <string name="all_apps_no_search_results" msgid="6332185285860416787">"Geen programme gevind wat met \"<xliff:g id="QUERY">%1$s</xliff:g>\" ooreenstem nie"</string>
<string name="out_of_space" msgid="4691004494942118364">"Niks meer spasie op die tuisskerm nie."</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"Geen plek meer in die Gunstelinge-laai nie"</string>
- <string name="invalid_hotseat_item" msgid="5779907847267573691">"Hierdie legstuk is te groot vir die Gunstelinge-laai"</string>
- <string name="shortcut_installed" msgid="1701742129426969556">"Kortpad \"<xliff:g id="NAME">%s</xliff:g>\" is geskep."</string>
- <string name="shortcut_uninstalled" msgid="8176767991305701821">"Kortpad \"<xliff:g id="NAME">%s</xliff:g>\" is verwyder."</string>
- <string name="shortcut_duplicate" msgid="9167217446062498127">"Kortpad \"<xliff:g id="NAME">%s</xliff:g>\" bestaan reeds."</string>
- <string name="title_select_shortcut" msgid="6680642571148153868">"Kies kortpad"</string>
- <string name="title_select_application" msgid="3280812711670683644">"Kies program"</string>
<string name="all_apps_button_label" msgid="9110807029020582876">"Programme"</string>
<string name="all_apps_home_button_label" msgid="252062713717058851">"Tuis"</string>
- <string name="delete_zone_label_workspace" msgid="4009607676751398685">"Verwyder"</string>
- <string name="delete_zone_label_all_apps" msgid="8083826390278958980">"Deïnstalleer"</string>
<string name="delete_target_label" msgid="1822697352535677073">"Verwyder"</string>
<string name="delete_target_uninstall_label" msgid="5100785476250872595">"Deïnstalleer"</string>
<string name="info_target_label" msgid="8053346143994679532">"Programinligting"</string>
- <string name="accessibility_all_apps_button" msgid="2603132375383800483">"Programme"</string>
- <string name="accessibility_delete_button" msgid="6466114477993744621">"Verwyder"</string>
- <string name="delete_zone_label_all_apps_system_app" msgid="449755632749610895">"Deïnstalleer opdatering"</string>
- <string name="cab_menu_delete_app" msgid="7435191475867183689">"Deïnstalleer program"</string>
- <string name="cab_menu_app_info" msgid="8593722221450362342">"Programbesonderhede"</string>
- <string name="cab_app_selection_text" msgid="374688303047985416">"1 program gekies"</string>
- <string name="cab_widget_selection_text" msgid="1833458597831541241">"1 legstuk gekies"</string>
- <string name="cab_folder_selection_text" msgid="7999992513806132118">"1 vouer gekies"</string>
- <string name="cab_shortcut_selection_text" msgid="2103811025667946450">"1 kortpad gekies"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"installeer kortpaaie"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"Laat \'n program toe om kortpaaie by te voeg sonder gebruikerinmenging."</string>
- <string name="permlab_uninstall_shortcut" msgid="864595034498083837">"deïnstalleer kortpaaie"</string>
- <string name="permdesc_uninstall_shortcut" msgid="5134129545001836849">"Laat die program toe om kortpaaie te verwyder sonder gebruikerinmenging."</string>
<string name="permlab_read_settings" msgid="1941457408239617576">"lees Tuis-instellings en -kortpaaie"</string>
<string name="permdesc_read_settings" msgid="5833423719057558387">"Laat die program toe om die instellings en kortpaaie in Tuis te lees."</string>
<string name="permlab_write_settings" msgid="3574213698004620587">"skryf Tuis-instellings en -kortpaaie"</string>
@@ -78,30 +48,17 @@
<string name="gadget_error_text" msgid="6081085226050792095">"Kon nie legstuk laai nie"</string>
<string name="gadget_setup_text" msgid="8274003207686040488">"Stel op"</string>
<string name="uninstall_system_app_text" msgid="4172046090762920660">"Dit is \'n stelselprogram en kan nie gedeïnstalleer word nie."</string>
- <string name="dream_name" msgid="1530253749244328964">"Vuurpyllanseerder"</string>
<string name="folder_hint_text" msgid="6617836969016293992">"Naamlose vouer"</string>
- <string name="workspace_description_format" msgid="2950174241104043327">"Tuisskerm %1$d"</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="apps_customize_apps_scroll_format" msgid="370005296147130238">"Programme-bladsy %1$d van %2$d"</string>
- <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"Legstukke-bladsy %1$d van %2$d"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"Welkom"</string>
- <string name="first_run_cling_description" msgid="6447072552696253358">"Maak jouself tuis."</string>
- <string name="first_run_cling_custom_content_hint" msgid="6090628589029352439"></string>
- <string name="first_run_cling_search_bar_hint" msgid="5909062802402452582"></string>
- <string name="first_run_cling_create_screens_hint" msgid="6950729526680114157">"Skep meer skerms vir programme en vouers"</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>
<string name="migration_cling_copy_apps" msgid="946331230090919440">"KOPIEER IKONE"</string>
<string name="migration_cling_use_default" msgid="2626475813981258626">"BEGIN VAN NUUTS AF"</string>
- <string name="workspace_cling_title" msgid="5626202359865825661">"Organiseer jou spasie"</string>
- <string name="workspace_cling_move_item" msgid="528201129978005352">"Raak en hou agtergrond om muurpapier, legstukke en instellings te bestuur."</string>
<string name="workspace_cling_longpress_title" msgid="9173998993909018310">"Muurpapiere, legstukke en instellings"</string>
<string name="workspace_cling_longpress_description" msgid="4119994475505235248">"Raak en hou agtergrond om te pasmaak"</string>
<string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"HET DIT"</string>
- <string name="folder_cling_title" msgid="3894908818693254164">"Hier\'s \'n vouer"</string>
- <string name="folder_cling_create_folder" msgid="6158215559475836131">"Om een soos dié te skep, raak en hou \'n program en skuif dit dan oor \'n ander een."</string>
- <string name="cling_dismiss" msgid="8962359497601507581">"OK"</string>
<string name="folder_opened" msgid="94695026776264709">"Vouer oopgemaak, <xliff:g id="WIDTH">%1$d</xliff:g> by <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
<string name="folder_tap_to_close" msgid="1884479294466410023">"Raak om vouer toe te maak"</string>
<string name="folder_tap_to_rename" msgid="9191075570492871147">"Raak om hernoem te stoor"</string>
@@ -111,14 +68,34 @@
<string name="widget_button_text" msgid="2880537293434387943">"Legstukke"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"Muurpapiere"</string>
<string name="settings_button_text" msgid="8119458837558863227">"Instellings"</string>
- <string name="package_state_enqueued" msgid="6227252464303085641">"Wag tans…"</string>
- <string name="package_state_downloading" msgid="4088770468458724721">"Laai tans af…"</string>
- <string name="package_state_installing" msgid="7588193972189849870">"Installeer tans…"</string>
+ <string name="allow_rotation_title" msgid="2118706734511831751">"Laat draai toe"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Onbekend"</string>
- <string name="package_state_error" msgid="7672093962724223588">"Nie teruggestel nie"</string>
- <string name="abandoned_clean_all" msgid="5256770727689657618">"Verwyder almal"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Verwyder"</string>
<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="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>
+ <string name="item_removed" msgid="851119963877842327">"Item is verwyder"</string>
+ <string name="action_move" msgid="4339390619886385032">"Skuif item"</string>
+ <string name="move_to_empty_cell" msgid="2833711483015685619">"Skuif na ry <xliff:g id="NUMBER_0">%1$s</xliff:g> kolom <xliff:g id="NUMBER_1">%2$s</xliff:g>"</string>
+ <string name="move_to_position" msgid="6750008980455459790">"Skuif na posisie <xliff:g id="NUMBER">%1$s</xliff:g>"</string>
+ <string name="move_to_hotseat_position" msgid="6295412897075147808">"Skuif na gunstelingposisie <xliff:g id="NUMBER">%1$s</xliff:g>"</string>
+ <string name="item_moved" msgid="4606538322571412879">"Item geskuif"</string>
+ <string name="add_to_folder" msgid="9040534766770853243">"Voeg by vouer: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="add_to_folder_with_app" msgid="4534929978967147231">"Voeg by vouer met <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="added_to_folder" msgid="4793259502305558003">"Item by vouer gevoeg"</string>
+ <string name="create_folder_with" msgid="4050141361160214248">"Skep vouer met: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="folder_created" msgid="6409794597405184510">"Vouer geskep"</string>
+ <string name="action_move_to_workspace" msgid="1603837886334246317">"Skuif na tuisskerm"</string>
+ <string name="action_move_screen_left" msgid="8854216831569401665">"Skuif skerm na links"</string>
+ <string name="action_move_screen_right" msgid="329334910274311123">"Skuif skerm na regs"</string>
+ <string name="screen_moved" msgid="266230079505650577">"Skerm is geskuif"</string>
+ <string name="action_resize" msgid="1802976324781771067">"Verander grootte"</string>
+ <string name="action_increase_width" msgid="8773715375078513326">"Vermeerder breedte"</string>
+ <string name="action_increase_height" msgid="459390020612501122">"Vermeerder hoogte"</string>
+ <string name="action_decrease_width" msgid="1374549771083094654">"Verminder breedte"</string>
+ <string name="action_decrease_height" msgid="282377193880900022">"Verminder hoogte"</string>
+ <string name="widget_resized" msgid="9130327887929620">"Legstukgrootte is verander na breedte <xliff:g id="NUMBER_0">%1$s</xliff:g> hoogte <xliff:g id="NUMBER_1">%2$s</xliff:g>"</string>
</resources>
diff --git a/res/values-am/strings.xml b/res/values-am/strings.xml
index 1a25f66cd..d7fed9de4 100644
--- a/res/values-am/strings.xml
+++ b/res/values-am/strings.xml
@@ -20,57 +20,27 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="application_name" msgid="5181331383435256801">"ማስጀመሪያ3"</string>
- <string name="home" msgid="7658288663002113681">"መነሻ"</string>
- <string name="uid_name" msgid="7820867637514617527">"Android ዋና መተግበሪያዎች"</string>
<string name="folder_name" msgid="7371454440695724752"></string>
+ <string name="work_folder_name" msgid="3753320833950115786">"ስራ"</string>
<string name="activity_not_found" msgid="8071924732094499514">"መተግበሪያ አልተጫነም።"</string>
<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="widgets_tab_label" msgid="2921133187116603919">"ፍርግሞች"</string>
- <string name="widget_adder" msgid="3201040140710381657">"ፍርግሞች"</string>
<string name="toggle_weight_watcher" msgid="5645299835184636119">"ማህደረ ማስታወሻ አሳይ"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"ፍርግም ለማንሳት ይንኩ እና ይያዙት"</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
- <string name="external_drop_widget_error" msgid="3165821058322217155">"ንጥሉን እዚህ የመነሻ ማያ ገጽ ላይ ማኖር አልተቻለም።"</string>
- <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"ለመፍጠር መግብር ይምረጡ"</string>
- <string name="rename_folder_label" msgid="3727762225964550653">"አቃፊ ስም"</string>
- <string name="rename_folder_title" msgid="3771389277707820891">"አቃፊ ዳግም ሰይም"</string>
- <string name="rename_action" msgid="5559600076028658757">"እሺ"</string>
- <string name="cancel_action" msgid="7009134900002915310">"ይቅር"</string>
- <string name="menu_item_add_item" msgid="1264911265836810421">"ወደ መነሻ ማያ ገጽ ያክሉ"</string>
- <string name="group_applications" msgid="3797214114206693605">"መተግበሪያዎች"</string>
- <string name="group_shortcuts" msgid="6012256992764410535">"አቋራጮች"</string>
- <string name="group_widgets" msgid="1569030723286851002">"ፍርግሞች"</string>
- <string name="completely_out_of_space" msgid="6106288382070760318">"የመነሻ ማያ ገጾችዎ ላይ ተጨማሪ ቦታ የለም።"</string>
+ <string name="all_apps_search_bar_hint" msgid="7084713969757597256">"መተግበሪያዎችን ይፈልጉ"</string>
+ <string name="all_apps_loading_message" msgid="7557140873644765180">"መተግበሪያዎችን በመጫን ላይ..."</string>
+ <string name="all_apps_no_search_results" msgid="6332185285860416787">"ከ«<xliff:g id="QUERY">%1$s</xliff:g>» ጋር የሚዛመዱ ምንም መተግበሪያዎች አልተገኙም"</string>
<string name="out_of_space" msgid="4691004494942118364">"በዚህ መነሻ ማያ ገጽ ላይ ምንም ቦታ የለም።"</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"በተወዳጆች መሣቢያ ውስጥ ተጨማሪ ቦታ የለም"</string>
- <string name="invalid_hotseat_item" msgid="5779907847267573691">"ይህ መግብር ወደ የተወዳጆች መሣቢያ ላይ እንዳይገባ በጣም ትልቅ ነው"</string>
- <string name="shortcut_installed" msgid="1701742129426969556">"አቋራጭ «<xliff:g id="NAME">%s</xliff:g>» ተፈጥሯል።"</string>
- <string name="shortcut_uninstalled" msgid="8176767991305701821">"አቋራጭ «<xliff:g id="NAME">%s</xliff:g>» ተወግዶ ነበር።"</string>
- <string name="shortcut_duplicate" msgid="9167217446062498127">"አቋራጭ «<xliff:g id="NAME">%s</xliff:g>» አስቀድሞ አለ።"</string>
- <string name="title_select_shortcut" msgid="6680642571148153868">"አቋራጭ ይምረጡ"</string>
- <string name="title_select_application" msgid="3280812711670683644">"መተግበሪያ ይምረጡ"</string>
<string name="all_apps_button_label" msgid="9110807029020582876">"መተግበሪያዎች"</string>
<string name="all_apps_home_button_label" msgid="252062713717058851">"መነሻ"</string>
- <string name="delete_zone_label_workspace" msgid="4009607676751398685">"አስወግድ"</string>
- <string name="delete_zone_label_all_apps" msgid="8083826390278958980">"አራግፍ"</string>
<string name="delete_target_label" msgid="1822697352535677073">"አስወግድ"</string>
<string name="delete_target_uninstall_label" msgid="5100785476250872595">"አራግፍ"</string>
<string name="info_target_label" msgid="8053346143994679532">"የመተግበሪያ መረጃ"</string>
- <string name="accessibility_all_apps_button" msgid="2603132375383800483">"መተግበሪያዎች"</string>
- <string name="accessibility_delete_button" msgid="6466114477993744621">"አስወግድ"</string>
- <string name="delete_zone_label_all_apps_system_app" msgid="449755632749610895">"ዝማኔ አራግፍ"</string>
- <string name="cab_menu_delete_app" msgid="7435191475867183689">"መተግበሪያ አራግፍ"</string>
- <string name="cab_menu_app_info" msgid="8593722221450362342">"የመተግበሪያ ዝርዝሮች"</string>
- <string name="cab_app_selection_text" msgid="374688303047985416">"1 መተግበሪያ ተመርጧል"</string>
- <string name="cab_widget_selection_text" msgid="1833458597831541241">"1 ፍርግም ተመርጧል"</string>
- <string name="cab_folder_selection_text" msgid="7999992513806132118">"1 አቃፊ ተመርጧል"</string>
- <string name="cab_shortcut_selection_text" msgid="2103811025667946450">"1 አቋራጭ ተመርጧል"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"አቋራጮችን ይጭናል"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"መተግበሪያው ያለተጠቃሚ ጣልቃ ገብነት አቋራጭ እንዲያክል ያስችለዋል።"</string>
- <string name="permlab_uninstall_shortcut" msgid="864595034498083837">"አቋራጮችን ያራግፋል"</string>
- <string name="permdesc_uninstall_shortcut" msgid="5134129545001836849">"መተግበሪያው አቋራጮችን ያለተጠቃሚ ጣልቃ ገብነት እንዲያስወግድ ያስችለዋል።"</string>
<string name="permlab_read_settings" msgid="1941457408239617576">"የመነሻ ቅንብሮች እና አቋራጮችን ያነባል"</string>
<string name="permdesc_read_settings" msgid="5833423719057558387">"መተግበሪያው በመነሻ ውስጥ ያሉ ቅንብሮችን እና አቋራጮችን እንዲያነብ ያስችለዋል።"</string>
<string name="permlab_write_settings" msgid="3574213698004620587">"የመነሻ ቅንብሮችን እና አቋራጮችን ይጽፋል"</string>
@@ -78,30 +48,17 @@
<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>
- <string name="dream_name" msgid="1530253749244328964">"የሮኬት ማስጀመሪያ"</string>
<string name="folder_hint_text" msgid="6617836969016293992">"ስም-አልባ አቃፊ"</string>
- <string name="workspace_description_format" msgid="2950174241104043327">"መነሻ ማያ ገጽ %1$d"</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="apps_customize_apps_scroll_format" msgid="370005296147130238">"የመተግበሪያዎች ገጽ %1$d ከ%2$d"</string>
- <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"የመግብሮች ገጽ %1$d ከ%2$d"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"እንኳን በደህና መጡ"</string>
- <string name="first_run_cling_description" msgid="6447072552696253358">"ልክ እቤትዎ እንዳሉ ሆነው ዘና ይበሉ።"</string>
- <string name="first_run_cling_custom_content_hint" msgid="6090628589029352439"></string>
- <string name="first_run_cling_search_bar_hint" msgid="5909062802402452582"></string>
- <string name="first_run_cling_create_screens_hint" msgid="6950729526680114157">"ለመተግበሪያዎች እና አቃፊዎች ተጨማሪ ማያ ገጾችን ይፍጠሩ"</string>
<string name="migration_cling_title" msgid="9181776667882933767">"የመተግበሪያ አዶዎችዎን ይቅዱ"</string>
<string name="migration_cling_description" msgid="2752413805582227644">"አዶዎች እና አቃፊዎች ከድሮው የመነሻ ማያ ገጾችዎ ይምጡ?"</string>
<string name="migration_cling_copy_apps" msgid="946331230090919440">"አዶዎችን ይቅዱ"</string>
<string name="migration_cling_use_default" msgid="2626475813981258626">"እንደ አዲስ ይጀምሩ"</string>
- <string name="workspace_cling_title" msgid="5626202359865825661">"ቦታዎን ያደራጁ"</string>
- <string name="workspace_cling_move_item" msgid="528201129978005352">"ልጣፍ ፣ ምግብሮችን እና ቅንብሮችን ለማቀናበር ጀርባውን ይንኩ እና ይያዙት።"</string>
<string name="workspace_cling_longpress_title" msgid="9173998993909018310">"የግድግዳ ወረቀቶች፣ ንዑስ ፕሮግራሞች እና ቅንብሮች"</string>
<string name="workspace_cling_longpress_description" msgid="4119994475505235248">"ለማበጀት ጀርባውን ነክተው ይያዙት"</string>
<string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"ገባኝ"</string>
- <string name="folder_cling_title" msgid="3894908818693254164">"አንድ አቃፊ እነሆ"</string>
- <string name="folder_cling_create_folder" msgid="6158215559475836131">"አንድ እንደዚህ አይነት ለመፍጠር መተግበሪያውን ነክተው ይያዙት እና ወደ ሌላ ያንቀሳቅሱት።"</string>
- <string name="cling_dismiss" msgid="8962359497601507581">"እሺ"</string>
<string name="folder_opened" msgid="94695026776264709">"አቃፊ ተከፍቷል፣ <xliff:g id="WIDTH">%1$d</xliff:g> በ<xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
<string name="folder_tap_to_close" msgid="1884479294466410023">"አቃፊን ለመዝጋት ይንኩ"</string>
<string name="folder_tap_to_rename" msgid="9191075570492871147">"ዳግም የተሰየመውን ለማስቀመጥ ይንኩ"</string>
@@ -111,14 +68,34 @@
<string name="widget_button_text" msgid="2880537293434387943">"ፍርግሞች"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"የግድግዳ ወረቀቶች"</string>
<string name="settings_button_text" msgid="8119458837558863227">"ቅንብሮች"</string>
- <string name="package_state_enqueued" msgid="6227252464303085641">"በመጠበቅ ላይ"</string>
- <string name="package_state_downloading" msgid="4088770468458724721">"በማውረድ ላይ"</string>
- <string name="package_state_installing" msgid="7588193972189849870">"በመጫን ላይ"</string>
+ <string name="allow_rotation_title" msgid="2118706734511831751">"ማሽከርከርን ይፍቀዱ"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"የማይታወቅ"</string>
- <string name="package_state_error" msgid="7672093962724223588">"ወደነበረበት አልተመለሰም"</string>
- <string name="abandoned_clean_all" msgid="5256770727689657618">"ሁሉንም አስወግድ"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"አስወግድ"</string>
<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="action_add_to_workspace" msgid="8902165848117513641">"ወደ መነሻ ማያ ገጽ ያክሉ"</string>
+ <string name="action_move_here" msgid="2170188780612570250">"ንጥልን ወደዚህ ውሰድ"</string>
+ <string name="item_added_to_workspace" msgid="4211073925752213539">"ወደ መነሻ ማያ ገጽ ንጥል ታክሏል"</string>
+ <string name="item_removed" msgid="851119963877842327">"ንጥል ነገር ተንቀሳቅሷል"</string>
+ <string name="action_move" msgid="4339390619886385032">"ንጥልን አንቀሳቅስ"</string>
+ <string name="move_to_empty_cell" msgid="2833711483015685619">"ወደ ረድፍ <xliff:g id="NUMBER_0">%1$s</xliff:g> ዓምድ <xliff:g id="NUMBER_1">%2$s</xliff:g> አንቀሳቅስ"</string>
+ <string name="move_to_position" msgid="6750008980455459790">"ወደ አቀማመጥ <xliff:g id="NUMBER">%1$s</xliff:g> አንቀሳቅስ"</string>
+ <string name="move_to_hotseat_position" msgid="6295412897075147808">"ወደ ተወዳጆች አቀማመጥ <xliff:g id="NUMBER">%1$s</xliff:g> አንቀሳቅስ"</string>
+ <string name="item_moved" msgid="4606538322571412879">"ንጥል ተንቀሳቅሷል"</string>
+ <string name="add_to_folder" msgid="9040534766770853243">"ወደ አቃፊ አክል፦ <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="add_to_folder_with_app" msgid="4534929978967147231">"ወደ አቃፊ አክል ከ<xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="added_to_folder" msgid="4793259502305558003">"ንጥል ወደ አቃፊ ታክሏል"</string>
+ <string name="create_folder_with" msgid="4050141361160214248">"አቃፊ ፍጠር ከዚህ ጋር፦ <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="folder_created" msgid="6409794597405184510">"አቃፊ ተፈጥሮዋል"</string>
+ <string name="action_move_to_workspace" msgid="1603837886334246317">"ወደ መነሻ ማያ ገጽ አንቀሳቅስ"</string>
+ <string name="action_move_screen_left" msgid="8854216831569401665">"ማያ ገጽን ወደ ግራ አንቀሳቅስ"</string>
+ <string name="action_move_screen_right" msgid="329334910274311123">"ማያ ገጽን ወደ ቀኝ አንቀሳቅስ"</string>
+ <string name="screen_moved" msgid="266230079505650577">"ማያ ገጽ ተንቀሳቅሷል"</string>
+ <string name="action_resize" msgid="1802976324781771067">"መጠን ቀይር"</string>
+ <string name="action_increase_width" msgid="8773715375078513326">"ስፋት ጨምር"</string>
+ <string name="action_increase_height" msgid="459390020612501122">"ቁመት ጨምር"</string>
+ <string name="action_decrease_width" msgid="1374549771083094654">"ስፋት ይቀንሱ"</string>
+ <string name="action_decrease_height" msgid="282377193880900022">"ቁመት ይቀንሱ"</string>
+ <string name="widget_resized" msgid="9130327887929620">"የመግብር መጠን ወደ ስፋት <xliff:g id="NUMBER_0">%1$s</xliff:g> ቁመት <xliff:g id="NUMBER_1">%2$s</xliff:g> ተለውጧል"</string>
</resources>
diff --git a/res/values-ar/strings.xml b/res/values-ar/strings.xml
index 592be5841..b7cd901de 100644
--- a/res/values-ar/strings.xml
+++ b/res/values-ar/strings.xml
@@ -20,57 +20,27 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="application_name" msgid="5181331383435256801">"Launcher3"</string>
- <string name="home" msgid="7658288663002113681">"الرئيسية"</string>
- <string name="uid_name" msgid="7820867637514617527">"‏تطبيقات Android الأساسية"</string>
<string name="folder_name" msgid="7371454440695724752"></string>
+ <string name="work_folder_name" msgid="3753320833950115786">"العمل"</string>
<string name="activity_not_found" msgid="8071924732094499514">"لم يتم تثبيت التطبيق."</string>
<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="widgets_tab_label" msgid="2921133187116603919">"الأدوات"</string>
- <string name="widget_adder" msgid="3201040140710381657">"الأدوات"</string>
<string name="toggle_weight_watcher" msgid="5645299835184636119">"عرض الذاكرة"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"المس مع الاستمرار لاختيار إحدى الأدوات."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
- <string name="external_drop_widget_error" msgid="3165821058322217155">"تعذر إسقاط العنصر على هذه الشاشة الرئيسية."</string>
- <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"اختيار أداة لإنشائها"</string>
- <string name="rename_folder_label" msgid="3727762225964550653">"اسم المجلد"</string>
- <string name="rename_folder_title" msgid="3771389277707820891">"إعادة تسمية المجلد"</string>
- <string name="rename_action" msgid="5559600076028658757">"موافق"</string>
- <string name="cancel_action" msgid="7009134900002915310">"إلغاء"</string>
- <string name="menu_item_add_item" msgid="1264911265836810421">"إضافة إلى الشاشة الرئيسية"</string>
- <string name="group_applications" msgid="3797214114206693605">"التطبيقات"</string>
- <string name="group_shortcuts" msgid="6012256992764410535">"الاختصارات"</string>
- <string name="group_widgets" msgid="1569030723286851002">"الأدوات"</string>
- <string name="completely_out_of_space" msgid="6106288382070760318">"ليس هناك مساحة أخرى في الشاشات الرئيسية."</string>
+ <string name="all_apps_search_bar_hint" msgid="7084713969757597256">"البحث في التطبيقات"</string>
+ <string name="all_apps_loading_message" msgid="7557140873644765180">"جارٍ تحميل التطبيقات…"</string>
+ <string name="all_apps_no_search_results" msgid="6332185285860416787">"لم يتم العثور على أية تطبيقات تتطابق مع \"<xliff:g id="QUERY">%1$s</xliff:g>\""</string>
<string name="out_of_space" msgid="4691004494942118364">"ليس هناك مساحة أخرى في هذه الشاشة الرئيسية."</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"لا يوجد المزيد من الحقول في علبة المفضلة"</string>
- <string name="invalid_hotseat_item" msgid="5779907847267573691">"هذه الأداة كبيرة جدًا مما يحول دون قبولها في علبة المفضّلة"</string>
- <string name="shortcut_installed" msgid="1701742129426969556">"تم إنشاء الاختصار \"<xliff:g id="NAME">%s</xliff:g>\"."</string>
- <string name="shortcut_uninstalled" msgid="8176767991305701821">"تمت إزالة الاختصار \"<xliff:g id="NAME">%s</xliff:g>\"."</string>
- <string name="shortcut_duplicate" msgid="9167217446062498127">"الاختصار \"<xliff:g id="NAME">%s</xliff:g>\" موجود من قبل."</string>
- <string name="title_select_shortcut" msgid="6680642571148153868">"اختيار اختصار"</string>
- <string name="title_select_application" msgid="3280812711670683644">"اختيار تطبيق"</string>
<string name="all_apps_button_label" msgid="9110807029020582876">"التطبيقات"</string>
<string name="all_apps_home_button_label" msgid="252062713717058851">"الرئيسية"</string>
- <string name="delete_zone_label_workspace" msgid="4009607676751398685">"إزالة"</string>
- <string name="delete_zone_label_all_apps" msgid="8083826390278958980">"إزالة"</string>
<string name="delete_target_label" msgid="1822697352535677073">"إزالة"</string>
<string name="delete_target_uninstall_label" msgid="5100785476250872595">"إزالة"</string>
<string name="info_target_label" msgid="8053346143994679532">"معلومات عن التطبيق"</string>
- <string name="accessibility_all_apps_button" msgid="2603132375383800483">"التطبيقات"</string>
- <string name="accessibility_delete_button" msgid="6466114477993744621">"إزالة"</string>
- <string name="delete_zone_label_all_apps_system_app" msgid="449755632749610895">"إزالة التحديث"</string>
- <string name="cab_menu_delete_app" msgid="7435191475867183689">"إزالة التطبيق"</string>
- <string name="cab_menu_app_info" msgid="8593722221450362342">"تفاصيل التطبيق"</string>
- <string name="cab_app_selection_text" msgid="374688303047985416">"تم تحديد تطبيق واحد"</string>
- <string name="cab_widget_selection_text" msgid="1833458597831541241">"تم تحديد أداة واحدة"</string>
- <string name="cab_folder_selection_text" msgid="7999992513806132118">"تم تحديد مجلد واحد"</string>
- <string name="cab_shortcut_selection_text" msgid="2103811025667946450">"تم تحديد اختصار واحد"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"تثبيت اختصارات"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"للسماح لتطبيق ما بإضافة اختصارات بدون تدخل المستخدم."</string>
- <string name="permlab_uninstall_shortcut" msgid="864595034498083837">"إزالة الاختصارات"</string>
- <string name="permdesc_uninstall_shortcut" msgid="5134129545001836849">"للسماح للتطبيق بإزالة الاختصارات بدون تدخل المستخدم."</string>
<string name="permlab_read_settings" msgid="1941457408239617576">"قراءة إعدادات واختصارات الشاشة الرئيسية"</string>
<string name="permdesc_read_settings" msgid="5833423719057558387">"للسماح للتطبيق بقراءة الإعدادات والاختصارات في الشاشة الرئيسية."</string>
<string name="permlab_write_settings" msgid="3574213698004620587">"كتابة إعدادات واختصارات الشاشة الرئيسية"</string>
@@ -78,30 +48,17 @@
<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>
- <string name="dream_name" msgid="1530253749244328964">"قاذفة صواريخ"</string>
<string name="folder_hint_text" msgid="6617836969016293992">"مجلد بدون اسم"</string>
- <string name="workspace_description_format" msgid="2950174241104043327">"‏الشاشة الرئيسية %1$d"</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="apps_customize_apps_scroll_format" msgid="370005296147130238">"‏صفحة التطبيقات %1$d من %2$d"</string>
- <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"‏صفحة الأدوات %1$d من %2$d"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"مرحبًا"</string>
- <string name="first_run_cling_description" msgid="6447072552696253358">"تصرف على راحتك."</string>
- <string name="first_run_cling_custom_content_hint" msgid="6090628589029352439"></string>
- <string name="first_run_cling_search_bar_hint" msgid="5909062802402452582"></string>
- <string name="first_run_cling_create_screens_hint" msgid="6950729526680114157">"إنشاء المزيد من الشاشات للتطبيقات والمجلدات"</string>
<string name="migration_cling_title" msgid="9181776667882933767">"نسخ رموز التطبيقات"</string>
<string name="migration_cling_description" msgid="2752413805582227644">"هل تريد استيراد رموز ومجلدات من الشاشات الرئيسية القديمة؟"</string>
<string name="migration_cling_copy_apps" msgid="946331230090919440">"نسخ الرموز"</string>
<string name="migration_cling_use_default" msgid="2626475813981258626">"بداية جديدة"</string>
- <string name="workspace_cling_title" msgid="5626202359865825661">"تنظيم مساحتك"</string>
- <string name="workspace_cling_move_item" msgid="528201129978005352">"المس مع الاستمرار الجزء الخلفي من صورة الشاشة لإدارة الخلفية والأدوات والإعدادات."</string>
<string name="workspace_cling_longpress_title" msgid="9173998993909018310">"الخلفيات والأدوات والإعدادات"</string>
<string name="workspace_cling_longpress_description" msgid="4119994475505235248">"المس مع الاستمرار الخلفية لتخصيصها"</string>
<string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"حسنًا"</string>
- <string name="folder_cling_title" msgid="3894908818693254164">"إليك المجلد"</string>
- <string name="folder_cling_create_folder" msgid="6158215559475836131">"لإنشاء مجلد مثل هذا، المس أحد التطبيقات مع استمرار اللمس، ثم حركه فوق آخر."</string>
- <string name="cling_dismiss" msgid="8962359497601507581">"موافق"</string>
<string name="folder_opened" msgid="94695026776264709">"تم فتح المجلد، بمقاس <xliff:g id="WIDTH">%1$d</xliff:g> في <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
<string name="folder_tap_to_close" msgid="1884479294466410023">"المس لإغلاق المجلد"</string>
<string name="folder_tap_to_rename" msgid="9191075570492871147">"المس لحفظ إعادة التسمية"</string>
@@ -111,14 +68,34 @@
<string name="widget_button_text" msgid="2880537293434387943">"الأدوات"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"الخلفيات"</string>
<string name="settings_button_text" msgid="8119458837558863227">"الإعدادات"</string>
- <string name="package_state_enqueued" msgid="6227252464303085641">"انتظار"</string>
- <string name="package_state_downloading" msgid="4088770468458724721">"جارٍ التنزيل"</string>
- <string name="package_state_installing" msgid="7588193972189849870">"جارٍ التثبيت"</string>
+ <string name="allow_rotation_title" msgid="2118706734511831751">"السماح بالتدوير"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"غير معروفة"</string>
- <string name="package_state_error" msgid="7672093962724223588">"استعادة مخفقة"</string>
- <string name="abandoned_clean_all" msgid="5256770727689657618">"إزالة الكل"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"إزالة"</string>
<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="action_add_to_workspace" msgid="8902165848117513641">"إضافة إلى الشاشة الرئيسية"</string>
+ <string name="action_move_here" msgid="2170188780612570250">"نقل العنصر إلى هنا"</string>
+ <string name="item_added_to_workspace" msgid="4211073925752213539">"تمت إضافة العنصر إلى الشاشة الرئيسية"</string>
+ <string name="item_removed" msgid="851119963877842327">"تم حذف العنصر"</string>
+ <string name="action_move" msgid="4339390619886385032">"نقل العنصر"</string>
+ <string name="move_to_empty_cell" msgid="2833711483015685619">"نقل إلى الصف <xliff:g id="NUMBER_0">%1$s</xliff:g> العمود <xliff:g id="NUMBER_1">%2$s</xliff:g>"</string>
+ <string name="move_to_position" msgid="6750008980455459790">"نقل إلى الموضع <xliff:g id="NUMBER">%1$s</xliff:g>"</string>
+ <string name="move_to_hotseat_position" msgid="6295412897075147808">"نقل إلى الموضع المفضل <xliff:g id="NUMBER">%1$s</xliff:g>"</string>
+ <string name="item_moved" msgid="4606538322571412879">"تم نقل العنصر"</string>
+ <string name="add_to_folder" msgid="9040534766770853243">"إضافة إلى المجلد: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="add_to_folder_with_app" msgid="4534929978967147231">"إضافة إلى المجلد الذي به <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="added_to_folder" msgid="4793259502305558003">"تمت إضافة العنصر إلى المجلد"</string>
+ <string name="create_folder_with" msgid="4050141361160214248">"إنشاء مجلد يتضمن: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="folder_created" msgid="6409794597405184510">"تم إنشاء المجلد"</string>
+ <string name="action_move_to_workspace" msgid="1603837886334246317">"نقل إلى الشاشة الرئيسية"</string>
+ <string name="action_move_screen_left" msgid="8854216831569401665">"نقل الشاشة إلى اليسار"</string>
+ <string name="action_move_screen_right" msgid="329334910274311123">"نقل الشاشة إلى اليمين"</string>
+ <string name="screen_moved" msgid="266230079505650577">"تم نقل الشاشة"</string>
+ <string name="action_resize" msgid="1802976324781771067">"تغيير حجم"</string>
+ <string name="action_increase_width" msgid="8773715375078513326">"زيادة العرض"</string>
+ <string name="action_increase_height" msgid="459390020612501122">"زيادة الارتفاع"</string>
+ <string name="action_decrease_width" msgid="1374549771083094654">"تقليل العرض"</string>
+ <string name="action_decrease_height" msgid="282377193880900022">"تقليل الارتفاع"</string>
+ <string name="widget_resized" msgid="9130327887929620">"تم تغيير حجم الأداة إلى العرض <xliff:g id="NUMBER_0">%1$s</xliff:g> والارتفاع <xliff:g id="NUMBER_1">%2$s</xliff:g>"</string>
</resources>
diff --git a/res/values-az-rAZ/strings.xml b/res/values-az-rAZ/strings.xml
index 0da8364ab..099a2208d 100644
--- a/res/values-az-rAZ/strings.xml
+++ b/res/values-az-rAZ/strings.xml
@@ -20,57 +20,27 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="application_name" msgid="5181331383435256801">"Launcher3"</string>
- <string name="home" msgid="7658288663002113681">"Əsas səhifə"</string>
- <string name="uid_name" msgid="7820867637514617527">"Əsas Android Tətbiqləri"</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>
<string name="activity_not_available" msgid="7456344436509528827">"Tətbiq əlçatmazdır"</string>
<string name="safemode_shortcut_error" msgid="9160126848219158407">"Güvənli rejimdə icazə verilməyən tətbiq endirildi"</string>
<string name="safemode_widget_error" msgid="4863470563535682004">"Vidcetlər Güvənli rejimdə deaktiv edilib"</string>
- <string name="widgets_tab_label" msgid="2921133187116603919">"Vidcetlər"</string>
- <string name="widget_adder" msgid="3201040140710381657">"Vidcetlər"</string>
<string name="toggle_weight_watcher" msgid="5645299835184636119">"Suvenirləri göstər"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"Vidceti götürmək üçün toxunub saxlayın."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
- <string name="external_drop_widget_error" msgid="3165821058322217155">"Bu Əsas ekrana element atmaq mümkün olmadı."</string>
- <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Yaratmaq üçün vidcet seçin"</string>
- <string name="rename_folder_label" msgid="3727762225964550653">"Qovluq adı"</string>
- <string name="rename_folder_title" msgid="3771389277707820891">"Qovluq adını dəyiş"</string>
- <string name="rename_action" msgid="5559600076028658757">"OK"</string>
- <string name="cancel_action" msgid="7009134900002915310">"Ləğv et"</string>
- <string name="menu_item_add_item" msgid="1264911265836810421">"Əsas ekrana əlavə et"</string>
- <string name="group_applications" msgid="3797214114206693605">"Tətbiqlər"</string>
- <string name="group_shortcuts" msgid="6012256992764410535">"Qısa yollar"</string>
- <string name="group_widgets" msgid="1569030723286851002">"Vidcet"</string>
- <string name="completely_out_of_space" msgid="6106288382070760318">"Əsas ekranlarınızda boş yer yoxdur."</string>
+ <string name="all_apps_search_bar_hint" msgid="7084713969757597256">"Tətbiq Axtarın"</string>
+ <string name="all_apps_loading_message" msgid="7557140873644765180">"Tətbiqlər endirilir..."</string>
+ <string name="all_apps_no_search_results" msgid="6332185285860416787">"\"<xliff:g id="QUERY">%1$s</xliff:g>\" sorğusuna uyğun Tətbiqlər tapılmadı"</string>
<string name="out_of_space" msgid="4691004494942118364">"Bu Əsas ekranda boş yer yoxdur."</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"Favoritlər-də yer yoxdur"</string>
- <string name="invalid_hotseat_item" msgid="5779907847267573691">"Bu vidcet Favorit-ə yerləşdirmək üçün çox böyükdür"</string>
- <string name="shortcut_installed" msgid="1701742129426969556">"\"<xliff:g id="NAME">%s</xliff:g>\" qısayolu yaradılıb."</string>
- <string name="shortcut_uninstalled" msgid="8176767991305701821">"\"<xliff:g id="NAME">%s</xliff:g>\" qısayolu kənarlaşdırıldı."</string>
- <string name="shortcut_duplicate" msgid="9167217446062498127">"\"<xliff:g id="NAME">%s</xliff:g>\" qısayolu artıq mövcuddur."</string>
- <string name="title_select_shortcut" msgid="6680642571148153868">"Qısayol seçin"</string>
- <string name="title_select_application" msgid="3280812711670683644">"Tətbiq seçin"</string>
<string name="all_apps_button_label" msgid="9110807029020582876">"Tətbiqlər"</string>
<string name="all_apps_home_button_label" msgid="252062713717058851">"Əsas səhifə"</string>
- <string name="delete_zone_label_workspace" msgid="4009607676751398685">"Yığışdır"</string>
- <string name="delete_zone_label_all_apps" msgid="8083826390278958980">"Sistemdən sil"</string>
<string name="delete_target_label" msgid="1822697352535677073">"Kənarlaşdır"</string>
<string name="delete_target_uninstall_label" msgid="5100785476250872595">"Sistemdən sil"</string>
<string name="info_target_label" msgid="8053346143994679532">"Tətbiq məlumatı"</string>
- <string name="accessibility_all_apps_button" msgid="2603132375383800483">"Tətbiqlər"</string>
- <string name="accessibility_delete_button" msgid="6466114477993744621">"Kənarlaşdır"</string>
- <string name="delete_zone_label_all_apps_system_app" msgid="449755632749610895">"Güncəlləməni sistemdən sil"</string>
- <string name="cab_menu_delete_app" msgid="7435191475867183689">"Tətbiqi sistemdən sil"</string>
- <string name="cab_menu_app_info" msgid="8593722221450362342">"Tətbiq məlumatları"</string>
- <string name="cab_app_selection_text" msgid="374688303047985416">"1 tətbiq seçildi"</string>
- <string name="cab_widget_selection_text" msgid="1833458597831541241">"1 vidcet seçilib"</string>
- <string name="cab_folder_selection_text" msgid="7999992513806132118">"1 qovluq seçildi"</string>
- <string name="cab_shortcut_selection_text" msgid="2103811025667946450">"1 qısayol seçilib"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"qısayolları quraşdır"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"Tətbiqə istifadəçi müdaxiləsi olmadan qısayolları əlavə etməyə icazə verir."</string>
- <string name="permlab_uninstall_shortcut" msgid="864595034498083837">"qısayolları sistemdən sil"</string>
- <string name="permdesc_uninstall_shortcut" msgid="5134129545001836849">"İstifadəçi müdaxiləsi olmadan tətbiqə qısayolları silməyə icazə verir."</string>
<string name="permlab_read_settings" msgid="1941457408239617576">"Əsas Səhifə ayarlarını və qısayolları oxuyun"</string>
<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>
@@ -78,30 +48,17 @@
<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>
- <string name="dream_name" msgid="1530253749244328964">"Raket Başladıcı"</string>
<string name="folder_hint_text" msgid="6617836969016293992">"Adsız Qovluq"</string>
- <string name="workspace_description_format" msgid="2950174241104043327">"Əsas Səhifə ekranı %1$d"</string>
<string name="default_scroll_format" msgid="7475544710230993317">"Səhifə %1$d of %2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"Əsas Səhifə ekranı %1$d of %2$d"</string>
- <string name="apps_customize_apps_scroll_format" msgid="370005296147130238">"%2$d tətbiq səhifəsi %1$d"</string>
- <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"%2$d vidcet səhifəsi %1$d"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"Xoş gəlmisiniz"</string>
- <string name="first_run_cling_description" msgid="6447072552696253358">"Özünüzü evinizdəki kimi hiss edin."</string>
- <string name="first_run_cling_custom_content_hint" msgid="6090628589029352439"></string>
- <string name="first_run_cling_search_bar_hint" msgid="5909062802402452582"></string>
- <string name="first_run_cling_create_screens_hint" msgid="6950729526680114157">"Tətbiqlər və qovluqlar üçün daha çox ekran yaradın"</string>
<string name="migration_cling_title" msgid="9181776667882933767">"Tətbiq ikonalarınızı kopyalayın"</string>
<string name="migration_cling_description" msgid="2752413805582227644">"Köhnə Əsas ekranınızda olan ikonalar və qovluqlar import edilsin?"</string>
<string name="migration_cling_copy_apps" msgid="946331230090919440">"İKONALARI KOPYALA"</string>
<string name="migration_cling_use_default" msgid="2626475813981258626">"YENİDƏN BAŞLA"</string>
- <string name="workspace_cling_title" msgid="5626202359865825661">"Sahənizi təşkil edin"</string>
- <string name="workspace_cling_move_item" msgid="528201129978005352">"Divar kağızını idarə etmək üçün arxa fona toxunun və saxlayın, vidcetlər və ayarlar."</string>
<string name="workspace_cling_longpress_title" msgid="9173998993909018310">"Divar kağızları, vidcetlər və ayarlar"</string>
<string name="workspace_cling_longpress_description" msgid="4119994475505235248">"Fərdiləşdirmək üçün arxa fona toxunaraq saxlayın"</string>
<string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"ANLADIM"</string>
- <string name="folder_cling_title" msgid="3894908818693254164">"Burada qovluq var"</string>
- <string name="folder_cling_create_folder" msgid="6158215559475836131">"Bunun kimi birini yaradın, tətbiqə toxunun və saxlayın, sonra da bunu digərinin üstünə daşıyın."</string>
- <string name="cling_dismiss" msgid="8962359497601507581">"OK"</string>
<string name="folder_opened" msgid="94695026776264709">"Qovluq açıldı, <xliff:g id="HEIGHT">%2$d</xliff:g> hündürlük ilə <xliff:g id="WIDTH">%1$d</xliff:g> enində"</string>
<string name="folder_tap_to_close" msgid="1884479294466410023">"Qovluğu bağlamaq üçün toxunun"</string>
<string name="folder_tap_to_rename" msgid="9191075570492871147">"Ad dəyişikliyini yadda saxlamaq üçün toxunun"</string>
@@ -111,14 +68,34 @@
<string name="widget_button_text" msgid="2880537293434387943">"Vidcet"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"Divar kağızları"</string>
<string name="settings_button_text" msgid="8119458837558863227">"Ayarlar"</string>
- <string name="package_state_enqueued" msgid="6227252464303085641">"Gözlənilir"</string>
- <string name="package_state_downloading" msgid="4088770468458724721">"Endirilir"</string>
- <string name="package_state_installing" msgid="7588193972189849870">"Quraşdırılır"</string>
+ <string name="allow_rotation_title" msgid="2118706734511831751">"Fırlatmağa icazə verin"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Naməlum"</string>
- <string name="package_state_error" msgid="7672093962724223588">"Bərpa edilməyib"</string>
- <string name="abandoned_clean_all" msgid="5256770727689657618">"Hamısını Silin"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Yığışdır"</string>
<string name="abandoned_search" msgid="891119232568284442">"Axtarış"</string>
<string name="abandoned_promises_title" msgid="7096178467971716750">"Bu tətbiq quraşdırılmayıb"</string>
<string name="abandoned_promise_explanation" msgid="3990027586878167529">"Bu ikona üçün tətbiq quraşdırılmayıb. Onu silə bilərsiniz, və ya tətbiqi taparaq manual yol ilə quraşdıra bilərsiniz."</string>
+ <string name="action_add_to_workspace" msgid="8902165848117513641">"Əsas ekrana əlavə edin"</string>
+ <string name="action_move_here" msgid="2170188780612570250">"Elementi bura köçürün"</string>
+ <string name="item_added_to_workspace" msgid="4211073925752213539">"Element əsas ekrana əlavə edildi"</string>
+ <string name="item_removed" msgid="851119963877842327">"Element silindi"</string>
+ <string name="action_move" msgid="4339390619886385032">"Elementi köçürün"</string>
+ <string name="move_to_empty_cell" msgid="2833711483015685619">"Sıra <xliff:g id="NUMBER_0">%1$s</xliff:g> sütun <xliff:g id="NUMBER_1">%2$s</xliff:g> köçürün"</string>
+ <string name="move_to_position" msgid="6750008980455459790">"<xliff:g id="NUMBER">%1$s</xliff:g> mövqeyinə köçürün"</string>
+ <string name="move_to_hotseat_position" msgid="6295412897075147808">"<xliff:g id="NUMBER">%1$s</xliff:g> sevimlilər mövqeyinə köçürün"</string>
+ <string name="item_moved" msgid="4606538322571412879">"Elementin yeri dəyişildi"</string>
+ <string name="add_to_folder" msgid="9040534766770853243">"Qovluğa əlavə edin: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="add_to_folder_with_app" msgid="4534929978967147231">"<xliff:g id="NAME">%1$s</xliff:g> adlı qovluğa əlavə edin"</string>
+ <string name="added_to_folder" msgid="4793259502305558003">"Element qovluğa əlavə edildi"</string>
+ <string name="create_folder_with" msgid="4050141361160214248">"Qovluq yaradın: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="folder_created" msgid="6409794597405184510">"Qovluq yaradıldı"</string>
+ <string name="action_move_to_workspace" msgid="1603837886334246317">"Əsas ekrana köçürün"</string>
+ <string name="action_move_screen_left" msgid="8854216831569401665">"Ekranı sola köçürün"</string>
+ <string name="action_move_screen_right" msgid="329334910274311123">"Ekranı sağa köçürün"</string>
+ <string name="screen_moved" msgid="266230079505650577">"Ekran köçürülüb"</string>
+ <string name="action_resize" msgid="1802976324781771067">"Ölçüsünü dəyişin"</string>
+ <string name="action_increase_width" msgid="8773715375078513326">"Eni artırın"</string>
+ <string name="action_increase_height" msgid="459390020612501122">"Hündürlüyü artırın"</string>
+ <string name="action_decrease_width" msgid="1374549771083094654">"Eni azaldın"</string>
+ <string name="action_decrease_height" msgid="282377193880900022">"Hündürlüyü azaldın"</string>
+ <string name="widget_resized" msgid="9130327887929620">"Vidcetin eni <xliff:g id="NUMBER_0">%1$s</xliff:g> hündürlüyü <xliff:g id="NUMBER_1">%2$s</xliff:g> kimi ölçüləndirildi"</string>
</resources>
diff --git a/res/values-be/strings.xml b/res/values-be/strings.xml
index 2015158d9..fc5390b80 100644
--- a/res/values-be/strings.xml
+++ b/res/values-be/strings.xml
@@ -173,8 +173,6 @@
<skip />
<!-- no translation found for first_run_cling_description (6447072552696253358) -->
<skip />
- <string name="first_run_cling_custom_content_hint" msgid="6090628589029352439"></string>
- <string name="first_run_cling_search_bar_hint" msgid="5909062802402452582"></string>
<!-- no translation found for first_run_cling_create_screens_hint (6950729526680114157) -->
<skip />
<!-- no translation found for workspace_cling_title (5626202359865825661) -->
@@ -199,10 +197,6 @@
<skip />
<!-- no translation found for folder_name_format (6629239338071103179) -->
<skip />
- <string name="custom_workspace_cling_title_1" msgid="3750880082935033085"></string>
- <string name="custom_workspace_cling_description_1" msgid="939966842147696724"></string>
- <string name="custom_workspace_cling_title_2" msgid="662588444436552198"></string>
- <string name="custom_workspace_cling_description_2" msgid="8097921091798539310"></string>
<!-- no translation found for widget_button_text (2880537293434387943) -->
<skip />
<!-- no translation found for wallpaper_button_text (8404103075899945851) -->
diff --git a/res/values-bg/strings.xml b/res/values-bg/strings.xml
index 3f710db30..eeaa1ede4 100644
--- a/res/values-bg/strings.xml
+++ b/res/values-bg/strings.xml
@@ -20,57 +20,27 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="application_name" msgid="5181331383435256801">"Launcher3"</string>
- <string name="home" msgid="7658288663002113681">"Начало"</string>
- <string name="uid_name" msgid="7820867637514617527">"Основни приложения на Android"</string>
<string name="folder_name" msgid="7371454440695724752"></string>
+ <string name="work_folder_name" msgid="3753320833950115786">"Работа"</string>
<string name="activity_not_found" msgid="8071924732094499514">"Приложението не е инсталирано."</string>
<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="widgets_tab_label" msgid="2921133187116603919">"Приспособления"</string>
- <string name="widget_adder" msgid="3201040140710381657">"Приспособления"</string>
<string name="toggle_weight_watcher" msgid="5645299835184636119">"Показване на паметта"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"Докоснете и задръжте за избор на приспособление."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
- <string name="external_drop_widget_error" msgid="3165821058322217155">"Не можа да се премести на този начален екран."</string>
- <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Избор на приспособл. за създаване"</string>
- <string name="rename_folder_label" msgid="3727762225964550653">"Име на папката"</string>
- <string name="rename_folder_title" msgid="3771389277707820891">"Преименуване на папка"</string>
- <string name="rename_action" msgid="5559600076028658757">"ОK"</string>
- <string name="cancel_action" msgid="7009134900002915310">"Отказ"</string>
- <string name="menu_item_add_item" msgid="1264911265836810421">"Добавяне към началния екран"</string>
- <string name="group_applications" msgid="3797214114206693605">"Приложения"</string>
- <string name="group_shortcuts" msgid="6012256992764410535">"Преки пътища"</string>
- <string name="group_widgets" msgid="1569030723286851002">"Приспособления"</string>
- <string name="completely_out_of_space" msgid="6106288382070760318">"На началните ви екрани няма повече място."</string>
+ <string name="all_apps_search_bar_hint" msgid="7084713969757597256">"Търсене в приложенията"</string>
+ <string name="all_apps_loading_message" msgid="7557140873644765180">"Приложенията се зареждат…"</string>
+ <string name="all_apps_no_search_results" msgid="6332185285860416787">"Няма намерени приложения, съответстващи на „<xliff:g id="QUERY">%1$s</xliff:g>“"</string>
<string name="out_of_space" msgid="4691004494942118364">"На този начален екран няма повече място."</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"Няма повече място в областта с любимите"</string>
- <string name="invalid_hotseat_item" msgid="5779907847267573691">"Това приспособление е твърде голямо за областта с любимите"</string>
- <string name="shortcut_installed" msgid="1701742129426969556">"Прекият път към <xliff:g id="NAME">%s</xliff:g> е създаден."</string>
- <string name="shortcut_uninstalled" msgid="8176767991305701821">"Прекият път към <xliff:g id="NAME">%s</xliff:g> бе премахнат."</string>
- <string name="shortcut_duplicate" msgid="9167217446062498127">"Прекият път към <xliff:g id="NAME">%s</xliff:g> вече съществува."</string>
- <string name="title_select_shortcut" msgid="6680642571148153868">"Избор на пряк път"</string>
- <string name="title_select_application" msgid="3280812711670683644">"Избор на приложение"</string>
<string name="all_apps_button_label" msgid="9110807029020582876">"Приложения"</string>
<string name="all_apps_home_button_label" msgid="252062713717058851">"Начало"</string>
- <string name="delete_zone_label_workspace" msgid="4009607676751398685">"Премахване"</string>
- <string name="delete_zone_label_all_apps" msgid="8083826390278958980">"Деинсталиране"</string>
<string name="delete_target_label" msgid="1822697352535677073">"Премахване"</string>
<string name="delete_target_uninstall_label" msgid="5100785476250872595">"Деинсталиране"</string>
<string name="info_target_label" msgid="8053346143994679532">"Информация за приложението"</string>
- <string name="accessibility_all_apps_button" msgid="2603132375383800483">"Приложения"</string>
- <string name="accessibility_delete_button" msgid="6466114477993744621">"Премахване"</string>
- <string name="delete_zone_label_all_apps_system_app" msgid="449755632749610895">"Деинст. на актуализацията"</string>
- <string name="cab_menu_delete_app" msgid="7435191475867183689">"Деинсталиране на приложението"</string>
- <string name="cab_menu_app_info" msgid="8593722221450362342">"Подробности за приложението"</string>
- <string name="cab_app_selection_text" msgid="374688303047985416">"Избрано е 1 приложение"</string>
- <string name="cab_widget_selection_text" msgid="1833458597831541241">"Избрано е 1 приспособление"</string>
- <string name="cab_folder_selection_text" msgid="7999992513806132118">"Избрана е 1 папка"</string>
- <string name="cab_shortcut_selection_text" msgid="2103811025667946450">"Избран е 1 пряк път"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"инсталиране на преки пътища"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"Разрешава на приложението да добавя преки пътища без намеса на потребителя."</string>
- <string name="permlab_uninstall_shortcut" msgid="864595034498083837">"деинсталиране на преки пътища"</string>
- <string name="permdesc_uninstall_shortcut" msgid="5134129545001836849">"Разрешава на приложението да премахва преки пътища без намеса на потребителя."</string>
<string name="permlab_read_settings" msgid="1941457408239617576">"четене на настройките и преките пътища в Начало"</string>
<string name="permdesc_read_settings" msgid="5833423719057558387">"Разрешава на приложението да чете настройките и преките пътища в Начало."</string>
<string name="permlab_write_settings" msgid="3574213698004620587">"запис на настройките и преките пътища в Начало"</string>
@@ -78,30 +48,17 @@
<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>
- <string name="dream_name" msgid="1530253749244328964">"Ракетна площадка"</string>
<string name="folder_hint_text" msgid="6617836969016293992">"Папка без име"</string>
- <string name="workspace_description_format" msgid="2950174241104043327">"Начален екран %1$d"</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="apps_customize_apps_scroll_format" msgid="370005296147130238">"Страница с приложения %1$d от %2$d"</string>
- <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"Страница с приспособления %1$d от %2$d"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"Добре дошли"</string>
- <string name="first_run_cling_description" msgid="6447072552696253358">"Персонализиране и приспособяване."</string>
- <string name="first_run_cling_custom_content_hint" msgid="6090628589029352439"></string>
- <string name="first_run_cling_search_bar_hint" msgid="5909062802402452582"></string>
- <string name="first_run_cling_create_screens_hint" msgid="6950729526680114157">"Създаване на още екрани за приложения и папки"</string>
<string name="migration_cling_title" msgid="9181776667882933767">"Икони на прилож. ви: Копиране"</string>
<string name="migration_cling_description" msgid="2752413805582227644">"Да се импортират ли иконите и папките от старите ви начални екрани?"</string>
<string name="migration_cling_copy_apps" msgid="946331230090919440">"КОПИРАНЕ НА ИКОНИТЕ"</string>
<string name="migration_cling_use_default" msgid="2626475813981258626">"СТАРТИРАНЕ ОТНАЧАЛО"</string>
- <string name="workspace_cling_title" msgid="5626202359865825661">"Организиране на мястото ви"</string>
- <string name="workspace_cling_move_item" msgid="528201129978005352">"Докоснете и задръжте фона, за да управлявате тапета, приспособленията и настройките."</string>
<string name="workspace_cling_longpress_title" msgid="9173998993909018310">"Тапети, приспособления и настройки"</string>
<string name="workspace_cling_longpress_description" msgid="4119994475505235248">"Докоснете и задръжте фона за персонализиране"</string>
<string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"РАЗБРАХ"</string>
- <string name="folder_cling_title" msgid="3894908818693254164">"Ето една папка"</string>
- <string name="folder_cling_create_folder" msgid="6158215559475836131">"За да създадете подобна, докоснете и задръжте приложение, след което го преместете върху друго."</string>
- <string name="cling_dismiss" msgid="8962359497601507581">"ОK"</string>
<string name="folder_opened" msgid="94695026776264709">"Папката е отворена – <xliff:g id="WIDTH">%1$d</xliff:g> на <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
<string name="folder_tap_to_close" msgid="1884479294466410023">"Докоснете, за да затворите папката"</string>
<string name="folder_tap_to_rename" msgid="9191075570492871147">"Докоснете, за да запазите новото име"</string>
@@ -111,14 +68,34 @@
<string name="widget_button_text" msgid="2880537293434387943">"Приспособления"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"Тапети"</string>
<string name="settings_button_text" msgid="8119458837558863227">"Настройки"</string>
- <string name="package_state_enqueued" msgid="6227252464303085641">"Изчаква"</string>
- <string name="package_state_downloading" msgid="4088770468458724721">"Изтегля се"</string>
- <string name="package_state_installing" msgid="7588193972189849870">"Инсталира се"</string>
+ <string name="allow_rotation_title" msgid="2118706734511831751">"Разрешаване на завъртането"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Няма информация"</string>
- <string name="package_state_error" msgid="7672093962724223588">"Не е възстановено"</string>
- <string name="abandoned_clean_all" msgid="5256770727689657618">"Премахване на всички"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Премахване"</string>
<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="action_add_to_workspace" msgid="8902165848117513641">"Добавяне към началния екран"</string>
+ <string name="action_move_here" msgid="2170188780612570250">"Преместване на елемента тук"</string>
+ <string name="item_added_to_workspace" msgid="4211073925752213539">"Елементът е добавен към началния екран"</string>
+ <string name="item_removed" msgid="851119963877842327">"Елементът е премахнат"</string>
+ <string name="action_move" msgid="4339390619886385032">"Преместване на елемента"</string>
+ <string name="move_to_empty_cell" msgid="2833711483015685619">"Преместване към ред <xliff:g id="NUMBER_0">%1$s</xliff:g>, колона <xliff:g id="NUMBER_1">%2$s</xliff:g>"</string>
+ <string name="move_to_position" msgid="6750008980455459790">"Преместване към позиция <xliff:g id="NUMBER">%1$s</xliff:g>"</string>
+ <string name="move_to_hotseat_position" msgid="6295412897075147808">"Преместване към позиция <xliff:g id="NUMBER">%1$s</xliff:g> в любимите"</string>
+ <string name="item_moved" msgid="4606538322571412879">"Елементът е преместен"</string>
+ <string name="add_to_folder" msgid="9040534766770853243">"Добавяне към папката „<xliff:g id="NAME">%1$s</xliff:g>“"</string>
+ <string name="add_to_folder_with_app" msgid="4534929978967147231">"Добавяне към папката, съдържаща <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="added_to_folder" msgid="4793259502305558003">"Елементът е добавен към папката"</string>
+ <string name="create_folder_with" msgid="4050141361160214248">"Създаване на папка с елемента „<xliff:g id="NAME">%1$s</xliff:g>“"</string>
+ <string name="folder_created" msgid="6409794597405184510">"Папката е създадена"</string>
+ <string name="action_move_to_workspace" msgid="1603837886334246317">"Преместване към началния екран"</string>
+ <string name="action_move_screen_left" msgid="8854216831569401665">"Преместване на екрана наляво"</string>
+ <string name="action_move_screen_right" msgid="329334910274311123">"Преместване на екрана надясно"</string>
+ <string name="screen_moved" msgid="266230079505650577">"Екранът е преместен"</string>
+ <string name="action_resize" msgid="1802976324781771067">"Преоразмеряване"</string>
+ <string name="action_increase_width" msgid="8773715375078513326">"Увеличаване на ширината"</string>
+ <string name="action_increase_height" msgid="459390020612501122">"Увеличаване на височината"</string>
+ <string name="action_decrease_width" msgid="1374549771083094654">"Намаляване на ширината"</string>
+ <string name="action_decrease_height" msgid="282377193880900022">"Намаляване на височината"</string>
+ <string name="widget_resized" msgid="9130327887929620">"Приспособлението е преоразмерено към ширина <xliff:g id="NUMBER_0">%1$s</xliff:g> и височина <xliff:g id="NUMBER_1">%2$s</xliff:g>"</string>
</resources>
diff --git a/res/values-bn-rBD/strings.xml b/res/values-bn-rBD/strings.xml
index 143420103..57f7b511d 100644
--- a/res/values-bn-rBD/strings.xml
+++ b/res/values-bn-rBD/strings.xml
@@ -20,57 +20,27 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="application_name" msgid="5181331383435256801">"লঞ্চার৩"</string>
- <string name="home" msgid="7658288663002113681">"হোম"</string>
- <string name="uid_name" msgid="7820867637514617527">"Android প্রাথমিক অ্যাপ্লিকেশানগুলি"</string>
<string name="folder_name" msgid="7371454440695724752"></string>
+ <string name="work_folder_name" msgid="3753320833950115786">"কাজ"</string>
<string name="activity_not_found" msgid="8071924732094499514">"অ্যাপ্লিকেশান ইনস্টল করা নেই৷"</string>
<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="widgets_tab_label" msgid="2921133187116603919">"উইজেটগুলি"</string>
- <string name="widget_adder" msgid="3201040140710381657">"উইজেটগুলি"</string>
<string name="toggle_weight_watcher" msgid="5645299835184636119">"মেম দেখান"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"একটি উইজেট তুলতে তা স্পর্শ করে ধরে রাখুন৷"</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
- <string name="external_drop_widget_error" msgid="3165821058322217155">"এই হোম স্ক্রীনে আইটেম রাখা যায়নি৷"</string>
- <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"তৈরি করেতে উইজেট চয়ন করুন"</string>
- <string name="rename_folder_label" msgid="3727762225964550653">"ফোল্ডারের নাম"</string>
- <string name="rename_folder_title" msgid="3771389277707820891">"ফোল্ডার পুনঃনামকরণ করুন"</string>
- <string name="rename_action" msgid="5559600076028658757">"ঠিক আছে"</string>
- <string name="cancel_action" msgid="7009134900002915310">"বাতিল করুন"</string>
- <string name="menu_item_add_item" msgid="1264911265836810421">"হোম স্ক্রীনে যোগ করুন"</string>
- <string name="group_applications" msgid="3797214114206693605">"অ্যাপ্লিকেশানগুলি"</string>
- <string name="group_shortcuts" msgid="6012256992764410535">"শর্টকাটগুলি"</string>
- <string name="group_widgets" msgid="1569030723286851002">"উইজেটগুলি"</string>
- <string name="completely_out_of_space" msgid="6106288382070760318">"আপনার হোম স্ক্রীনগুলিতে আর কোনো জায়গা নেই৷"</string>
+ <string name="all_apps_search_bar_hint" msgid="7084713969757597256">"অ্যাপ্লিকেশানগুলি অনুসন্ধান করুন"</string>
+ <string name="all_apps_loading_message" msgid="7557140873644765180">"অ্যাপ্লিকেশানগুলি লোড হচ্ছে..."</string>
+ <string name="all_apps_no_search_results" msgid="6332185285860416787">"\"<xliff:g id="QUERY">%1$s</xliff:g>\" এর সাথে মেলে এমন কোনো অ্যাপ্লিকেশান পাওয়া যায়নি"</string>
<string name="out_of_space" msgid="4691004494942118364">"এই হোম স্ক্রীনে আর কোনো জায়গা নেই৷"</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"পছন্দসই ট্রে-তে আর কোনো জায়গা নেই"</string>
- <string name="invalid_hotseat_item" msgid="5779907847267573691">"পছন্দসই ট্রে\'র জন্য এই উইজেটটি খুবই বড়"</string>
- <string name="shortcut_installed" msgid="1701742129426969556">"শর্টকাট \"<xliff:g id="NAME">%s</xliff:g>\" তৈরি করা হয়েছে৷"</string>
- <string name="shortcut_uninstalled" msgid="8176767991305701821">"শর্টকাট \"<xliff:g id="NAME">%s</xliff:g>\" সরানো হয়েছে৷"</string>
- <string name="shortcut_duplicate" msgid="9167217446062498127">"শর্টকাট <xliff:g id="NAME">%s</xliff:g> আগে থেকেই আছে৷"</string>
- <string name="title_select_shortcut" msgid="6680642571148153868">"শর্টকাট চয়ন করুন"</string>
- <string name="title_select_application" msgid="3280812711670683644">"অ্যাপ্লিকেশান চয়ন করুন"</string>
<string name="all_apps_button_label" msgid="9110807029020582876">"অ্যাপ্লিকেশানগুলি"</string>
<string name="all_apps_home_button_label" msgid="252062713717058851">"হোম"</string>
- <string name="delete_zone_label_workspace" msgid="4009607676751398685">"সরান"</string>
- <string name="delete_zone_label_all_apps" msgid="8083826390278958980">"আনইনস্টল করুন"</string>
<string name="delete_target_label" msgid="1822697352535677073">"সরান"</string>
<string name="delete_target_uninstall_label" msgid="5100785476250872595">"আনইনস্টল করুন"</string>
<string name="info_target_label" msgid="8053346143994679532">"অ্যাপ্লিকেশানের তথ্য"</string>
- <string name="accessibility_all_apps_button" msgid="2603132375383800483">"অ্যাপ্লিকেশানগুলি"</string>
- <string name="accessibility_delete_button" msgid="6466114477993744621">"সরান"</string>
- <string name="delete_zone_label_all_apps_system_app" msgid="449755632749610895">"আপডেট আনইনস্টল করুন"</string>
- <string name="cab_menu_delete_app" msgid="7435191475867183689">"অ্যাপ্লিকেশান আনইনস্টল করুন"</string>
- <string name="cab_menu_app_info" msgid="8593722221450362342">"অ্যাপ্লিকেশানের বিশদ বিবরণ"</string>
- <string name="cab_app_selection_text" msgid="374688303047985416">"১টি অ্যাপ্লিকেশান নির্বাচন করা হয়েছে"</string>
- <string name="cab_widget_selection_text" msgid="1833458597831541241">"১টি উইজেট নির্বাচন করা হয়েছে"</string>
- <string name="cab_folder_selection_text" msgid="7999992513806132118">"১টি ফোল্ডার নির্বাচন করা হয়েছে"</string>
- <string name="cab_shortcut_selection_text" msgid="2103811025667946450">"১টি শর্টকাট নির্বাচন করা হয়েছে"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"শর্টকাটগুলি ইনস্টল করে"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"একটি অ্যাপ্লিকেশানকে ব্যবহারকারীর হস্তক্ষেপ ছাড়াই শর্টকাটগুলি যোগ করার অনুমতি দেয়৷"</string>
- <string name="permlab_uninstall_shortcut" msgid="864595034498083837">"শর্টকাটগুলি আনইনস্টল করে"</string>
- <string name="permdesc_uninstall_shortcut" msgid="5134129545001836849">"অ্যাপ্লিকেশানটিকে ব্যবহারকারীর হস্তক্ষেপ ছাড়াই শর্টকাটগুলি সরানোর অনুমতি দেয়৷"</string>
<string name="permlab_read_settings" msgid="1941457408239617576">"হোম সেটিংস এবং শর্টকাটগুলি পড়ে"</string>
<string name="permdesc_read_settings" msgid="5833423719057558387">"হোমে অ্যাপ্লিকেশানটিকে সেটিংস এবং শর্টকাটগুলি পড়তে দেয়৷"</string>
<string name="permlab_write_settings" msgid="3574213698004620587">"হোম সেটিংস এবং শর্টকাটগুলি লেখে"</string>
@@ -78,30 +48,17 @@
<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>
- <string name="dream_name" msgid="1530253749244328964">"রকেট লঞ্চার"</string>
<string name="folder_hint_text" msgid="6617836969016293992">"নামবিহীন ফোল্ডার"</string>
- <string name="workspace_description_format" msgid="2950174241104043327">"%1$d নম্বর হোম স্ক্রীন"</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="apps_customize_apps_scroll_format" msgid="370005296147130238">"%2$dটির মধ্যে %1$dটি অ্যাপ্লিকেশান পৃষ্ঠা"</string>
- <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"%2$dটির মধ্যে %1$dটি উইজেট পৃষ্ঠা"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"স্বাগতম"</string>
- <string name="first_run_cling_description" msgid="6447072552696253358">"নিজের বাড়ির মতো স্বাচ্ছন্দ্য বোধ করুন৷"</string>
- <string name="first_run_cling_custom_content_hint" msgid="6090628589029352439"></string>
- <string name="first_run_cling_search_bar_hint" msgid="5909062802402452582"></string>
- <string name="first_run_cling_create_screens_hint" msgid="6950729526680114157">"অ্যাপ্লিকেশান এবং ফোল্ডারগুলির জন্য আরো স্ক্রীn তৈরি করুন"</string>
<string name="migration_cling_title" msgid="9181776667882933767">"আপনার অ্যাপ্লিকেশান আইকনগুলি অনুলিপি করুন"</string>
<string name="migration_cling_description" msgid="2752413805582227644">"আপনার পুরানো হোম স্ক্রীন থেকে আইকন এবং ফোল্ডারগুলি আমদানি করবেন?"</string>
<string name="migration_cling_copy_apps" msgid="946331230090919440">"আইকনগুলি অনুলিপি করুন"</string>
<string name="migration_cling_use_default" msgid="2626475813981258626">"নতুন করে শুরু করুন"</string>
- <string name="workspace_cling_title" msgid="5626202359865825661">"আপনার স্থান সংগঠিত করুন"</string>
- <string name="workspace_cling_move_item" msgid="528201129978005352">"ওয়ালপেপার, উইজেট এবং সেটিংস পরিচালনা করতে পটভূমি স্পর্শ করে ধরে রাখুন৷"</string>
<string name="workspace_cling_longpress_title" msgid="9173998993909018310">"ওয়ালপেপার, উইজেট এবং সেটিংস"</string>
<string name="workspace_cling_longpress_description" msgid="4119994475505235248">"কাস্টমাইজ করার জন্য পটভূমি স্পর্শ করে ধরে থাকুন"</string>
<string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"বুঝেছি"</string>
- <string name="folder_cling_title" msgid="3894908818693254164">"এখানে একটি ফোল্ডার আছে"</string>
- <string name="folder_cling_create_folder" msgid="6158215559475836131">"এটির মতো একটি তৈরি করতে, একটি অ্যাপ্লিকেশান স্পর্শ করে ধরে রাখুন, এবং তারপরে এটিকে অন্য একটির উপরে সরিয়ে নিয়ে যান৷"</string>
- <string name="cling_dismiss" msgid="8962359497601507581">"ঠিক আছে"</string>
<string name="folder_opened" msgid="94695026776264709">"ফোল্ডার খোলা হয়েছে, <xliff:g id="WIDTH">%1$d</xliff:g> বাই <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
<string name="folder_tap_to_close" msgid="1884479294466410023">"ফোল্ডার বন্ধ করতে স্পর্শ করুন"</string>
<string name="folder_tap_to_rename" msgid="9191075570492871147">"পুনঃনামকরণ সংরক্ষণ করতে স্পর্শ করুন"</string>
@@ -111,14 +68,34 @@
<string name="widget_button_text" msgid="2880537293434387943">"উইজেটগুলি"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"ওয়ালপেপারগুলি"</string>
<string name="settings_button_text" msgid="8119458837558863227">"সেটিংস"</string>
- <string name="package_state_enqueued" msgid="6227252464303085641">"প্রতীক্ষা"</string>
- <string name="package_state_downloading" msgid="4088770468458724721">"ডাউনলোড হচ্ছে"</string>
- <string name="package_state_installing" msgid="7588193972189849870">"ইনস্টল করা হচ্ছে"</string>
+ <string name="allow_rotation_title" msgid="2118706734511831751">"ঘূর্ণনের অনুমতি দিন"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"অজানা"</string>
- <string name="package_state_error" msgid="7672093962724223588">"পুনঃস্থাপন করা যায়নি"</string>
- <string name="abandoned_clean_all" msgid="5256770727689657618">"সবগুলি সরান"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"সরান"</string>
<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="action_add_to_workspace" msgid="8902165848117513641">"হোম স্ক্রীনে যোগ করুন"</string>
+ <string name="action_move_here" msgid="2170188780612570250">"এখানে আইটেম সরান"</string>
+ <string name="item_added_to_workspace" msgid="4211073925752213539">"হোম স্ক্রীনে আইটেম যোগ করা হয়েছে"</string>
+ <string name="item_removed" msgid="851119963877842327">"আইটেম সরানো হয়েছে"</string>
+ <string name="action_move" msgid="4339390619886385032">"আইটেম সরান"</string>
+ <string name="move_to_empty_cell" msgid="2833711483015685619">"সারি <xliff:g id="NUMBER_0">%1$s</xliff:g> কলাম <xliff:g id="NUMBER_1">%2$s</xliff:g> এ সরান"</string>
+ <string name="move_to_position" msgid="6750008980455459790">"অবস্থানে সরান <xliff:g id="NUMBER">%1$s</xliff:g>"</string>
+ <string name="move_to_hotseat_position" msgid="6295412897075147808">"পছন্দসই অবস্থানে সরান <xliff:g id="NUMBER">%1$s</xliff:g>"</string>
+ <string name="item_moved" msgid="4606538322571412879">"আইটেম সরানো হয়েছে"</string>
+ <string name="add_to_folder" msgid="9040534766770853243">"ফোল্ডারে যোগ করুন: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="add_to_folder_with_app" msgid="4534929978967147231">"<xliff:g id="NAME">%1$s</xliff:g> সহ ফোল্ডারে যোগ করা হয়েছে"</string>
+ <string name="added_to_folder" msgid="4793259502305558003">"আইটেম ফোল্ডারে যোগ করা হয়েছে"</string>
+ <string name="create_folder_with" msgid="4050141361160214248">"এর সাথে ফোল্ডার তৈরি করুন: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="folder_created" msgid="6409794597405184510">"ফোল্ডার তৈরি করা হয়েছে"</string>
+ <string name="action_move_to_workspace" msgid="1603837886334246317">"হোম স্ক্রীনে সরান"</string>
+ <string name="action_move_screen_left" msgid="8854216831569401665">"স্ক্রীন বাম দিকে সরান"</string>
+ <string name="action_move_screen_right" msgid="329334910274311123">"স্ক্রীন ডান দিকে সরান"</string>
+ <string name="screen_moved" msgid="266230079505650577">"স্ক্রীন সরানো হয়েছে"</string>
+ <string name="action_resize" msgid="1802976324781771067">"পুনরায় আকার দিন"</string>
+ <string name="action_increase_width" msgid="8773715375078513326">"প্রস্থ বাড়ান"</string>
+ <string name="action_increase_height" msgid="459390020612501122">"উচ্চতা বাড়ান"</string>
+ <string name="action_decrease_width" msgid="1374549771083094654">"প্রস্থ কমান"</string>
+ <string name="action_decrease_height" msgid="282377193880900022">"উচ্চতা কমান"</string>
+ <string name="widget_resized" msgid="9130327887929620">"উইজেটের আকার প্রস্থ <xliff:g id="NUMBER_0">%1$s</xliff:g> উচ্চতা <xliff:g id="NUMBER_1">%2$s</xliff:g> তে পরিবর্তন করা হয়েছে"</string>
</resources>
diff --git a/res/values-ca/strings.xml b/res/values-ca/strings.xml
index 89e582a81..83f284a9d 100644
--- a/res/values-ca/strings.xml
+++ b/res/values-ca/strings.xml
@@ -20,57 +20,27 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="application_name" msgid="5181331383435256801">"Launcher3"</string>
- <string name="home" msgid="7658288663002113681">"Inici"</string>
- <string name="uid_name" msgid="7820867637514617527">"Aplicacions principals d\'Android"</string>
<string name="folder_name" msgid="7371454440695724752"></string>
+ <string name="work_folder_name" msgid="3753320833950115786">"Feina"</string>
<string name="activity_not_found" msgid="8071924732094499514">"L\'aplicació no s\'ha instal·lat."</string>
<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="widgets_tab_label" msgid="2921133187116603919">"Widgets"</string>
- <string name="widget_adder" msgid="3201040140710381657">"Widgets"</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="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
- <string name="external_drop_widget_error" msgid="3165821058322217155">"No s\'ha pogut deixar anar l\'element a Inici."</string>
- <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Tria el widget que vulguis crear"</string>
- <string name="rename_folder_label" msgid="3727762225964550653">"Nom de la carpeta"</string>
- <string name="rename_folder_title" msgid="3771389277707820891">"Canvi de nom de la carpeta"</string>
- <string name="rename_action" msgid="5559600076028658757">"D\'acord"</string>
- <string name="cancel_action" msgid="7009134900002915310">"Cancel·la"</string>
- <string name="menu_item_add_item" msgid="1264911265836810421">"Afegir a la pantalla d\'inici"</string>
- <string name="group_applications" msgid="3797214114206693605">"Aplicacions"</string>
- <string name="group_shortcuts" msgid="6012256992764410535">"Dreceres"</string>
- <string name="group_widgets" msgid="1569030723286851002">"Widgets"</string>
- <string name="completely_out_of_space" msgid="6106288382070760318">"No queda espai a les pantalles d\'inici."</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>
+ <string name="all_apps_no_search_results" msgid="6332185285860416787">"No s\'ha trobat cap aplicació que coincideixi amb <xliff:g id="QUERY">%1$s</xliff:g>"</string>
<string name="out_of_space" msgid="4691004494942118364">"Ja no queda espai en aquesta pantalla d\'inici."</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"No hi ha més espai a la safata Preferits."</string>
- <string name="invalid_hotseat_item" msgid="5779907847267573691">"Aquest widget és massa gran per a la safata Preferits."</string>
- <string name="shortcut_installed" msgid="1701742129426969556">"S\'ha creat la drecera \"<xliff:g id="NAME">%s</xliff:g>\"."</string>
- <string name="shortcut_uninstalled" msgid="8176767991305701821">"S\'ha suprimit la drecera \"<xliff:g id="NAME">%s</xliff:g>\"."</string>
- <string name="shortcut_duplicate" msgid="9167217446062498127">"La drecera \"<xliff:g id="NAME">%s</xliff:g>\" ja existeix."</string>
- <string name="title_select_shortcut" msgid="6680642571148153868">"Tria d\'una drecera"</string>
- <string name="title_select_application" msgid="3280812711670683644">"Tria d\'una aplicació"</string>
<string name="all_apps_button_label" msgid="9110807029020582876">"Aplicacions"</string>
<string name="all_apps_home_button_label" msgid="252062713717058851">"Inici"</string>
- <string name="delete_zone_label_workspace" msgid="4009607676751398685">"Suprimeix"</string>
- <string name="delete_zone_label_all_apps" msgid="8083826390278958980">"Desinstal·la"</string>
<string name="delete_target_label" msgid="1822697352535677073">"Suprimeix"</string>
<string name="delete_target_uninstall_label" msgid="5100785476250872595">"Desinstal·la"</string>
<string name="info_target_label" msgid="8053346143994679532">"Informació de l\'aplicació"</string>
- <string name="accessibility_all_apps_button" msgid="2603132375383800483">"Aplicacions"</string>
- <string name="accessibility_delete_button" msgid="6466114477993744621">"Suprimeix"</string>
- <string name="delete_zone_label_all_apps_system_app" msgid="449755632749610895">"Desinstal·la l\'actualització"</string>
- <string name="cab_menu_delete_app" msgid="7435191475867183689">"Desinstal·la l\'aplicació"</string>
- <string name="cab_menu_app_info" msgid="8593722221450362342">"Detalls de l\'aplicació"</string>
- <string name="cab_app_selection_text" msgid="374688303047985416">"1 aplicació seleccionada"</string>
- <string name="cab_widget_selection_text" msgid="1833458597831541241">"1 widget seleccionat"</string>
- <string name="cab_folder_selection_text" msgid="7999992513806132118">"1 carpeta seleccionada"</string>
- <string name="cab_shortcut_selection_text" msgid="2103811025667946450">"1 drecera seleccionada"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"instal·la dreceres"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"Permet que una aplicació afegeixi dreceres sense la intervenció de l\'usuari."</string>
- <string name="permlab_uninstall_shortcut" msgid="864595034498083837">"desinstal·la dreceres"</string>
- <string name="permdesc_uninstall_shortcut" msgid="5134129545001836849">"Permet que l\'aplicació suprimeixi dreceres sense la intervenció de l\'usuari."</string>
<string name="permlab_read_settings" msgid="1941457408239617576">"llegeix la configuració i les dreceres de la pantalla d\'inici"</string>
<string name="permdesc_read_settings" msgid="5833423719057558387">"Permet que l\'aplicació llegeixi la configuració i les dreceres de la pantalla d\'inici."</string>
<string name="permlab_write_settings" msgid="3574213698004620587">"escriu la configuració i les dreceres de la pantalla d\'inici"</string>
@@ -78,30 +48,17 @@
<string name="gadget_error_text" msgid="6081085226050792095">"S\'ha produït un problema en carregar el widget"</string>
<string name="gadget_setup_text" msgid="8274003207686040488">"Configuració"</string>
<string name="uninstall_system_app_text" msgid="4172046090762920660">"Aquesta aplicació és una aplicació del sistema i no es pot desinstal·lar."</string>
- <string name="dream_name" msgid="1530253749244328964">"Rocket Launcher"</string>
<string name="folder_hint_text" msgid="6617836969016293992">"Carpeta sense nom"</string>
- <string name="workspace_description_format" msgid="2950174241104043327">"Pantalla d\'inici %1$d"</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="apps_customize_apps_scroll_format" msgid="370005296147130238">"Pàgina d\'aplicacions %1$d de %2$d"</string>
- <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"Pàgina de widgets %1$d de %2$d"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"Us donem la benvinguda"</string>
- <string name="first_run_cling_description" msgid="6447072552696253358">"Personalitza la pantalla d\'inici"</string>
- <string name="first_run_cling_custom_content_hint" msgid="6090628589029352439"></string>
- <string name="first_run_cling_search_bar_hint" msgid="5909062802402452582"></string>
- <string name="first_run_cling_create_screens_hint" msgid="6950729526680114157">"Crea més pantalles per a aplicacions i carpetes"</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>
<string name="migration_cling_copy_apps" msgid="946331230090919440">"COPIA LES ICONES."</string>
<string name="migration_cling_use_default" msgid="2626475813981258626">"NOU COMENÇAMENT"</string>
- <string name="workspace_cling_title" msgid="5626202359865825661">"Organitza el teu espai"</string>
- <string name="workspace_cling_move_item" msgid="528201129978005352">"Toca i mantén premut el fons per gestionar el fons de pantalla, els widgets i la configuració."</string>
<string name="workspace_cling_longpress_title" msgid="9173998993909018310">"Fons de pantalla, widgets i configuració"</string>
<string name="workspace_cling_longpress_description" msgid="4119994475505235248">"Mantén premut el fons per fer personalitzacions."</string>
<string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"D\'ACORD"</string>
- <string name="folder_cling_title" msgid="3894908818693254164">"Aquí hi ha una carpeta"</string>
- <string name="folder_cling_create_folder" msgid="6158215559475836131">"Per crear-ne una com aquesta, mantén premuda una aplicació i, a continuació, mou-la sobre una altra."</string>
- <string name="cling_dismiss" msgid="8962359497601507581">"D\'acord"</string>
<string name="folder_opened" msgid="94695026776264709">"S\'ha obert la carpeta, <xliff:g id="WIDTH">%1$d</xliff:g> per <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
<string name="folder_tap_to_close" msgid="1884479294466410023">"Toca per tancar la carpeta"</string>
<string name="folder_tap_to_rename" msgid="9191075570492871147">"Toca per desar el canvi de nom"</string>
@@ -111,14 +68,34 @@
<string name="widget_button_text" msgid="2880537293434387943">"Widgets"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"Fons de pantalla"</string>
<string name="settings_button_text" msgid="8119458837558863227">"Configuració"</string>
- <string name="package_state_enqueued" msgid="6227252464303085641">"En espera"</string>
- <string name="package_state_downloading" msgid="4088770468458724721">"S\'està baixant"</string>
- <string name="package_state_installing" msgid="7588193972189849870">"Instal·lant"</string>
+ <string name="allow_rotation_title" msgid="2118706734511831751">"Permet la rotació"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Desconegut"</string>
- <string name="package_state_error" msgid="7672093962724223588">"No restaurat"</string>
- <string name="abandoned_clean_all" msgid="5256770727689657618">"Suprimeix-ho tot"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Suprimeix"</string>
<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="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>
+ <string name="item_removed" msgid="851119963877842327">"S\'ha suprimit l\'element"</string>
+ <string name="action_move" msgid="4339390619886385032">"Desplaça l\'element"</string>
+ <string name="move_to_empty_cell" msgid="2833711483015685619">"Desplaça l\'element a la fila <xliff:g id="NUMBER_0">%1$s</xliff:g> i la columna <xliff:g id="NUMBER_1">%2$s</xliff:g>"</string>
+ <string name="move_to_position" msgid="6750008980455459790">"Desplaça l\'element a la posició <xliff:g id="NUMBER">%1$s</xliff:g>"</string>
+ <string name="move_to_hotseat_position" msgid="6295412897075147808">"Desplaça l\'element a la posició de preferits <xliff:g id="NUMBER">%1$s</xliff:g>"</string>
+ <string name="item_moved" msgid="4606538322571412879">"Element desplaçat"</string>
+ <string name="add_to_folder" msgid="9040534766770853243">"Afegeix l\'element a la carpeta: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="add_to_folder_with_app" msgid="4534929978967147231">"Afegeix l\'element a la carpeta amb <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="added_to_folder" msgid="4793259502305558003">"Element afegit a la carpeta"</string>
+ <string name="create_folder_with" msgid="4050141361160214248">"Crea una carpeta amb: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="folder_created" msgid="6409794597405184510">"Carpeta creada"</string>
+ <string name="action_move_to_workspace" msgid="1603837886334246317">"Desplaça a la pantalla d\'inici"</string>
+ <string name="action_move_screen_left" msgid="8854216831569401665">"Desplaça pantalla a l\'esquerra"</string>
+ <string name="action_move_screen_right" msgid="329334910274311123">"Desplaça pantalla a la dreta"</string>
+ <string name="screen_moved" msgid="266230079505650577">"S\'ha desplaçat la pantalla"</string>
+ <string name="action_resize" msgid="1802976324781771067">"Canvia la mida"</string>
+ <string name="action_increase_width" msgid="8773715375078513326">"Augmenta l\'amplada"</string>
+ <string name="action_increase_height" msgid="459390020612501122">"Augmenta l\'alçada"</string>
+ <string name="action_decrease_width" msgid="1374549771083094654">"Redueix l\'amplada"</string>
+ <string name="action_decrease_height" msgid="282377193880900022">"Redueix l\'alçada"</string>
+ <string name="widget_resized" msgid="9130327887929620">"S\'ha canviat la mida del widget a l\'amplada <xliff:g id="NUMBER_0">%1$s</xliff:g> i l\'alçada <xliff:g id="NUMBER_1">%2$s</xliff:g>"</string>
</resources>
diff --git a/res/values-cs/strings.xml b/res/values-cs/strings.xml
index 0288806f4..c99a7ed84 100644
--- a/res/values-cs/strings.xml
+++ b/res/values-cs/strings.xml
@@ -20,57 +20,27 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="application_name" msgid="5181331383435256801">"Launcher3"</string>
- <string name="home" msgid="7658288663002113681">"Plocha"</string>
- <string name="uid_name" msgid="7820867637514617527">"Android Core Apps"</string>
<string name="folder_name" msgid="7371454440695724752"></string>
+ <string name="work_folder_name" msgid="3753320833950115786">"Práce"</string>
<string name="activity_not_found" msgid="8071924732094499514">"Aplikace není nainstalována."</string>
<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="widgets_tab_label" msgid="2921133187116603919">"Widgety"</string>
- <string name="widget_adder" msgid="3201040140710381657">"Widgety"</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="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
- <string name="external_drop_widget_error" msgid="3165821058322217155">"Na tuto plochu položku nelze přesunout."</string>
- <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Vyberte widget k vytvoření"</string>
- <string name="rename_folder_label" msgid="3727762225964550653">"Název složky"</string>
- <string name="rename_folder_title" msgid="3771389277707820891">"Přejmenovat složku"</string>
- <string name="rename_action" msgid="5559600076028658757">"OK"</string>
- <string name="cancel_action" msgid="7009134900002915310">"Zrušit"</string>
- <string name="menu_item_add_item" msgid="1264911265836810421">"Přidat na plochu"</string>
- <string name="group_applications" msgid="3797214114206693605">"Aplikace"</string>
- <string name="group_shortcuts" msgid="6012256992764410535">"Klávesové zkratky"</string>
- <string name="group_widgets" msgid="1569030723286851002">"Widgety"</string>
- <string name="completely_out_of_space" msgid="6106288382070760318">"Na plochách již není místo."</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>
+ <string name="all_apps_no_search_results" msgid="6332185285860416787">"Dotazu „<xliff:g id="QUERY">%1$s</xliff:g>“ neodpovídají žádné aplikace"</string>
<string name="out_of_space" msgid="4691004494942118364">"Na této ploše již není místo."</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"Na panelu Oblíbené položky již není místo."</string>
- <string name="invalid_hotseat_item" msgid="5779907847267573691">"Tento widget je pro panel Oblíbené položky příliš velký."</string>
- <string name="shortcut_installed" msgid="1701742129426969556">"Zástupce aplikace <xliff:g id="NAME">%s</xliff:g> byl vytvořen."</string>
- <string name="shortcut_uninstalled" msgid="8176767991305701821">"Zástupce aplikace <xliff:g id="NAME">%s</xliff:g> byl odebrán."</string>
- <string name="shortcut_duplicate" msgid="9167217446062498127">"Zástupce aplikace <xliff:g id="NAME">%s</xliff:g> již existuje."</string>
- <string name="title_select_shortcut" msgid="6680642571148153868">"Výběr zástupce"</string>
- <string name="title_select_application" msgid="3280812711670683644">"Výběr aplikace"</string>
<string name="all_apps_button_label" msgid="9110807029020582876">"Aplikace"</string>
<string name="all_apps_home_button_label" msgid="252062713717058851">"Plocha"</string>
- <string name="delete_zone_label_workspace" msgid="4009607676751398685">"Odstranit"</string>
- <string name="delete_zone_label_all_apps" msgid="8083826390278958980">"Odinstalovat"</string>
<string name="delete_target_label" msgid="1822697352535677073">"Odstranit"</string>
<string name="delete_target_uninstall_label" msgid="5100785476250872595">"Odinstalovat"</string>
<string name="info_target_label" msgid="8053346143994679532">"Informace o aplikaci"</string>
- <string name="accessibility_all_apps_button" msgid="2603132375383800483">"Aplikace"</string>
- <string name="accessibility_delete_button" msgid="6466114477993744621">"Odstranit"</string>
- <string name="delete_zone_label_all_apps_system_app" msgid="449755632749610895">"Odinstalovat aktualizaci"</string>
- <string name="cab_menu_delete_app" msgid="7435191475867183689">"Odinstalovat aplikaci"</string>
- <string name="cab_menu_app_info" msgid="8593722221450362342">"Podrobnosti o aplikaci"</string>
- <string name="cab_app_selection_text" msgid="374688303047985416">"Vybrána 1 aplikace"</string>
- <string name="cab_widget_selection_text" msgid="1833458597831541241">"Vybrán 1 widget"</string>
- <string name="cab_folder_selection_text" msgid="7999992513806132118">"Vybrána 1 složka"</string>
- <string name="cab_shortcut_selection_text" msgid="2103811025667946450">"Vybrán 1 zástupce"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"instalace zástupce"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"Umožňuje aplikaci přidat zástupce bez zásahu uživatele."</string>
- <string name="permlab_uninstall_shortcut" msgid="864595034498083837">"odinstalovat zástupce"</string>
- <string name="permdesc_uninstall_shortcut" msgid="5134129545001836849">"Umožňuje aplikaci odstranit zástupce bez zásahu uživatele."</string>
<string name="permlab_read_settings" msgid="1941457408239617576">"čtení nastavení a odkazů plochy"</string>
<string name="permdesc_read_settings" msgid="5833423719057558387">"Umožňuje aplikaci číst nastavení a odkazy na ploše."</string>
<string name="permlab_write_settings" msgid="3574213698004620587">"zápis nastavení a odkazů plochy"</string>
@@ -78,30 +48,17 @@
<string name="gadget_error_text" msgid="6081085226050792095">"Problém s načtením widgetu"</string>
<string name="gadget_setup_text" msgid="8274003207686040488">"Nastavení"</string>
<string name="uninstall_system_app_text" msgid="4172046090762920660">"Toto je systémová aplikace a nelze ji odinstalovat."</string>
- <string name="dream_name" msgid="1530253749244328964">"Rocket Launcher"</string>
<string name="folder_hint_text" msgid="6617836969016293992">"Složka bez názvu"</string>
- <string name="workspace_description_format" msgid="2950174241104043327">"Plocha %1$d"</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="apps_customize_apps_scroll_format" msgid="370005296147130238">"Stránka aplikací %1$d z %2$d"</string>
- <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"Stránka widgetů %1$d z %2$d"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"Vítejte"</string>
- <string name="first_run_cling_description" msgid="6447072552696253358">"Udělejte si pohodlí."</string>
- <string name="first_run_cling_custom_content_hint" msgid="6090628589029352439"></string>
- <string name="first_run_cling_search_bar_hint" msgid="5909062802402452582"></string>
- <string name="first_run_cling_create_screens_hint" msgid="6950729526680114157">"Vytvořte několik obrazovek pro aplikace a složky"</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>
<string name="migration_cling_copy_apps" msgid="946331230090919440">"ZKOPÍROVAT IKONY"</string>
<string name="migration_cling_use_default" msgid="2626475813981258626">"ZAČÍT S VÝCHOZÍM ROZVRŽENÍM"</string>
- <string name="workspace_cling_title" msgid="5626202359865825661">"Organizace prostoru"</string>
- <string name="workspace_cling_move_item" msgid="528201129978005352">"Chcete-li spravovat tapetu, widgety a nastavení, dotkněte se pozadí a přidržte je."</string>
<string name="workspace_cling_longpress_title" msgid="9173998993909018310">"Tapety, widgety a nastavení"</string>
<string name="workspace_cling_longpress_description" msgid="4119994475505235248">"Pozadí můžete přizpůsobit klepnutím a podržením"</string>
<string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"ROZUMÍM"</string>
- <string name="folder_cling_title" msgid="3894908818693254164">"Toto je složka"</string>
- <string name="folder_cling_create_folder" msgid="6158215559475836131">"Chcete-li vytvořit složku, přetáhněte aplikaci na jinou aplikaci."</string>
- <string name="cling_dismiss" msgid="8962359497601507581">"OK"</string>
<string name="folder_opened" msgid="94695026776264709">"Složka otevřena, rozměry <xliff:g id="WIDTH">%1$d</xliff:g> x <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
<string name="folder_tap_to_close" msgid="1884479294466410023">"Dotykem složku zavřete"</string>
<string name="folder_tap_to_rename" msgid="9191075570492871147">"Dotykem uložíte změnu názvu"</string>
@@ -111,14 +68,34 @@
<string name="widget_button_text" msgid="2880537293434387943">"Widgety"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"Tapety"</string>
<string name="settings_button_text" msgid="8119458837558863227">"Nastavení"</string>
- <string name="package_state_enqueued" msgid="6227252464303085641">"Čekání"</string>
- <string name="package_state_downloading" msgid="4088770468458724721">"Stahování"</string>
- <string name="package_state_installing" msgid="7588193972189849870">"Instalace"</string>
+ <string name="allow_rotation_title" msgid="2118706734511831751">"Povolit otáčení"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Neznámé"</string>
- <string name="package_state_error" msgid="7672093962724223588">"Nebylo obnoveno"</string>
- <string name="abandoned_clean_all" msgid="5256770727689657618">"Odstranit vše"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Odstranit"</string>
<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="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>
+ <string name="item_removed" msgid="851119963877842327">"Položka byla odstraněna"</string>
+ <string name="action_move" msgid="4339390619886385032">"Přesunout položku"</string>
+ <string name="move_to_empty_cell" msgid="2833711483015685619">"Přesunout na řádek <xliff:g id="NUMBER_0">%1$s</xliff:g> do sloupce <xliff:g id="NUMBER_1">%2$s</xliff:g>"</string>
+ <string name="move_to_position" msgid="6750008980455459790">"Přesunout na pozici <xliff:g id="NUMBER">%1$s</xliff:g>"</string>
+ <string name="move_to_hotseat_position" msgid="6295412897075147808">"Přesunout do oblíbených položek na pozici <xliff:g id="NUMBER">%1$s</xliff:g>"</string>
+ <string name="item_moved" msgid="4606538322571412879">"Položka byla přesunuta"</string>
+ <string name="add_to_folder" msgid="9040534766770853243">"Přidat do složky: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="add_to_folder_with_app" msgid="4534929978967147231">"Přidat do složky s aplikací <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="added_to_folder" msgid="4793259502305558003">"Položka byla přidána do složky"</string>
+ <string name="create_folder_with" msgid="4050141361160214248">"Vytvořit složku s položkou <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="folder_created" msgid="6409794597405184510">"Složka byla vytvořena"</string>
+ <string name="action_move_to_workspace" msgid="1603837886334246317">"Přesunout na plochu"</string>
+ <string name="action_move_screen_left" msgid="8854216831569401665">"Přesunout obrazovku doleva"</string>
+ <string name="action_move_screen_right" msgid="329334910274311123">"Přesunout obrazovku doprava"</string>
+ <string name="screen_moved" msgid="266230079505650577">"Obrazovka byla přesunuta"</string>
+ <string name="action_resize" msgid="1802976324781771067">"Změnit velikost"</string>
+ <string name="action_increase_width" msgid="8773715375078513326">"Zvýšit šířku"</string>
+ <string name="action_increase_height" msgid="459390020612501122">"Zvýšit výšku"</string>
+ <string name="action_decrease_width" msgid="1374549771083094654">"Snížit šířku"</string>
+ <string name="action_decrease_height" msgid="282377193880900022">"Snížit výšku"</string>
+ <string name="widget_resized" msgid="9130327887929620">"Velikost widgetu upravena: šířka <xliff:g id="NUMBER_0">%1$s</xliff:g>, výška <xliff:g id="NUMBER_1">%2$s</xliff:g>"</string>
</resources>
diff --git a/res/values-da/strings.xml b/res/values-da/strings.xml
index 5fa6aa6b6..eeab92e6e 100644
--- a/res/values-da/strings.xml
+++ b/res/values-da/strings.xml
@@ -20,57 +20,27 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="application_name" msgid="5181331383435256801">"Launcher3"</string>
- <string name="home" msgid="7658288663002113681">"Startskærm"</string>
- <string name="uid_name" msgid="7820867637514617527">"Kerneapps i Android"</string>
<string name="folder_name" msgid="7371454440695724752"></string>
+ <string name="work_folder_name" msgid="3753320833950115786">"Arbejde"</string>
<string name="activity_not_found" msgid="8071924732094499514">"Appen er ikke installeret."</string>
<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="widgets_tab_label" msgid="2921133187116603919">"Widgets"</string>
- <string name="widget_adder" msgid="3201040140710381657">"Widgets"</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="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
- <string name="external_drop_widget_error" msgid="3165821058322217155">"Elementet kunne ikke trækkes til startskærmen."</string>
- <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Vælg den widget, du vil oprette"</string>
- <string name="rename_folder_label" msgid="3727762225964550653">"Mappenavn"</string>
- <string name="rename_folder_title" msgid="3771389277707820891">"Omdøb mappe"</string>
- <string name="rename_action" msgid="5559600076028658757">"OK"</string>
- <string name="cancel_action" msgid="7009134900002915310">"Annuller"</string>
- <string name="menu_item_add_item" msgid="1264911265836810421">"Føj til startskærm"</string>
- <string name="group_applications" msgid="3797214114206693605">"Apps"</string>
- <string name="group_shortcuts" msgid="6012256992764410535">"Genveje"</string>
- <string name="group_widgets" msgid="1569030723286851002">"Widgets"</string>
- <string name="completely_out_of_space" msgid="6106288382070760318">"Der er ikke mere plads på dine startskærme."</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>
+ <string name="all_apps_no_search_results" msgid="6332185285860416787">"Der blev ikke fundet nogen apps, som matcher \"<xliff:g id="QUERY">%1$s</xliff:g>\""</string>
<string name="out_of_space" msgid="4691004494942118364">"Der er ikke mere plads på denne startskærm."</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"Der er ikke mere plads i bakken Foretrukne"</string>
- <string name="invalid_hotseat_item" msgid="5779907847267573691">"Denne widget er for stor til bakken Foretrukne"</string>
- <string name="shortcut_installed" msgid="1701742129426969556">"Genvejen \"<xliff:g id="NAME">%s</xliff:g>\" blev oprettet."</string>
- <string name="shortcut_uninstalled" msgid="8176767991305701821">"Genvejen \"<xliff:g id="NAME">%s</xliff:g>\" blev fjernet."</string>
- <string name="shortcut_duplicate" msgid="9167217446062498127">"Genvejen \"<xliff:g id="NAME">%s</xliff:g>\" findes allerede."</string>
- <string name="title_select_shortcut" msgid="6680642571148153868">"Vælg genvej"</string>
- <string name="title_select_application" msgid="3280812711670683644">"Vælg app"</string>
<string name="all_apps_button_label" msgid="9110807029020582876">"Apps"</string>
<string name="all_apps_home_button_label" msgid="252062713717058851">"Startskærm"</string>
- <string name="delete_zone_label_workspace" msgid="4009607676751398685">"Fjern"</string>
- <string name="delete_zone_label_all_apps" msgid="8083826390278958980">"Afinstaller"</string>
<string name="delete_target_label" msgid="1822697352535677073">"Fjern"</string>
<string name="delete_target_uninstall_label" msgid="5100785476250872595">"Afinstaller"</string>
<string name="info_target_label" msgid="8053346143994679532">"Oplysninger om appen"</string>
- <string name="accessibility_all_apps_button" msgid="2603132375383800483">"Apps"</string>
- <string name="accessibility_delete_button" msgid="6466114477993744621">"Fjern"</string>
- <string name="delete_zone_label_all_apps_system_app" msgid="449755632749610895">"Afinstaller opdatering"</string>
- <string name="cab_menu_delete_app" msgid="7435191475867183689">"Afinstaller appen"</string>
- <string name="cab_menu_app_info" msgid="8593722221450362342">"Oplysninger om appen"</string>
- <string name="cab_app_selection_text" msgid="374688303047985416">"1 app er valgt"</string>
- <string name="cab_widget_selection_text" msgid="1833458597831541241">"1 widget er valgt"</string>
- <string name="cab_folder_selection_text" msgid="7999992513806132118">"1 mappe er valgt"</string>
- <string name="cab_shortcut_selection_text" msgid="2103811025667946450">"1 genvej er valgt"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"installere genveje"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"Tillader, at en app tilføjer genveje uden brugerens indgriben."</string>
- <string name="permlab_uninstall_shortcut" msgid="864595034498083837">"afinstaller genveje"</string>
- <string name="permdesc_uninstall_shortcut" msgid="5134129545001836849">"Tillader, at appen fjerner genveje uden brugerens indgriben."</string>
<string name="permlab_read_settings" msgid="1941457408239617576">"læs indstillinger og genveje for startskærmen"</string>
<string name="permdesc_read_settings" msgid="5833423719057558387">"Tillader, at appen læser indstillingerne og genvejene på startskærmen."</string>
<string name="permlab_write_settings" msgid="3574213698004620587">"skrive indstillinger og genveje for startskærmen"</string>
@@ -78,30 +48,17 @@
<string name="gadget_error_text" msgid="6081085226050792095">"Der er problemer med indlæsning af widgetten"</string>
<string name="gadget_setup_text" msgid="8274003207686040488">"Konfigurer"</string>
<string name="uninstall_system_app_text" msgid="4172046090762920660">"Dette er en systemapp, som ikke kan afinstalleres."</string>
- <string name="dream_name" msgid="1530253749244328964">"Rocket Launcher"</string>
<string name="folder_hint_text" msgid="6617836969016293992">"Unavngiven mappe"</string>
- <string name="workspace_description_format" msgid="2950174241104043327">"Startskærm %1$d"</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="apps_customize_apps_scroll_format" msgid="370005296147130238">"Apps-side %1$d ud af %2$d"</string>
- <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"Widgets-side %1$d ud af %2$d"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"Velkommen"</string>
- <string name="first_run_cling_description" msgid="6447072552696253358">"Føl dig hjemme."</string>
- <string name="first_run_cling_custom_content_hint" msgid="6090628589029352439"></string>
- <string name="first_run_cling_search_bar_hint" msgid="5909062802402452582"></string>
- <string name="first_run_cling_create_screens_hint" msgid="6950729526680114157">"Opret flere skærme til apps og mapper"</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>
<string name="migration_cling_copy_apps" msgid="946331230090919440">"KOPIÉR IKONER"</string>
<string name="migration_cling_use_default" msgid="2626475813981258626">"START PÅ EN FRISK"</string>
- <string name="workspace_cling_title" msgid="5626202359865825661">"Organiser din arbejdsplads"</string>
- <string name="workspace_cling_move_item" msgid="528201129978005352">"Tryk på en baggrund, og hold fingeren nede for at administrere baggrunde, widgets og indstillinger."</string>
<string name="workspace_cling_longpress_title" msgid="9173998993909018310">"Baggrunde, widgets og indstillinger"</string>
<string name="workspace_cling_longpress_description" msgid="4119994475505235248">"Tryk på baggrunden, og hold fingeren nede for at tilpasse den"</string>
<string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"OK, FORSTÅET"</string>
- <string name="folder_cling_title" msgid="3894908818693254164">"Her kan du se en mappe"</string>
- <string name="folder_cling_create_folder" msgid="6158215559475836131">"Du kan oprette en mappe magen til denne ved at trykke på en app og holde fingeren nede, mens du flytter appen til en anden mappe."</string>
- <string name="cling_dismiss" msgid="8962359497601507581">"OK"</string>
<string name="folder_opened" msgid="94695026776264709">"Mappen er åben, <xliff:g id="WIDTH">%1$d</xliff:g> gange <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
<string name="folder_tap_to_close" msgid="1884479294466410023">"Tryk for at lukke mappen"</string>
<string name="folder_tap_to_rename" msgid="9191075570492871147">"Tryk for at gemme det nye navn"</string>
@@ -111,14 +68,34 @@
<string name="widget_button_text" msgid="2880537293434387943">"Widgets"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"Baggrunde"</string>
<string name="settings_button_text" msgid="8119458837558863227">"Indstillinger"</string>
- <string name="package_state_enqueued" msgid="6227252464303085641">"Afventer"</string>
- <string name="package_state_downloading" msgid="4088770468458724721">"Downloader"</string>
- <string name="package_state_installing" msgid="7588193972189849870">"Installerer"</string>
+ <string name="allow_rotation_title" msgid="2118706734511831751">"Tillad rotation"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Ukendt"</string>
- <string name="package_state_error" msgid="7672093962724223588">"Ikke gendannet"</string>
- <string name="abandoned_clean_all" msgid="5256770727689657618">"Slet alle"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Fjern"</string>
<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="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>
+ <string name="item_removed" msgid="851119963877842327">"Elementet er fjernet"</string>
+ <string name="action_move" msgid="4339390619886385032">"Flyt element"</string>
+ <string name="move_to_empty_cell" msgid="2833711483015685619">"Flyt til række <xliff:g id="NUMBER_0">%1$s</xliff:g>, kolonne <xliff:g id="NUMBER_1">%2$s</xliff:g>"</string>
+ <string name="move_to_position" msgid="6750008980455459790">"Flyt til position <xliff:g id="NUMBER">%1$s</xliff:g>"</string>
+ <string name="move_to_hotseat_position" msgid="6295412897075147808">"Flyt til foretrukne position <xliff:g id="NUMBER">%1$s</xliff:g>"</string>
+ <string name="item_moved" msgid="4606538322571412879">"Elementet blev flyttet"</string>
+ <string name="add_to_folder" msgid="9040534766770853243">"Føj til mappen: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="add_to_folder_with_app" msgid="4534929978967147231">"Føj til mappen, der indeholder <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="added_to_folder" msgid="4793259502305558003">"Elementet blev føjet til mappen"</string>
+ <string name="create_folder_with" msgid="4050141361160214248">"Opret mappe med: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="folder_created" msgid="6409794597405184510">"Mappen blev oprettet"</string>
+ <string name="action_move_to_workspace" msgid="1603837886334246317">"Flyt til startskærmen"</string>
+ <string name="action_move_screen_left" msgid="8854216831569401665">"Flyt skærmen til venstre"</string>
+ <string name="action_move_screen_right" msgid="329334910274311123">"Flyt skærmen til højre"</string>
+ <string name="screen_moved" msgid="266230079505650577">"Skærmen er flyttet"</string>
+ <string name="action_resize" msgid="1802976324781771067">"Tilpas størrelse"</string>
+ <string name="action_increase_width" msgid="8773715375078513326">"Øg bredden"</string>
+ <string name="action_increase_height" msgid="459390020612501122">"Øg højden"</string>
+ <string name="action_decrease_width" msgid="1374549771083094654">"Reducer bredden"</string>
+ <string name="action_decrease_height" msgid="282377193880900022">"Reducer højden"</string>
+ <string name="widget_resized" msgid="9130327887929620">"Størrelsen for widgetten er ændret til bredde <xliff:g id="NUMBER_0">%1$s</xliff:g> og højde <xliff:g id="NUMBER_1">%2$s</xliff:g>"</string>
</resources>
diff --git a/res/values-de/strings.xml b/res/values-de/strings.xml
index 059983ecf..ac6f76b0c 100644
--- a/res/values-de/strings.xml
+++ b/res/values-de/strings.xml
@@ -20,57 +20,27 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="application_name" msgid="5181331383435256801">"Launcher3"</string>
- <string name="home" msgid="7658288663002113681">"Startseite"</string>
- <string name="uid_name" msgid="7820867637514617527">"Android Core Apps"</string>
<string name="folder_name" msgid="7371454440695724752"></string>
+ <string name="work_folder_name" msgid="3753320833950115786">"Arbeit"</string>
<string name="activity_not_found" msgid="8071924732094499514">"App ist nicht installiert."</string>
<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="widgets_tab_label" msgid="2921133187116603919">"Widgets"</string>
- <string name="widget_adder" msgid="3201040140710381657">"Widgets"</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="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
- <string name="external_drop_widget_error" msgid="3165821058322217155">"Element wurde nicht auf diesem Startbildschirm abgelegt."</string>
- <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Widget zum Erstellen auswählen"</string>
- <string name="rename_folder_label" msgid="3727762225964550653">"Ordnername"</string>
- <string name="rename_folder_title" msgid="3771389277707820891">"Ordner umbenennen"</string>
- <string name="rename_action" msgid="5559600076028658757">"OK"</string>
- <string name="cancel_action" msgid="7009134900002915310">"Abbrechen"</string>
- <string name="menu_item_add_item" msgid="1264911265836810421">"Zum Startbildschirm hinzufügen"</string>
- <string name="group_applications" msgid="3797214114206693605">"Apps"</string>
- <string name="group_shortcuts" msgid="6012256992764410535">"Verknüpfungen"</string>
- <string name="group_widgets" msgid="1569030723286851002">"Widgets"</string>
- <string name="completely_out_of_space" msgid="6106288382070760318">"Auf Ihren Startbildschirmen ist kein Platz mehr vorhanden."</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>
+ <string name="all_apps_no_search_results" msgid="6332185285860416787">"Keine Apps für \"<xliff:g id="QUERY">%1$s</xliff:g>\" gefunden"</string>
<string name="out_of_space" msgid="4691004494942118364">"Auf diesem Startbildschirm ist kein Platz mehr vorhanden."</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"Ablage \"Favoriten\" ist voll."</string>
- <string name="invalid_hotseat_item" msgid="5779907847267573691">"Dieses Widget ist zu groß für die Ablage \"Favoriten\"."</string>
- <string name="shortcut_installed" msgid="1701742129426969556">"Verknüpfung \"<xliff:g id="NAME">%s</xliff:g>\" wurde erstellt."</string>
- <string name="shortcut_uninstalled" msgid="8176767991305701821">"Verknüpfung \"<xliff:g id="NAME">%s</xliff:g>\" wurde entfernt."</string>
- <string name="shortcut_duplicate" msgid="9167217446062498127">"Verknüpfung \"<xliff:g id="NAME">%s</xliff:g>\" ist bereits vorhanden."</string>
- <string name="title_select_shortcut" msgid="6680642571148153868">"Verknüpfung auswählen"</string>
- <string name="title_select_application" msgid="3280812711670683644">"App auswählen"</string>
<string name="all_apps_button_label" msgid="9110807029020582876">"Apps"</string>
<string name="all_apps_home_button_label" msgid="252062713717058851">"Startseite"</string>
- <string name="delete_zone_label_workspace" msgid="4009607676751398685">"Entfernen"</string>
- <string name="delete_zone_label_all_apps" msgid="8083826390278958980">"Deinstallieren"</string>
<string name="delete_target_label" msgid="1822697352535677073">"Entfernen"</string>
<string name="delete_target_uninstall_label" msgid="5100785476250872595">"Deinstallieren"</string>
<string name="info_target_label" msgid="8053346143994679532">"App-Info"</string>
- <string name="accessibility_all_apps_button" msgid="2603132375383800483">"Apps"</string>
- <string name="accessibility_delete_button" msgid="6466114477993744621">"Entfernen"</string>
- <string name="delete_zone_label_all_apps_system_app" msgid="449755632749610895">"Update deinstallieren"</string>
- <string name="cab_menu_delete_app" msgid="7435191475867183689">"App deinstallieren"</string>
- <string name="cab_menu_app_info" msgid="8593722221450362342">"App-Details"</string>
- <string name="cab_app_selection_text" msgid="374688303047985416">"1 App ausgewählt"</string>
- <string name="cab_widget_selection_text" msgid="1833458597831541241">"1 Widget ausgewählt"</string>
- <string name="cab_folder_selection_text" msgid="7999992513806132118">"1 Ordner ausgewählt"</string>
- <string name="cab_shortcut_selection_text" msgid="2103811025667946450">"1 Verknüpfung ausgewählt"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"Verknüpfungen installieren"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"Ermöglicht einer App das Hinzufügen von Verknüpfungen ohne Eingreifen des Nutzers"</string>
- <string name="permlab_uninstall_shortcut" msgid="864595034498083837">"Verknüpfungen deinstallieren"</string>
- <string name="permdesc_uninstall_shortcut" msgid="5134129545001836849">"Ermöglicht einer App das Entfernen von Verknüpfungen ohne Eingreifen des Nutzers"</string>
<string name="permlab_read_settings" msgid="1941457408239617576">"Einstellungen und Verknüpfungen auf dem Startbildschirm lesen"</string>
<string name="permdesc_read_settings" msgid="5833423719057558387">"Ermöglicht der App, die Einstellungen und Verknüpfungen auf dem Startbildschirm zu lesen"</string>
<string name="permlab_write_settings" msgid="3574213698004620587">"Einstellungen und Verknüpfungen für den Startbildschirm schreiben"</string>
@@ -78,30 +48,17 @@
<string name="gadget_error_text" msgid="6081085226050792095">"Problem beim Laden des Widgets"</string>
<string name="gadget_setup_text" msgid="8274003207686040488">"Einrichten"</string>
<string name="uninstall_system_app_text" msgid="4172046090762920660">"Dies ist eine Systemanwendung, die nicht deinstalliert werden kann."</string>
- <string name="dream_name" msgid="1530253749244328964">"Rocket Launcher"</string>
<string name="folder_hint_text" msgid="6617836969016293992">"Unbenannter Ordner"</string>
- <string name="workspace_description_format" msgid="2950174241104043327">"Startbildschirm %1$d"</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="apps_customize_apps_scroll_format" msgid="370005296147130238">"Apps-Seite %1$d von %2$d"</string>
- <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"Widgets-Seite %1$d von %2$d"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"Hallo!"</string>
- <string name="first_run_cling_description" msgid="6447072552696253358">"Gerät personalisieren"</string>
- <string name="first_run_cling_custom_content_hint" msgid="6090628589029352439"></string>
- <string name="first_run_cling_search_bar_hint" msgid="5909062802402452582"></string>
- <string name="first_run_cling_create_screens_hint" msgid="6950729526680114157">"Mehr Bildschirme für Apps und Ordner erstellen"</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>
<string name="migration_cling_copy_apps" msgid="946331230090919440">"Symbole kopieren"</string>
<string name="migration_cling_use_default" msgid="2626475813981258626">"Standardübersicht verwenden"</string>
- <string name="workspace_cling_title" msgid="5626202359865825661">"Arbeitsbereich organisieren"</string>
- <string name="workspace_cling_move_item" msgid="528201129978005352">"Hintergrund berühren und halten, um Hintergrund, Widgets und Einstellungen zu verwalten"</string>
<string name="workspace_cling_longpress_title" msgid="9173998993909018310">"Hintergründe, Widgets &amp; Einstellungen"</string>
<string name="workspace_cling_longpress_description" msgid="4119994475505235248">"Berühren und halten Sie den Hintergrund, um ihn anzupassen."</string>
<string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"OK"</string>
- <string name="folder_cling_title" msgid="3894908818693254164">"Hier ist ein Ordner"</string>
- <string name="folder_cling_create_folder" msgid="6158215559475836131">"Um einen Ordner zu erstellen, berühren und halten Sie eine App und verschieben Sie sie auf eine andere."</string>
- <string name="cling_dismiss" msgid="8962359497601507581">"OK"</string>
<string name="folder_opened" msgid="94695026776264709">"Ordner geöffnet, <xliff:g id="WIDTH">%1$d</xliff:g> x <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
<string name="folder_tap_to_close" msgid="1884479294466410023">"Ordner durch Berühren schließen"</string>
<string name="folder_tap_to_rename" msgid="9191075570492871147">"Umbenennung durch Berühren speichern"</string>
@@ -111,14 +68,34 @@
<string name="widget_button_text" msgid="2880537293434387943">"Widgets"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"Hintergründe"</string>
<string name="settings_button_text" msgid="8119458837558863227">"Einstellungen"</string>
- <string name="package_state_enqueued" msgid="6227252464303085641">"Warten"</string>
- <string name="package_state_downloading" msgid="4088770468458724721">"Download läuft"</string>
- <string name="package_state_installing" msgid="7588193972189849870">"Installation"</string>
+ <string name="allow_rotation_title" msgid="2118706734511831751">"Drehung zulassen"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Unbekannt"</string>
- <string name="package_state_error" msgid="7672093962724223588">"Nicht wiederhergestellt"</string>
- <string name="abandoned_clean_all" msgid="5256770727689657618">"Alle entfernen"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Entfernen"</string>
<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="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>
+ <string name="item_removed" msgid="851119963877842327">"Element entfernt"</string>
+ <string name="action_move" msgid="4339390619886385032">"Element verschieben"</string>
+ <string name="move_to_empty_cell" msgid="2833711483015685619">"In Zeile <xliff:g id="NUMBER_0">%1$s</xliff:g>, Spalte <xliff:g id="NUMBER_1">%2$s</xliff:g> verschoben"</string>
+ <string name="move_to_position" msgid="6750008980455459790">"Auf Position <xliff:g id="NUMBER">%1$s</xliff:g> verschoben"</string>
+ <string name="move_to_hotseat_position" msgid="6295412897075147808">"Auf Favoritenposition <xliff:g id="NUMBER">%1$s</xliff:g> verschoben"</string>
+ <string name="item_moved" msgid="4606538322571412879">"Element verschoben"</string>
+ <string name="add_to_folder" msgid="9040534766770853243">"Zum Ordner \"<xliff:g id="NAME">%1$s</xliff:g>\" hinzufügen"</string>
+ <string name="add_to_folder_with_app" msgid="4534929978967147231">"Zum Ordner hinzufügen, in dem sich <xliff:g id="NAME">%1$s</xliff:g> befindet"</string>
+ <string name="added_to_folder" msgid="4793259502305558003">"Element zum Ordner hinzugefügt"</string>
+ <string name="create_folder_with" msgid="4050141361160214248">"Anhand von <xliff:g id="NAME">%1$s</xliff:g> Ordner erstellen"</string>
+ <string name="folder_created" msgid="6409794597405184510">"Ordner erstellt"</string>
+ <string name="action_move_to_workspace" msgid="1603837886334246317">"Auf Startbildschirm verschieben"</string>
+ <string name="action_move_screen_left" msgid="8854216831569401665">"Bildschirm nach links"</string>
+ <string name="action_move_screen_right" msgid="329334910274311123">"Bildschirm nach rechts"</string>
+ <string name="screen_moved" msgid="266230079505650577">"Bildschirm verschoben"</string>
+ <string name="action_resize" msgid="1802976324781771067">"Größe anpassen"</string>
+ <string name="action_increase_width" msgid="8773715375078513326">"Breite vergrößern"</string>
+ <string name="action_increase_height" msgid="459390020612501122">"Höhe vergrößern"</string>
+ <string name="action_decrease_width" msgid="1374549771083094654">"Breite verringern"</string>
+ <string name="action_decrease_height" msgid="282377193880900022">"Höhe verringern"</string>
+ <string name="widget_resized" msgid="9130327887929620">"Größe des Widgets zu Breite <xliff:g id="NUMBER_0">%1$s</xliff:g> und Höhe <xliff:g id="NUMBER_1">%2$s</xliff:g> geändert"</string>
</resources>
diff --git a/res/values-el/strings.xml b/res/values-el/strings.xml
index 7e5989d3e..a60458a97 100644
--- a/res/values-el/strings.xml
+++ b/res/values-el/strings.xml
@@ -20,57 +20,27 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="application_name" msgid="5181331383435256801">"Launcher3"</string>
- <string name="home" msgid="7658288663002113681">"Αρχική οθόνη"</string>
- <string name="uid_name" msgid="7820867637514617527">"Βασικές εφαρμογές Android"</string>
<string name="folder_name" msgid="7371454440695724752"></string>
+ <string name="work_folder_name" msgid="3753320833950115786">"Εργασία"</string>
<string name="activity_not_found" msgid="8071924732094499514">"Η εφαρμογή δεν έχει εγκατασταθεί."</string>
<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="widgets_tab_label" msgid="2921133187116603919">"Γραφικά στοιχεία"</string>
- <string name="widget_adder" msgid="3201040140710381657">"Γραφικά στοιχεία"</string>
<string name="toggle_weight_watcher" msgid="5645299835184636119">"Εμφάνιση Mem"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"Αγγίξτε παρατεταμένα για να πάρετε ένα γραφ.στοιχ."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
- <string name="external_drop_widget_error" msgid="3165821058322217155">"Αδυναμία τοποθέτησης στοιχείου στην Αρχική οθόνη."</string>
- <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Επιλ. γραφ. στοιχείο για δημιουργία"</string>
- <string name="rename_folder_label" msgid="3727762225964550653">"Όνομα φακέλου"</string>
- <string name="rename_folder_title" msgid="3771389277707820891">"Μετονομασία φακέλου"</string>
- <string name="rename_action" msgid="5559600076028658757">"OK"</string>
- <string name="cancel_action" msgid="7009134900002915310">"Ακύρωση"</string>
- <string name="menu_item_add_item" msgid="1264911265836810421">"Προσθήκη στην αρχική οθόνη"</string>
- <string name="group_applications" msgid="3797214114206693605">"Εφαρμογές"</string>
- <string name="group_shortcuts" msgid="6012256992764410535">"Συντομεύσεις"</string>
- <string name="group_widgets" msgid="1569030723286851002">"Γραφικά στοιχεία"</string>
- <string name="completely_out_of_space" msgid="6106288382070760318">"Δεν υπάρχει άλλος χώρος στις Αρχικές οθόνες σας."</string>
+ <string name="all_apps_search_bar_hint" msgid="7084713969757597256">"Αναζήτηση εφαρμογών"</string>
+ <string name="all_apps_loading_message" msgid="7557140873644765180">"Φόρτωση εφαρμογών…"</string>
+ <string name="all_apps_no_search_results" msgid="6332185285860416787">"Δεν βρέθηκαν εφαρμογές για το ερώτημα \"<xliff:g id="QUERY">%1$s</xliff:g>\""</string>
<string name="out_of_space" msgid="4691004494942118364">"Δεν υπάρχει χώρος σε αυτήν την αρχική οθόνη."</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"Δεν υπάρχει επιπλέον χώρος στην περιοχή Αγαπημένα"</string>
- <string name="invalid_hotseat_item" msgid="5779907847267573691">"Αυτό το γραφικό στοιχείο είναι πολύ μεγάλο για την περιοχή Αγαπημένα."</string>
- <string name="shortcut_installed" msgid="1701742129426969556">"Δημιουργήθηκε η συντόμευση \"<xliff:g id="NAME">%s</xliff:g>\"."</string>
- <string name="shortcut_uninstalled" msgid="8176767991305701821">"Η συντόμευση \"<xliff:g id="NAME">%s</xliff:g>\" καταργήθηκε."</string>
- <string name="shortcut_duplicate" msgid="9167217446062498127">"Η συντόμευση \"<xliff:g id="NAME">%s</xliff:g>\" υπάρχει ήδη."</string>
- <string name="title_select_shortcut" msgid="6680642571148153868">"Επιλογή συντόμευσης"</string>
- <string name="title_select_application" msgid="3280812711670683644">"Επιλογή εφαρμογής"</string>
<string name="all_apps_button_label" msgid="9110807029020582876">"Εφαρμογές"</string>
<string name="all_apps_home_button_label" msgid="252062713717058851">"Αρχική οθόνη"</string>
- <string name="delete_zone_label_workspace" msgid="4009607676751398685">"Κατάργηση"</string>
- <string name="delete_zone_label_all_apps" msgid="8083826390278958980">"Κατάργηση εγκατάστασης"</string>
<string name="delete_target_label" msgid="1822697352535677073">"Κατάργηση"</string>
<string name="delete_target_uninstall_label" msgid="5100785476250872595">"Κατάργηση εγκατάστασης"</string>
<string name="info_target_label" msgid="8053346143994679532">"Πληροφορίες εφαρμογής"</string>
- <string name="accessibility_all_apps_button" msgid="2603132375383800483">"Εφαρμογές"</string>
- <string name="accessibility_delete_button" msgid="6466114477993744621">"Κατάργηση"</string>
- <string name="delete_zone_label_all_apps_system_app" msgid="449755632749610895">"Κατάργηση εγκατάστασης ενημέρωσης"</string>
- <string name="cab_menu_delete_app" msgid="7435191475867183689">"Κατάργηση εγκατάστασης εφαρμογής"</string>
- <string name="cab_menu_app_info" msgid="8593722221450362342">"Λεπτομέρειες εφαρμογής"</string>
- <string name="cab_app_selection_text" msgid="374688303047985416">"Επιλέχτηκε 1 εφαρμογή"</string>
- <string name="cab_widget_selection_text" msgid="1833458597831541241">"Επιλέχτηκε 1 γραφικό στοιχείο"</string>
- <string name="cab_folder_selection_text" msgid="7999992513806132118">"Επιλέχτηκε 1 φάκελος"</string>
- <string name="cab_shortcut_selection_text" msgid="2103811025667946450">"Επιλέχτηκε 1 συντόμευση"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"εγκατάσταση συντομεύσεων"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"Επιτρέπει σε μια εφαρμογή την προσθήκη συντομεύσεων χωρίς την παρέμβαση του χρήστη."</string>
- <string name="permlab_uninstall_shortcut" msgid="864595034498083837">"κατάργηση εγκατάστασης συντομεύσεων"</string>
- <string name="permdesc_uninstall_shortcut" msgid="5134129545001836849">"Επιτρέπει στην εφαρμογή την κατάργηση συντομεύσεων χωρίς την παρέμβαση του χρήστη."</string>
<string name="permlab_read_settings" msgid="1941457408239617576">"ανάγνωση ρυθμίσεων και συντομεύσεων αρχικής οθόνης"</string>
<string name="permdesc_read_settings" msgid="5833423719057558387">"Επιτρέπει στην εφαρμογή την ανάγνωση των ρυθμίσεων και των συντομεύσεων στην Αρχική οθόνη."</string>
<string name="permlab_write_settings" msgid="3574213698004620587">"εγγραφή ρυθμίσεων και συντομεύσεων αρχικής οθόνης"</string>
@@ -78,30 +48,17 @@
<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>
- <string name="dream_name" msgid="1530253749244328964">"Rocket Launcher"</string>
<string name="folder_hint_text" msgid="6617836969016293992">"Φάκελος χωρίς όνομα"</string>
- <string name="workspace_description_format" msgid="2950174241104043327">"Αρχική οθόνη %1$d"</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="apps_customize_apps_scroll_format" msgid="370005296147130238">"Σελίδα εφαρμογών %1$d από %2$d"</string>
- <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"Σελίδα γραφικών στοιχείων %1$d από %2$d"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"Καλώς ορίσατε"</string>
- <string name="first_run_cling_description" msgid="6447072552696253358">"Νιώστε σαν στο σπίτι σας."</string>
- <string name="first_run_cling_custom_content_hint" msgid="6090628589029352439"></string>
- <string name="first_run_cling_search_bar_hint" msgid="5909062802402452582"></string>
- <string name="first_run_cling_create_screens_hint" msgid="6950729526680114157">"Δημιουργία περισσότερων οθονών για εφαρμογές και φακέλους"</string>
<string name="migration_cling_title" msgid="9181776667882933767">"Αντιγραφή εικονιδίων εφαρμογών"</string>
<string name="migration_cling_description" msgid="2752413805582227644">"Εισαγωγή εικονιδίων και φακέλων από παλιές αρχικές οθόνες;"</string>
<string name="migration_cling_copy_apps" msgid="946331230090919440">"ΑΝΤΙΓΡΑΦΗ ΕΙΚΟΝΙΔΙΩΝ"</string>
<string name="migration_cling_use_default" msgid="2626475813981258626">"ΝΕΑ ΕΝΑΡΞΗ"</string>
- <string name="workspace_cling_title" msgid="5626202359865825661">"Οργανώστε το χώρο σας"</string>
- <string name="workspace_cling_move_item" msgid="528201129978005352">"Αγγίξτε παρατεταμένα το φόντο για να διαχειριστείτε την ταπετσαρία, τα γραφικά στοιχεία και τις ρυθμίσεις."</string>
<string name="workspace_cling_longpress_title" msgid="9173998993909018310">"Ταπετσαρίες, γραφικά στοιχεία και ρυθμίσεις"</string>
<string name="workspace_cling_longpress_description" msgid="4119994475505235248">"Αγγίξτε παρατεταμένα το παρασκήνιο για προσαρμογή"</string>
<string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"ΕΓΙΝΕ"</string>
- <string name="folder_cling_title" msgid="3894908818693254164">"Ορίστε ένας φάκελος"</string>
- <string name="folder_cling_create_folder" msgid="6158215559475836131">"Για να δημιουργήσετε έναν φάκελο σαν κι αυτόν, πατήστε παρατεταμένα μια εφαρμογή και στη συνέχεια, μετακινήστε τη πάνω σε μια άλλη."</string>
- <string name="cling_dismiss" msgid="8962359497601507581">"OK"</string>
<string name="folder_opened" msgid="94695026776264709">"Άνοιγμα φακέλου, <xliff:g id="WIDTH">%1$d</xliff:g> επί <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
<string name="folder_tap_to_close" msgid="1884479294466410023">"Αγγίξτε για να κλείσετε τον φάκελο"</string>
<string name="folder_tap_to_rename" msgid="9191075570492871147">"Αγγίξτε για να αποθηκεύσετε το νέο όνομα"</string>
@@ -111,14 +68,34 @@
<string name="widget_button_text" msgid="2880537293434387943">"Γραφικά στοιχεία"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"Ταπετσαρίες"</string>
<string name="settings_button_text" msgid="8119458837558863227">"Ρυθμίσεις"</string>
- <string name="package_state_enqueued" msgid="6227252464303085641">"Αναμονή"</string>
- <string name="package_state_downloading" msgid="4088770468458724721">"Λήψη "</string>
- <string name="package_state_installing" msgid="7588193972189849870">"Εγκατάσταση"</string>
+ <string name="allow_rotation_title" msgid="2118706734511831751">"Να επιτρέπεται η περιστροφή"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Άγνωστο"</string>
- <string name="package_state_error" msgid="7672093962724223588">"Δεν ανακτήθηκε"</string>
- <string name="abandoned_clean_all" msgid="5256770727689657618">"Κατάργηση όλων"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Κατάργηση"</string>
<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="action_add_to_workspace" msgid="8902165848117513641">"Προσθήκη στην αρχική οθόνη"</string>
+ <string name="action_move_here" msgid="2170188780612570250">"Μετακίνηση στοιχείου εδώ"</string>
+ <string name="item_added_to_workspace" msgid="4211073925752213539">"Το στοιχείο προστέθηκε στην αρχική οθόνη"</string>
+ <string name="item_removed" msgid="851119963877842327">"Το στοιχείο καταργήθηκε"</string>
+ <string name="action_move" msgid="4339390619886385032">"Μετακίνηση στοιχείου"</string>
+ <string name="move_to_empty_cell" msgid="2833711483015685619">"Μετακίνηση στη σειρά <xliff:g id="NUMBER_0">%1$s</xliff:g>, στήλη <xliff:g id="NUMBER_1">%2$s</xliff:g>"</string>
+ <string name="move_to_position" msgid="6750008980455459790">"Μετακίνηση στη θέση <xliff:g id="NUMBER">%1$s</xliff:g>"</string>
+ <string name="move_to_hotseat_position" msgid="6295412897075147808">"Μετακίνηση στη θέση <xliff:g id="NUMBER">%1$s</xliff:g> στα αγαπημένα"</string>
+ <string name="item_moved" msgid="4606538322571412879">"Το στοιχείο καταργήθηκε"</string>
+ <string name="add_to_folder" msgid="9040534766770853243">"Προσθήκη στο φάκελο: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="add_to_folder_with_app" msgid="4534929978967147231">"Προσθήκη στο φάκελο με την εφαρμογή <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="added_to_folder" msgid="4793259502305558003">"Το στοιχείο προστέθηκε στο φάκελο"</string>
+ <string name="create_folder_with" msgid="4050141361160214248">"Δημιουργία φακέλου με: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="folder_created" msgid="6409794597405184510">"Δημιουργήθηκε φάκελος"</string>
+ <string name="action_move_to_workspace" msgid="1603837886334246317">"Μετακίνηση Αρχικής οθόνης"</string>
+ <string name="action_move_screen_left" msgid="8854216831569401665">"Μετακίνηση οθόνης αριστερά"</string>
+ <string name="action_move_screen_right" msgid="329334910274311123">"Μετακίνηση οθόνης δεξιά"</string>
+ <string name="screen_moved" msgid="266230079505650577">"Η οθόνη μετακινήθηκε"</string>
+ <string name="action_resize" msgid="1802976324781771067">"Προσαρμογή μεγέθους"</string>
+ <string name="action_increase_width" msgid="8773715375078513326">"Αύξηση του πλάτους"</string>
+ <string name="action_increase_height" msgid="459390020612501122">"Αύξηση του ύψους"</string>
+ <string name="action_decrease_width" msgid="1374549771083094654">"μείωση του πλάτους"</string>
+ <string name="action_decrease_height" msgid="282377193880900022">"Μείωση του ύψους"</string>
+ <string name="widget_resized" msgid="9130327887929620">"Έγινε προσαρμογή του μεγέθους του γραφικού στοιχείου σε <xliff:g id="NUMBER_0">%1$s</xliff:g> πλάτος και <xliff:g id="NUMBER_1">%2$s</xliff:g> ύψος"</string>
</resources>
diff --git a/res/values-en-rAU/strings.xml b/res/values-en-rAU/strings.xml
index 0d004fef5..09963e422 100644
--- a/res/values-en-rAU/strings.xml
+++ b/res/values-en-rAU/strings.xml
@@ -20,57 +20,27 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="application_name" msgid="5181331383435256801">"Launcher3"</string>
- <string name="home" msgid="7658288663002113681">"Home"</string>
- <string name="uid_name" msgid="7820867637514617527">"Android Core Apps"</string>
<string name="folder_name" msgid="7371454440695724752"></string>
+ <string name="work_folder_name" msgid="3753320833950115786">"Work"</string>
<string name="activity_not_found" msgid="8071924732094499514">"App isn\'t installed."</string>
<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="widgets_tab_label" msgid="2921133187116603919">"Widgets"</string>
- <string name="widget_adder" msgid="3201040140710381657">"Widgets"</string>
<string name="toggle_weight_watcher" msgid="5645299835184636119">"Show Mem"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"Touch &amp; hold to pick up a widget."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
- <string name="external_drop_widget_error" msgid="3165821058322217155">"Couldn\'t drop item on this Home screen."</string>
- <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Choose widget to create"</string>
- <string name="rename_folder_label" msgid="3727762225964550653">"Folder name"</string>
- <string name="rename_folder_title" msgid="3771389277707820891">"Rename folder"</string>
- <string name="rename_action" msgid="5559600076028658757">"OK"</string>
- <string name="cancel_action" msgid="7009134900002915310">"Cancel"</string>
- <string name="menu_item_add_item" msgid="1264911265836810421">"Add to Home screen"</string>
- <string name="group_applications" msgid="3797214114206693605">"Apps"</string>
- <string name="group_shortcuts" msgid="6012256992764410535">"Shortcuts"</string>
- <string name="group_widgets" msgid="1569030723286851002">"Widgets"</string>
- <string name="completely_out_of_space" msgid="6106288382070760318">"No more room on your Home screens."</string>
+ <string name="all_apps_search_bar_hint" msgid="7084713969757597256">"Search Apps"</string>
+ <string name="all_apps_loading_message" msgid="7557140873644765180">"Loading Apps…"</string>
+ <string name="all_apps_no_search_results" msgid="6332185285860416787">"No Apps found matching \"<xliff:g id="QUERY">%1$s</xliff:g>\""</string>
<string name="out_of_space" msgid="4691004494942118364">"No more room on this Home screen."</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"No more room in the Favourites tray"</string>
- <string name="invalid_hotseat_item" msgid="5779907847267573691">"This widget is too large for the Favourites tray"</string>
- <string name="shortcut_installed" msgid="1701742129426969556">"Shortcut \"<xliff:g id="NAME">%s</xliff:g>\" created."</string>
- <string name="shortcut_uninstalled" msgid="8176767991305701821">"Shortcut \"<xliff:g id="NAME">%s</xliff:g>\" was removed."</string>
- <string name="shortcut_duplicate" msgid="9167217446062498127">"Shortcut \"<xliff:g id="NAME">%s</xliff:g>\" already exists."</string>
- <string name="title_select_shortcut" msgid="6680642571148153868">"Choose shortcut"</string>
- <string name="title_select_application" msgid="3280812711670683644">"Choose app"</string>
<string name="all_apps_button_label" msgid="9110807029020582876">"Apps"</string>
<string name="all_apps_home_button_label" msgid="252062713717058851">"Home"</string>
- <string name="delete_zone_label_workspace" msgid="4009607676751398685">"Remove"</string>
- <string name="delete_zone_label_all_apps" msgid="8083826390278958980">"Uninstall"</string>
<string name="delete_target_label" msgid="1822697352535677073">"Remove"</string>
<string name="delete_target_uninstall_label" msgid="5100785476250872595">"Uninstall"</string>
<string name="info_target_label" msgid="8053346143994679532">"App info"</string>
- <string name="accessibility_all_apps_button" msgid="2603132375383800483">"Apps"</string>
- <string name="accessibility_delete_button" msgid="6466114477993744621">"Remove"</string>
- <string name="delete_zone_label_all_apps_system_app" msgid="449755632749610895">"Uninstall update"</string>
- <string name="cab_menu_delete_app" msgid="7435191475867183689">"Uninstall app"</string>
- <string name="cab_menu_app_info" msgid="8593722221450362342">"App details"</string>
- <string name="cab_app_selection_text" msgid="374688303047985416">"1 app selected"</string>
- <string name="cab_widget_selection_text" msgid="1833458597831541241">"1 widget selected"</string>
- <string name="cab_folder_selection_text" msgid="7999992513806132118">"1 folder selected"</string>
- <string name="cab_shortcut_selection_text" msgid="2103811025667946450">"1 shortcut selected"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"install shortcuts"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"Allows an app to add shortcuts without user intervention."</string>
- <string name="permlab_uninstall_shortcut" msgid="864595034498083837">"uninstall shortcuts"</string>
- <string name="permdesc_uninstall_shortcut" msgid="5134129545001836849">"Allows the app to remove shortcuts without user intervention."</string>
<string name="permlab_read_settings" msgid="1941457408239617576">"read Home settings and shortcuts"</string>
<string name="permdesc_read_settings" msgid="5833423719057558387">"Allows the app to read the settings and shortcuts in Home."</string>
<string name="permlab_write_settings" msgid="3574213698004620587">"write Home settings and shortcuts"</string>
@@ -78,30 +48,17 @@
<string name="gadget_error_text" msgid="6081085226050792095">"Problem loading widget"</string>
<string name="gadget_setup_text" msgid="8274003207686040488">"Setup"</string>
<string name="uninstall_system_app_text" msgid="4172046090762920660">"This is a system app and can\'t be uninstalled."</string>
- <string name="dream_name" msgid="1530253749244328964">"Rocket Launcher"</string>
<string name="folder_hint_text" msgid="6617836969016293992">"Unnamed Folder"</string>
- <string name="workspace_description_format" msgid="2950174241104043327">"Home screen %1$d"</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="apps_customize_apps_scroll_format" msgid="370005296147130238">"Apps page %1$d of %2$d"</string>
- <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"Widgets page %1$d of %2$d"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"Welcome"</string>
- <string name="first_run_cling_description" msgid="6447072552696253358">"Make yourself at home."</string>
- <string name="first_run_cling_custom_content_hint" msgid="6090628589029352439"></string>
- <string name="first_run_cling_search_bar_hint" msgid="5909062802402452582"></string>
- <string name="first_run_cling_create_screens_hint" msgid="6950729526680114157">"Create more screens for apps and folders"</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>
<string name="migration_cling_copy_apps" msgid="946331230090919440">"COPY ICONS"</string>
<string name="migration_cling_use_default" msgid="2626475813981258626">"START AFRESH"</string>
- <string name="workspace_cling_title" msgid="5626202359865825661">"Organise your space"</string>
- <string name="workspace_cling_move_item" msgid="528201129978005352">"Touch &amp; hold background to manage wallpaper, widgets and settings."</string>
<string name="workspace_cling_longpress_title" msgid="9173998993909018310">"Wallpapers, widgets, &amp; settings"</string>
<string name="workspace_cling_longpress_description" msgid="4119994475505235248">"Touch &amp; hold background to customise"</string>
<string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"GOT IT"</string>
- <string name="folder_cling_title" msgid="3894908818693254164">"Here\'s a folder"</string>
- <string name="folder_cling_create_folder" msgid="6158215559475836131">"To create one like this, touch &amp; hold an app, then move it over another."</string>
- <string name="cling_dismiss" msgid="8962359497601507581">"OK"</string>
<string name="folder_opened" msgid="94695026776264709">"Folder opened, <xliff:g id="WIDTH">%1$d</xliff:g> by <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
<string name="folder_tap_to_close" msgid="1884479294466410023">"Touch to close folder"</string>
<string name="folder_tap_to_rename" msgid="9191075570492871147">"Touch to save rename"</string>
@@ -111,14 +68,34 @@
<string name="widget_button_text" msgid="2880537293434387943">"Widgets"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"Wallpapers"</string>
<string name="settings_button_text" msgid="8119458837558863227">"Settings"</string>
- <string name="package_state_enqueued" msgid="6227252464303085641">"Waiting"</string>
- <string name="package_state_downloading" msgid="4088770468458724721">"Downloading"</string>
- <string name="package_state_installing" msgid="7588193972189849870">"Installing"</string>
+ <string name="allow_rotation_title" msgid="2118706734511831751">"Allow rotation"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Unknown"</string>
- <string name="package_state_error" msgid="7672093962724223588">"Not restored"</string>
- <string name="abandoned_clean_all" msgid="5256770727689657618">"Remove All"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Remove"</string>
<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="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>
+ <string name="item_removed" msgid="851119963877842327">"Item removed"</string>
+ <string name="action_move" msgid="4339390619886385032">"Move item"</string>
+ <string name="move_to_empty_cell" msgid="2833711483015685619">"Move to row <xliff:g id="NUMBER_0">%1$s</xliff:g> column <xliff:g id="NUMBER_1">%2$s</xliff:g>"</string>
+ <string name="move_to_position" msgid="6750008980455459790">"Move to position <xliff:g id="NUMBER">%1$s</xliff:g>"</string>
+ <string name="move_to_hotseat_position" msgid="6295412897075147808">"Move to favourites position <xliff:g id="NUMBER">%1$s</xliff:g>"</string>
+ <string name="item_moved" msgid="4606538322571412879">"Item moved"</string>
+ <string name="add_to_folder" msgid="9040534766770853243">"Add to folder: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="add_to_folder_with_app" msgid="4534929978967147231">"Add to folder with <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="added_to_folder" msgid="4793259502305558003">"Item added to folder"</string>
+ <string name="create_folder_with" msgid="4050141361160214248">"Create folder with: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="folder_created" msgid="6409794597405184510">"Folder created"</string>
+ <string name="action_move_to_workspace" msgid="1603837886334246317">"Move to Home screen"</string>
+ <string name="action_move_screen_left" msgid="8854216831569401665">"Move screen to left"</string>
+ <string name="action_move_screen_right" msgid="329334910274311123">"Move screen to right"</string>
+ <string name="screen_moved" msgid="266230079505650577">"Screen moved"</string>
+ <string name="action_resize" msgid="1802976324781771067">"Re-size"</string>
+ <string name="action_increase_width" msgid="8773715375078513326">"Increase width"</string>
+ <string name="action_increase_height" msgid="459390020612501122">"Increase height"</string>
+ <string name="action_decrease_width" msgid="1374549771083094654">"Decrease width"</string>
+ <string name="action_decrease_height" msgid="282377193880900022">"Decrease height"</string>
+ <string name="widget_resized" msgid="9130327887929620">"Widget re-sized to width <xliff:g id="NUMBER_0">%1$s</xliff:g> height <xliff:g id="NUMBER_1">%2$s</xliff:g>"</string>
</resources>
diff --git a/res/values-en-rGB/strings.xml b/res/values-en-rGB/strings.xml
index 0d004fef5..09963e422 100644
--- a/res/values-en-rGB/strings.xml
+++ b/res/values-en-rGB/strings.xml
@@ -20,57 +20,27 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="application_name" msgid="5181331383435256801">"Launcher3"</string>
- <string name="home" msgid="7658288663002113681">"Home"</string>
- <string name="uid_name" msgid="7820867637514617527">"Android Core Apps"</string>
<string name="folder_name" msgid="7371454440695724752"></string>
+ <string name="work_folder_name" msgid="3753320833950115786">"Work"</string>
<string name="activity_not_found" msgid="8071924732094499514">"App isn\'t installed."</string>
<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="widgets_tab_label" msgid="2921133187116603919">"Widgets"</string>
- <string name="widget_adder" msgid="3201040140710381657">"Widgets"</string>
<string name="toggle_weight_watcher" msgid="5645299835184636119">"Show Mem"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"Touch &amp; hold to pick up a widget."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
- <string name="external_drop_widget_error" msgid="3165821058322217155">"Couldn\'t drop item on this Home screen."</string>
- <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Choose widget to create"</string>
- <string name="rename_folder_label" msgid="3727762225964550653">"Folder name"</string>
- <string name="rename_folder_title" msgid="3771389277707820891">"Rename folder"</string>
- <string name="rename_action" msgid="5559600076028658757">"OK"</string>
- <string name="cancel_action" msgid="7009134900002915310">"Cancel"</string>
- <string name="menu_item_add_item" msgid="1264911265836810421">"Add to Home screen"</string>
- <string name="group_applications" msgid="3797214114206693605">"Apps"</string>
- <string name="group_shortcuts" msgid="6012256992764410535">"Shortcuts"</string>
- <string name="group_widgets" msgid="1569030723286851002">"Widgets"</string>
- <string name="completely_out_of_space" msgid="6106288382070760318">"No more room on your Home screens."</string>
+ <string name="all_apps_search_bar_hint" msgid="7084713969757597256">"Search Apps"</string>
+ <string name="all_apps_loading_message" msgid="7557140873644765180">"Loading Apps…"</string>
+ <string name="all_apps_no_search_results" msgid="6332185285860416787">"No Apps found matching \"<xliff:g id="QUERY">%1$s</xliff:g>\""</string>
<string name="out_of_space" msgid="4691004494942118364">"No more room on this Home screen."</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"No more room in the Favourites tray"</string>
- <string name="invalid_hotseat_item" msgid="5779907847267573691">"This widget is too large for the Favourites tray"</string>
- <string name="shortcut_installed" msgid="1701742129426969556">"Shortcut \"<xliff:g id="NAME">%s</xliff:g>\" created."</string>
- <string name="shortcut_uninstalled" msgid="8176767991305701821">"Shortcut \"<xliff:g id="NAME">%s</xliff:g>\" was removed."</string>
- <string name="shortcut_duplicate" msgid="9167217446062498127">"Shortcut \"<xliff:g id="NAME">%s</xliff:g>\" already exists."</string>
- <string name="title_select_shortcut" msgid="6680642571148153868">"Choose shortcut"</string>
- <string name="title_select_application" msgid="3280812711670683644">"Choose app"</string>
<string name="all_apps_button_label" msgid="9110807029020582876">"Apps"</string>
<string name="all_apps_home_button_label" msgid="252062713717058851">"Home"</string>
- <string name="delete_zone_label_workspace" msgid="4009607676751398685">"Remove"</string>
- <string name="delete_zone_label_all_apps" msgid="8083826390278958980">"Uninstall"</string>
<string name="delete_target_label" msgid="1822697352535677073">"Remove"</string>
<string name="delete_target_uninstall_label" msgid="5100785476250872595">"Uninstall"</string>
<string name="info_target_label" msgid="8053346143994679532">"App info"</string>
- <string name="accessibility_all_apps_button" msgid="2603132375383800483">"Apps"</string>
- <string name="accessibility_delete_button" msgid="6466114477993744621">"Remove"</string>
- <string name="delete_zone_label_all_apps_system_app" msgid="449755632749610895">"Uninstall update"</string>
- <string name="cab_menu_delete_app" msgid="7435191475867183689">"Uninstall app"</string>
- <string name="cab_menu_app_info" msgid="8593722221450362342">"App details"</string>
- <string name="cab_app_selection_text" msgid="374688303047985416">"1 app selected"</string>
- <string name="cab_widget_selection_text" msgid="1833458597831541241">"1 widget selected"</string>
- <string name="cab_folder_selection_text" msgid="7999992513806132118">"1 folder selected"</string>
- <string name="cab_shortcut_selection_text" msgid="2103811025667946450">"1 shortcut selected"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"install shortcuts"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"Allows an app to add shortcuts without user intervention."</string>
- <string name="permlab_uninstall_shortcut" msgid="864595034498083837">"uninstall shortcuts"</string>
- <string name="permdesc_uninstall_shortcut" msgid="5134129545001836849">"Allows the app to remove shortcuts without user intervention."</string>
<string name="permlab_read_settings" msgid="1941457408239617576">"read Home settings and shortcuts"</string>
<string name="permdesc_read_settings" msgid="5833423719057558387">"Allows the app to read the settings and shortcuts in Home."</string>
<string name="permlab_write_settings" msgid="3574213698004620587">"write Home settings and shortcuts"</string>
@@ -78,30 +48,17 @@
<string name="gadget_error_text" msgid="6081085226050792095">"Problem loading widget"</string>
<string name="gadget_setup_text" msgid="8274003207686040488">"Setup"</string>
<string name="uninstall_system_app_text" msgid="4172046090762920660">"This is a system app and can\'t be uninstalled."</string>
- <string name="dream_name" msgid="1530253749244328964">"Rocket Launcher"</string>
<string name="folder_hint_text" msgid="6617836969016293992">"Unnamed Folder"</string>
- <string name="workspace_description_format" msgid="2950174241104043327">"Home screen %1$d"</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="apps_customize_apps_scroll_format" msgid="370005296147130238">"Apps page %1$d of %2$d"</string>
- <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"Widgets page %1$d of %2$d"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"Welcome"</string>
- <string name="first_run_cling_description" msgid="6447072552696253358">"Make yourself at home."</string>
- <string name="first_run_cling_custom_content_hint" msgid="6090628589029352439"></string>
- <string name="first_run_cling_search_bar_hint" msgid="5909062802402452582"></string>
- <string name="first_run_cling_create_screens_hint" msgid="6950729526680114157">"Create more screens for apps and folders"</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>
<string name="migration_cling_copy_apps" msgid="946331230090919440">"COPY ICONS"</string>
<string name="migration_cling_use_default" msgid="2626475813981258626">"START AFRESH"</string>
- <string name="workspace_cling_title" msgid="5626202359865825661">"Organise your space"</string>
- <string name="workspace_cling_move_item" msgid="528201129978005352">"Touch &amp; hold background to manage wallpaper, widgets and settings."</string>
<string name="workspace_cling_longpress_title" msgid="9173998993909018310">"Wallpapers, widgets, &amp; settings"</string>
<string name="workspace_cling_longpress_description" msgid="4119994475505235248">"Touch &amp; hold background to customise"</string>
<string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"GOT IT"</string>
- <string name="folder_cling_title" msgid="3894908818693254164">"Here\'s a folder"</string>
- <string name="folder_cling_create_folder" msgid="6158215559475836131">"To create one like this, touch &amp; hold an app, then move it over another."</string>
- <string name="cling_dismiss" msgid="8962359497601507581">"OK"</string>
<string name="folder_opened" msgid="94695026776264709">"Folder opened, <xliff:g id="WIDTH">%1$d</xliff:g> by <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
<string name="folder_tap_to_close" msgid="1884479294466410023">"Touch to close folder"</string>
<string name="folder_tap_to_rename" msgid="9191075570492871147">"Touch to save rename"</string>
@@ -111,14 +68,34 @@
<string name="widget_button_text" msgid="2880537293434387943">"Widgets"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"Wallpapers"</string>
<string name="settings_button_text" msgid="8119458837558863227">"Settings"</string>
- <string name="package_state_enqueued" msgid="6227252464303085641">"Waiting"</string>
- <string name="package_state_downloading" msgid="4088770468458724721">"Downloading"</string>
- <string name="package_state_installing" msgid="7588193972189849870">"Installing"</string>
+ <string name="allow_rotation_title" msgid="2118706734511831751">"Allow rotation"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Unknown"</string>
- <string name="package_state_error" msgid="7672093962724223588">"Not restored"</string>
- <string name="abandoned_clean_all" msgid="5256770727689657618">"Remove All"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Remove"</string>
<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="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>
+ <string name="item_removed" msgid="851119963877842327">"Item removed"</string>
+ <string name="action_move" msgid="4339390619886385032">"Move item"</string>
+ <string name="move_to_empty_cell" msgid="2833711483015685619">"Move to row <xliff:g id="NUMBER_0">%1$s</xliff:g> column <xliff:g id="NUMBER_1">%2$s</xliff:g>"</string>
+ <string name="move_to_position" msgid="6750008980455459790">"Move to position <xliff:g id="NUMBER">%1$s</xliff:g>"</string>
+ <string name="move_to_hotseat_position" msgid="6295412897075147808">"Move to favourites position <xliff:g id="NUMBER">%1$s</xliff:g>"</string>
+ <string name="item_moved" msgid="4606538322571412879">"Item moved"</string>
+ <string name="add_to_folder" msgid="9040534766770853243">"Add to folder: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="add_to_folder_with_app" msgid="4534929978967147231">"Add to folder with <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="added_to_folder" msgid="4793259502305558003">"Item added to folder"</string>
+ <string name="create_folder_with" msgid="4050141361160214248">"Create folder with: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="folder_created" msgid="6409794597405184510">"Folder created"</string>
+ <string name="action_move_to_workspace" msgid="1603837886334246317">"Move to Home screen"</string>
+ <string name="action_move_screen_left" msgid="8854216831569401665">"Move screen to left"</string>
+ <string name="action_move_screen_right" msgid="329334910274311123">"Move screen to right"</string>
+ <string name="screen_moved" msgid="266230079505650577">"Screen moved"</string>
+ <string name="action_resize" msgid="1802976324781771067">"Re-size"</string>
+ <string name="action_increase_width" msgid="8773715375078513326">"Increase width"</string>
+ <string name="action_increase_height" msgid="459390020612501122">"Increase height"</string>
+ <string name="action_decrease_width" msgid="1374549771083094654">"Decrease width"</string>
+ <string name="action_decrease_height" msgid="282377193880900022">"Decrease height"</string>
+ <string name="widget_resized" msgid="9130327887929620">"Widget re-sized to width <xliff:g id="NUMBER_0">%1$s</xliff:g> height <xliff:g id="NUMBER_1">%2$s</xliff:g>"</string>
</resources>
diff --git a/res/values-en-rIN/strings.xml b/res/values-en-rIN/strings.xml
index 0d004fef5..09963e422 100644
--- a/res/values-en-rIN/strings.xml
+++ b/res/values-en-rIN/strings.xml
@@ -20,57 +20,27 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="application_name" msgid="5181331383435256801">"Launcher3"</string>
- <string name="home" msgid="7658288663002113681">"Home"</string>
- <string name="uid_name" msgid="7820867637514617527">"Android Core Apps"</string>
<string name="folder_name" msgid="7371454440695724752"></string>
+ <string name="work_folder_name" msgid="3753320833950115786">"Work"</string>
<string name="activity_not_found" msgid="8071924732094499514">"App isn\'t installed."</string>
<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="widgets_tab_label" msgid="2921133187116603919">"Widgets"</string>
- <string name="widget_adder" msgid="3201040140710381657">"Widgets"</string>
<string name="toggle_weight_watcher" msgid="5645299835184636119">"Show Mem"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"Touch &amp; hold to pick up a widget."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
- <string name="external_drop_widget_error" msgid="3165821058322217155">"Couldn\'t drop item on this Home screen."</string>
- <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Choose widget to create"</string>
- <string name="rename_folder_label" msgid="3727762225964550653">"Folder name"</string>
- <string name="rename_folder_title" msgid="3771389277707820891">"Rename folder"</string>
- <string name="rename_action" msgid="5559600076028658757">"OK"</string>
- <string name="cancel_action" msgid="7009134900002915310">"Cancel"</string>
- <string name="menu_item_add_item" msgid="1264911265836810421">"Add to Home screen"</string>
- <string name="group_applications" msgid="3797214114206693605">"Apps"</string>
- <string name="group_shortcuts" msgid="6012256992764410535">"Shortcuts"</string>
- <string name="group_widgets" msgid="1569030723286851002">"Widgets"</string>
- <string name="completely_out_of_space" msgid="6106288382070760318">"No more room on your Home screens."</string>
+ <string name="all_apps_search_bar_hint" msgid="7084713969757597256">"Search Apps"</string>
+ <string name="all_apps_loading_message" msgid="7557140873644765180">"Loading Apps…"</string>
+ <string name="all_apps_no_search_results" msgid="6332185285860416787">"No Apps found matching \"<xliff:g id="QUERY">%1$s</xliff:g>\""</string>
<string name="out_of_space" msgid="4691004494942118364">"No more room on this Home screen."</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"No more room in the Favourites tray"</string>
- <string name="invalid_hotseat_item" msgid="5779907847267573691">"This widget is too large for the Favourites tray"</string>
- <string name="shortcut_installed" msgid="1701742129426969556">"Shortcut \"<xliff:g id="NAME">%s</xliff:g>\" created."</string>
- <string name="shortcut_uninstalled" msgid="8176767991305701821">"Shortcut \"<xliff:g id="NAME">%s</xliff:g>\" was removed."</string>
- <string name="shortcut_duplicate" msgid="9167217446062498127">"Shortcut \"<xliff:g id="NAME">%s</xliff:g>\" already exists."</string>
- <string name="title_select_shortcut" msgid="6680642571148153868">"Choose shortcut"</string>
- <string name="title_select_application" msgid="3280812711670683644">"Choose app"</string>
<string name="all_apps_button_label" msgid="9110807029020582876">"Apps"</string>
<string name="all_apps_home_button_label" msgid="252062713717058851">"Home"</string>
- <string name="delete_zone_label_workspace" msgid="4009607676751398685">"Remove"</string>
- <string name="delete_zone_label_all_apps" msgid="8083826390278958980">"Uninstall"</string>
<string name="delete_target_label" msgid="1822697352535677073">"Remove"</string>
<string name="delete_target_uninstall_label" msgid="5100785476250872595">"Uninstall"</string>
<string name="info_target_label" msgid="8053346143994679532">"App info"</string>
- <string name="accessibility_all_apps_button" msgid="2603132375383800483">"Apps"</string>
- <string name="accessibility_delete_button" msgid="6466114477993744621">"Remove"</string>
- <string name="delete_zone_label_all_apps_system_app" msgid="449755632749610895">"Uninstall update"</string>
- <string name="cab_menu_delete_app" msgid="7435191475867183689">"Uninstall app"</string>
- <string name="cab_menu_app_info" msgid="8593722221450362342">"App details"</string>
- <string name="cab_app_selection_text" msgid="374688303047985416">"1 app selected"</string>
- <string name="cab_widget_selection_text" msgid="1833458597831541241">"1 widget selected"</string>
- <string name="cab_folder_selection_text" msgid="7999992513806132118">"1 folder selected"</string>
- <string name="cab_shortcut_selection_text" msgid="2103811025667946450">"1 shortcut selected"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"install shortcuts"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"Allows an app to add shortcuts without user intervention."</string>
- <string name="permlab_uninstall_shortcut" msgid="864595034498083837">"uninstall shortcuts"</string>
- <string name="permdesc_uninstall_shortcut" msgid="5134129545001836849">"Allows the app to remove shortcuts without user intervention."</string>
<string name="permlab_read_settings" msgid="1941457408239617576">"read Home settings and shortcuts"</string>
<string name="permdesc_read_settings" msgid="5833423719057558387">"Allows the app to read the settings and shortcuts in Home."</string>
<string name="permlab_write_settings" msgid="3574213698004620587">"write Home settings and shortcuts"</string>
@@ -78,30 +48,17 @@
<string name="gadget_error_text" msgid="6081085226050792095">"Problem loading widget"</string>
<string name="gadget_setup_text" msgid="8274003207686040488">"Setup"</string>
<string name="uninstall_system_app_text" msgid="4172046090762920660">"This is a system app and can\'t be uninstalled."</string>
- <string name="dream_name" msgid="1530253749244328964">"Rocket Launcher"</string>
<string name="folder_hint_text" msgid="6617836969016293992">"Unnamed Folder"</string>
- <string name="workspace_description_format" msgid="2950174241104043327">"Home screen %1$d"</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="apps_customize_apps_scroll_format" msgid="370005296147130238">"Apps page %1$d of %2$d"</string>
- <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"Widgets page %1$d of %2$d"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"Welcome"</string>
- <string name="first_run_cling_description" msgid="6447072552696253358">"Make yourself at home."</string>
- <string name="first_run_cling_custom_content_hint" msgid="6090628589029352439"></string>
- <string name="first_run_cling_search_bar_hint" msgid="5909062802402452582"></string>
- <string name="first_run_cling_create_screens_hint" msgid="6950729526680114157">"Create more screens for apps and folders"</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>
<string name="migration_cling_copy_apps" msgid="946331230090919440">"COPY ICONS"</string>
<string name="migration_cling_use_default" msgid="2626475813981258626">"START AFRESH"</string>
- <string name="workspace_cling_title" msgid="5626202359865825661">"Organise your space"</string>
- <string name="workspace_cling_move_item" msgid="528201129978005352">"Touch &amp; hold background to manage wallpaper, widgets and settings."</string>
<string name="workspace_cling_longpress_title" msgid="9173998993909018310">"Wallpapers, widgets, &amp; settings"</string>
<string name="workspace_cling_longpress_description" msgid="4119994475505235248">"Touch &amp; hold background to customise"</string>
<string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"GOT IT"</string>
- <string name="folder_cling_title" msgid="3894908818693254164">"Here\'s a folder"</string>
- <string name="folder_cling_create_folder" msgid="6158215559475836131">"To create one like this, touch &amp; hold an app, then move it over another."</string>
- <string name="cling_dismiss" msgid="8962359497601507581">"OK"</string>
<string name="folder_opened" msgid="94695026776264709">"Folder opened, <xliff:g id="WIDTH">%1$d</xliff:g> by <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
<string name="folder_tap_to_close" msgid="1884479294466410023">"Touch to close folder"</string>
<string name="folder_tap_to_rename" msgid="9191075570492871147">"Touch to save rename"</string>
@@ -111,14 +68,34 @@
<string name="widget_button_text" msgid="2880537293434387943">"Widgets"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"Wallpapers"</string>
<string name="settings_button_text" msgid="8119458837558863227">"Settings"</string>
- <string name="package_state_enqueued" msgid="6227252464303085641">"Waiting"</string>
- <string name="package_state_downloading" msgid="4088770468458724721">"Downloading"</string>
- <string name="package_state_installing" msgid="7588193972189849870">"Installing"</string>
+ <string name="allow_rotation_title" msgid="2118706734511831751">"Allow rotation"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Unknown"</string>
- <string name="package_state_error" msgid="7672093962724223588">"Not restored"</string>
- <string name="abandoned_clean_all" msgid="5256770727689657618">"Remove All"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Remove"</string>
<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="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>
+ <string name="item_removed" msgid="851119963877842327">"Item removed"</string>
+ <string name="action_move" msgid="4339390619886385032">"Move item"</string>
+ <string name="move_to_empty_cell" msgid="2833711483015685619">"Move to row <xliff:g id="NUMBER_0">%1$s</xliff:g> column <xliff:g id="NUMBER_1">%2$s</xliff:g>"</string>
+ <string name="move_to_position" msgid="6750008980455459790">"Move to position <xliff:g id="NUMBER">%1$s</xliff:g>"</string>
+ <string name="move_to_hotseat_position" msgid="6295412897075147808">"Move to favourites position <xliff:g id="NUMBER">%1$s</xliff:g>"</string>
+ <string name="item_moved" msgid="4606538322571412879">"Item moved"</string>
+ <string name="add_to_folder" msgid="9040534766770853243">"Add to folder: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="add_to_folder_with_app" msgid="4534929978967147231">"Add to folder with <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="added_to_folder" msgid="4793259502305558003">"Item added to folder"</string>
+ <string name="create_folder_with" msgid="4050141361160214248">"Create folder with: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="folder_created" msgid="6409794597405184510">"Folder created"</string>
+ <string name="action_move_to_workspace" msgid="1603837886334246317">"Move to Home screen"</string>
+ <string name="action_move_screen_left" msgid="8854216831569401665">"Move screen to left"</string>
+ <string name="action_move_screen_right" msgid="329334910274311123">"Move screen to right"</string>
+ <string name="screen_moved" msgid="266230079505650577">"Screen moved"</string>
+ <string name="action_resize" msgid="1802976324781771067">"Re-size"</string>
+ <string name="action_increase_width" msgid="8773715375078513326">"Increase width"</string>
+ <string name="action_increase_height" msgid="459390020612501122">"Increase height"</string>
+ <string name="action_decrease_width" msgid="1374549771083094654">"Decrease width"</string>
+ <string name="action_decrease_height" msgid="282377193880900022">"Decrease height"</string>
+ <string name="widget_resized" msgid="9130327887929620">"Widget re-sized to width <xliff:g id="NUMBER_0">%1$s</xliff:g> height <xliff:g id="NUMBER_1">%2$s</xliff:g>"</string>
</resources>
diff --git a/res/values-es-rUS/strings.xml b/res/values-es-rUS/strings.xml
index 4408080e2..636674293 100644
--- a/res/values-es-rUS/strings.xml
+++ b/res/values-es-rUS/strings.xml
@@ -20,57 +20,27 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="application_name" msgid="5181331383435256801">"Launcher3"</string>
- <string name="home" msgid="7658288663002113681">"Pantalla principal"</string>
- <string name="uid_name" msgid="7820867637514617527">"Aplicaciones básicas de Android"</string>
<string name="folder_name" msgid="7371454440695724752"></string>
+ <string name="work_folder_name" msgid="3753320833950115786">"Trabajo"</string>
<string name="activity_not_found" msgid="8071924732094499514">"No se instaló la aplicación."</string>
<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="widgets_tab_label" msgid="2921133187116603919">"Widgets"</string>
- <string name="widget_adder" msgid="3201040140710381657">"Widgets"</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="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
- <string name="external_drop_widget_error" msgid="3165821058322217155">"Error al soltar elemento en la pantalla principal"</string>
- <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Elegir los widgets para crear"</string>
- <string name="rename_folder_label" msgid="3727762225964550653">"Nombre de carpeta"</string>
- <string name="rename_folder_title" msgid="3771389277707820891">"Cambiar nombre de carpeta"</string>
- <string name="rename_action" msgid="5559600076028658757">"Aceptar"</string>
- <string name="cancel_action" msgid="7009134900002915310">"Cancelar"</string>
- <string name="menu_item_add_item" msgid="1264911265836810421">"Agregar a la pantalla principal"</string>
- <string name="group_applications" msgid="3797214114206693605">"Aplicaciones"</string>
- <string name="group_shortcuts" msgid="6012256992764410535">"Accesos directos"</string>
- <string name="group_widgets" msgid="1569030723286851002">"Widgets"</string>
- <string name="completely_out_of_space" msgid="6106288382070760318">"No hay más espacio en tus pantallas principales."</string>
+ <string name="all_apps_search_bar_hint" msgid="7084713969757597256">"Buscar aplicaciones"</string>
+ <string name="all_apps_loading_message" msgid="7557140873644765180">"Cargando aplicaciones…"</string>
+ <string name="all_apps_no_search_results" msgid="6332185285860416787">"No hay aplicaciones que coincidan con <xliff:g id="QUERY">%1$s</xliff:g>."</string>
<string name="out_of_space" msgid="4691004494942118364">"No hay más espacio en esta pantalla principal."</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"La bandeja de favoritos está llena."</string>
- <string name="invalid_hotseat_item" msgid="5779907847267573691">"Este widget es demasiado grande para la bandeja de favoritos."</string>
- <string name="shortcut_installed" msgid="1701742129426969556">"Se creó el acceso directo \"<xliff:g id="NAME">%s</xliff:g>\"."</string>
- <string name="shortcut_uninstalled" msgid="8176767991305701821">"Se eliminó el acceso directo \"<xliff:g id="NAME">%s</xliff:g>\"."</string>
- <string name="shortcut_duplicate" msgid="9167217446062498127">"El acceso directo \"<xliff:g id="NAME">%s</xliff:g>\" ya existe."</string>
- <string name="title_select_shortcut" msgid="6680642571148153868">"Elegir acceso directo"</string>
- <string name="title_select_application" msgid="3280812711670683644">"Elegir aplicación"</string>
<string name="all_apps_button_label" msgid="9110807029020582876">"Aplicaciones"</string>
<string name="all_apps_home_button_label" msgid="252062713717058851">"Pantalla principal"</string>
- <string name="delete_zone_label_workspace" msgid="4009607676751398685">"Eliminar"</string>
- <string name="delete_zone_label_all_apps" msgid="8083826390278958980">"Desinstalar"</string>
<string name="delete_target_label" msgid="1822697352535677073">"Eliminar"</string>
<string name="delete_target_uninstall_label" msgid="5100785476250872595">"Desinstalar"</string>
<string name="info_target_label" msgid="8053346143994679532">"Información de la aplicación"</string>
- <string name="accessibility_all_apps_button" msgid="2603132375383800483">"Aplicaciones"</string>
- <string name="accessibility_delete_button" msgid="6466114477993744621">"Eliminar"</string>
- <string name="delete_zone_label_all_apps_system_app" msgid="449755632749610895">"Desinstalar actualización"</string>
- <string name="cab_menu_delete_app" msgid="7435191475867183689">"Desinstalar aplicación"</string>
- <string name="cab_menu_app_info" msgid="8593722221450362342">"Detalles de la aplicación"</string>
- <string name="cab_app_selection_text" msgid="374688303047985416">"Se seleccionó 1 aplicación."</string>
- <string name="cab_widget_selection_text" msgid="1833458597831541241">"Se seleccionó 1 widget."</string>
- <string name="cab_folder_selection_text" msgid="7999992513806132118">"Se seleccionó 1 carpeta."</string>
- <string name="cab_shortcut_selection_text" msgid="2103811025667946450">"Se seleccionó 1 acceso directo."</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"instalar accesos directos"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"Permite que una aplicación agregue accesos directos sin que el usuario intervenga."</string>
- <string name="permlab_uninstall_shortcut" msgid="864595034498083837">"desinstalar accesos directos"</string>
- <string name="permdesc_uninstall_shortcut" msgid="5134129545001836849">"Permite que la aplicación elimine accesos directos sin que el usuario intervenga."</string>
<string name="permlab_read_settings" msgid="1941457408239617576">"leer configuración y accesos directos de la pantalla principal"</string>
<string name="permdesc_read_settings" msgid="5833423719057558387">"Permite que la aplicación lea la configuración y los accesos directos de la pantalla principal."</string>
<string name="permlab_write_settings" msgid="3574213698004620587">"escribir configuración y accesos directos de la pantalla principal"</string>
@@ -78,30 +48,17 @@
<string name="gadget_error_text" msgid="6081085226050792095">"Problema al cargar el widget"</string>
<string name="gadget_setup_text" msgid="8274003207686040488">"Configuración"</string>
<string name="uninstall_system_app_text" msgid="4172046090762920660">"Esta es una aplicación del sistema y no se puede desinstalar."</string>
- <string name="dream_name" msgid="1530253749244328964">"Lanzacohetes"</string>
<string name="folder_hint_text" msgid="6617836969016293992">"Carpeta sin nombre"</string>
- <string name="workspace_description_format" msgid="2950174241104043327">"Pantalla principal %1$d"</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="apps_customize_apps_scroll_format" msgid="370005296147130238">"Página de aplicaciones %1$d de %2$d"</string>
- <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"Página de widgets %1$d de %2$d"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"Bienvenido"</string>
- <string name="first_run_cling_description" msgid="6447072552696253358">"Siéntete como en casa."</string>
- <string name="first_run_cling_custom_content_hint" msgid="6090628589029352439"></string>
- <string name="first_run_cling_search_bar_hint" msgid="5909062802402452582"></string>
- <string name="first_run_cling_create_screens_hint" msgid="6950729526680114157">"Crea más pantallas para aplicaciones y carpetas."</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>
<string name="migration_cling_copy_apps" msgid="946331230090919440">"COPIAR ÍCONOS"</string>
<string name="migration_cling_use_default" msgid="2626475813981258626">"EMPEZAR DE CERO"</string>
- <string name="workspace_cling_title" msgid="5626202359865825661">"Organiza tu espacio"</string>
- <string name="workspace_cling_move_item" msgid="528201129978005352">"Mantén presionado el fondo para administrar el fondo de pantalla, los widgets y la configuración."</string>
<string name="workspace_cling_longpress_title" msgid="9173998993909018310">"Fondos, widgets y configuración"</string>
<string name="workspace_cling_longpress_description" msgid="4119994475505235248">"Mantén presionado el fondo para personalizarlo"</string>
<string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"ENTENDIDO"</string>
- <string name="folder_cling_title" msgid="3894908818693254164">"Aquí tienes una carpeta"</string>
- <string name="folder_cling_create_folder" msgid="6158215559475836131">"Para crear una carpeta como esta, mantén presionada una aplicación y luego muévela sobre otra."</string>
- <string name="cling_dismiss" msgid="8962359497601507581">"Aceptar"</string>
<string name="folder_opened" msgid="94695026776264709">"Carpeta abierta, <xliff:g id="WIDTH">%1$d</xliff:g> por <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
<string name="folder_tap_to_close" msgid="1884479294466410023">"Toca para cerrar la carpeta."</string>
<string name="folder_tap_to_rename" msgid="9191075570492871147">"Toca para guardar el nuevo nombre."</string>
@@ -111,14 +68,34 @@
<string name="widget_button_text" msgid="2880537293434387943">"Widgets"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"Fondos de pantalla"</string>
<string name="settings_button_text" msgid="8119458837558863227">"Configuración"</string>
- <string name="package_state_enqueued" msgid="6227252464303085641">"Pendiente"</string>
- <string name="package_state_downloading" msgid="4088770468458724721">"Descargando"</string>
- <string name="package_state_installing" msgid="7588193972189849870">"Instalando"</string>
+ <string name="allow_rotation_title" msgid="2118706734511831751">"Permitir la rotación"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Desconocido"</string>
- <string name="package_state_error" msgid="7672093962724223588">"No restaurado"</string>
- <string name="abandoned_clean_all" msgid="5256770727689657618">"Eliminar todo"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Eliminar"</string>
<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="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>
+ <string name="item_removed" msgid="851119963877842327">"Se eliminó el elemento."</string>
+ <string name="action_move" msgid="4339390619886385032">"Mover elemento"</string>
+ <string name="move_to_empty_cell" msgid="2833711483015685619">"Mover a fila <xliff:g id="NUMBER_0">%1$s</xliff:g>, columna <xliff:g id="NUMBER_1">%2$s</xliff:g>"</string>
+ <string name="move_to_position" msgid="6750008980455459790">"Mover a la posición número <xliff:g id="NUMBER">%1$s</xliff:g>"</string>
+ <string name="move_to_hotseat_position" msgid="6295412897075147808">"Mover a la posición de favoritos número <xliff:g id="NUMBER">%1$s</xliff:g>"</string>
+ <string name="item_moved" msgid="4606538322571412879">"Elemento movido"</string>
+ <string name="add_to_folder" msgid="9040534766770853243">"Agregar a carpeta: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="add_to_folder_with_app" msgid="4534929978967147231">"Agregar a la carpeta que contiene <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="added_to_folder" msgid="4793259502305558003">"Elemento agregado a la carpeta"</string>
+ <string name="create_folder_with" msgid="4050141361160214248">"Crear carpeta con: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="folder_created" msgid="6409794597405184510">"Carpeta creada"</string>
+ <string name="action_move_to_workspace" msgid="1603837886334246317">"Mover a la pantalla principal"</string>
+ <string name="action_move_screen_left" msgid="8854216831569401665">"Mover pantalla a la izquierda"</string>
+ <string name="action_move_screen_right" msgid="329334910274311123">"Mover pantalla a la derecha"</string>
+ <string name="screen_moved" msgid="266230079505650577">"Se movió la pantalla."</string>
+ <string name="action_resize" msgid="1802976324781771067">"Ajustar tamaño"</string>
+ <string name="action_increase_width" msgid="8773715375078513326">"Aumentar el ancho"</string>
+ <string name="action_increase_height" msgid="459390020612501122">"Aumentar la altura"</string>
+ <string name="action_decrease_width" msgid="1374549771083094654">"Reducir el ancho"</string>
+ <string name="action_decrease_height" msgid="282377193880900022">"Reducir la altura"</string>
+ <string name="widget_resized" msgid="9130327887929620">"Se cambió la dimensión del widget a <xliff:g id="NUMBER_0">%1$s</xliff:g> de ancho y <xliff:g id="NUMBER_1">%2$s</xliff:g> de alto."</string>
</resources>
diff --git a/res/values-es/strings.xml b/res/values-es/strings.xml
index 898d0eaa5..34331fce9 100644
--- a/res/values-es/strings.xml
+++ b/res/values-es/strings.xml
@@ -20,57 +20,27 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="application_name" msgid="5181331383435256801">"Launcher3"</string>
- <string name="home" msgid="7658288663002113681">"Home"</string>
- <string name="uid_name" msgid="7820867637514617527">"Aplicaciones básicas de Android"</string>
<string name="folder_name" msgid="7371454440695724752"></string>
+ <string name="work_folder_name" msgid="3753320833950115786">"Trabajo"</string>
<string name="activity_not_found" msgid="8071924732094499514">"La aplicación no está instalada."</string>
<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="widgets_tab_label" msgid="2921133187116603919">"Widgets"</string>
- <string name="widget_adder" msgid="3201040140710381657">"Widgets"</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="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
- <string name="external_drop_widget_error" msgid="3165821058322217155">"Error al arrastrar elemento a pantalla de inicio."</string>
- <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Selecciona widget a añadir"</string>
- <string name="rename_folder_label" msgid="3727762225964550653">"Nombre de carpeta"</string>
- <string name="rename_folder_title" msgid="3771389277707820891">"Cambiar nombre de carpeta"</string>
- <string name="rename_action" msgid="5559600076028658757">"Aceptar"</string>
- <string name="cancel_action" msgid="7009134900002915310">"Cancelar"</string>
- <string name="menu_item_add_item" msgid="1264911265836810421">"Añadir a la pantalla de inicio"</string>
- <string name="group_applications" msgid="3797214114206693605">"Aplicaciones"</string>
- <string name="group_shortcuts" msgid="6012256992764410535">"Accesos directos"</string>
- <string name="group_widgets" msgid="1569030723286851002">"Widgets"</string>
- <string name="completely_out_of_space" msgid="6106288382070760318">"No queda espacio en las pantallas de inicio."</string>
+ <string name="all_apps_search_bar_hint" msgid="7084713969757597256">"Busca aplicaciones"</string>
+ <string name="all_apps_loading_message" msgid="7557140873644765180">"Cargando aplicaciones…"</string>
+ <string name="all_apps_no_search_results" msgid="6332185285860416787">"No se han encontrado aplicaciones que contengan \"<xliff:g id="QUERY">%1$s</xliff:g>\""</string>
<string name="out_of_space" msgid="4691004494942118364">"No queda espacio en la pantalla de inicio."</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"La bandeja de favoritos está completa"</string>
- <string name="invalid_hotseat_item" msgid="5779907847267573691">"Este widget es demasiado grande para la bandeja de favoritos"</string>
- <string name="shortcut_installed" msgid="1701742129426969556">"Se ha creado el acceso directo \"<xliff:g id="NAME">%s</xliff:g>\"."</string>
- <string name="shortcut_uninstalled" msgid="8176767991305701821">"Se ha eliminado el acceso directo \"<xliff:g id="NAME">%s</xliff:g>\"."</string>
- <string name="shortcut_duplicate" msgid="9167217446062498127">"El acceso directo \"<xliff:g id="NAME">%s</xliff:g>\" ya existe."</string>
- <string name="title_select_shortcut" msgid="6680642571148153868">"Selecciona un acceso directo"</string>
- <string name="title_select_application" msgid="3280812711670683644">"Selecciona una aplicación"</string>
<string name="all_apps_button_label" msgid="9110807029020582876">"Aplicaciones"</string>
<string name="all_apps_home_button_label" msgid="252062713717058851">"Inicio"</string>
- <string name="delete_zone_label_workspace" msgid="4009607676751398685">"Eliminar"</string>
- <string name="delete_zone_label_all_apps" msgid="8083826390278958980">"Desinstalar"</string>
<string name="delete_target_label" msgid="1822697352535677073">"Eliminar"</string>
<string name="delete_target_uninstall_label" msgid="5100785476250872595">"Desinstalar"</string>
<string name="info_target_label" msgid="8053346143994679532">"Información de la aplicación"</string>
- <string name="accessibility_all_apps_button" msgid="2603132375383800483">"Aplicaciones"</string>
- <string name="accessibility_delete_button" msgid="6466114477993744621">"Eliminar"</string>
- <string name="delete_zone_label_all_apps_system_app" msgid="449755632749610895">"Desinstalar actualización"</string>
- <string name="cab_menu_delete_app" msgid="7435191475867183689">"Desinstalar aplicación"</string>
- <string name="cab_menu_app_info" msgid="8593722221450362342">"Información de la aplicación"</string>
- <string name="cab_app_selection_text" msgid="374688303047985416">"1 aplicación seleccionada"</string>
- <string name="cab_widget_selection_text" msgid="1833458597831541241">"1 widget seleccionado"</string>
- <string name="cab_folder_selection_text" msgid="7999992513806132118">"1 carpeta seleccionada"</string>
- <string name="cab_shortcut_selection_text" msgid="2103811025667946450">"1 acceso directo seleccionado"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"instalar accesos directos"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"Permite que una aplicación añada accesos directos sin intervención del usuario."</string>
- <string name="permlab_uninstall_shortcut" msgid="864595034498083837">"desinstalar accesos directos"</string>
- <string name="permdesc_uninstall_shortcut" msgid="5134129545001836849">"Permite que la aplicación elimine accesos directos sin intervención del usuario."</string>
<string name="permlab_read_settings" msgid="1941457408239617576">"leer información de accesos directos y de ajustes de la pantalla de inicio"</string>
<string name="permdesc_read_settings" msgid="5833423719057558387">"Permite que la aplicación consulte los ajustes y los accesos directos de la pantalla de inicio."</string>
<string name="permlab_write_settings" msgid="3574213698004620587">"escribir información de accesos directos y de ajustes de la pantalla de inicio"</string>
@@ -78,30 +48,17 @@
<string name="gadget_error_text" msgid="6081085226050792095">"Problema al cargar el widget"</string>
<string name="gadget_setup_text" msgid="8274003207686040488">"Configuración"</string>
<string name="uninstall_system_app_text" msgid="4172046090762920660">"Esta aplicación es del sistema y no se puede desinstalar."</string>
- <string name="dream_name" msgid="1530253749244328964">"Rocket Launcher"</string>
<string name="folder_hint_text" msgid="6617836969016293992">"Carpeta sin nombre"</string>
- <string name="workspace_description_format" msgid="2950174241104043327">"Pantalla de inicio %1$d"</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="apps_customize_apps_scroll_format" msgid="370005296147130238">"Página de aplicaciones %1$d de %2$d"</string>
- <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"Página de widgets %1$d de %2$d"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"Te damos la bienvenida"</string>
- <string name="first_run_cling_description" msgid="6447072552696253358">"Personaliza tu pantalla de inicio."</string>
- <string name="first_run_cling_custom_content_hint" msgid="6090628589029352439"></string>
- <string name="first_run_cling_search_bar_hint" msgid="5909062802402452582"></string>
- <string name="first_run_cling_create_screens_hint" msgid="6950729526680114157">"Crea más pantallas para aplicaciones y carpetas"</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>
<string name="migration_cling_copy_apps" msgid="946331230090919440">"COPIAR ICONOS"</string>
<string name="migration_cling_use_default" msgid="2626475813981258626">"AJUSTES PREDETERMINADOS"</string>
- <string name="workspace_cling_title" msgid="5626202359865825661">"Organiza tu espacio"</string>
- <string name="workspace_cling_move_item" msgid="528201129978005352">"Mantén pulsado el fondo para gestionar el fondo de pantalla, los widgets y los ajustes."</string>
<string name="workspace_cling_longpress_title" msgid="9173998993909018310">"Fondos de pantalla, widgets y ajustes"</string>
<string name="workspace_cling_longpress_description" msgid="4119994475505235248">"Mantén pulsado el fondo para personalizarlo"</string>
<string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"ENTENDIDO"</string>
- <string name="folder_cling_title" msgid="3894908818693254164">"Esto es una carpeta"</string>
- <string name="folder_cling_create_folder" msgid="6158215559475836131">"Para crear una carpeta como esta, mantén pulsada una aplicación y muévela sobre otra."</string>
- <string name="cling_dismiss" msgid="8962359497601507581">"Aceptar"</string>
<string name="folder_opened" msgid="94695026776264709">"Carpeta abierta, <xliff:g id="WIDTH">%1$d</xliff:g> por <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
<string name="folder_tap_to_close" msgid="1884479294466410023">"Toca para cerrar la carpeta"</string>
<string name="folder_tap_to_rename" msgid="9191075570492871147">"Toca para cambiar el nuevo nombre"</string>
@@ -111,14 +68,34 @@
<string name="widget_button_text" msgid="2880537293434387943">"Widgets"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"Fondos de pantalla"</string>
<string name="settings_button_text" msgid="8119458837558863227">"Ajustes"</string>
- <string name="package_state_enqueued" msgid="6227252464303085641">"Esperando"</string>
- <string name="package_state_downloading" msgid="4088770468458724721">"Descargando"</string>
- <string name="package_state_installing" msgid="7588193972189849870">"Instalando"</string>
+ <string name="allow_rotation_title" msgid="2118706734511831751">"Permitir rotación"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Desconocido"</string>
- <string name="package_state_error" msgid="7672093962724223588">"No restaurado"</string>
- <string name="abandoned_clean_all" msgid="5256770727689657618">"Eliminar todo"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Eliminar"</string>
<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="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>
+ <string name="item_removed" msgid="851119963877842327">"Elemento eliminado"</string>
+ <string name="action_move" msgid="4339390619886385032">"Mover elemento"</string>
+ <string name="move_to_empty_cell" msgid="2833711483015685619">"Mover a la fila <xliff:g id="NUMBER_0">%1$s</xliff:g>, columna <xliff:g id="NUMBER_1">%2$s</xliff:g>"</string>
+ <string name="move_to_position" msgid="6750008980455459790">"Mover a la posición número <xliff:g id="NUMBER">%1$s</xliff:g>"</string>
+ <string name="move_to_hotseat_position" msgid="6295412897075147808">"Mover a la posición número <xliff:g id="NUMBER">%1$s</xliff:g> de favoritos"</string>
+ <string name="item_moved" msgid="4606538322571412879">"Elemento movido"</string>
+ <string name="add_to_folder" msgid="9040534766770853243">"Añadir a carpeta: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="add_to_folder_with_app" msgid="4534929978967147231">"Añadir a la carpeta con <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="added_to_folder" msgid="4793259502305558003">"Elemento añadido a carpeta"</string>
+ <string name="create_folder_with" msgid="4050141361160214248">"Crear carpeta con: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="folder_created" msgid="6409794597405184510">"Carpeta creada"</string>
+ <string name="action_move_to_workspace" msgid="1603837886334246317">"Mover a la pantalla de inicio"</string>
+ <string name="action_move_screen_left" msgid="8854216831569401665">"Mover pantalla a la izquierda"</string>
+ <string name="action_move_screen_right" msgid="329334910274311123">"Mover pantalla a la derecha"</string>
+ <string name="screen_moved" msgid="266230079505650577">"Pantalla movida"</string>
+ <string name="action_resize" msgid="1802976324781771067">"Modificar tamaño"</string>
+ <string name="action_increase_width" msgid="8773715375078513326">"Aumentar ancho"</string>
+ <string name="action_increase_height" msgid="459390020612501122">"Aumentar altura"</string>
+ <string name="action_decrease_width" msgid="1374549771083094654">"Reducir ancho"</string>
+ <string name="action_decrease_height" msgid="282377193880900022">"Reducir altura"</string>
+ <string name="widget_resized" msgid="9130327887929620">"Se ha modificado el tamaño del widget a <xliff:g id="NUMBER_0">%1$s</xliff:g> de ancho y <xliff:g id="NUMBER_1">%2$s</xliff:g> de alto"</string>
</resources>
diff --git a/res/values-et-rEE/strings.xml b/res/values-et-rEE/strings.xml
index 76b20aba7..c4ba823cc 100644
--- a/res/values-et-rEE/strings.xml
+++ b/res/values-et-rEE/strings.xml
@@ -20,57 +20,27 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="application_name" msgid="5181331383435256801">"Launcher3"</string>
- <string name="home" msgid="7658288663002113681">"Avaekraan"</string>
- <string name="uid_name" msgid="7820867637514617527">"Androidi tuumrakendused"</string>
<string name="folder_name" msgid="7371454440695724752"></string>
+ <string name="work_folder_name" msgid="3753320833950115786">"Töö"</string>
<string name="activity_not_found" msgid="8071924732094499514">"Rakendus pole installitud."</string>
<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="widgets_tab_label" msgid="2921133187116603919">"Vidinad"</string>
- <string name="widget_adder" msgid="3201040140710381657">"Vidinad"</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="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
- <string name="external_drop_widget_error" msgid="3165821058322217155">"Üksust ei saanud sellele avaekraanile tuua."</string>
- <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Valige loomiseks vidin"</string>
- <string name="rename_folder_label" msgid="3727762225964550653">"Kausta nimi"</string>
- <string name="rename_folder_title" msgid="3771389277707820891">"Kausta ümbernimetamine"</string>
- <string name="rename_action" msgid="5559600076028658757">"OK"</string>
- <string name="cancel_action" msgid="7009134900002915310">"Tühista"</string>
- <string name="menu_item_add_item" msgid="1264911265836810421">"Avaekraanile lisamine"</string>
- <string name="group_applications" msgid="3797214114206693605">"Rakendused"</string>
- <string name="group_shortcuts" msgid="6012256992764410535">"Otseteed"</string>
- <string name="group_widgets" msgid="1569030723286851002">"Vidinad"</string>
- <string name="completely_out_of_space" msgid="6106288382070760318">"Teie avaekraanidel ei ole enam ruumi."</string>
+ <string name="all_apps_search_bar_hint" msgid="7084713969757597256">"Otsige rakendustest"</string>
+ <string name="all_apps_loading_message" msgid="7557140873644765180">"Rakenduste laadimine ..."</string>
+ <string name="all_apps_no_search_results" msgid="6332185285860416787">"Päringule „<xliff:g id="QUERY">%1$s</xliff:g>” ei vastanud ükski rakendus"</string>
<string name="out_of_space" msgid="4691004494942118364">"Sellel avaekraanil pole enam ruumi."</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"Salves Lemmikud pole rohkem ruumi"</string>
- <string name="invalid_hotseat_item" msgid="5779907847267573691">"See vidin on salve Lemmikud jaoks liiga suur"</string>
- <string name="shortcut_installed" msgid="1701742129426969556">"Otsetee „<xliff:g id="NAME">%s</xliff:g>” on loodud."</string>
- <string name="shortcut_uninstalled" msgid="8176767991305701821">"Otsetee „<xliff:g id="NAME">%s</xliff:g>” on eemaldatud."</string>
- <string name="shortcut_duplicate" msgid="9167217446062498127">"Otsetee „<xliff:g id="NAME">%s</xliff:g>” on juba olemas."</string>
- <string name="title_select_shortcut" msgid="6680642571148153868">"Otsetee valimine"</string>
- <string name="title_select_application" msgid="3280812711670683644">"Rakenduse valimine"</string>
<string name="all_apps_button_label" msgid="9110807029020582876">"Rakendused"</string>
<string name="all_apps_home_button_label" msgid="252062713717058851">"Avaekraan"</string>
- <string name="delete_zone_label_workspace" msgid="4009607676751398685">"Eemalda"</string>
- <string name="delete_zone_label_all_apps" msgid="8083826390278958980">"Desinstalli"</string>
<string name="delete_target_label" msgid="1822697352535677073">"Eemalda"</string>
<string name="delete_target_uninstall_label" msgid="5100785476250872595">"Desinstalli"</string>
<string name="info_target_label" msgid="8053346143994679532">"Rakenduse teave"</string>
- <string name="accessibility_all_apps_button" msgid="2603132375383800483">"Rakendused"</string>
- <string name="accessibility_delete_button" msgid="6466114477993744621">"Eemalda"</string>
- <string name="delete_zone_label_all_apps_system_app" msgid="449755632749610895">"Desinstalli värskendus"</string>
- <string name="cab_menu_delete_app" msgid="7435191475867183689">"Rakenduse desinstallimine"</string>
- <string name="cab_menu_app_info" msgid="8593722221450362342">"Rakenduse üksikasjad"</string>
- <string name="cab_app_selection_text" msgid="374688303047985416">"Valitud on 1 rakendus"</string>
- <string name="cab_widget_selection_text" msgid="1833458597831541241">"Valitud on 1 vidin"</string>
- <string name="cab_folder_selection_text" msgid="7999992513806132118">"Valitud on 1 kaust"</string>
- <string name="cab_shortcut_selection_text" msgid="2103811025667946450">"Valitud on 1 otsetee"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"installi otseteed"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"Võimaldab rakendusel lisada otseteid kasutaja sekkumiseta."</string>
- <string name="permlab_uninstall_shortcut" msgid="864595034498083837">"desinstalli otseteed"</string>
- <string name="permdesc_uninstall_shortcut" msgid="5134129545001836849">"Võimaldab rakendusel eemaldada otseteid kasutaja sekkumiseta."</string>
<string name="permlab_read_settings" msgid="1941457408239617576">"loe avaekraani seadeid ja otseteid"</string>
<string name="permdesc_read_settings" msgid="5833423719057558387">"Võimaldab rakendusel lugeda avaekraanil seadeid ja otseteid."</string>
<string name="permlab_write_settings" msgid="3574213698004620587">"kirjuta avaekraani seaded ja otseteed"</string>
@@ -78,30 +48,17 @@
<string name="gadget_error_text" msgid="6081085226050792095">"Probleem vidina laadimisel"</string>
<string name="gadget_setup_text" msgid="8274003207686040488">"Seadistamine"</string>
<string name="uninstall_system_app_text" msgid="4172046090762920660">"See on süsteemirakendus ja seda ei saa desinstallida."</string>
- <string name="dream_name" msgid="1530253749244328964">"Rocket Launcher"</string>
<string name="folder_hint_text" msgid="6617836969016293992">"Nimetu kaust"</string>
- <string name="workspace_description_format" msgid="2950174241104043327">"Avaekraan %1$d"</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="apps_customize_apps_scroll_format" msgid="370005296147130238">"Rakenduste leht %1$d/%2$d"</string>
- <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"Vidinate leht %1$d/%2$d"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"Tere tulemast"</string>
- <string name="first_run_cling_description" msgid="6447072552696253358">"Tundke end nagu kodus."</string>
- <string name="first_run_cling_custom_content_hint" msgid="6090628589029352439"></string>
- <string name="first_run_cling_search_bar_hint" msgid="5909062802402452582"></string>
- <string name="first_run_cling_create_screens_hint" msgid="6950729526680114157">"Looge rakenduste ja kaustade jaoks rohkem ekraanikuvasid"</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>
<string name="migration_cling_copy_apps" msgid="946331230090919440">"KOPEERI IKOONID"</string>
<string name="migration_cling_use_default" msgid="2626475813981258626">"ALUSTA ALGUSEST"</string>
- <string name="workspace_cling_title" msgid="5626202359865825661">"Korraldage oma ruumi"</string>
- <string name="workspace_cling_move_item" msgid="528201129978005352">"Taustapildi, vidinate ja seadete haldamiseks puudutage tausta ning hoidke seda all."</string>
<string name="workspace_cling_longpress_title" msgid="9173998993909018310">"Taustapildid, vidinad ja seaded"</string>
<string name="workspace_cling_longpress_description" msgid="4119994475505235248">"Kohandamiseks puudutage ja hoidke tausta all"</string>
<string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"SELGE"</string>
- <string name="folder_cling_title" msgid="3894908818693254164">"Siin on kaust"</string>
- <string name="folder_cling_create_folder" msgid="6158215559475836131">"Sarnase loomiseks vajutage ja hoidke rakendust all, seejärel viige see teise peale."</string>
- <string name="cling_dismiss" msgid="8962359497601507581">"OK"</string>
<string name="folder_opened" msgid="94695026776264709">"Kaust on avatud, <xliff:g id="WIDTH">%1$d</xliff:g> x <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
<string name="folder_tap_to_close" msgid="1884479294466410023">"Puudutage kausta sulgemiseks"</string>
<string name="folder_tap_to_rename" msgid="9191075570492871147">"Puudutage uue nime salvestamiseks"</string>
@@ -111,14 +68,34 @@
<string name="widget_button_text" msgid="2880537293434387943">"Vidinad"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"Taustapildid"</string>
<string name="settings_button_text" msgid="8119458837558863227">"Seaded"</string>
- <string name="package_state_enqueued" msgid="6227252464303085641">"Ootamine"</string>
- <string name="package_state_downloading" msgid="4088770468458724721">"Allalaadimine"</string>
- <string name="package_state_installing" msgid="7588193972189849870">"Installimine"</string>
+ <string name="allow_rotation_title" msgid="2118706734511831751">"Luba pööramine"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Teadmata"</string>
- <string name="package_state_error" msgid="7672093962724223588">"Ei taastatud"</string>
- <string name="abandoned_clean_all" msgid="5256770727689657618">"Eemalda kõik"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Eemalda"</string>
<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="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>
+ <string name="item_removed" msgid="851119963877842327">"Üksus eemaldati"</string>
+ <string name="action_move" msgid="4339390619886385032">"Teisalda üksus"</string>
+ <string name="move_to_empty_cell" msgid="2833711483015685619">"Teisaldamine <xliff:g id="NUMBER_0">%1$s</xliff:g>. rea <xliff:g id="NUMBER_1">%2$s</xliff:g>. veergu"</string>
+ <string name="move_to_position" msgid="6750008980455459790">"Teisaldamine <xliff:g id="NUMBER">%1$s</xliff:g>. positsioonile"</string>
+ <string name="move_to_hotseat_position" msgid="6295412897075147808">"Teisaldamine lemmikute <xliff:g id="NUMBER">%1$s</xliff:g>. positsioonile"</string>
+ <string name="item_moved" msgid="4606538322571412879">"Üksus teisaldati"</string>
+ <string name="add_to_folder" msgid="9040534766770853243">"Lisamine kausta: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="add_to_folder_with_app" msgid="4534929978967147231">"Lisamine kausta nimega <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="added_to_folder" msgid="4793259502305558003">"Üksus lisati kausta"</string>
+ <string name="create_folder_with" msgid="4050141361160214248">"Kausta loomine nimega <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="folder_created" msgid="6409794597405184510">"Kaust on loodud"</string>
+ <string name="action_move_to_workspace" msgid="1603837886334246317">"Teisalda avaekraanile"</string>
+ <string name="action_move_screen_left" msgid="8854216831569401665">"Teisalda ekraan vasakule"</string>
+ <string name="action_move_screen_right" msgid="329334910274311123">"Teisalda ekraan paremale"</string>
+ <string name="screen_moved" msgid="266230079505650577">"Ekraan teisaldati"</string>
+ <string name="action_resize" msgid="1802976324781771067">"Muuda suurust"</string>
+ <string name="action_increase_width" msgid="8773715375078513326">"Suurenda laiust"</string>
+ <string name="action_increase_height" msgid="459390020612501122">"Suurenda kõrgust"</string>
+ <string name="action_decrease_width" msgid="1374549771083094654">"Vähenda laiust"</string>
+ <string name="action_decrease_height" msgid="282377193880900022">"Vähenda kõrgust"</string>
+ <string name="widget_resized" msgid="9130327887929620">"Vidina suurust muudeti. Laius: <xliff:g id="NUMBER_0">%1$s</xliff:g>. Kõrgus: <xliff:g id="NUMBER_1">%2$s</xliff:g>"</string>
</resources>
diff --git a/res/values-et/strings.xml b/res/values-et/strings.xml
index 3b0deb85b..afed3b548 100644
--- a/res/values-et/strings.xml
+++ b/res/values-et/strings.xml
@@ -20,95 +20,34 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="application_name" msgid="8424725141379931883">"Käivitaja"</string>
- <string name="home" msgid="5921706419368316758">"Kodu"</string>
- <string name="uid_name" msgid="3371120195364560632">"Androidi tuumrakendused"</string>
<string name="folder_name" msgid="8551881338202938211"></string>
- <string name="chooser_wallpaper" msgid="6063168087625352235">"Taustapildi valimiskoht:"</string>
<string name="wallpaper_instructions" msgid="4215640646180727542">"Määra taustapilt"</string>
<string name="pick_wallpaper" msgid="5630222540525626723">"Taustapildid"</string>
<string name="activity_not_found" msgid="217823393239365967">"Rakendus pole installitud."</string>
- <string name="widgets_tab_label" msgid="9145860100000983599">"Vidinad"</string>
<string name="long_press_widget_to_add" msgid="7395697462851217506">"Vidina valimiseks puudutage seda pikalt."</string>
- <string name="market" msgid="2652226429823445833">"Pood"</string>
<string name="widget_dims_format" msgid="1386418557719032947">"%1$d × %2$d"</string>
- <string name="external_drop_widget_error" msgid="2285187188524172774">"Üksust ei saa sellele avaekraanile tuua."</string>
- <string name="external_drop_widget_pick_title" msgid="7040647073452295370">"Valige loomiseks vidin"</string>
- <string name="rename_folder_label" msgid="5646236631298452787">"Kausta nimi"</string>
- <string name="rename_folder_title" msgid="4544573104191526550">"Nimeta kaust ümber"</string>
- <string name="rename_action" msgid="6016003384693240896">"OK"</string>
- <string name="cancel_action" msgid="3811860427489435048">"Tühista"</string>
- <string name="menu_item_add_item" msgid="6233177331075781114">"Lisa avamenüüsse"</string>
- <string name="group_applications" msgid="2103752818818161976">"Rakendused"</string>
- <string name="group_shortcuts" msgid="9133529424900391877">"Otseteed"</string>
- <string name="group_widgets" msgid="6704978494073105844">"Vidinad"</string>
- <string name="completely_out_of_space" msgid="1759078539443491182">"Teie avakuvadel ei ole enam ruumi."</string>
<string name="out_of_space" msgid="8365249326091984698">"Sellel avalehel pole enam ruumi."</string>
<string name="hotseat_out_of_space" msgid="6304886797358479361">"Kohandataval dokialal pole rohkem ruumi."</string>
- <string name="invalid_hotseat_item" msgid="6545340627805449250">"See vidin on tööpunkti jaoks liiga suur."</string>
- <string name="shortcut_installed" msgid="7071557296331322355">"Otsetee „<xliff:g id="NAME">%s</xliff:g>” loodud."</string>
- <string name="shortcut_uninstalled" msgid="2129499669449749995">"Otsetee „<xliff:g id="NAME">%s</xliff:g>” eemaldatud."</string>
- <string name="shortcut_duplicate" msgid="4757756326465060694">"Otsetee „<xliff:g id="NAME">%s</xliff:g>” on juba olemas."</string>
- <string name="title_select_shortcut" msgid="1873670208166882222">"Otsetee valimine"</string>
- <string name="title_select_application" msgid="1793455815754848652">"Rakenduse valimine"</string>
<string name="all_apps_button_label" msgid="2578400570124163469">"Rakendused"</string>
<string name="all_apps_home_button_label" msgid="1022222300329398558">"Kodu"</string>
- <string name="delete_zone_label_workspace" msgid="7153615831493049150">"Eemalda"</string>
- <string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Desinstalli"</string>
<string name="delete_target_label" msgid="665300185123139530">"Eemalda"</string>
<string name="delete_target_uninstall_label" msgid="748894921183769150">"Desinstalli"</string>
<string name="info_target_label" msgid="4019495079517426980">"Rakenduse teave"</string>
- <string name="accessibility_search_button" msgid="816822994629942611">"Otsing"</string>
- <string name="accessibility_voice_search_button" msgid="3938249215065842475">"Häälotsing"</string>
- <string name="accessibility_all_apps_button" msgid="8803738611398979849">"Rakendused"</string>
- <string name="accessibility_delete_button" msgid="3628162007991023603">"Eemalda"</string>
- <string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Desinstalli värskendus"</string>
- <string name="menu_add" msgid="3065046628354640854">"Lisa"</string>
- <string name="menu_manage_apps" msgid="2308685199463588895">"Rakenduste haldamine"</string>
- <string name="menu_wallpaper" msgid="5837429080911269832">"Taustapilt"</string>
- <string name="menu_search" msgid="4826514464423239041">"Otsing"</string>
- <string name="menu_notifications" msgid="6424587053194766192">"Teadistused"</string>
- <string name="menu_settings" msgid="3946232973327980394">"Süsteemiseaded"</string>
- <string name="menu_help" msgid="4901160661634590633">"Abi"</string>
- <string name="cab_menu_delete_app" msgid="4089398025537640349">"Rakenduse desinstallimine"</string>
- <string name="cab_menu_app_info" msgid="914548323652698884">"Rakenduse üksikasjad"</string>
- <string name="cab_app_selection_text" msgid="6378522164293415735">"Valitud on 1 rakendus"</string>
- <string name="cab_widget_selection_text" msgid="962527270506951955">"1 vidin on valitud"</string>
- <string name="cab_folder_selection_text" msgid="8916111874189565067">"1 kaust on valitud"</string>
- <string name="cab_shortcut_selection_text" msgid="8115847384500412878">"1 otsetee on valitud"</string>
<string name="permlab_install_shortcut" msgid="1201690825493376489">"otseteede installimine"</string>
<string name="permdesc_install_shortcut" msgid="8634424803272077038">"Võimaldab rakendusel lisada otseteid kasutaja sekkumiseta."</string>
- <string name="permlab_uninstall_shortcut" msgid="7696645932555926449">"otseteede desinstallimine"</string>
- <string name="permdesc_uninstall_shortcut" msgid="274355570620220977">"Võimaldab rakendusel eemaldada otseteid kasutaja sekkumiseta."</string>
<string name="permlab_read_settings" msgid="3452408290738106747">"avalehe seadete ja otseteede lugemine"</string>
<string name="permdesc_read_settings" msgid="5788109303585403679">"Võimaldab rakendusel lugeda avalehe seadeid ja otseteid."</string>
<string name="permlab_write_settings" msgid="1360567537236705628">"avalehe seadete ja otseteede kirjutamine"</string>
<string name="permdesc_write_settings" msgid="8530105489115785531">"Võimaldab rakendusel muuta avalehel seadeid ja otseteid."</string>
<string name="gadget_error_text" msgid="8359351016167075858">"Probleem vidina laadimisel"</string>
<string name="uninstall_system_app_text" msgid="6429814133777046491">"See on süsteemirakendus ja seda ei saa desinstallida."</string>
- <string name="dream_name" msgid="2847171357608437154">"Rocket Launcher"</string>
<string name="folder_hint_text" msgid="8633351560105748141">"Nimeta kaust"</string>
- <string name="workspace_description_format" msgid="2968608205939373034">"Avakuva %1$d"</string>
<string name="default_scroll_format" msgid="4057140866420001240">"Leht %1$d/%2$d"</string>
<string name="workspace_scroll_format" msgid="1704767047951143301">"Avakuva %1$d/%2$d"</string>
- <string name="apps_customize_apps_scroll_format" msgid="5494241912377704885">"Rakenduste leht %1$d/%2$d"</string>
- <string name="apps_customize_widgets_scroll_format" msgid="5383009742241717437">"Vidinate leht %1$d/%2$d"</string>
- <string name="workspace_cling_title" msgid="738396473989890567">"Tunne end nagu kodus"</string>
- <string name="workspace_cling_move_item" msgid="791013895761065070">"Võite panna oma lemmikrakendused siia."</string>
- <string name="workspace_cling_open_all_apps" msgid="2459977609848572588">"Kõikide oma rakenduste nägemiseks puudutage ringi."</string>
- <string name="all_apps_cling_title" msgid="2559734712581447107">"Valige mõned rakendused"</string>
- <string name="all_apps_cling_add_item" msgid="5665035103260318891">"Rakenduse lisamiseks avakuvale puudutage seda pikalt."</string>
- <string name="folder_cling_title" msgid="4308949882377840953">"Korraldage oma rakendused kaustadesse"</string>
- <string name="folder_cling_move_item" msgid="270598675060435169">"Rakenduse liigutamiseks pange sõrm rakendusele ja hoidke seda."</string>
- <string name="folder_cling_create_folder" msgid="8352867485656129478">"Avakuval uue kausta tegemiseks virnastage üks rakendus teisele."</string>
- <string name="cling_dismiss" msgid="2780907108735868381">"OK"</string>
<string name="folder_opened" msgid="1262064100943801533">"Kaust on avatud, <xliff:g id="WIDTH">%1$d</xliff:g> x <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
<string name="folder_tap_to_close" msgid="1335478160661137579">"Puudutage kausta sulgemiseks"</string>
<string name="folder_tap_to_rename" msgid="5201612989905472442">"Puudutage uue nime salvestamiseks"</string>
<string name="folder_closed" msgid="3130534551370511932">"Kaust suletud"</string>
<string name="folder_renamed" msgid="7951233572858053642">"Kausta uus nimi: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="folder_name_format" msgid="3051680259794759037">"<xliff:g id="NAME">%1$s</xliff:g>"</string>
- <string name="custom_workspace_cling_title_1" msgid="1433009175359948587"></string>
- <string name="custom_workspace_cling_description_1" msgid="6875529190849858047"></string>
- <string name="custom_workspace_cling_title_2" msgid="5516006164661020362"></string>
- <string name="custom_workspace_cling_description_2" msgid="2758258454975288377"></string>
</resources>
diff --git a/res/values-eu-rES/strings.xml b/res/values-eu-rES/strings.xml
index e02479c0e..8bfca6cd1 100644
--- a/res/values-eu-rES/strings.xml
+++ b/res/values-eu-rES/strings.xml
@@ -20,57 +20,27 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="application_name" msgid="5181331383435256801">"Abiarazlea3"</string>
- <string name="home" msgid="7658288663002113681">"Hasiera"</string>
- <string name="uid_name" msgid="7820867637514617527">"Android-en nukleoko aplikazioak"</string>
<string name="folder_name" msgid="7371454440695724752"></string>
+ <string name="work_folder_name" msgid="3753320833950115786">"Lana"</string>
<string name="activity_not_found" msgid="8071924732094499514">"Aplikazioa instalatu gabe dago."</string>
<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="widgets_tab_label" msgid="2921133187116603919">"Widgetak"</string>
- <string name="widget_adder" msgid="3201040140710381657">"Widgetak"</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="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
- <string name="external_drop_widget_error" msgid="3165821058322217155">"Ezin izan da elementua hasierako pantailan jaregin."</string>
- <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Aukeratu sortu beharreko widgeta"</string>
- <string name="rename_folder_label" msgid="3727762225964550653">"Karpetaren izena"</string>
- <string name="rename_folder_title" msgid="3771389277707820891">"Aldatu karpetaren izena"</string>
- <string name="rename_action" msgid="5559600076028658757">"Ados"</string>
- <string name="cancel_action" msgid="7009134900002915310">"Utzi"</string>
- <string name="menu_item_add_item" msgid="1264911265836810421">"Gehitu hasierako pantailan"</string>
- <string name="group_applications" msgid="3797214114206693605">"Aplikazioak"</string>
- <string name="group_shortcuts" msgid="6012256992764410535">"Lasterbideak"</string>
- <string name="group_widgets" msgid="1569030723286851002">"Widgetak"</string>
- <string name="completely_out_of_space" msgid="6106288382070760318">"Hasierako pantailetan ez dago toki gehiago."</string>
+ <string name="all_apps_search_bar_hint" msgid="7084713969757597256">"Bilatu aplikazioetan"</string>
+ <string name="all_apps_loading_message" msgid="7557140873644765180">"Aplikazioak kargatzen…"</string>
+ <string name="all_apps_no_search_results" msgid="6332185285860416787">"Ez da aurkitu \"<xliff:g id="QUERY">%1$s</xliff:g>\" bilaketarekin bat datorren aplikaziorik"</string>
<string name="out_of_space" msgid="4691004494942118364">"Hasierako pantaila honetan ez dago toki gehiago."</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"Ez dago toki gehiago Gogokoak erretiluan"</string>
- <string name="invalid_hotseat_item" msgid="5779907847267573691">"Widgeta handiegia da Gogokoak erretiluan ezartzeko"</string>
- <string name="shortcut_installed" msgid="1701742129426969556">"\"<xliff:g id="NAME">%s</xliff:g>\" lasterbidea sortu da."</string>
- <string name="shortcut_uninstalled" msgid="8176767991305701821">"\"<xliff:g id="NAME">%s</xliff:g>\" lasterbidea kendu da."</string>
- <string name="shortcut_duplicate" msgid="9167217446062498127">"\"<xliff:g id="NAME">%s</xliff:g>\" lasterbidea lehendik dago."</string>
- <string name="title_select_shortcut" msgid="6680642571148153868">"Aukeratu lasterbidea"</string>
- <string name="title_select_application" msgid="3280812711670683644">"Aukeratu aplikazioa"</string>
<string name="all_apps_button_label" msgid="9110807029020582876">"Aplikazioak"</string>
<string name="all_apps_home_button_label" msgid="252062713717058851">"Hasiera"</string>
- <string name="delete_zone_label_workspace" msgid="4009607676751398685">"Kendu"</string>
- <string name="delete_zone_label_all_apps" msgid="8083826390278958980">"Desinstalatu"</string>
<string name="delete_target_label" msgid="1822697352535677073">"Kendu"</string>
<string name="delete_target_uninstall_label" msgid="5100785476250872595">"Desinstalatu"</string>
<string name="info_target_label" msgid="8053346143994679532">"Aplikazioaren informazioa"</string>
- <string name="accessibility_all_apps_button" msgid="2603132375383800483">"Aplikazioak"</string>
- <string name="accessibility_delete_button" msgid="6466114477993744621">"Kendu"</string>
- <string name="delete_zone_label_all_apps_system_app" msgid="449755632749610895">"Desinstalatu eguneratzea"</string>
- <string name="cab_menu_delete_app" msgid="7435191475867183689">"Desinstalatu aplikazioa"</string>
- <string name="cab_menu_app_info" msgid="8593722221450362342">"Aplikazioaren xehetasunak"</string>
- <string name="cab_app_selection_text" msgid="374688303047985416">"Aplikazio bat hautatu da"</string>
- <string name="cab_widget_selection_text" msgid="1833458597831541241">"Widget bat hautatu da"</string>
- <string name="cab_folder_selection_text" msgid="7999992513806132118">"Karpeta bat hautatu da"</string>
- <string name="cab_shortcut_selection_text" msgid="2103811025667946450">"Lasterbide bat hautatu da"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"Instalatu lasterbideak"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"Erabiltzaileak ezer egin gabe lasterbideak gehitzea baimentzen die aplikazioei."</string>
- <string name="permlab_uninstall_shortcut" msgid="864595034498083837">"Desinstalatu lasterbideak"</string>
- <string name="permdesc_uninstall_shortcut" msgid="5134129545001836849">"Erabiltzaileak ezer egin gabe lasterbideak kentzea baimentzen die aplikazioei."</string>
<string name="permlab_read_settings" msgid="1941457408239617576">"Irakurri hasierako ezarpenak eta lasterbideak"</string>
<string name="permdesc_read_settings" msgid="5833423719057558387">"Hasierako pantailako ezarpenak eta lasterbideak irakurtzea baimentzen die aplikazioei."</string>
<string name="permlab_write_settings" msgid="3574213698004620587">"Idatzi hasierako ezarpenak eta lasterbideak"</string>
@@ -78,30 +48,17 @@
<string name="gadget_error_text" msgid="6081085226050792095">"Arazo bat izan da widgeta kargatzean"</string>
<string name="gadget_setup_text" msgid="8274003207686040488">"Konfigurazioa"</string>
<string name="uninstall_system_app_text" msgid="4172046090762920660">"Sistema-aplikazioa da hau eta ezin da desinstalatu."</string>
- <string name="dream_name" msgid="1530253749244328964">"Rocket Launcher"</string>
<string name="folder_hint_text" msgid="6617836969016293992">"Izenik gabeko karpeta"</string>
- <string name="workspace_description_format" msgid="2950174241104043327">"%1$d hasierako pantaila"</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="apps_customize_apps_scroll_format" msgid="370005296147130238">"%1$d/%2$d aplikazio-orria"</string>
- <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"%1$d/%2$d widget-orria"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"Ongi etorri"</string>
- <string name="first_run_cling_description" msgid="6447072552696253358">"Pertsonalizatu hasierako pantaila nahieran."</string>
- <string name="first_run_cling_custom_content_hint" msgid="6090628589029352439"></string>
- <string name="first_run_cling_search_bar_hint" msgid="5909062802402452582"></string>
- <string name="first_run_cling_create_screens_hint" msgid="6950729526680114157">"Sortu pantaila gehiago aplikazioak eta karpetak ezartzeko"</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>
<string name="migration_cling_copy_apps" msgid="946331230090919440">"KOPIATU IKONOAK"</string>
<string name="migration_cling_use_default" msgid="2626475813981258626">"HASI HUTSETIK"</string>
- <string name="workspace_cling_title" msgid="5626202359865825661">"Antolatu zure txokoa"</string>
- <string name="workspace_cling_move_item" msgid="528201129978005352">"Eduki ukituta atzeko planoa horma-paperak, widgetak eta ezarpenak kudeatzeko."</string>
<string name="workspace_cling_longpress_title" msgid="9173998993909018310">"Horma-paperak, widgetak eta ezarpenak"</string>
<string name="workspace_cling_longpress_description" msgid="4119994475505235248">"Pertsonalizatzeko, eduki ukituta atzeko planoa"</string>
<string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"ADOS"</string>
- <string name="folder_cling_title" msgid="3894908818693254164">"Hortxe duzu karpeta"</string>
- <string name="folder_cling_create_folder" msgid="6158215559475836131">"Horrelako bat sortzeko, eduki ukituta aplikazio bat eta eraman beste baten gainera."</string>
- <string name="cling_dismiss" msgid="8962359497601507581">"Ados"</string>
<string name="folder_opened" msgid="94695026776264709">"Karpeta ireki da: <xliff:g id="WIDTH">%1$d</xliff:g> x <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
<string name="folder_tap_to_close" msgid="1884479294466410023">"Karpeta ixteko, uki ezazu"</string>
<string name="folder_tap_to_rename" msgid="9191075570492871147">"Karpetaren izen berria gordetzeko, uki ezazu"</string>
@@ -111,14 +68,34 @@
<string name="widget_button_text" msgid="2880537293434387943">"Widgetak"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"Horma-paperak"</string>
<string name="settings_button_text" msgid="8119458837558863227">"Ezarpenak"</string>
- <string name="package_state_enqueued" msgid="6227252464303085641">"Zain"</string>
- <string name="package_state_downloading" msgid="4088770468458724721">"Deskargatzen"</string>
- <string name="package_state_installing" msgid="7588193972189849870">"Instalatzen"</string>
+ <string name="allow_rotation_title" msgid="2118706734511831751">"Baimendu biratzeko aukera"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Ezezaguna"</string>
- <string name="package_state_error" msgid="7672093962724223588">"Ez da leheneratu"</string>
- <string name="abandoned_clean_all" msgid="5256770727689657618">"Kendu guztiak"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Kendu"</string>
<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="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>
+ <string name="item_removed" msgid="851119963877842327">"Kendu da elementua"</string>
+ <string name="action_move" msgid="4339390619886385032">"Mugitu elementua"</string>
+ <string name="move_to_empty_cell" msgid="2833711483015685619">"Eraman <xliff:g id="NUMBER_0">%1$s</xliff:g>. errenkadara, <xliff:g id="NUMBER_1">%2$s</xliff:g>. zutabera"</string>
+ <string name="move_to_position" msgid="6750008980455459790">"Eraman <xliff:g id="NUMBER">%1$s</xliff:g>. postura"</string>
+ <string name="move_to_hotseat_position" msgid="6295412897075147808">"Eraman gogokoen <xliff:g id="NUMBER">%1$s</xliff:g>. postura"</string>
+ <string name="item_moved" msgid="4606538322571412879">"Elementua mugitu da"</string>
+ <string name="add_to_folder" msgid="9040534766770853243">"Gehitu <xliff:g id="NAME">%1$s</xliff:g> karpetan"</string>
+ <string name="add_to_folder_with_app" msgid="4534929978967147231">"Gehitu <xliff:g id="NAME">%1$s</xliff:g> duen karpetan"</string>
+ <string name="added_to_folder" msgid="4793259502305558003">"Elementua karpetan gehitu da"</string>
+ <string name="create_folder_with" msgid="4050141361160214248">"Sortu karpeta <xliff:g id="NAME">%1$s</xliff:g> elementuarekin"</string>
+ <string name="folder_created" msgid="6409794597405184510">"Karpeta sortu da"</string>
+ <string name="action_move_to_workspace" msgid="1603837886334246317">"Eraman hasierako pantailara"</string>
+ <string name="action_move_screen_left" msgid="8854216831569401665">"Eraman pantaila ezkerrera"</string>
+ <string name="action_move_screen_right" msgid="329334910274311123">"Eraman pantaila eskuinera"</string>
+ <string name="screen_moved" msgid="266230079505650577">"Mugitu da pantaila"</string>
+ <string name="action_resize" msgid="1802976324781771067">"Aldatu tamaina"</string>
+ <string name="action_increase_width" msgid="8773715375078513326">"Handitu zabalera"</string>
+ <string name="action_increase_height" msgid="459390020612501122">"Handitu altuera"</string>
+ <string name="action_decrease_width" msgid="1374549771083094654">"Txikitu zabalera"</string>
+ <string name="action_decrease_height" msgid="282377193880900022">"Txikitu altuera"</string>
+ <string name="widget_resized" msgid="9130327887929620">"Aldatu da widgetaren tamaina. Zabalera: <xliff:g id="NUMBER_0">%1$s</xliff:g>. Altuera: <xliff:g id="NUMBER_1">%2$s</xliff:g>."</string>
</resources>
diff --git a/res/values-fa/strings.xml b/res/values-fa/strings.xml
index 924cccf75..701d59d50 100644
--- a/res/values-fa/strings.xml
+++ b/res/values-fa/strings.xml
@@ -20,57 +20,27 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="application_name" msgid="5181331383435256801">"Launcher3"</string>
- <string name="home" msgid="7658288663002113681">"صفحه اصلی"</string>
- <string name="uid_name" msgid="7820867637514617527">"‏برنامه‌های Android Core"</string>
<string name="folder_name" msgid="7371454440695724752"></string>
+ <string name="work_folder_name" msgid="3753320833950115786">"کاری"</string>
<string name="activity_not_found" msgid="8071924732094499514">"برنامه نصب نشده است."</string>
<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="widgets_tab_label" msgid="2921133187116603919">"ابزارک‌ها"</string>
- <string name="widget_adder" msgid="3201040140710381657">"ابزارک‌ها"</string>
<string name="toggle_weight_watcher" msgid="5645299835184636119">"‏نمایش Mem"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"برای انتخاب ابزارک لمس کنید و نگه دارید."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
- <string name="external_drop_widget_error" msgid="3165821058322217155">"این مورد را نمی‌توان در این صفحه اصلی رها کرد."</string>
- <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"انتخاب ابزارکی که باید ایجاد شود"</string>
- <string name="rename_folder_label" msgid="3727762225964550653">"نام پوشه"</string>
- <string name="rename_folder_title" msgid="3771389277707820891">"تغییر نام پوشه"</string>
- <string name="rename_action" msgid="5559600076028658757">"تأیید"</string>
- <string name="cancel_action" msgid="7009134900002915310">"لغو"</string>
- <string name="menu_item_add_item" msgid="1264911265836810421">"افزودن به صفحه اصلی"</string>
- <string name="group_applications" msgid="3797214114206693605">"برنامه‌ها"</string>
- <string name="group_shortcuts" msgid="6012256992764410535">"میان‌برها"</string>
- <string name="group_widgets" msgid="1569030723286851002">"ابزارک‌ها"</string>
- <string name="completely_out_of_space" msgid="6106288382070760318">"فضای بیشتری در صفحات نمایش اصلی شما موجود نیست."</string>
+ <string name="all_apps_search_bar_hint" msgid="7084713969757597256">"جستجوی برنامه‌ها"</string>
+ <string name="all_apps_loading_message" msgid="7557140873644765180">"در حال بارگیری برنامه‌ها..."</string>
+ <string name="all_apps_no_search_results" msgid="6332185285860416787">"هیچ برنامه‌ای مطابق با «<xliff:g id="QUERY">%1$s</xliff:g>» پیدا نشد"</string>
<string name="out_of_space" msgid="4691004494942118364">"فضای بیشتری در این صفحه اصلی موجود نیست."</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"فضای بیشتری در سینی موارد دلخواه وجود ندارد"</string>
- <string name="invalid_hotseat_item" msgid="5779907847267573691">"این ابزارک برای سینی موارد دلخواه بسیار بزرگ است"</string>
- <string name="shortcut_installed" msgid="1701742129426969556">"میان‌بر «<xliff:g id="NAME">%s</xliff:g>» ایجاد شد."</string>
- <string name="shortcut_uninstalled" msgid="8176767991305701821">"میان‌بر «<xliff:g id="NAME">%s</xliff:g>» حذف شد."</string>
- <string name="shortcut_duplicate" msgid="9167217446062498127">"میان‌بر «<xliff:g id="NAME">%s</xliff:g>» در حال حاضر وجود دارد."</string>
- <string name="title_select_shortcut" msgid="6680642571148153868">"انتخاب میان‌بر"</string>
- <string name="title_select_application" msgid="3280812711670683644">"انتخاب برنامه"</string>
<string name="all_apps_button_label" msgid="9110807029020582876">"برنامه‌ها"</string>
<string name="all_apps_home_button_label" msgid="252062713717058851">"صفحه اصلی"</string>
- <string name="delete_zone_label_workspace" msgid="4009607676751398685">"حذف"</string>
- <string name="delete_zone_label_all_apps" msgid="8083826390278958980">"حذف نصب"</string>
<string name="delete_target_label" msgid="1822697352535677073">"حذف"</string>
<string name="delete_target_uninstall_label" msgid="5100785476250872595">"حذف نصب"</string>
<string name="info_target_label" msgid="8053346143994679532">"اطلاعات برنامه"</string>
- <string name="accessibility_all_apps_button" msgid="2603132375383800483">"برنامه‌ها"</string>
- <string name="accessibility_delete_button" msgid="6466114477993744621">"حذف"</string>
- <string name="delete_zone_label_all_apps_system_app" msgid="449755632749610895">"حذف نصب به‌روزرسانی"</string>
- <string name="cab_menu_delete_app" msgid="7435191475867183689">"حذف نصب برنامه"</string>
- <string name="cab_menu_app_info" msgid="8593722221450362342">"جزئیات برنامه"</string>
- <string name="cab_app_selection_text" msgid="374688303047985416">"۱ برنامه انتخاب شد"</string>
- <string name="cab_widget_selection_text" msgid="1833458597831541241">"۱ ابزارک انتخاب شد"</string>
- <string name="cab_folder_selection_text" msgid="7999992513806132118">"۱ پوشه انتخاب شد"</string>
- <string name="cab_shortcut_selection_text" msgid="2103811025667946450">"۱ میان‌بر انتخاب شد"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"نصب میان‌برها"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"به برنامه اجازه می‌دهد میان‌برها را بدون دخالت کاربر اضافه کند."</string>
- <string name="permlab_uninstall_shortcut" msgid="864595034498083837">"حذف نصب میان‌برها"</string>
- <string name="permdesc_uninstall_shortcut" msgid="5134129545001836849">"به برنامه اجازه می‌دهد میان‌برها را بدون دخالت کاربر حذف کند."</string>
<string name="permlab_read_settings" msgid="1941457408239617576">"خواندن تنظیمات و میان‌برهای صفحه اصلی"</string>
<string name="permdesc_read_settings" msgid="5833423719057558387">"به برنامه اجازه می‌دهد تنظیمات و میان‌برها را در صفحه اصلی بخواند."</string>
<string name="permlab_write_settings" msgid="3574213698004620587">"نوشتن تنظیمات و میان‌برهای صفحه اصلی"</string>
@@ -78,30 +48,17 @@
<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>
- <string name="dream_name" msgid="1530253749244328964">"Rocket Launcher"</string>
<string name="folder_hint_text" msgid="6617836969016293992">"پوشه بی‌نام"</string>
- <string name="workspace_description_format" msgid="2950174241104043327">"‏صفحه اصلی %1$d"</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="apps_customize_apps_scroll_format" msgid="370005296147130238">"‏صفحه برنامه‌ها %1$d از %2$d"</string>
- <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"‏صفحه ابزارک‌ها %1$d از %2$d"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"خوش آمدید"</string>
- <string name="first_run_cling_description" msgid="6447072552696253358">"راحت باشید."</string>
- <string name="first_run_cling_custom_content_hint" msgid="6090628589029352439"></string>
- <string name="first_run_cling_search_bar_hint" msgid="5909062802402452582"></string>
- <string name="first_run_cling_create_screens_hint" msgid="6950729526680114157">"صفحات بیشتری را برای برنامه‌ها و پوشه‌ها ایجاد کنید"</string>
<string name="migration_cling_title" msgid="9181776667882933767">"کپی کردن نمادهای برنامه شما"</string>
<string name="migration_cling_description" msgid="2752413805582227644">"نمادها و پوشه‌ها از صفحه‌های اصلی قدیمی شما وارد شوند؟"</string>
<string name="migration_cling_copy_apps" msgid="946331230090919440">"کپی نمادها"</string>
<string name="migration_cling_use_default" msgid="2626475813981258626">"شروع تازه"</string>
- <string name="workspace_cling_title" msgid="5626202359865825661">"فضای خود را سازماندهی کنید"</string>
- <string name="workspace_cling_move_item" msgid="528201129978005352">"برای مدیریت کاغذدیواری، ابزارک‌ها و تنظیمات، پس‌زمینه را لمس کرده و نگه‌دارید."</string>
<string name="workspace_cling_longpress_title" msgid="9173998993909018310">"کاغذدیواری‌ها، ابزارک‌ها و تنظیمات"</string>
<string name="workspace_cling_longpress_description" msgid="4119994475505235248">"برای سفارشی کردن، پس‌زمینه را لمس کنید و نگه‌دارید"</string>
<string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"متوجه شدم"</string>
- <string name="folder_cling_title" msgid="3894908818693254164">"اینجا یک پوشه است"</string>
- <string name="folder_cling_create_folder" msgid="6158215559475836131">"برای ایجاد پوشه‌ای مثل این، یک برنامه را لمس کرده و نگه‌دارید، سپس آن را روی برنامه دیگر بیاندازید."</string>
- <string name="cling_dismiss" msgid="8962359497601507581">"تأیید"</string>
<string name="folder_opened" msgid="94695026776264709">"پوشه باز شده، <xliff:g id="WIDTH">%1$d</xliff:g> در <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
<string name="folder_tap_to_close" msgid="1884479294466410023">"برای بستن پوشه لمس کنید"</string>
<string name="folder_tap_to_rename" msgid="9191075570492871147">"برای ذخیره تغییر نام لمس کنید"</string>
@@ -111,14 +68,34 @@
<string name="widget_button_text" msgid="2880537293434387943">"ابزارک‌ها"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"کاغذدیواری‌ها"</string>
<string name="settings_button_text" msgid="8119458837558863227">"تنظیمات"</string>
- <string name="package_state_enqueued" msgid="6227252464303085641">"در حال انتظار"</string>
- <string name="package_state_downloading" msgid="4088770468458724721">"در حال دانلود"</string>
- <string name="package_state_installing" msgid="7588193972189849870">"در حال نصب"</string>
+ <string name="allow_rotation_title" msgid="2118706734511831751">"چرخش مجاز است"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"نامشخص"</string>
- <string name="package_state_error" msgid="7672093962724223588">"بازیابی نشد"</string>
- <string name="abandoned_clean_all" msgid="5256770727689657618">"حذف همه"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"حذف"</string>
<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="action_add_to_workspace" msgid="8902165848117513641">"افزودن به صفحه اصلی"</string>
+ <string name="action_move_here" msgid="2170188780612570250">"انتقال مورد به اینجا"</string>
+ <string name="item_added_to_workspace" msgid="4211073925752213539">"مورد به صفحه اصلی اضافه شد"</string>
+ <string name="item_removed" msgid="851119963877842327">"مورد حذف شد"</string>
+ <string name="action_move" msgid="4339390619886385032">"انتقال مورد"</string>
+ <string name="move_to_empty_cell" msgid="2833711483015685619">"انتقال به سطر <xliff:g id="NUMBER_0">%1$s</xliff:g> ستون <xliff:g id="NUMBER_1">%2$s</xliff:g>"</string>
+ <string name="move_to_position" msgid="6750008980455459790">"انتقال به موقعیت <xliff:g id="NUMBER">%1$s</xliff:g>"</string>
+ <string name="move_to_hotseat_position" msgid="6295412897075147808">"انتقال به موقعیت دلخواه <xliff:g id="NUMBER">%1$s</xliff:g>"</string>
+ <string name="item_moved" msgid="4606538322571412879">"مورد منتقل شد"</string>
+ <string name="add_to_folder" msgid="9040534766770853243">"افزودن به پوشه: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="add_to_folder_with_app" msgid="4534929978967147231">"افزودن به پوشه حاوی <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="added_to_folder" msgid="4793259502305558003">"مورد به پوشه اضافه شد"</string>
+ <string name="create_folder_with" msgid="4050141361160214248">"ایجاد پوشه با: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="folder_created" msgid="6409794597405184510">"پوشه ایجاد شد"</string>
+ <string name="action_move_to_workspace" msgid="1603837886334246317">"انتقال به صفحه اصلی"</string>
+ <string name="action_move_screen_left" msgid="8854216831569401665">"انتقال صفحه به چپ"</string>
+ <string name="action_move_screen_right" msgid="329334910274311123">"انتقال صفحه به راست"</string>
+ <string name="screen_moved" msgid="266230079505650577">"صفحه منتقل شد"</string>
+ <string name="action_resize" msgid="1802976324781771067">"تغییر اندازه"</string>
+ <string name="action_increase_width" msgid="8773715375078513326">"افزایش عرض"</string>
+ <string name="action_increase_height" msgid="459390020612501122">"افزایش ارتفاع"</string>
+ <string name="action_decrease_width" msgid="1374549771083094654">"کاهش عرض"</string>
+ <string name="action_decrease_height" msgid="282377193880900022">"کاهش ارتفاع"</string>
+ <string name="widget_resized" msgid="9130327887929620">"اندازه ابزارک به عرض <xliff:g id="NUMBER_0">%1$s</xliff:g> ارتفاع <xliff:g id="NUMBER_1">%2$s</xliff:g> تغییر کرد"</string>
</resources>
diff --git a/res/values-fi/strings.xml b/res/values-fi/strings.xml
index a5da03f43..f0766d68a 100644
--- a/res/values-fi/strings.xml
+++ b/res/values-fi/strings.xml
@@ -20,57 +20,27 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="application_name" msgid="5181331383435256801">"Launcher3"</string>
- <string name="home" msgid="7658288663002113681">"Aloitusruutu"</string>
- <string name="uid_name" msgid="7820867637514617527">"Androidin ydinsovellukset"</string>
<string name="folder_name" msgid="7371454440695724752"></string>
+ <string name="work_folder_name" msgid="3753320833950115786">"Työ"</string>
<string name="activity_not_found" msgid="8071924732094499514">"Sovellusta ei ole asennettu."</string>
<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="widgets_tab_label" msgid="2921133187116603919">"Widgetit"</string>
- <string name="widget_adder" msgid="3201040140710381657">"Widgetit"</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="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
- <string name="external_drop_widget_error" msgid="3165821058322217155">"Kohteen lisääminen tähän aloitusruutuun epäonnistui."</string>
- <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Valitse luotava widget"</string>
- <string name="rename_folder_label" msgid="3727762225964550653">"Kansion nimi"</string>
- <string name="rename_folder_title" msgid="3771389277707820891">"Nimeä kansio uudelleen"</string>
- <string name="rename_action" msgid="5559600076028658757">"OK"</string>
- <string name="cancel_action" msgid="7009134900002915310">"Peruuta"</string>
- <string name="menu_item_add_item" msgid="1264911265836810421">"Lisää aloitusruutuun"</string>
- <string name="group_applications" msgid="3797214114206693605">"Sovellukset"</string>
- <string name="group_shortcuts" msgid="6012256992764410535">"Pikakuvakkeet"</string>
- <string name="group_widgets" msgid="1569030723286851002">"Widgetit"</string>
- <string name="completely_out_of_space" msgid="6106288382070760318">"Aloitusruuduilla ei ole enää tilaa."</string>
+ <string name="all_apps_search_bar_hint" msgid="7084713969757597256">"Sovellushaku"</string>
+ <string name="all_apps_loading_message" msgid="7557140873644765180">"Ladataan sovelluksia…"</string>
+ <string name="all_apps_no_search_results" msgid="6332185285860416787">"”<xliff:g id="QUERY">%1$s</xliff:g>” ei palauttanut sovelluksia."</string>
<string name="out_of_space" msgid="4691004494942118364">"Tässä aloitusruudussa ei ole enää tilaa."</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"Suosikit-valikossa ei ole enää tilaa"</string>
- <string name="invalid_hotseat_item" msgid="5779907847267573691">"Tämä widget on liian suuri Suosikit-valikkoon lisättäväksi"</string>
- <string name="shortcut_installed" msgid="1701742129426969556">"Pikakuvake <xliff:g id="NAME">%s</xliff:g> luotiin."</string>
- <string name="shortcut_uninstalled" msgid="8176767991305701821">"Pikakuvake <xliff:g id="NAME">%s</xliff:g> poistettiin."</string>
- <string name="shortcut_duplicate" msgid="9167217446062498127">"Pikakuvake <xliff:g id="NAME">%s</xliff:g> on jo olemassa."</string>
- <string name="title_select_shortcut" msgid="6680642571148153868">"Valitse pikakuvake"</string>
- <string name="title_select_application" msgid="3280812711670683644">"Valitse sovellus"</string>
<string name="all_apps_button_label" msgid="9110807029020582876">"Sovellukset"</string>
<string name="all_apps_home_button_label" msgid="252062713717058851">"Aloitusruutu"</string>
- <string name="delete_zone_label_workspace" msgid="4009607676751398685">"Poista"</string>
- <string name="delete_zone_label_all_apps" msgid="8083826390278958980">"Poista"</string>
<string name="delete_target_label" msgid="1822697352535677073">"Poista"</string>
<string name="delete_target_uninstall_label" msgid="5100785476250872595">"Poista"</string>
<string name="info_target_label" msgid="8053346143994679532">"Sovelluksen tiedot"</string>
- <string name="accessibility_all_apps_button" msgid="2603132375383800483">"Sovellukset"</string>
- <string name="accessibility_delete_button" msgid="6466114477993744621">"Poista"</string>
- <string name="delete_zone_label_all_apps_system_app" msgid="449755632749610895">"Poista päivitys"</string>
- <string name="cab_menu_delete_app" msgid="7435191475867183689">"Poista sovellus"</string>
- <string name="cab_menu_app_info" msgid="8593722221450362342">"Sovelluksen tiedot"</string>
- <string name="cab_app_selection_text" msgid="374688303047985416">"1 sovellus valittu"</string>
- <string name="cab_widget_selection_text" msgid="1833458597831541241">"1 widget valittu"</string>
- <string name="cab_folder_selection_text" msgid="7999992513806132118">"1 kansio valittu"</string>
- <string name="cab_shortcut_selection_text" msgid="2103811025667946450">"1 pikakuvake valittu"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"asenna pikakuvakkeita"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"Antaa sovelluksen lisätä pikakuvakkeita itsenäisesti ilman käyttäjän valintaa."</string>
- <string name="permlab_uninstall_shortcut" msgid="864595034498083837">"poista pikakuvakkeita"</string>
- <string name="permdesc_uninstall_shortcut" msgid="5134129545001836849">"Antaa sovelluksen poistaa pikakuvakkeita ilman käyttäjän valintaa."</string>
<string name="permlab_read_settings" msgid="1941457408239617576">"lue aloitusruudun asetuksia ja pikakuvakkeita"</string>
<string name="permdesc_read_settings" msgid="5833423719057558387">"Antaa sovelluksen lukea aloitusruudun asetukset ja pikakuvakkeet."</string>
<string name="permlab_write_settings" msgid="3574213698004620587">"kirjoita aloitusruudun asetuksia ja pikakuvakkeita"</string>
@@ -78,30 +48,17 @@
<string name="gadget_error_text" msgid="6081085226050792095">"Ongelma ladattaessa widgetiä"</string>
<string name="gadget_setup_text" msgid="8274003207686040488">"Asetus"</string>
<string name="uninstall_system_app_text" msgid="4172046090762920660">"Tämä on järjestelmäsovellus, eikä sitä voi poistaa."</string>
- <string name="dream_name" msgid="1530253749244328964">"Sinko"</string>
<string name="folder_hint_text" msgid="6617836969016293992">"Nimetön kansio"</string>
- <string name="workspace_description_format" msgid="2950174241104043327">"Aloitusruutu %1$d"</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="apps_customize_apps_scroll_format" msgid="370005296147130238">"Apps-sivu %1$d / %2$d"</string>
- <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"Widgetit-sivu %1$d / %2$d"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"Tervetuloa"</string>
- <string name="first_run_cling_description" msgid="6447072552696253358">"Ole kuin kotonasi."</string>
- <string name="first_run_cling_custom_content_hint" msgid="6090628589029352439"></string>
- <string name="first_run_cling_search_bar_hint" msgid="5909062802402452582"></string>
- <string name="first_run_cling_create_screens_hint" msgid="6950729526680114157">"Luo lisää ruutuja sovelluksille ja kansioille"</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>
<string name="migration_cling_copy_apps" msgid="946331230090919440">"KOPIOI KUVAKKEET"</string>
<string name="migration_cling_use_default" msgid="2626475813981258626">"ALOITA ALUSTA"</string>
- <string name="workspace_cling_title" msgid="5626202359865825661">"Järjestä tilasi"</string>
- <string name="workspace_cling_move_item" msgid="528201129978005352">"Hallitse taustakuvaa, widgetejä ja asetuksia koskettamalla taustaa pitkään."</string>
<string name="workspace_cling_longpress_title" msgid="9173998993909018310">"Taustakuvat, widgetit ja asetukset"</string>
<string name="workspace_cling_longpress_description" msgid="4119994475505235248">"Muokkaa taustaa koskettamalla ja painamalla pitkään"</string>
<string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"SELVÄ"</string>
- <string name="folder_cling_title" msgid="3894908818693254164">"Tässä on kansio"</string>
- <string name="folder_cling_create_folder" msgid="6158215559475836131">"Luo se seuraavasti: kosketa sovellusta pitkään ja siirrä se sitten toisen päälle."</string>
- <string name="cling_dismiss" msgid="8962359497601507581">"OK"</string>
<string name="folder_opened" msgid="94695026776264709">"Kansio avattu, koko <xliff:g id="WIDTH">%1$d</xliff:g> x <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
<string name="folder_tap_to_close" msgid="1884479294466410023">"Sulje kansio koskettamalla"</string>
<string name="folder_tap_to_rename" msgid="9191075570492871147">"Tallenna uudella nimellä koskettamalla"</string>
@@ -111,14 +68,34 @@
<string name="widget_button_text" msgid="2880537293434387943">"Widgetit"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"Taustakuvat"</string>
<string name="settings_button_text" msgid="8119458837558863227">"Asetukset"</string>
- <string name="package_state_enqueued" msgid="6227252464303085641">"Odottaa"</string>
- <string name="package_state_downloading" msgid="4088770468458724721">"Ladataan"</string>
- <string name="package_state_installing" msgid="7588193972189849870">"Asennetaan"</string>
+ <string name="allow_rotation_title" msgid="2118706734511831751">"Salli kierto"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Tuntematon"</string>
- <string name="package_state_error" msgid="7672093962724223588">"Ei palautettu"</string>
- <string name="abandoned_clean_all" msgid="5256770727689657618">"Poista kaikki"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Poista"</string>
<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="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>
+ <string name="item_removed" msgid="851119963877842327">"Kohde poistettiin."</string>
+ <string name="action_move" msgid="4339390619886385032">"Siirrä kohde"</string>
+ <string name="move_to_empty_cell" msgid="2833711483015685619">"Siirrä rivin <xliff:g id="NUMBER_0">%1$s</xliff:g> sarakkeeseen <xliff:g id="NUMBER_1">%2$s</xliff:g>."</string>
+ <string name="move_to_position" msgid="6750008980455459790">"Siirrä kohtaan <xliff:g id="NUMBER">%1$s</xliff:g>."</string>
+ <string name="move_to_hotseat_position" msgid="6295412897075147808">"Siirrä suosikkien kohtaan <xliff:g id="NUMBER">%1$s</xliff:g>."</string>
+ <string name="item_moved" msgid="4606538322571412879">"Kohde on siirretty."</string>
+ <string name="add_to_folder" msgid="9040534766770853243">"Lisää kansioon <xliff:g id="NAME">%1$s</xliff:g>."</string>
+ <string name="add_to_folder_with_app" msgid="4534929978967147231">"Lisää samaan kansioon sovelluksen <xliff:g id="NAME">%1$s</xliff:g> kanssa."</string>
+ <string name="added_to_folder" msgid="4793259502305558003">"Kohde on lisätty kansioon."</string>
+ <string name="create_folder_with" msgid="4050141361160214248">"Luo kansio, jossa on <xliff:g id="NAME">%1$s</xliff:g>."</string>
+ <string name="folder_created" msgid="6409794597405184510">"Kansio on luotu."</string>
+ <string name="action_move_to_workspace" msgid="1603837886334246317">"Siirrä aloitusnäytölle"</string>
+ <string name="action_move_screen_left" msgid="8854216831569401665">"Siirrä näyttöä vasemmalle"</string>
+ <string name="action_move_screen_right" msgid="329334910274311123">"Siirrä näyttöä oikealle"</string>
+ <string name="screen_moved" msgid="266230079505650577">"Näyttö siirrettiin."</string>
+ <string name="action_resize" msgid="1802976324781771067">"Muuta kokoa"</string>
+ <string name="action_increase_width" msgid="8773715375078513326">"Lisää leveyttä"</string>
+ <string name="action_increase_height" msgid="459390020612501122">"Lisää korkeutta"</string>
+ <string name="action_decrease_width" msgid="1374549771083094654">"Vähennä leveyttä"</string>
+ <string name="action_decrease_height" msgid="282377193880900022">"Vähennä korkeutta"</string>
+ <string name="widget_resized" msgid="9130327887929620">"Widgetin kokoa muutettiin. Sen leveys on nyt <xliff:g id="NUMBER_0">%1$s</xliff:g> ja korkeus <xliff:g id="NUMBER_1">%2$s</xliff:g>."</string>
</resources>
diff --git a/res/values-fr-rCA/strings.xml b/res/values-fr-rCA/strings.xml
index 62a2b894e..0c19ef268 100644
--- a/res/values-fr-rCA/strings.xml
+++ b/res/values-fr-rCA/strings.xml
@@ -20,57 +20,27 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="application_name" msgid="5181331383435256801">"Lanceur3"</string>
- <string name="home" msgid="7658288663002113681">"Accueil"</string>
- <string name="uid_name" msgid="7820867637514617527">"Applications de base Android"</string>
<string name="folder_name" msgid="7371454440695724752"></string>
+ <string name="work_folder_name" msgid="3753320833950115786">"Travail"</string>
<string name="activity_not_found" msgid="8071924732094499514">"L\'application n\'est pas installée."</string>
<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="widgets_tab_label" msgid="2921133187116603919">"Widgets"</string>
- <string name="widget_adder" msgid="3201040140710381657">"Widgets"</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="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
- <string name="external_drop_widget_error" msgid="3165821058322217155">"Imposs. de déposer l\'élément sur l\'écran d\'accueil"</string>
- <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Sélectionnez le widget à créer"</string>
- <string name="rename_folder_label" msgid="3727762225964550653">"Nom du dossier"</string>
- <string name="rename_folder_title" msgid="3771389277707820891">"Renommer le dossier"</string>
- <string name="rename_action" msgid="5559600076028658757">"OK"</string>
- <string name="cancel_action" msgid="7009134900002915310">"Annuler"</string>
- <string name="menu_item_add_item" msgid="1264911265836810421">"Ajouter à l\'écran d\'accueil"</string>
- <string name="group_applications" msgid="3797214114206693605">"Applications"</string>
- <string name="group_shortcuts" msgid="6012256992764410535">"Raccourcis"</string>
- <string name="group_widgets" msgid="1569030723286851002">"Widgets"</string>
- <string name="completely_out_of_space" msgid="6106288382070760318">"Vous n\'avez plus d\'espace libre sur vos écrans d\'accueil."</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>
+ <string name="all_apps_no_search_results" msgid="6332185285860416787">"Aucune application trouvée correspondant à « <xliff:g id="QUERY">%1$s</xliff:g> »"</string>
<string name="out_of_space" msgid="4691004494942118364">"Pas d\'espace libre sur l\'écran d\'accueil."</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"Il n\'y a plus d\'espace dans la zone des favoris"</string>
- <string name="invalid_hotseat_item" msgid="5779907847267573691">"Ce widget est trop volumineux pour la zone des favoris"</string>
- <string name="shortcut_installed" msgid="1701742129426969556">"Le raccourci « <xliff:g id="NAME">%s</xliff:g> » a été créé."</string>
- <string name="shortcut_uninstalled" msgid="8176767991305701821">"Le raccourci « <xliff:g id="NAME">%s</xliff:g> » a été supprimé."</string>
- <string name="shortcut_duplicate" msgid="9167217446062498127">"Le raccourci « <xliff:g id="NAME">%s</xliff:g> » existe déjà."</string>
- <string name="title_select_shortcut" msgid="6680642571148153868">"Sélectionner un raccourci"</string>
- <string name="title_select_application" msgid="3280812711670683644">"Sélectionner une application"</string>
<string name="all_apps_button_label" msgid="9110807029020582876">"Applications"</string>
<string name="all_apps_home_button_label" msgid="252062713717058851">"Accueil"</string>
- <string name="delete_zone_label_workspace" msgid="4009607676751398685">"Supprimer"</string>
- <string name="delete_zone_label_all_apps" msgid="8083826390278958980">"Désinstaller"</string>
<string name="delete_target_label" msgid="1822697352535677073">"Supprimer"</string>
<string name="delete_target_uninstall_label" msgid="5100785476250872595">"Désinstaller"</string>
<string name="info_target_label" msgid="8053346143994679532">"Détails de l\'application"</string>
- <string name="accessibility_all_apps_button" msgid="2603132375383800483">"Applications"</string>
- <string name="accessibility_delete_button" msgid="6466114477993744621">"Supprimer"</string>
- <string name="delete_zone_label_all_apps_system_app" msgid="449755632749610895">"Désinstaller la mise à jour"</string>
- <string name="cab_menu_delete_app" msgid="7435191475867183689">"Désinstaller l\'application"</string>
- <string name="cab_menu_app_info" msgid="8593722221450362342">"Détails de l\'application"</string>
- <string name="cab_app_selection_text" msgid="374688303047985416">"1 application sélectionnée"</string>
- <string name="cab_widget_selection_text" msgid="1833458597831541241">"1 widget sélectionné"</string>
- <string name="cab_folder_selection_text" msgid="7999992513806132118">"1 dossier sélectionné"</string>
- <string name="cab_shortcut_selection_text" msgid="2103811025667946450">"1 raccourci sélectionné"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"installer des raccourcis"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"Permet à une application d\'ajouter des raccourcis sans l\'intervention de l\'utilisateur."</string>
- <string name="permlab_uninstall_shortcut" msgid="864595034498083837">"désinstaller des raccourcis"</string>
- <string name="permdesc_uninstall_shortcut" msgid="5134129545001836849">"Permet à l\'application de supprimer des raccourcis sans l\'intervention de l\'utilisateur."</string>
<string name="permlab_read_settings" msgid="1941457408239617576">"lire les paramètres et les raccourcis de la page d\'accueil"</string>
<string name="permdesc_read_settings" msgid="5833423719057558387">"Permet à l\'application de lire les paramètres et les raccourcis de l\'écran d\'accueil."</string>
<string name="permlab_write_settings" msgid="3574213698004620587">"enregistrer les paramètres de la page d\'accueil et des raccourcis"</string>
@@ -78,30 +48,17 @@
<string name="gadget_error_text" msgid="6081085226050792095">"Problème lors du chargement du widget"</string>
<string name="gadget_setup_text" msgid="8274003207686040488">"Configuration"</string>
<string name="uninstall_system_app_text" msgid="4172046090762920660">"Impossible de désinstaller cette application, car il s\'agit d\'une application système."</string>
- <string name="dream_name" msgid="1530253749244328964">"Lance-missile"</string>
<string name="folder_hint_text" msgid="6617836969016293992">"Dossier sans nom"</string>
- <string name="workspace_description_format" msgid="2950174241104043327">"Écran d\'accueil %1$d"</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="apps_customize_apps_scroll_format" msgid="370005296147130238">"Page des applications : %1$d sur %2$d"</string>
- <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"Page des widgets : %1$d sur %2$d"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"Bienvenue"</string>
- <string name="first_run_cling_description" msgid="6447072552696253358">"Faites comme chez vous."</string>
- <string name="first_run_cling_custom_content_hint" msgid="6090628589029352439"></string>
- <string name="first_run_cling_search_bar_hint" msgid="5909062802402452582"></string>
- <string name="first_run_cling_create_screens_hint" msgid="6950729526680114157">"Créer plus d\'écrans pour les applications et les dossiers"</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>
<string name="migration_cling_copy_apps" msgid="946331230090919440">"COPIER LES ICÔNES"</string>
<string name="migration_cling_use_default" msgid="2626475813981258626">"DISPOSITION PAR DÉFAUT"</string>
- <string name="workspace_cling_title" msgid="5626202359865825661">"Organiser son espace personnel"</string>
- <string name="workspace_cling_move_item" msgid="528201129978005352">"Maintenez votre doigt sur l\'arrière-plan pour gérer les fonds d\'écran, les widgets et les paramètres."</string>
<string name="workspace_cling_longpress_title" msgid="9173998993909018310">"Fonds d\'écran, widgets et paramètres"</string>
<string name="workspace_cling_longpress_description" msgid="4119994475505235248">"Maintenez le doigt sur le fond d\'écran pour personnaliser"</string>
<string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"J\'ai compris"</string>
- <string name="folder_cling_title" msgid="3894908818693254164">"Voici un dossier"</string>
- <string name="folder_cling_create_folder" msgid="6158215559475836131">"Pour créer un dossier comme ça, maintenez votre doigt sur une application, puis déplacez-la sur une autre."</string>
- <string name="cling_dismiss" msgid="8962359497601507581">"OK"</string>
<string name="folder_opened" msgid="94695026776264709">"Dossier ouvert, <xliff:g id="WIDTH">%1$d</xliff:g> par <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
<string name="folder_tap_to_close" msgid="1884479294466410023">"Toucher pour fermer le dossier"</string>
<string name="folder_tap_to_rename" msgid="9191075570492871147">"Toucher pour enregistrer le nouveau nom"</string>
@@ -111,14 +68,34 @@
<string name="widget_button_text" msgid="2880537293434387943">"Widgets"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"Fonds d\'écran"</string>
<string name="settings_button_text" msgid="8119458837558863227">"Paramètres"</string>
- <string name="package_state_enqueued" msgid="6227252464303085641">"En attente"</string>
- <string name="package_state_downloading" msgid="4088770468458724721">"Téléchargement..."</string>
- <string name="package_state_installing" msgid="7588193972189849870">"Installation…"</string>
+ <string name="allow_rotation_title" msgid="2118706734511831751">"Permettre la rotation"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Inconnu"</string>
- <string name="package_state_error" msgid="7672093962724223588">"Non restauré"</string>
- <string name="abandoned_clean_all" msgid="5256770727689657618">"Tout supprimer"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Supprimer"</string>
<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="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>
+ <string name="item_removed" msgid="851119963877842327">"Élément supprimé"</string>
+ <string name="action_move" msgid="4339390619886385032">"Déplacer l\'élément"</string>
+ <string name="move_to_empty_cell" msgid="2833711483015685619">"Déplacer vers rangée <xliff:g id="NUMBER_0">%1$s</xliff:g> colonne <xliff:g id="NUMBER_1">%2$s</xliff:g>"</string>
+ <string name="move_to_position" msgid="6750008980455459790">"Déplacer vers la position <xliff:g id="NUMBER">%1$s</xliff:g>"</string>
+ <string name="move_to_hotseat_position" msgid="6295412897075147808">"Déplacer vers la position <xliff:g id="NUMBER">%1$s</xliff:g> dans les favoris"</string>
+ <string name="item_moved" msgid="4606538322571412879">"Élément déplacé"</string>
+ <string name="add_to_folder" msgid="9040534766770853243">"Ajouter au dossier : <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="add_to_folder_with_app" msgid="4534929978967147231">"Ajouter au dossier contenant <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="added_to_folder" msgid="4793259502305558003">"Élément ajouté au dossier"</string>
+ <string name="create_folder_with" msgid="4050141361160214248">"Créer un dossier avec : <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="folder_created" msgid="6409794597405184510">"Dossier créé"</string>
+ <string name="action_move_to_workspace" msgid="1603837886334246317">"Déplacer sur l\'écran d\'accueil"</string>
+ <string name="action_move_screen_left" msgid="8854216831569401665">"Déplacer l\'écran à gauche"</string>
+ <string name="action_move_screen_right" msgid="329334910274311123">"Déplacer l\'écran à droite"</string>
+ <string name="screen_moved" msgid="266230079505650577">"Écran déplacé"</string>
+ <string name="action_resize" msgid="1802976324781771067">"Redimensionner"</string>
+ <string name="action_increase_width" msgid="8773715375078513326">"Augmenter la largeur"</string>
+ <string name="action_increase_height" msgid="459390020612501122">"Augmenter la hauteur"</string>
+ <string name="action_decrease_width" msgid="1374549771083094654">"Diminuer la largeur"</string>
+ <string name="action_decrease_height" msgid="282377193880900022">"Diminuer la hauteur"</string>
+ <string name="widget_resized" msgid="9130327887929620">"Le widget a été redimensionné (largeur : <xliff:g id="NUMBER_0">%1$s</xliff:g>, hauteur : <xliff:g id="NUMBER_1">%2$s</xliff:g>)"</string>
</resources>
diff --git a/res/values-fr/strings.xml b/res/values-fr/strings.xml
index d23b6a492..662bcf14e 100644
--- a/res/values-fr/strings.xml
+++ b/res/values-fr/strings.xml
@@ -20,57 +20,27 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="application_name" msgid="5181331383435256801">"Launcher3"</string>
- <string name="home" msgid="7658288663002113681">"Accueil"</string>
- <string name="uid_name" msgid="7820867637514617527">"Applications de base Android"</string>
<string name="folder_name" msgid="7371454440695724752"></string>
+ <string name="work_folder_name" msgid="3753320833950115786">"Android Work"</string>
<string name="activity_not_found" msgid="8071924732094499514">"L\'application n\'est pas installée."</string>
<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="widgets_tab_label" msgid="2921133187116603919">"Widgets"</string>
- <string name="widget_adder" msgid="3201040140710381657">"Widgets"</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="widget_dims_format" msgid="2370757736025621599">"%1$d x %2$d"</string>
- <string name="external_drop_widget_error" msgid="3165821058322217155">"Impossible de déposer élément sur écran d\'accueil."</string>
- <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Sélectionner le widget à créer"</string>
- <string name="rename_folder_label" msgid="3727762225964550653">"Nom du dossier"</string>
- <string name="rename_folder_title" msgid="3771389277707820891">"Renommer le dossier"</string>
- <string name="rename_action" msgid="5559600076028658757">"OK"</string>
- <string name="cancel_action" msgid="7009134900002915310">"Annuler"</string>
- <string name="menu_item_add_item" msgid="1264911265836810421">"Ajouter à l\'écran d\'accueil"</string>
- <string name="group_applications" msgid="3797214114206693605">"Applications"</string>
- <string name="group_shortcuts" msgid="6012256992764410535">"Raccourcis"</string>
- <string name="group_widgets" msgid="1569030723286851002">"Widgets"</string>
- <string name="completely_out_of_space" msgid="6106288382070760318">"Vous n\'avez plus d\'espace libre sur vos écrans d\'accueil."</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>
+ <string name="all_apps_no_search_results" msgid="6332185285860416787">"Aucune application ne correspond à la requête \"<xliff:g id="QUERY">%1$s</xliff:g>\"."</string>
<string name="out_of_space" msgid="4691004494942118364">"Pas d\'espace libre sur cet écran d\'accueil."</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"Plus d\'espace disponible dans la zone de favoris."</string>
- <string name="invalid_hotseat_item" msgid="5779907847267573691">"Ce widget est trop volumineux pour la zone de favoris."</string>
- <string name="shortcut_installed" msgid="1701742129426969556">"Le raccourci \"<xliff:g id="NAME">%s</xliff:g>\" a été créé."</string>
- <string name="shortcut_uninstalled" msgid="8176767991305701821">"Le raccourci \"<xliff:g id="NAME">%s</xliff:g>\" a été supprimé."</string>
- <string name="shortcut_duplicate" msgid="9167217446062498127">"Le raccourci \"<xliff:g id="NAME">%s</xliff:g>\" existe déjà."</string>
- <string name="title_select_shortcut" msgid="6680642571148153868">"Sélectionner un raccourci"</string>
- <string name="title_select_application" msgid="3280812711670683644">"Sélectionner une application"</string>
<string name="all_apps_button_label" msgid="9110807029020582876">"Applications"</string>
<string name="all_apps_home_button_label" msgid="252062713717058851">"Accueil"</string>
- <string name="delete_zone_label_workspace" msgid="4009607676751398685">"Supprimer"</string>
- <string name="delete_zone_label_all_apps" msgid="8083826390278958980">"Désinstaller"</string>
<string name="delete_target_label" msgid="1822697352535677073">"Supprimer"</string>
<string name="delete_target_uninstall_label" msgid="5100785476250872595">"Désinstaller"</string>
<string name="info_target_label" msgid="8053346143994679532">"Informations sur l\'application"</string>
- <string name="accessibility_all_apps_button" msgid="2603132375383800483">"Applications"</string>
- <string name="accessibility_delete_button" msgid="6466114477993744621">"Supprimer"</string>
- <string name="delete_zone_label_all_apps_system_app" msgid="449755632749610895">"Désinstaller la mise à jour"</string>
- <string name="cab_menu_delete_app" msgid="7435191475867183689">"Désinstaller l\'application"</string>
- <string name="cab_menu_app_info" msgid="8593722221450362342">"Informations sur l\'application"</string>
- <string name="cab_app_selection_text" msgid="374688303047985416">"1 application sélectionnée"</string>
- <string name="cab_widget_selection_text" msgid="1833458597831541241">"1 widget sélectionné"</string>
- <string name="cab_folder_selection_text" msgid="7999992513806132118">"1 dossier sélectionné"</string>
- <string name="cab_shortcut_selection_text" msgid="2103811025667946450">"1 raccourci sélectionné"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"installer des raccourcis"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"Permettre à une application d\'ajouter des raccourcis sans l\'intervention de l\'utilisateur"</string>
- <string name="permlab_uninstall_shortcut" msgid="864595034498083837">"désinstaller des raccourcis"</string>
- <string name="permdesc_uninstall_shortcut" msgid="5134129545001836849">"Permettre à l\'application de supprimer des raccourcis sans l\'intervention de l\'utilisateur"</string>
<string name="permlab_read_settings" msgid="1941457408239617576">"lire les paramètres et les raccourcis de l\'écran d\'accueil"</string>
<string name="permdesc_read_settings" msgid="5833423719057558387">"Permettre à l\'application de lire les paramètres et les raccourcis de l\'écran d\'accueil"</string>
<string name="permlab_write_settings" msgid="3574213698004620587">"modifier les paramètres et les raccourcis de l\'écran d\'accueil"</string>
@@ -78,30 +48,17 @@
<string name="gadget_error_text" msgid="6081085226050792095">"Problème lors du chargement du widget."</string>
<string name="gadget_setup_text" msgid="8274003207686040488">"Configuration"</string>
<string name="uninstall_system_app_text" msgid="4172046090762920660">"Impossible de désinstaller cette application, car il s\'agit d\'une application système."</string>
- <string name="dream_name" msgid="1530253749244328964">"Rocket Launcher"</string>
<string name="folder_hint_text" msgid="6617836969016293992">"Dossier sans nom"</string>
- <string name="workspace_description_format" msgid="2950174241104043327">"Écran d\'accueil %1$d"</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="apps_customize_apps_scroll_format" msgid="370005296147130238">"Page des applications %1$d sur %2$d"</string>
- <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"Page des widgets %1$d sur %2$d"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"Bienvenue"</string>
- <string name="first_run_cling_description" msgid="6447072552696253358">"Familiarisez-vous avec l\'écran d\'accueil."</string>
- <string name="first_run_cling_custom_content_hint" msgid="6090628589029352439"></string>
- <string name="first_run_cling_search_bar_hint" msgid="5909062802402452582"></string>
- <string name="first_run_cling_create_screens_hint" msgid="6950729526680114157">"Créez des écrans personnalisés pour vos applis et dossiers"</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>
<string name="migration_cling_copy_apps" msgid="946331230090919440">"COPIER LES ICÔNES"</string>
<string name="migration_cling_use_default" msgid="2626475813981258626">"DISPOSITION PAR DÉFAUT"</string>
- <string name="workspace_cling_title" msgid="5626202359865825661">"Organisez votre espace"</string>
- <string name="workspace_cling_move_item" msgid="528201129978005352">"Appuyez de manière prolongée sur l\'arrière-plan pour gérer les fonds d\'écran, les widgets et les paramètres."</string>
<string name="workspace_cling_longpress_title" msgid="9173998993909018310">"Fonds d\'écran, widgets et paramètres"</string>
<string name="workspace_cling_longpress_description" msgid="4119994475505235248">"Appuyez de manière prolongée sur l\'arrière-plan pour le personnaliser."</string>
<string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"OK"</string>
- <string name="folder_cling_title" msgid="3894908818693254164">"Voici un dossier"</string>
- <string name="folder_cling_create_folder" msgid="6158215559475836131">"Pour en créer un, appuyez de manière prolongée sur une application, puis déplacez-la vers une autre."</string>
- <string name="cling_dismiss" msgid="8962359497601507581">"OK"</string>
<string name="folder_opened" msgid="94695026776264709">"Dossier ouvert, <xliff:g id="WIDTH">%1$d</xliff:g> par <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
<string name="folder_tap_to_close" msgid="1884479294466410023">"Appuyez pour fermer le dossier."</string>
<string name="folder_tap_to_rename" msgid="9191075570492871147">"Appuyez pour enregistrer le nouveau nom."</string>
@@ -111,14 +68,34 @@
<string name="widget_button_text" msgid="2880537293434387943">"Widgets"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"Fonds d\'écran"</string>
<string name="settings_button_text" msgid="8119458837558863227">"Paramètres"</string>
- <string name="package_state_enqueued" msgid="6227252464303085641">"En attente"</string>
- <string name="package_state_downloading" msgid="4088770468458724721">"Téléchargement…"</string>
- <string name="package_state_installing" msgid="7588193972189849870">"Installation…"</string>
+ <string name="allow_rotation_title" msgid="2118706734511831751">"Autoriser la rotation"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Inconnu"</string>
- <string name="package_state_error" msgid="7672093962724223588">"Non restauré"</string>
- <string name="abandoned_clean_all" msgid="5256770727689657618">"Tout supprimer"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Supprimer"</string>
<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="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>
+ <string name="item_removed" msgid="851119963877842327">"L\'élément a bien été supprimé."</string>
+ <string name="action_move" msgid="4339390619886385032">"Déplacer l\'élément"</string>
+ <string name="move_to_empty_cell" msgid="2833711483015685619">"Déplacer vers la ligne <xliff:g id="NUMBER_0">%1$s</xliff:g>, colonne <xliff:g id="NUMBER_1">%2$s</xliff:g>"</string>
+ <string name="move_to_position" msgid="6750008980455459790">"Déplacer vers la position <xliff:g id="NUMBER">%1$s</xliff:g>"</string>
+ <string name="move_to_hotseat_position" msgid="6295412897075147808">"Déplacer vers la position <xliff:g id="NUMBER">%1$s</xliff:g> dans les favoris"</string>
+ <string name="item_moved" msgid="4606538322571412879">"Élément déplacé"</string>
+ <string name="add_to_folder" msgid="9040534766770853243">"Ajouter au dossier \"<xliff:g id="NAME">%1$s</xliff:g>\""</string>
+ <string name="add_to_folder_with_app" msgid="4534929978967147231">"Ajouter au dossier contenant \"<xliff:g id="NAME">%1$s</xliff:g>\""</string>
+ <string name="added_to_folder" msgid="4793259502305558003">"Élément ajouté au dossier"</string>
+ <string name="create_folder_with" msgid="4050141361160214248">"Créer un dossier avec \"<xliff:g id="NAME">%1$s</xliff:g>\""</string>
+ <string name="folder_created" msgid="6409794597405184510">"Dossier créé"</string>
+ <string name="action_move_to_workspace" msgid="1603837886334246317">"Déplacer vers l\'écran d\'accueil"</string>
+ <string name="action_move_screen_left" msgid="8854216831569401665">"Déplacer l\'écran vers la gauche"</string>
+ <string name="action_move_screen_right" msgid="329334910274311123">"Déplacer l\'écran vers la droite"</string>
+ <string name="screen_moved" msgid="266230079505650577">"L\'écran a bien été déplacé."</string>
+ <string name="action_resize" msgid="1802976324781771067">"Redimensionner"</string>
+ <string name="action_increase_width" msgid="8773715375078513326">"Augmenter la largeur"</string>
+ <string name="action_increase_height" msgid="459390020612501122">"Augmenter la hauteur"</string>
+ <string name="action_decrease_width" msgid="1374549771083094654">"Diminuer la largeur"</string>
+ <string name="action_decrease_height" msgid="282377193880900022">"Diminuer la hauteur"</string>
+ <string name="widget_resized" msgid="9130327887929620">"Le widget a bien été redimensionné (largeur : <xliff:g id="NUMBER_0">%1$s</xliff:g>, hauteur : <xliff:g id="NUMBER_1">%2$s</xliff:g>)."</string>
</resources>
diff --git a/res/values-gl-rES/strings.xml b/res/values-gl-rES/strings.xml
index 96a53dc09..6cf76a7c0 100644
--- a/res/values-gl-rES/strings.xml
+++ b/res/values-gl-rES/strings.xml
@@ -20,57 +20,27 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="application_name" msgid="5181331383435256801">"Launcher3"</string>
- <string name="home" msgid="7658288663002113681">"Inicio"</string>
- <string name="uid_name" msgid="7820867637514617527">"Aplicacións básicas de Android"</string>
<string name="folder_name" msgid="7371454440695724752"></string>
+ <string name="work_folder_name" msgid="3753320833950115786">"Traballo"</string>
<string name="activity_not_found" msgid="8071924732094499514">"A aplicación non está instalada"</string>
<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="widgets_tab_label" msgid="2921133187116603919">"Widgets"</string>
- <string name="widget_adder" msgid="3201040140710381657">"Widgets"</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="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
- <string name="external_drop_widget_error" msgid="3165821058322217155">"Non se puido engadir á pantalla de inicio."</string>
- <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Escolle o widget que queiras crear"</string>
- <string name="rename_folder_label" msgid="3727762225964550653">"Nome do cartafol"</string>
- <string name="rename_folder_title" msgid="3771389277707820891">"Cambiar o nome do cartafol"</string>
- <string name="rename_action" msgid="5559600076028658757">"Aceptar"</string>
- <string name="cancel_action" msgid="7009134900002915310">"Cancelar"</string>
- <string name="menu_item_add_item" msgid="1264911265836810421">"Engadir á pantalla de inicio"</string>
- <string name="group_applications" msgid="3797214114206693605">"Aplicacións"</string>
- <string name="group_shortcuts" msgid="6012256992764410535">"Atallos"</string>
- <string name="group_widgets" msgid="1569030723286851002">"Widgets"</string>
- <string name="completely_out_of_space" msgid="6106288382070760318">"Non hai máis espazo nas pantallas de inicio."</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>
+ <string name="all_apps_no_search_results" msgid="6332185285860416787">"Non se atoparon aplicacións que coincidan con \"<xliff:g id="QUERY">%1$s</xliff:g>\""</string>
<string name="out_of_space" msgid="4691004494942118364">"Non hai máis espazo nesta pantalla de inicio."</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"Non hai máis espazo na bandexa de favoritos"</string>
- <string name="invalid_hotseat_item" msgid="5779907847267573691">"Este widget é demasiado grande para a bandexa de favoritos"</string>
- <string name="shortcut_installed" msgid="1701742129426969556">"Creouse o atallo \"<xliff:g id="NAME">%s</xliff:g>\"."</string>
- <string name="shortcut_uninstalled" msgid="8176767991305701821">"Eliminouse o atallo \"<xliff:g id="NAME">%s</xliff:g>\"."</string>
- <string name="shortcut_duplicate" msgid="9167217446062498127">"O atallo \"<xliff:g id="NAME">%s</xliff:g>\" xa existe."</string>
- <string name="title_select_shortcut" msgid="6680642571148153868">"Escoller un atallo"</string>
- <string name="title_select_application" msgid="3280812711670683644">"Escoller unha aplicación"</string>
<string name="all_apps_button_label" msgid="9110807029020582876">"Aplicacións"</string>
<string name="all_apps_home_button_label" msgid="252062713717058851">"Inicio"</string>
- <string name="delete_zone_label_workspace" msgid="4009607676751398685">"Eliminar"</string>
- <string name="delete_zone_label_all_apps" msgid="8083826390278958980">"Desinstalar"</string>
<string name="delete_target_label" msgid="1822697352535677073">"Eliminar"</string>
<string name="delete_target_uninstall_label" msgid="5100785476250872595">"Desinstalar"</string>
<string name="info_target_label" msgid="8053346143994679532">"Información da aplicación"</string>
- <string name="accessibility_all_apps_button" msgid="2603132375383800483">"Aplicacións"</string>
- <string name="accessibility_delete_button" msgid="6466114477993744621">"Eliminar"</string>
- <string name="delete_zone_label_all_apps_system_app" msgid="449755632749610895">"Desinstalar actualización"</string>
- <string name="cab_menu_delete_app" msgid="7435191475867183689">"Desinstalar aplicación"</string>
- <string name="cab_menu_app_info" msgid="8593722221450362342">"Detalles da aplicación"</string>
- <string name="cab_app_selection_text" msgid="374688303047985416">"1 aplicación seleccionada"</string>
- <string name="cab_widget_selection_text" msgid="1833458597831541241">"1 widget seleccionado"</string>
- <string name="cab_folder_selection_text" msgid="7999992513806132118">"1 cartafol seleccionado"</string>
- <string name="cab_shortcut_selection_text" msgid="2103811025667946450">"1 atallo seleccionado"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"instalar atallos"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"Permite a unha aplicación engadir atallos sen intervención do usuario."</string>
- <string name="permlab_uninstall_shortcut" msgid="864595034498083837">"desinstalar atallos"</string>
- <string name="permdesc_uninstall_shortcut" msgid="5134129545001836849">"Permite a unha aplicación eliminar atallos sen intervención do usuario."</string>
<string name="permlab_read_settings" msgid="1941457408239617576">"ler a configuración e os atallos da pantalla de inicio"</string>
<string name="permdesc_read_settings" msgid="5833423719057558387">"Permite a unha aplicación ler a configuración e os atallos da páxina de inicio."</string>
<string name="permlab_write_settings" msgid="3574213698004620587">"modificar a configuración e os atallos da pantalla de inicio"</string>
@@ -78,30 +48,17 @@
<string name="gadget_error_text" msgid="6081085226050792095">"Produciuse un problema ao cargar o widget"</string>
<string name="gadget_setup_text" msgid="8274003207686040488">"Configuración"</string>
<string name="uninstall_system_app_text" msgid="4172046090762920660">"Esta aplicación é do sistema e non se pode desinstalar."</string>
- <string name="dream_name" msgid="1530253749244328964">"Lanzacohetes"</string>
<string name="folder_hint_text" msgid="6617836969016293992">"Cartafol sen nome"</string>
- <string name="workspace_description_format" msgid="2950174241104043327">"Pantalla de inicio %1$d"</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="apps_customize_apps_scroll_format" msgid="370005296147130238">"Páxina de aplicacións %1$d de %2$d"</string>
- <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"Páxina de widgets %1$d de %2$d"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"Dámosche a benvida"</string>
- <string name="first_run_cling_description" msgid="6447072552696253358">"Síntete como na túa casa."</string>
- <string name="first_run_cling_custom_content_hint" msgid="6090628589029352439"></string>
- <string name="first_run_cling_search_bar_hint" msgid="5909062802402452582"></string>
- <string name="first_run_cling_create_screens_hint" msgid="6950729526680114157">"Crea máis pantallas para aplicacións e cartafoles"</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>
<string name="migration_cling_copy_apps" msgid="946331230090919440">"COPIAR ICONAS"</string>
<string name="migration_cling_use_default" msgid="2626475813981258626">"COMEZAR DE CERO"</string>
- <string name="workspace_cling_title" msgid="5626202359865825661">"Organiza o espazo"</string>
- <string name="workspace_cling_move_item" msgid="528201129978005352">"Mantén premido o fondo para xestionar o fondo de pantalla e máis."</string>
<string name="workspace_cling_longpress_title" msgid="9173998993909018310">"Fondos pantalla, widgets e configuración"</string>
<string name="workspace_cling_longpress_description" msgid="4119994475505235248">"Mantén tocado o segundo plano para personalizar"</string>
<string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"DE ACORDO"</string>
- <string name="folder_cling_title" msgid="3894908818693254164">"Isto é un cartafol"</string>
- <string name="folder_cling_create_folder" msgid="6158215559475836131">"Para crear un igual, mantén premida a aplicación e móvea sobre outra."</string>
- <string name="cling_dismiss" msgid="8962359497601507581">"Aceptar"</string>
<string name="folder_opened" msgid="94695026776264709">"Abriuse o cartafol, <xliff:g id="WIDTH">%1$d</xliff:g> por <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
<string name="folder_tap_to_close" msgid="1884479294466410023">"Toca para pechar o cartafol"</string>
<string name="folder_tap_to_rename" msgid="9191075570492871147">"Toca para gardar o cambio de nome"</string>
@@ -111,14 +68,34 @@
<string name="widget_button_text" msgid="2880537293434387943">"Widgets"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"Fondos de pantalla"</string>
<string name="settings_button_text" msgid="8119458837558863227">"Configuración"</string>
- <string name="package_state_enqueued" msgid="6227252464303085641">"En espera"</string>
- <string name="package_state_downloading" msgid="4088770468458724721">"Descargando"</string>
- <string name="package_state_installing" msgid="7588193972189849870">"Instalando"</string>
+ <string name="allow_rotation_title" msgid="2118706734511831751">"Permitir xiro"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Descoñecido"</string>
- <string name="package_state_error" msgid="7672093962724223588">"Non restaurado"</string>
- <string name="abandoned_clean_all" msgid="5256770727689657618">"Eliminar todas"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Eliminar"</string>
<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="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>
+ <string name="item_removed" msgid="851119963877842327">"Eliminouse o elemento"</string>
+ <string name="action_move" msgid="4339390619886385032">"Mover elemento"</string>
+ <string name="move_to_empty_cell" msgid="2833711483015685619">"Mover á fila <xliff:g id="NUMBER_0">%1$s</xliff:g> columna <xliff:g id="NUMBER_1">%2$s</xliff:g>"</string>
+ <string name="move_to_position" msgid="6750008980455459790">"Mover á posición <xliff:g id="NUMBER">%1$s</xliff:g>"</string>
+ <string name="move_to_hotseat_position" msgid="6295412897075147808">"Mover á posición dos favoritos <xliff:g id="NUMBER">%1$s</xliff:g>"</string>
+ <string name="item_moved" msgid="4606538322571412879">"Moveuse o elemento"</string>
+ <string name="add_to_folder" msgid="9040534766770853243">"Engadir ao cartafol: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="add_to_folder_with_app" msgid="4534929978967147231">"Engadir ao cartafol con <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="added_to_folder" msgid="4793259502305558003">"Engadiuse o elemento ao cartafol"</string>
+ <string name="create_folder_with" msgid="4050141361160214248">"Crear cartafol con: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="folder_created" msgid="6409794597405184510">"Creouse o cartafol"</string>
+ <string name="action_move_to_workspace" msgid="1603837886334246317">"Mover á pantalla de inicio"</string>
+ <string name="action_move_screen_left" msgid="8854216831569401665">"Mover pantalla á esquerda"</string>
+ <string name="action_move_screen_right" msgid="329334910274311123">"Mover pantalla á dereita"</string>
+ <string name="screen_moved" msgid="266230079505650577">"Moveuse a pantalla"</string>
+ <string name="action_resize" msgid="1802976324781771067">"Cambiar tamaño"</string>
+ <string name="action_increase_width" msgid="8773715375078513326">"Aumentar ancho"</string>
+ <string name="action_increase_height" msgid="459390020612501122">"Aumentar altura"</string>
+ <string name="action_decrease_width" msgid="1374549771083094654">"Reducir ancho"</string>
+ <string name="action_decrease_height" msgid="282377193880900022">"Reducir altura"</string>
+ <string name="widget_resized" msgid="9130327887929620">"Cambiouse o tamaño do widget polo ancho <xliff:g id="NUMBER_0">%1$s</xliff:g> e a altura <xliff:g id="NUMBER_1">%2$s</xliff:g>"</string>
</resources>
diff --git a/res/values-gu-rIN/strings.xml b/res/values-gu-rIN/strings.xml
index a2798d6b9..4a2274f1b 100644
--- a/res/values-gu-rIN/strings.xml
+++ b/res/values-gu-rIN/strings.xml
@@ -20,57 +20,27 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="application_name" msgid="5181331383435256801">"Launcher3"</string>
- <string name="home" msgid="7658288663002113681">"હોમ"</string>
- <string name="uid_name" msgid="7820867637514617527">"Android Core એપ્લિકેશન્સ"</string>
<string name="folder_name" msgid="7371454440695724752"></string>
+ <string name="work_folder_name" msgid="3753320833950115786">"કાર્યાલય"</string>
<string name="activity_not_found" msgid="8071924732094499514">"એપ્લિકેશન ઇન્સ્ટોલ થઈ નથી."</string>
<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="widgets_tab_label" msgid="2921133187116603919">"વિજેટ્સ"</string>
- <string name="widget_adder" msgid="3201040140710381657">"વિજેટ્સ"</string>
- <string name="toggle_weight_watcher" msgid="5645299835184636119">"Mem દર્શાવો"</string>
+ <string name="toggle_weight_watcher" msgid="5645299835184636119">"Mem બતાવો"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"વિજેટ ચૂંટવા માટે ટચ કરો અને પકડી રાખો."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
- <string name="external_drop_widget_error" msgid="3165821058322217155">"આ હોમ સ્ક્રીન પર આઇટમ છોડી શકાઈ નથી."</string>
- <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"બનાવવા માટે વિજેટ પસંદ કરો"</string>
- <string name="rename_folder_label" msgid="3727762225964550653">"ફોલ્ડરનું નામ"</string>
- <string name="rename_folder_title" msgid="3771389277707820891">"ફોલ્ડરનું નામ બદલો"</string>
- <string name="rename_action" msgid="5559600076028658757">"ઑકે"</string>
- <string name="cancel_action" msgid="7009134900002915310">"રદ કરો"</string>
- <string name="menu_item_add_item" msgid="1264911265836810421">"હોમ સ્ક્રીન પર ઉમેરો"</string>
- <string name="group_applications" msgid="3797214114206693605">"એપ્લિકેશન્સ"</string>
- <string name="group_shortcuts" msgid="6012256992764410535">"શોર્ટકટ્સ"</string>
- <string name="group_widgets" msgid="1569030723286851002">"વિજેટ્સ"</string>
- <string name="completely_out_of_space" msgid="6106288382070760318">"તમારી હોમ સ્ક્રીન પર વધુ જગ્યા નથી."</string>
+ <string name="all_apps_search_bar_hint" msgid="7084713969757597256">"શોધ એપ્લિકેશનો"</string>
+ <string name="all_apps_loading_message" msgid="7557140873644765180">"એપ્લિકેશનો લોડ કરી રહ્યું છે…"</string>
+ <string name="all_apps_no_search_results" msgid="6332185285860416787">"\"<xliff:g id="QUERY">%1$s</xliff:g>\" થી મેળ ખાતી કોઈ એપ્લિકેશનો મળી નથી"</string>
<string name="out_of_space" msgid="4691004494942118364">"આ હોમ સ્ક્રીન પર વધુ જગ્યા નથી."</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"મનપસંદ ટ્રે પર વધુ જગ્યા નથી"</string>
- <string name="invalid_hotseat_item" msgid="5779907847267573691">"મનપસંદ ટ્રે માટે આ વિજેટ ખૂબ મોટું છે"</string>
- <string name="shortcut_installed" msgid="1701742129426969556">"\"<xliff:g id="NAME">%s</xliff:g>\" શોર્ટકટ બનાવ્યું."</string>
- <string name="shortcut_uninstalled" msgid="8176767991305701821">"\"<xliff:g id="NAME">%s</xliff:g>\" શોર્ટકટ દૂર કર્યું હતું."</string>
- <string name="shortcut_duplicate" msgid="9167217446062498127">"\"<xliff:g id="NAME">%s</xliff:g>\" શોર્ટકટ પહેલાંથી અસ્તિત્વમાં છે."</string>
- <string name="title_select_shortcut" msgid="6680642571148153868">"શોર્ટકટ પસંદ કરો"</string>
- <string name="title_select_application" msgid="3280812711670683644">"એપ્લિકેશન પસંદ કરો"</string>
- <string name="all_apps_button_label" msgid="9110807029020582876">"એપ્લિકેશન્સ"</string>
+ <string name="all_apps_button_label" msgid="9110807029020582876">"એપ્લિકેશનો"</string>
<string name="all_apps_home_button_label" msgid="252062713717058851">"હોમ"</string>
- <string name="delete_zone_label_workspace" msgid="4009607676751398685">"દૂર કરો"</string>
- <string name="delete_zone_label_all_apps" msgid="8083826390278958980">"અનઇન્સ્ટોલ કરો"</string>
<string name="delete_target_label" msgid="1822697352535677073">"દૂર કરો"</string>
<string name="delete_target_uninstall_label" msgid="5100785476250872595">"અનઇન્સ્ટોલ કરો"</string>
<string name="info_target_label" msgid="8053346143994679532">"એપ્લિકેશન માહિતી"</string>
- <string name="accessibility_all_apps_button" msgid="2603132375383800483">"એપ્લિકેશન્સ"</string>
- <string name="accessibility_delete_button" msgid="6466114477993744621">"દૂર કરો"</string>
- <string name="delete_zone_label_all_apps_system_app" msgid="449755632749610895">"અપડેટ અનઇન્સ્ટોલ કરો"</string>
- <string name="cab_menu_delete_app" msgid="7435191475867183689">"એપ્લિકેશન અનઇન્સ્ટોલ કરો"</string>
- <string name="cab_menu_app_info" msgid="8593722221450362342">"એપ્લિકેશનની વિગતો"</string>
- <string name="cab_app_selection_text" msgid="374688303047985416">"1 એપ્લિકેશન પસંદ કરી"</string>
- <string name="cab_widget_selection_text" msgid="1833458597831541241">"1 વિજેટ પસંદ કર્યું"</string>
- <string name="cab_folder_selection_text" msgid="7999992513806132118">"1 ફોલ્ડર પસંદ કર્યું"</string>
- <string name="cab_shortcut_selection_text" msgid="2103811025667946450">"1 શોર્ટકટ પસંદ કર્યું"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"શોર્ટકટ્સ ઇન્સ્ટોલ કરો"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"એપ્લિકેશનને વપરાશકર્તા હસ્તક્ષેપ વગર શોર્ટકટ્સ ઉમેરવાની મંજૂરી આપે છે."</string>
- <string name="permlab_uninstall_shortcut" msgid="864595034498083837">"શોર્ટકટ્સ અનઇન્સ્ટોલ કરો"</string>
- <string name="permdesc_uninstall_shortcut" msgid="5134129545001836849">"એપ્લિકેશનને વપરાશકર્તા હસ્તક્ષેપ વગર શોર્ટકટ્સ દૂર કરવાની મંજૂરી આપે છે."</string>
<string name="permlab_read_settings" msgid="1941457408239617576">"હોમ સેટિંગ્સ અને શોર્ટકટ્સ વાંચો"</string>
<string name="permdesc_read_settings" msgid="5833423719057558387">"એપ્લિકેશનને હોમમાં સેટિંગ્સ અને શોર્ટકટ્સ વાંચવાની મંજૂરી આપે છે."</string>
<string name="permlab_write_settings" msgid="3574213698004620587">"હોમ સેટિંગ્સ અને શોર્ટકટ્સ લખો"</string>
@@ -78,30 +48,17 @@
<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>
- <string name="dream_name" msgid="1530253749244328964">"રોકેટ લોન્ચર"</string>
<string name="folder_hint_text" msgid="6617836969016293992">"અનામી ફોલ્ડર"</string>
- <string name="workspace_description_format" msgid="2950174241104043327">"%1$d હોમ સ્ક્રીન"</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="apps_customize_apps_scroll_format" msgid="370005296147130238">"%2$d માંથી %1$d એપ્લિકેશન્સ પૃષ્ઠ"</string>
- <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"%2$d માંથી %1$d વિજેટ્સ પૃષ્ઠ"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"સ્વાગત છે"</string>
- <string name="first_run_cling_description" msgid="6447072552696253358">"ઘરે જાતે બનાવે છે."</string>
- <string name="first_run_cling_custom_content_hint" msgid="6090628589029352439"></string>
- <string name="first_run_cling_search_bar_hint" msgid="5909062802402452582"></string>
- <string name="first_run_cling_create_screens_hint" msgid="6950729526680114157">"એપ્લિકેશન્સ અને ફોલ્ડર્સ માટે વધુ સ્ક્રીન બનાવો"</string>
<string name="migration_cling_title" msgid="9181776667882933767">"તમારા એપ્લિકેશન આયકન્સને કૉપિ કરો"</string>
<string name="migration_cling_description" msgid="2752413805582227644">"તમારી જૂની હોમ સ્ક્રીન્સથી આયકન્સ અને ફોલ્ડર્સને આયાત કરીએ?"</string>
<string name="migration_cling_copy_apps" msgid="946331230090919440">"આયકન્સને કૉપિ કરો"</string>
<string name="migration_cling_use_default" msgid="2626475813981258626">"નવેસરથી પ્રારંભ કરો"</string>
- <string name="workspace_cling_title" msgid="5626202359865825661">"તમારા સ્થાનને ગોઠવો"</string>
- <string name="workspace_cling_move_item" msgid="528201129978005352">"વૉલપેપર, વિજેટ્સ અને સેટિંગ્સને સંચાલિત કરવા માટે પૃષ્ઠભૂમિને ટચ કરો અને પકડી રાખો."</string>
<string name="workspace_cling_longpress_title" msgid="9173998993909018310">"વૉલપેપર્સ, વિજેટ્સ અને સેટિંગ્સ"</string>
<string name="workspace_cling_longpress_description" msgid="4119994475505235248">"પૃષ્ઠભૂમિને કસ્ટમાઇઝ કરવા માટે ટચ કરો અને પકડી રાખો"</string>
<string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"સમજાઈ ગયું"</string>
- <string name="folder_cling_title" msgid="3894908818693254164">"અહીં ફોલ્ડર છે"</string>
- <string name="folder_cling_create_folder" msgid="6158215559475836131">"આના જેવું એક બનાવવા માટે, એપ્લિકેશનને ટચ કરો અને પકડી રાખો, પછી તેને બીજીમાં ખસેડો."</string>
- <string name="cling_dismiss" msgid="8962359497601507581">"ઑકે"</string>
<string name="folder_opened" msgid="94695026776264709">"<xliff:g id="WIDTH">%1$d</xliff:g> બાય <xliff:g id="HEIGHT">%2$d</xliff:g> નું ફોલ્ડર ખોલ્યું"</string>
<string name="folder_tap_to_close" msgid="1884479294466410023">"ફોલ્ડર બંધ કરવા માટે ટચ કરો"</string>
<string name="folder_tap_to_rename" msgid="9191075570492871147">"નામ બદલવાનું સાચવવા માટે ટચ કરો"</string>
@@ -111,14 +68,34 @@
<string name="widget_button_text" msgid="2880537293434387943">"વિજેટ્સ"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"વૉલપેપર્સ"</string>
<string name="settings_button_text" msgid="8119458837558863227">"સેટિંગ્સ"</string>
- <string name="package_state_enqueued" msgid="6227252464303085641">"રાહ જુએ છે"</string>
- <string name="package_state_downloading" msgid="4088770468458724721">"ડાઉનલોડ કરે છે"</string>
- <string name="package_state_installing" msgid="7588193972189849870">"ઇન્સ્ટોલ કરી રહ્યું છે"</string>
+ <string name="allow_rotation_title" msgid="2118706734511831751">"પરિભ્રમણને મંજૂરી આપો"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"અજાણ્યો"</string>
- <string name="package_state_error" msgid="7672093962724223588">"પુનર્સ્થાપિત કર્યું નથી"</string>
- <string name="abandoned_clean_all" msgid="5256770727689657618">"બધું દૂર કરો"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"દૂર કરો"</string>
<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="action_add_to_workspace" msgid="8902165848117513641">"હોમ સ્ક્રીન પર ઉમેરો"</string>
+ <string name="action_move_here" msgid="2170188780612570250">"આઇટમ અહીં ખસેડો"</string>
+ <string name="item_added_to_workspace" msgid="4211073925752213539">"હોમ સ્ક્રીનમાં આઇટમ ઉમેરી"</string>
+ <string name="item_removed" msgid="851119963877842327">"આઇટમ દૂર કરી"</string>
+ <string name="action_move" msgid="4339390619886385032">"આઇટમ ખસેડો"</string>
+ <string name="move_to_empty_cell" msgid="2833711483015685619">"<xliff:g id="NUMBER_0">%1$s</xliff:g> પંક્તિ <xliff:g id="NUMBER_1">%2$s</xliff:g> કૉલમ પર ખસેડો"</string>
+ <string name="move_to_position" msgid="6750008980455459790">"<xliff:g id="NUMBER">%1$s</xliff:g> સ્થિતિ પર ખસેડો"</string>
+ <string name="move_to_hotseat_position" msgid="6295412897075147808">"મનપસંદ સ્થિતિ <xliff:g id="NUMBER">%1$s</xliff:g> પર ખસેડો"</string>
+ <string name="item_moved" msgid="4606538322571412879">"આઇટમ ખસેડી"</string>
+ <string name="add_to_folder" msgid="9040534766770853243">"ફોલ્ડરમાં ઉમેરો: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="add_to_folder_with_app" msgid="4534929978967147231">"<xliff:g id="NAME">%1$s</xliff:g> સાથે ફોલ્ડરમાં ઉમેરો"</string>
+ <string name="added_to_folder" msgid="4793259502305558003">"ફોલ્ડરમાં આઇટમ ઉમેરી"</string>
+ <string name="create_folder_with" msgid="4050141361160214248">"આની સાથે ફોલ્ડર બનાવો: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="folder_created" msgid="6409794597405184510">"ફોલ્ડર બનાવ્યું"</string>
+ <string name="action_move_to_workspace" msgid="1603837886334246317">"હોમ સ્ક્રીન પર ખસેડો"</string>
+ <string name="action_move_screen_left" msgid="8854216831569401665">"સ્ક્રીનને ડાબી બાજુ ખસેડો"</string>
+ <string name="action_move_screen_right" msgid="329334910274311123">"સ્ક્રીનને જમણી બાજુ ખસેડો"</string>
+ <string name="screen_moved" msgid="266230079505650577">"સ્ક્રીન ખસેડી"</string>
+ <string name="action_resize" msgid="1802976324781771067">"આકાર બદલો"</string>
+ <string name="action_increase_width" msgid="8773715375078513326">"પહોળાઈ વધારો"</string>
+ <string name="action_increase_height" msgid="459390020612501122">"ઊંચાઈ વધારો"</string>
+ <string name="action_decrease_width" msgid="1374549771083094654">"પહોળાઈ ઘટાડો"</string>
+ <string name="action_decrease_height" msgid="282377193880900022">"ઊંચાઈ ઘટાડો"</string>
+ <string name="widget_resized" msgid="9130327887929620">"વિજેટનો આકાર બદલીને <xliff:g id="NUMBER_0">%1$s</xliff:g> પહોળાઈ <xliff:g id="NUMBER_1">%2$s</xliff:g> ઊંચાઈ કર્યો"</string>
</resources>
diff --git a/res/values-hi/strings.xml b/res/values-hi/strings.xml
index 0599da0e8..6fdbf2441 100644
--- a/res/values-hi/strings.xml
+++ b/res/values-hi/strings.xml
@@ -20,57 +20,27 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="application_name" msgid="5181331383435256801">"Launcher3"</string>
- <string name="home" msgid="7658288663002113681">"होम"</string>
- <string name="uid_name" msgid="7820867637514617527">"Android के मुख्य ऐप्लिकेशन"</string>
<string name="folder_name" msgid="7371454440695724752"></string>
+ <string name="work_folder_name" msgid="3753320833950115786">"कार्यस्‍थल"</string>
<string name="activity_not_found" msgid="8071924732094499514">"एप्‍लिकेशन इंस्‍टॉल नहीं है."</string>
<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="widgets_tab_label" msgid="2921133187116603919">"शॉर्टकट"</string>
- <string name="widget_adder" msgid="3201040140710381657">"शॉर्टकट"</string>
<string name="toggle_weight_watcher" msgid="5645299835184636119">"मेमोरी दिखाएं"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"विजेट को चुनने के लिए स्‍पर्श करके रखें."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
- <string name="external_drop_widget_error" msgid="3165821058322217155">"आइटम को इस होम स्‍क्रीन पर नहीं छोड़ा जा सका."</string>
- <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"बनाने के लिए विजेट चुनें"</string>
- <string name="rename_folder_label" msgid="3727762225964550653">"फ़ोल्‍डर का नाम"</string>
- <string name="rename_folder_title" msgid="3771389277707820891">"फ़ोल्‍डर का नाम बदलें"</string>
- <string name="rename_action" msgid="5559600076028658757">"ठीक"</string>
- <string name="cancel_action" msgid="7009134900002915310">"अभी नहीं"</string>
- <string name="menu_item_add_item" msgid="1264911265836810421">"होम स्‍क्रीन में जोड़ें"</string>
- <string name="group_applications" msgid="3797214114206693605">"ऐप्लिकेशन"</string>
- <string name="group_shortcuts" msgid="6012256992764410535">"शॉर्टकट"</string>
- <string name="group_widgets" msgid="1569030723286851002">"शॉर्टकट"</string>
- <string name="completely_out_of_space" msgid="6106288382070760318">"आपकी होम स्‍क्रीन पर स्थान शेष नहीं है."</string>
+ <string name="all_apps_search_bar_hint" msgid="7084713969757597256">"ऐप्‍स खोजें"</string>
+ <string name="all_apps_loading_message" msgid="7557140873644765180">"ऐप्स लोड हो रहे हैं..."</string>
+ <string name="all_apps_no_search_results" msgid="6332185285860416787">"\"<xliff:g id="QUERY">%1$s</xliff:g>\" से मिलान करने वाला कोई ऐप नहीं मिला"</string>
<string name="out_of_space" msgid="4691004494942118364">"इस होम स्‍क्रीन पर स्थान शेष नहीं है."</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"पसंदीदा ट्रे में और स्थान नहीं है"</string>
- <string name="invalid_hotseat_item" msgid="5779907847267573691">"पसंदीदा ट्रे के लिए यह विजेट बहुत ही बड़ा है"</string>
- <string name="shortcut_installed" msgid="1701742129426969556">"शॉर्टकट \"<xliff:g id="NAME">%s</xliff:g>\" बनाया गया."</string>
- <string name="shortcut_uninstalled" msgid="8176767991305701821">"शॉर्टकट \"<xliff:g id="NAME">%s</xliff:g>\" निकाल दिया गया था."</string>
- <string name="shortcut_duplicate" msgid="9167217446062498127">"शॉर्टकट \"<xliff:g id="NAME">%s</xliff:g>\" पहले से मौजूद है."</string>
- <string name="title_select_shortcut" msgid="6680642571148153868">"शॉर्टकट चुनें"</string>
- <string name="title_select_application" msgid="3280812711670683644">"एप्‍लिकेशन चुनें"</string>
<string name="all_apps_button_label" msgid="9110807029020582876">"ऐप्लिकेशन"</string>
<string name="all_apps_home_button_label" msgid="252062713717058851">"होम"</string>
- <string name="delete_zone_label_workspace" msgid="4009607676751398685">"निकालें"</string>
- <string name="delete_zone_label_all_apps" msgid="8083826390278958980">"अनइंस्टॉल करें"</string>
<string name="delete_target_label" msgid="1822697352535677073">"निकालें"</string>
<string name="delete_target_uninstall_label" msgid="5100785476250872595">"अनइंस्टॉल करें"</string>
<string name="info_target_label" msgid="8053346143994679532">"ऐप्लिकेशन की जानकारी"</string>
- <string name="accessibility_all_apps_button" msgid="2603132375383800483">"ऐप्लिकेशन"</string>
- <string name="accessibility_delete_button" msgid="6466114477993744621">"निकालें"</string>
- <string name="delete_zone_label_all_apps_system_app" msgid="449755632749610895">"अपडेट अनइंस्‍टॉल करें"</string>
- <string name="cab_menu_delete_app" msgid="7435191475867183689">"ऐप्लिकेशन अनइंस्‍टॉल करें"</string>
- <string name="cab_menu_app_info" msgid="8593722221450362342">"ऐप्लिकेशन का विवरण"</string>
- <string name="cab_app_selection_text" msgid="374688303047985416">"1 एप्‍लिकेशन चयनित"</string>
- <string name="cab_widget_selection_text" msgid="1833458597831541241">"1 विजेट चयनित"</string>
- <string name="cab_folder_selection_text" msgid="7999992513806132118">"1 फ़ोल्‍डर चयनित"</string>
- <string name="cab_shortcut_selection_text" msgid="2103811025667946450">"1 शॉर्टकट चयनित"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"शॉर्टकट इंस्‍टॉल करें"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"ऐप्लिकेशन को उपयोगकर्ता के हस्‍तक्षेप के बिना शॉर्टकट जोड़ने देती है."</string>
- <string name="permlab_uninstall_shortcut" msgid="864595034498083837">"शॉर्टकट अनइंस्टॉल करें"</string>
- <string name="permdesc_uninstall_shortcut" msgid="5134129545001836849">"ऐप्लिकेशन को उपयोगकर्ता के हस्‍तक्षेप के बिना शॉर्टकट निकालने देती है."</string>
<string name="permlab_read_settings" msgid="1941457408239617576">"होम सेटिंग और शॉर्टकट पढ़ें"</string>
<string name="permdesc_read_settings" msgid="5833423719057558387">"ऐप्लिकेशन को होम में सेटिंग और शॉर्टकट पढ़ने देती है."</string>
<string name="permlab_write_settings" msgid="3574213698004620587">"होम सेटिंग और शॉर्टकट लिखें"</string>
@@ -78,30 +48,17 @@
<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>
- <string name="dream_name" msgid="1530253749244328964">"रॉकेट लॉन्‍चर"</string>
<string name="folder_hint_text" msgid="6617836969016293992">"अनामित फ़ोल्डर"</string>
- <string name="workspace_description_format" msgid="2950174241104043327">"होम स्‍क्रीन %1$d"</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="apps_customize_apps_scroll_format" msgid="370005296147130238">"ऐप्लिकेशन पृष्ठ %2$d में से %1$d"</string>
- <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"शॉर्टकट %2$d में से %1$d"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"स्वागत है"</string>
- <string name="first_run_cling_description" msgid="6447072552696253358">"जैसा चाहें वैसा उपयोग करें."</string>
- <string name="first_run_cling_custom_content_hint" msgid="6090628589029352439"></string>
- <string name="first_run_cling_search_bar_hint" msgid="5909062802402452582"></string>
- <string name="first_run_cling_create_screens_hint" msgid="6950729526680114157">"ऐप्लिकेशन और फ़ोल्डर के लिए और अधिक स्क्रीन बनाएं"</string>
<string name="migration_cling_title" msgid="9181776667882933767">"ऐप्स आइकन की प्रतिलिपि बनाएं"</string>
<string name="migration_cling_description" msgid="2752413805582227644">"अपनी पुरानी होम स्क्रीन से आइकन और फ़ोल्डर आयात करें?"</string>
<string name="migration_cling_copy_apps" msgid="946331230090919440">"आइकन की प्रतिलिपि बनाएं"</string>
<string name="migration_cling_use_default" msgid="2626475813981258626">"फिर से शुरू करें"</string>
- <string name="workspace_cling_title" msgid="5626202359865825661">"अपने स्थान को व्यवस्थित करें"</string>
- <string name="workspace_cling_move_item" msgid="528201129978005352">"वॉलपेपर, शॉर्टकट और सेटिंग प्रबंधित करने के लिए पृष्ठभूमि को स्पर्श करके रखें."</string>
<string name="workspace_cling_longpress_title" msgid="9173998993909018310">"वॉलपेपर, शॉर्टकट और सेटिंग"</string>
<string name="workspace_cling_longpress_description" msgid="4119994475505235248">"पृष्ठभूमि कस्टमाइज़ करने के लिए स्पर्श करके रखें"</string>
<string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"समझ लिया"</string>
- <string name="folder_cling_title" msgid="3894908818693254164">"यहां एक फ़ोल्डर है"</string>
- <string name="folder_cling_create_folder" msgid="6158215559475836131">"इसके जैसा कोई एक बनाने के लिए, किसी ऐप्लिकेशन को स्पर्श करके रखें, फिर इसे किसी दूसरे पर ले जाएं."</string>
- <string name="cling_dismiss" msgid="8962359497601507581">"ठीक"</string>
<string name="folder_opened" msgid="94695026776264709">"फ़ोल्डर खोला गया, <xliff:g id="WIDTH">%1$d</xliff:g> गुणा <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
<string name="folder_tap_to_close" msgid="1884479294466410023">"फ़ोल्‍डर बंद करने के लिए स्‍पर्श करें"</string>
<string name="folder_tap_to_rename" msgid="9191075570492871147">"बदला गया नाम सहेजने के लिए स्पर्श करें"</string>
@@ -111,14 +68,34 @@
<string name="widget_button_text" msgid="2880537293434387943">"शॉर्टकट"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"वॉलपेपर"</string>
<string name="settings_button_text" msgid="8119458837558863227">"सेटिंग"</string>
- <string name="package_state_enqueued" msgid="6227252464303085641">"प्रतीक्षा में"</string>
- <string name="package_state_downloading" msgid="4088770468458724721">"डाउनलोड हो रहा है"</string>
- <string name="package_state_installing" msgid="7588193972189849870">"इंस्टॉल हो रहा है"</string>
+ <string name="allow_rotation_title" msgid="2118706734511831751">"रोटेशन की अनुमति दें"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"अज्ञात"</string>
- <string name="package_state_error" msgid="7672093962724223588">"पुन:स्थापित नहीं हुआ"</string>
- <string name="abandoned_clean_all" msgid="5256770727689657618">"सभी निकालें"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"निकालें"</string>
<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="action_add_to_workspace" msgid="8902165848117513641">"होम स्‍क्रीन में जोड़ें"</string>
+ <string name="action_move_here" msgid="2170188780612570250">"आइटम यहां ले जाएं"</string>
+ <string name="item_added_to_workspace" msgid="4211073925752213539">"होम स्क्रीन में आइटम जोड़ा गया"</string>
+ <string name="item_removed" msgid="851119963877842327">"आइटम निकाला गया"</string>
+ <string name="action_move" msgid="4339390619886385032">"आइटम ले जाएं"</string>
+ <string name="move_to_empty_cell" msgid="2833711483015685619">"पंक्ति <xliff:g id="NUMBER_0">%1$s</xliff:g> स्तंभ <xliff:g id="NUMBER_1">%2$s</xliff:g> पर ले जाएं"</string>
+ <string name="move_to_position" msgid="6750008980455459790">"<xliff:g id="NUMBER">%1$s</xliff:g> स्थिति पर ले जाएं"</string>
+ <string name="move_to_hotseat_position" msgid="6295412897075147808">"<xliff:g id="NUMBER">%1$s</xliff:g> की पसंदीदा स्थिति पर ले जाएं"</string>
+ <string name="item_moved" msgid="4606538322571412879">"आइटम ले जाया गया"</string>
+ <string name="add_to_folder" msgid="9040534766770853243">"फ़ोल्डर में जोड़ें: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="add_to_folder_with_app" msgid="4534929978967147231">"<xliff:g id="NAME">%1$s</xliff:g> के साथ फ़ोल्डर में जोड़ें"</string>
+ <string name="added_to_folder" msgid="4793259502305558003">"आइटम फ़ोल्डर में जोड़ा गया"</string>
+ <string name="create_folder_with" msgid="4050141361160214248">"इसके साथ फ़ोल्डर बनाएं: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="folder_created" msgid="6409794597405184510">"फ़ोल्डर बनाया गया"</string>
+ <string name="action_move_to_workspace" msgid="1603837886334246317">"होम स्क्रीन पर ले जाएं"</string>
+ <string name="action_move_screen_left" msgid="8854216831569401665">"स्क्रीन को बाएं ले जाएं"</string>
+ <string name="action_move_screen_right" msgid="329334910274311123">"स्क्रीन को दाएं ले जाएं"</string>
+ <string name="screen_moved" msgid="266230079505650577">"स्क्रीन ले जाई गई"</string>
+ <string name="action_resize" msgid="1802976324781771067">"आकार बदलें"</string>
+ <string name="action_increase_width" msgid="8773715375078513326">"चौड़ाई बढ़ाएं"</string>
+ <string name="action_increase_height" msgid="459390020612501122">"ऊंचाई बढ़ाएं"</string>
+ <string name="action_decrease_width" msgid="1374549771083094654">"चौड़ाई घटाएं"</string>
+ <string name="action_decrease_height" msgid="282377193880900022">"ऊंचाई घटाएं"</string>
+ <string name="widget_resized" msgid="9130327887929620">"विजेट का आकार बदलकर उसकी चौड़ाई <xliff:g id="NUMBER_0">%1$s</xliff:g> और ऊंचाई <xliff:g id="NUMBER_1">%2$s</xliff:g> कर दी गई"</string>
</resources>
diff --git a/res/values-hr/strings.xml b/res/values-hr/strings.xml
index 00810a76c..a54a7e4b0 100644
--- a/res/values-hr/strings.xml
+++ b/res/values-hr/strings.xml
@@ -20,57 +20,27 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="application_name" msgid="5181331383435256801">"Pokretač3"</string>
- <string name="home" msgid="7658288663002113681">"Početna"</string>
- <string name="uid_name" msgid="7820867637514617527">"Matične aplikacije za Android"</string>
<string name="folder_name" msgid="7371454440695724752"></string>
+ <string name="work_folder_name" msgid="3753320833950115786">"Posao"</string>
<string name="activity_not_found" msgid="8071924732094499514">"Aplikacija nije instalirana."</string>
<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="widgets_tab_label" msgid="2921133187116603919">"Widgeti"</string>
- <string name="widget_adder" msgid="3201040140710381657">"Widgeti"</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="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
- <string name="external_drop_widget_error" msgid="3165821058322217155">"Stavka nije ispuštena na ovaj početni zaslon."</string>
- <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Odabir widgeta za stvaranje"</string>
- <string name="rename_folder_label" msgid="3727762225964550653">"Naziv mape"</string>
- <string name="rename_folder_title" msgid="3771389277707820891">"Preimenovanje mape"</string>
- <string name="rename_action" msgid="5559600076028658757">"U redu"</string>
- <string name="cancel_action" msgid="7009134900002915310">"Odustani"</string>
- <string name="menu_item_add_item" msgid="1264911265836810421">"Dodavanje na početni zaslon"</string>
- <string name="group_applications" msgid="3797214114206693605">"Aplikacije"</string>
- <string name="group_shortcuts" msgid="6012256992764410535">"Prečaci"</string>
- <string name="group_widgets" msgid="1569030723286851002">"Widgeti"</string>
- <string name="completely_out_of_space" msgid="6106288382070760318">"Na vašim početnim zaslonima više nema mjesta."</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>
+ <string name="all_apps_no_search_results" msgid="6332185285860416787">"Nema aplikacija podudarnih s upitom \"<xliff:g id="QUERY">%1$s</xliff:g>\""</string>
<string name="out_of_space" msgid="4691004494942118364">"Na ovom početnom zaslonu više nema mjesta."</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"Nema više prostora na traci Favoriti"</string>
- <string name="invalid_hotseat_item" msgid="5779907847267573691">"Widget je prevelik za traku Favoriti"</string>
- <string name="shortcut_installed" msgid="1701742129426969556">"Izrađen je prečac za \"<xliff:g id="NAME">%s</xliff:g>\"."</string>
- <string name="shortcut_uninstalled" msgid="8176767991305701821">"Uklonjen je prečac za \"<xliff:g id="NAME">%s</xliff:g>\"."</string>
- <string name="shortcut_duplicate" msgid="9167217446062498127">"Prečac za \"<xliff:g id="NAME">%s</xliff:g>\" već postoji."</string>
- <string name="title_select_shortcut" msgid="6680642571148153868">"Odabir prečaca"</string>
- <string name="title_select_application" msgid="3280812711670683644">"Odabir aplikacije"</string>
<string name="all_apps_button_label" msgid="9110807029020582876">"Aplikacije"</string>
<string name="all_apps_home_button_label" msgid="252062713717058851">"Početna"</string>
- <string name="delete_zone_label_workspace" msgid="4009607676751398685">"Ukloni"</string>
- <string name="delete_zone_label_all_apps" msgid="8083826390278958980">"Deinstaliraj"</string>
<string name="delete_target_label" msgid="1822697352535677073">"Ukloni"</string>
<string name="delete_target_uninstall_label" msgid="5100785476250872595">"Deinstaliraj"</string>
<string name="info_target_label" msgid="8053346143994679532">"Informacije o aplikaciji"</string>
- <string name="accessibility_all_apps_button" msgid="2603132375383800483">"Aplikacije"</string>
- <string name="accessibility_delete_button" msgid="6466114477993744621">"Ukloni"</string>
- <string name="delete_zone_label_all_apps_system_app" msgid="449755632749610895">"Deinstalacija ažuriranja"</string>
- <string name="cab_menu_delete_app" msgid="7435191475867183689">"Deinstaliranje aplikacije"</string>
- <string name="cab_menu_app_info" msgid="8593722221450362342">"Pojedinosti o aplikaciji"</string>
- <string name="cab_app_selection_text" msgid="374688303047985416">"Odabrana je 1 aplikacija"</string>
- <string name="cab_widget_selection_text" msgid="1833458597831541241">"Odabran je 1 widget"</string>
- <string name="cab_folder_selection_text" msgid="7999992513806132118">"Odabrana je 1 mapa"</string>
- <string name="cab_shortcut_selection_text" msgid="2103811025667946450">"Odabran je 1 prečac"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"instaliranje prečaca"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"Aplikaciji omogućuje dodavanje prečaca bez intervencije korisnika."</string>
- <string name="permlab_uninstall_shortcut" msgid="864595034498083837">"deinstaliranje prečaca"</string>
- <string name="permdesc_uninstall_shortcut" msgid="5134129545001836849">"Aplikaciji omogućuje uklanjanje prečaca bez intervencije korisnika."</string>
<string name="permlab_read_settings" msgid="1941457408239617576">"čitanje postavki početnog zaslona i prečaca"</string>
<string name="permdesc_read_settings" msgid="5833423719057558387">"Aplikaciji omogućuje čitanje postavki i prečaca na početnom zaslonu."</string>
<string name="permlab_write_settings" msgid="3574213698004620587">"pisanje postavki početnog zaslona i prečaca"</string>
@@ -78,30 +48,17 @@
<string name="gadget_error_text" msgid="6081085226050792095">"Problem pri učitavanju widgeta"</string>
<string name="gadget_setup_text" msgid="8274003207686040488">"Postavljanje"</string>
<string name="uninstall_system_app_text" msgid="4172046090762920660">"Ovo je aplikacija sustava i ne može se ukloniti."</string>
- <string name="dream_name" msgid="1530253749244328964">"Lansirna rampa"</string>
<string name="folder_hint_text" msgid="6617836969016293992">"Neimenovana mapa"</string>
- <string name="workspace_description_format" msgid="2950174241104043327">"Početni zaslon %1$d"</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="apps_customize_apps_scroll_format" msgid="370005296147130238">"Stranica aplikacija %1$d od %2$d"</string>
- <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"Stranica widgeta %1$d od %2$d"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"Dobro došli"</string>
- <string name="first_run_cling_description" msgid="6447072552696253358">"Osjećajte se kao kod kuće."</string>
- <string name="first_run_cling_custom_content_hint" msgid="6090628589029352439"></string>
- <string name="first_run_cling_search_bar_hint" msgid="5909062802402452582"></string>
- <string name="first_run_cling_create_screens_hint" msgid="6950729526680114157">"Izradite više zaslona za aplikacije i mape"</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>
<string name="migration_cling_copy_apps" msgid="946331230090919440">"KOPIRAJ IKONE"</string>
<string name="migration_cling_use_default" msgid="2626475813981258626">"POKRENI NOVO"</string>
- <string name="workspace_cling_title" msgid="5626202359865825661">"Organizirajte svoj prostor"</string>
- <string name="workspace_cling_move_item" msgid="528201129978005352">"Dodirnite i držite pozadinu da biste upravljali pozadinskom slikom, widgetima i postavkama."</string>
<string name="workspace_cling_longpress_title" msgid="9173998993909018310">"Pozadine, widgeti i postavke"</string>
<string name="workspace_cling_longpress_description" msgid="4119994475505235248">"Dodirnite i zadržite pozadinu radi prilagodbe"</string>
<string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"SHVAĆAM"</string>
- <string name="folder_cling_title" msgid="3894908818693254164">"Evo mape"</string>
- <string name="folder_cling_create_folder" msgid="6158215559475836131">"Da biste izradili ovakvu mapu, dodirnite i držite aplikaciju pa je pomaknite preko druge aplikacije."</string>
- <string name="cling_dismiss" msgid="8962359497601507581">"U redu"</string>
<string name="folder_opened" msgid="94695026776264709">"Mapa je otvorena, <xliff:g id="WIDTH">%1$d</xliff:g> x <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
<string name="folder_tap_to_close" msgid="1884479294466410023">"Dodirnite da biste zatvorili mapu"</string>
<string name="folder_tap_to_rename" msgid="9191075570492871147">"Dodirnite da biste spremili preimenovanje"</string>
@@ -111,14 +68,34 @@
<string name="widget_button_text" msgid="2880537293434387943">"Widgeti"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"Pozadine"</string>
<string name="settings_button_text" msgid="8119458837558863227">"Postavke"</string>
- <string name="package_state_enqueued" msgid="6227252464303085641">"Čekanje"</string>
- <string name="package_state_downloading" msgid="4088770468458724721">"Preuzimanje"</string>
- <string name="package_state_installing" msgid="7588193972189849870">"Instaliranje"</string>
+ <string name="allow_rotation_title" msgid="2118706734511831751">"Dopusti rotaciju"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Nepoznato"</string>
- <string name="package_state_error" msgid="7672093962724223588">"Nije vraćeno"</string>
- <string name="abandoned_clean_all" msgid="5256770727689657618">"Ukloni sve"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Ukloni"</string>
<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="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>
+ <string name="item_removed" msgid="851119963877842327">"Stavka je uklonjena"</string>
+ <string name="action_move" msgid="4339390619886385032">"Premještanje stavke"</string>
+ <string name="move_to_empty_cell" msgid="2833711483015685619">"Premještanje u redak <xliff:g id="NUMBER_0">%1$s</xliff:g>, stupac <xliff:g id="NUMBER_1">%2$s</xliff:g>"</string>
+ <string name="move_to_position" msgid="6750008980455459790">"Premještanje na položaj <xliff:g id="NUMBER">%1$s</xliff:g>"</string>
+ <string name="move_to_hotseat_position" msgid="6295412897075147808">"Premještanje na položaj favorita <xliff:g id="NUMBER">%1$s</xliff:g>"</string>
+ <string name="item_moved" msgid="4606538322571412879">"Stavka premještena"</string>
+ <string name="add_to_folder" msgid="9040534766770853243">"Dodavanje u mapu: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="add_to_folder_with_app" msgid="4534929978967147231">"Dodavanje u mapu s aplikacijom <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="added_to_folder" msgid="4793259502305558003">"Stavka dodana u mapu"</string>
+ <string name="create_folder_with" msgid="4050141361160214248">"Izrada mape pomoću stavke: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="folder_created" msgid="6409794597405184510">"Mapa izrađena"</string>
+ <string name="action_move_to_workspace" msgid="1603837886334246317">"Premještanje na početni zaslon"</string>
+ <string name="action_move_screen_left" msgid="8854216831569401665">"Premještanje zaslona ulijevo"</string>
+ <string name="action_move_screen_right" msgid="329334910274311123">"Premještanje zaslona udesno"</string>
+ <string name="screen_moved" msgid="266230079505650577">"Zaslon je premješten"</string>
+ <string name="action_resize" msgid="1802976324781771067">"Promjena veličine"</string>
+ <string name="action_increase_width" msgid="8773715375078513326">"Povećanje širine"</string>
+ <string name="action_increase_height" msgid="459390020612501122">"Povećanje visine"</string>
+ <string name="action_decrease_width" msgid="1374549771083094654">"Smanjenje širine"</string>
+ <string name="action_decrease_height" msgid="282377193880900022">"Smanjenje visine"</string>
+ <string name="widget_resized" msgid="9130327887929620">"Širina widgeta promijenjena je na <xliff:g id="NUMBER_0">%1$s</xliff:g>, a visina na <xliff:g id="NUMBER_1">%2$s</xliff:g>"</string>
</resources>
diff --git a/res/values-hu/strings.xml b/res/values-hu/strings.xml
index 513548a2a..e9fc5747f 100644
--- a/res/values-hu/strings.xml
+++ b/res/values-hu/strings.xml
@@ -20,57 +20,27 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="application_name" msgid="5181331383435256801">"Launcher3"</string>
- <string name="home" msgid="7658288663002113681">"Főoldal"</string>
- <string name="uid_name" msgid="7820867637514617527">"Alap Android-alkalmazások"</string>
<string name="folder_name" msgid="7371454440695724752"></string>
+ <string name="work_folder_name" msgid="3753320833950115786">"Munka"</string>
<string name="activity_not_found" msgid="8071924732094499514">"Az alkalmazás nincs telepítve."</string>
<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="widgets_tab_label" msgid="2921133187116603919">"Modulok"</string>
- <string name="widget_adder" msgid="3201040140710381657">"Modulok"</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="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
- <string name="external_drop_widget_error" msgid="3165821058322217155">"Nem lehet elemeket dobni erre a kezdőképernyőre."</string>
- <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"A létrehozáshoz válasszon modult"</string>
- <string name="rename_folder_label" msgid="3727762225964550653">"Mappa neve"</string>
- <string name="rename_folder_title" msgid="3771389277707820891">"Mappa átnevezése"</string>
- <string name="rename_action" msgid="5559600076028658757">"OK"</string>
- <string name="cancel_action" msgid="7009134900002915310">"Mégse"</string>
- <string name="menu_item_add_item" msgid="1264911265836810421">"Hozzáadás a kezdőképernyőhöz"</string>
- <string name="group_applications" msgid="3797214114206693605">"Alkalmazások"</string>
- <string name="group_shortcuts" msgid="6012256992764410535">"Parancsikonok"</string>
- <string name="group_widgets" msgid="1569030723286851002">"Modulok"</string>
- <string name="completely_out_of_space" msgid="6106288382070760318">"Nincs több hely a kezdőképernyőkön."</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>
+ <string name="all_apps_no_search_results" msgid="6332185285860416787">"Egy alkalmazás sem található a(z) „<xliff:g id="QUERY">%1$s</xliff:g>” lekérdezésre."</string>
<string name="out_of_space" msgid="4691004494942118364">"Nincs több hely ezen a kezdőképernyőn."</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"Nincs több hely a Kedvencek tálcán"</string>
- <string name="invalid_hotseat_item" msgid="5779907847267573691">"Ez a modul túl nagy a Kedvencek tálcán való elhelyezéshez"</string>
- <string name="shortcut_installed" msgid="1701742129426969556">"A(z) „<xliff:g id="NAME">%s</xliff:g>” parancsikon létrehozva."</string>
- <string name="shortcut_uninstalled" msgid="8176767991305701821">"A(z) „<xliff:g id="NAME">%s</xliff:g>” parancsikon eltávolítva."</string>
- <string name="shortcut_duplicate" msgid="9167217446062498127">"A(z) „<xliff:g id="NAME">%s</xliff:g>” parancsikon már létezik."</string>
- <string name="title_select_shortcut" msgid="6680642571148153868">"Parancsikon választása"</string>
- <string name="title_select_application" msgid="3280812711670683644">"Válasszon alkalmazást"</string>
<string name="all_apps_button_label" msgid="9110807029020582876">"Alkalmazások"</string>
<string name="all_apps_home_button_label" msgid="252062713717058851">"Főoldal"</string>
- <string name="delete_zone_label_workspace" msgid="4009607676751398685">"Eltávolítás"</string>
- <string name="delete_zone_label_all_apps" msgid="8083826390278958980">"Eltávolítás"</string>
<string name="delete_target_label" msgid="1822697352535677073">"Eltávolítás"</string>
<string name="delete_target_uninstall_label" msgid="5100785476250872595">"Eltávolítás"</string>
<string name="info_target_label" msgid="8053346143994679532">"Alkalmazásinformáció"</string>
- <string name="accessibility_all_apps_button" msgid="2603132375383800483">"Alkalmazások"</string>
- <string name="accessibility_delete_button" msgid="6466114477993744621">"Eltávolítás"</string>
- <string name="delete_zone_label_all_apps_system_app" msgid="449755632749610895">"Eltávolítja a frissítést"</string>
- <string name="cab_menu_delete_app" msgid="7435191475867183689">"Alkalmazás eltávolítása"</string>
- <string name="cab_menu_app_info" msgid="8593722221450362342">"Az alkalmazás adatai"</string>
- <string name="cab_app_selection_text" msgid="374688303047985416">"1 alkalmazás kiválasztva"</string>
- <string name="cab_widget_selection_text" msgid="1833458597831541241">"1 modul kiválasztva"</string>
- <string name="cab_folder_selection_text" msgid="7999992513806132118">"1 mappa kiválasztva"</string>
- <string name="cab_shortcut_selection_text" msgid="2103811025667946450">"1 parancsikon kiválasztva"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"parancsikonok telepítése"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"Lehetővé teszi egy alkalmazás számára, hogy felhasználói beavatkozás nélkül adjon hozzá parancsikonokat."</string>
- <string name="permlab_uninstall_shortcut" msgid="864595034498083837">"parancsikonok eltávolítása"</string>
- <string name="permdesc_uninstall_shortcut" msgid="5134129545001836849">"Lehetővé teszi egy alkalmazás számára, hogy felhasználói beavatkozás nélkül távolítson el parancsikonokat."</string>
<string name="permlab_read_settings" msgid="1941457408239617576">"Főoldal beállításainak és parancsikonjainak beolvasása"</string>
<string name="permdesc_read_settings" msgid="5833423719057558387">"Lehetővé teszi az alkalmazás számára, hogy beolvassa a kezdőképernyő beállításait és parancsikonjait."</string>
<string name="permlab_write_settings" msgid="3574213698004620587">"Főoldal beállításainak és parancsikonjainak írása"</string>
@@ -78,30 +48,17 @@
<string name="gadget_error_text" msgid="6081085226050792095">"Probléma történt a modul betöltésekor"</string>
<string name="gadget_setup_text" msgid="8274003207686040488">"Beállítás"</string>
<string name="uninstall_system_app_text" msgid="4172046090762920660">"Ez egy rendszeralkalmazás, és nem lehet eltávolítani."</string>
- <string name="dream_name" msgid="1530253749244328964">"Aknavető"</string>
<string name="folder_hint_text" msgid="6617836969016293992">"Névtelen mappa"</string>
- <string name="workspace_description_format" msgid="2950174241104043327">"%1$d. kezdőképernyő"</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="apps_customize_apps_scroll_format" msgid="370005296147130238">"%2$d/%1$d. alkalmazásoldal"</string>
- <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"%2$d/%1$d. moduloldal"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"Üdvözöljük!"</string>
- <string name="first_run_cling_description" msgid="6447072552696253358">"Varázsolja egyedivé készülékét."</string>
- <string name="first_run_cling_custom_content_hint" msgid="6090628589029352439"></string>
- <string name="first_run_cling_search_bar_hint" msgid="5909062802402452582"></string>
- <string name="first_run_cling_create_screens_hint" msgid="6950729526680114157">"Hozzon létre további képernyőket az alkalmazásoknak és mappáknak"</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>
<string name="migration_cling_copy_apps" msgid="946331230090919440">"IKONOK MÁSOLÁSA"</string>
<string name="migration_cling_use_default" msgid="2626475813981258626">"TELJESEN ÚJ"</string>
- <string name="workspace_cling_title" msgid="5626202359865825661">"Munkaterület rendezése"</string>
- <string name="workspace_cling_move_item" msgid="528201129978005352">"Érintse meg és tartsa lenyomva a hátteret a háttérkép, modulok és beállítások kezeléséhez."</string>
<string name="workspace_cling_longpress_title" msgid="9173998993909018310">"Háttérképek, modulok és beállítások"</string>
<string name="workspace_cling_longpress_description" msgid="4119994475505235248">"Érintse meg és tartsa lenyomva a személyre szabáshoz"</string>
<string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"MEGÉRTETTEM"</string>
- <string name="folder_cling_title" msgid="3894908818693254164">"Itt egy mappa"</string>
- <string name="folder_cling_create_folder" msgid="6158215559475836131">"Mappa létrehozásához érintse meg és tartsa lenyomva az alkalmazást, majd húzza egy másik fölé."</string>
- <string name="cling_dismiss" msgid="8962359497601507581">"OK"</string>
<string name="folder_opened" msgid="94695026776264709">"Mappa megnyitva – szélesség: <xliff:g id="WIDTH">%1$d</xliff:g>; magasság: <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
<string name="folder_tap_to_close" msgid="1884479294466410023">"Érintse meg a mappa bezárásához"</string>
<string name="folder_tap_to_rename" msgid="9191075570492871147">"Érintse meg az átnevezés mentéséhez"</string>
@@ -111,14 +68,34 @@
<string name="widget_button_text" msgid="2880537293434387943">"Modulok"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"Háttérképek"</string>
<string name="settings_button_text" msgid="8119458837558863227">"Beállítások"</string>
- <string name="package_state_enqueued" msgid="6227252464303085641">"Várakozik"</string>
- <string name="package_state_downloading" msgid="4088770468458724721">"Letöltés alatt"</string>
- <string name="package_state_installing" msgid="7588193972189849870">"Települ"</string>
+ <string name="allow_rotation_title" msgid="2118706734511831751">"Elforgatás engedélyezése"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Ismeretlen"</string>
- <string name="package_state_error" msgid="7672093962724223588">"Nincs visszaállítva"</string>
- <string name="abandoned_clean_all" msgid="5256770727689657618">"Az összes eltávolítása"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Eltávolítás"</string>
<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="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>
+ <string name="item_removed" msgid="851119963877842327">"Elem eltávolítva"</string>
+ <string name="action_move" msgid="4339390619886385032">"Elem mozgatása"</string>
+ <string name="move_to_empty_cell" msgid="2833711483015685619">"Áthelyezés ide: <xliff:g id="NUMBER_0">%1$s</xliff:g>. sor, <xliff:g id="NUMBER_1">%2$s</xliff:g>. oszlop"</string>
+ <string name="move_to_position" msgid="6750008980455459790">"Áthelyezés a(z) <xliff:g id="NUMBER">%1$s</xliff:g>. pozícióba"</string>
+ <string name="move_to_hotseat_position" msgid="6295412897075147808">"Áthelyezés a kedvencek <xliff:g id="NUMBER">%1$s</xliff:g>. pozíciójába"</string>
+ <string name="item_moved" msgid="4606538322571412879">"Elem áthelyezve"</string>
+ <string name="add_to_folder" msgid="9040534766770853243">"Hozzáadás a(z) <xliff:g id="NAME">%1$s</xliff:g> mappához"</string>
+ <string name="add_to_folder_with_app" msgid="4534929978967147231">"Hozzáadás a mappához a következővel: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="added_to_folder" msgid="4793259502305558003">"Elem hozzáadva a mappához"</string>
+ <string name="create_folder_with" msgid="4050141361160214248">"Mappa létrehozása a következővel: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="folder_created" msgid="6409794597405184510">"Mappa létrehozva"</string>
+ <string name="action_move_to_workspace" msgid="1603837886334246317">"Áthelyezés a kezdőképernyőre"</string>
+ <string name="action_move_screen_left" msgid="8854216831569401665">"Képernyő mozgatása balra"</string>
+ <string name="action_move_screen_right" msgid="329334910274311123">"Képernyő mozgatása jobbra"</string>
+ <string name="screen_moved" msgid="266230079505650577">"Képernyő áthelyezve"</string>
+ <string name="action_resize" msgid="1802976324781771067">"Átméretezés"</string>
+ <string name="action_increase_width" msgid="8773715375078513326">"Szélesség növelése"</string>
+ <string name="action_increase_height" msgid="459390020612501122">"Magasság növelése"</string>
+ <string name="action_decrease_width" msgid="1374549771083094654">"Szélesség csökkentése"</string>
+ <string name="action_decrease_height" msgid="282377193880900022">"Magasság csökkentése"</string>
+ <string name="widget_resized" msgid="9130327887929620">"Modul átméretezve <xliff:g id="NUMBER_0">%1$s</xliff:g> szélességre és <xliff:g id="NUMBER_1">%2$s</xliff:g> magasságra"</string>
</resources>
diff --git a/res/values-hy-rAM/strings.xml b/res/values-hy-rAM/strings.xml
index 4af794e6f..de4aed158 100644
--- a/res/values-hy-rAM/strings.xml
+++ b/res/values-hy-rAM/strings.xml
@@ -20,57 +20,27 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="application_name" msgid="5181331383435256801">"Launcher3"</string>
- <string name="home" msgid="7658288663002113681">"Հիմնական"</string>
- <string name="uid_name" msgid="7820867637514617527">"Android Core Apps"</string>
<string name="folder_name" msgid="7371454440695724752"></string>
+ <string name="work_folder_name" msgid="3753320833950115786">"Աշխատանքային"</string>
<string name="activity_not_found" msgid="8071924732094499514">"Ծրագիրը տեղադրված չէ:"</string>
<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="widgets_tab_label" msgid="2921133187116603919">"Վիջեթներ"</string>
- <string name="widget_adder" msgid="3201040140710381657">"Վիջեթներ"</string>
<string name="toggle_weight_watcher" msgid="5645299835184636119">"Ցուցադրել մեմը"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"Հպեք և պահեք՝ վիջեթն ընտրելու համար:"</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
- <string name="external_drop_widget_error" msgid="3165821058322217155">"Հնարավոր չէ տեղադրել տարրն այս հիմնական էկրանին:"</string>
- <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Ստեղծելու համար ընտրեք վիջեթը"</string>
- <string name="rename_folder_label" msgid="3727762225964550653">"Պանակի անունը"</string>
- <string name="rename_folder_title" msgid="3771389277707820891">"Վերանվանել պանակը"</string>
- <string name="rename_action" msgid="5559600076028658757">"Լավ"</string>
- <string name="cancel_action" msgid="7009134900002915310">"Չեղարկել"</string>
- <string name="menu_item_add_item" msgid="1264911265836810421">"Ավելացնել հիմնական էկրանին"</string>
- <string name="group_applications" msgid="3797214114206693605">"Ծրագրեր"</string>
- <string name="group_shortcuts" msgid="6012256992764410535">"Դյուրանցումներ"</string>
- <string name="group_widgets" msgid="1569030723286851002">"Վիջեթներ"</string>
- <string name="completely_out_of_space" msgid="6106288382070760318">"Այլևս տեղ չկա ձեր հիմնական էկրաններին:"</string>
+ <string name="all_apps_search_bar_hint" msgid="7084713969757597256">"Հավելվածների որոնում"</string>
+ <string name="all_apps_loading_message" msgid="7557140873644765180">"Հավելվածների բեռնում…"</string>
+ <string name="all_apps_no_search_results" msgid="6332185285860416787">"«<xliff:g id="QUERY">%1$s</xliff:g>» հարցմանը համապատասխանող հավելվածներ չեն գտնվել"</string>
<string name="out_of_space" msgid="4691004494942118364">"Այլևս տեղ չկա այս հիմնական էկրանին:"</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"Ընտրյալների ցուցակում այլևս ազատ տեղ չկա"</string>
- <string name="invalid_hotseat_item" msgid="5779907847267573691">"Այս վիջեթը շատ մեծ է Ընտրյալների ցուցակի համար"</string>
- <string name="shortcut_installed" msgid="1701742129426969556">"«<xliff:g id="NAME">%s</xliff:g>» դյուրանցումը ստեղծված է:"</string>
- <string name="shortcut_uninstalled" msgid="8176767991305701821">"«<xliff:g id="NAME">%s</xliff:g>» դյուրանցումը հեռացվեց:"</string>
- <string name="shortcut_duplicate" msgid="9167217446062498127">"«<xliff:g id="NAME">%s</xliff:g>» դյուրանցումն արդեն գոյություն ունի:"</string>
- <string name="title_select_shortcut" msgid="6680642571148153868">"Ընտրել դյուրանցումը"</string>
- <string name="title_select_application" msgid="3280812711670683644">"Ընտրել ծրագիրը"</string>
<string name="all_apps_button_label" msgid="9110807029020582876">"Ծրագրեր"</string>
<string name="all_apps_home_button_label" msgid="252062713717058851">"Հիմնական"</string>
- <string name="delete_zone_label_workspace" msgid="4009607676751398685">"Հեռացնել"</string>
- <string name="delete_zone_label_all_apps" msgid="8083826390278958980">"Ապատեղադրել"</string>
<string name="delete_target_label" msgid="1822697352535677073">"Հեռացնել"</string>
<string name="delete_target_uninstall_label" msgid="5100785476250872595">"Ապատեղադրել"</string>
<string name="info_target_label" msgid="8053346143994679532">"Ծրագրի տեղեկություններ"</string>
- <string name="accessibility_all_apps_button" msgid="2603132375383800483">"Ծրագրեր"</string>
- <string name="accessibility_delete_button" msgid="6466114477993744621">"Հեռացնել"</string>
- <string name="delete_zone_label_all_apps_system_app" msgid="449755632749610895">"Ապատեղադրել թարմացումը"</string>
- <string name="cab_menu_delete_app" msgid="7435191475867183689">"Ապատեղադրել ծրագիրը"</string>
- <string name="cab_menu_app_info" msgid="8593722221450362342">"Ծրագրի մանրամասներ"</string>
- <string name="cab_app_selection_text" msgid="374688303047985416">"1 ընտրված ծրագիր"</string>
- <string name="cab_widget_selection_text" msgid="1833458597831541241">"1 ընտրված վիջեթ"</string>
- <string name="cab_folder_selection_text" msgid="7999992513806132118">"1 ընտրված պանակ"</string>
- <string name="cab_shortcut_selection_text" msgid="2103811025667946450">"1 ընտրված դյուրանցում"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"տեղադրել դյուրանցումներ"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"Ծրագրին թույլ է տալիս ավելացնել դյուրանցումներ՝ առանց օգտագործողի միջամտության:"</string>
- <string name="permlab_uninstall_shortcut" msgid="864595034498083837">"ապատեղադրել դյուրանցումները"</string>
- <string name="permdesc_uninstall_shortcut" msgid="5134129545001836849">"Ծրագրին թույլ է տալիս հեռացնել դյուրանցումներ՝ առանց օգտագործողի միջամտության:"</string>
<string name="permlab_read_settings" msgid="1941457408239617576">"կարդալ հիմնաէջի կարգավորումներն ու դյուրանցումները"</string>
<string name="permdesc_read_settings" msgid="5833423719057558387">"Ծրագրին թույլ է տալիս կարդալ հիմնաէջի կարգավորումներն ու դյուրանցումները:"</string>
<string name="permlab_write_settings" msgid="3574213698004620587">"ստեղծել հիմնաէջի կարգավորումներ ու դյուրանցումներ"</string>
@@ -78,30 +48,17 @@
<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>
- <string name="dream_name" msgid="1530253749244328964">"Հրթիռային թողարկիչ"</string>
<string name="folder_hint_text" msgid="6617836969016293992">"Անանուն պանակ"</string>
- <string name="workspace_description_format" msgid="2950174241104043327">"Հիմնական էկրան %1$d"</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="apps_customize_apps_scroll_format" msgid="370005296147130238">"Ծրագրերի էջերը՝ %1$d %2$d-ից"</string>
- <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"Վիջեթների էջերը՝ %1$d %2$d-ից"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"Բարի գալուստ"</string>
- <string name="first_run_cling_description" msgid="6447072552696253358">"Զգացեք ձեզ ինչպես տանը:"</string>
- <string name="first_run_cling_custom_content_hint" msgid="6090628589029352439"></string>
- <string name="first_run_cling_search_bar_hint" msgid="5909062802402452582"></string>
- <string name="first_run_cling_create_screens_hint" msgid="6950729526680114157">"Ստեղծեք նոր էկրաններ ծրագրերի և պանակների համար"</string>
<string name="migration_cling_title" msgid="9181776667882933767">"Պատճենել ձեր ծրագրի պատկերակները"</string>
<string name="migration_cling_description" msgid="2752413805582227644">"Ներմուծե՞լ պատկերակները և պանակները ձեր նախկին Հիմնական էկրանից"</string>
<string name="migration_cling_copy_apps" msgid="946331230090919440">"ՊԱՏՃԵՆԵԼ ՊԱՏԿԵՐԱԿՆԵՐԸ"</string>
<string name="migration_cling_use_default" msgid="2626475813981258626">"ՄԵԿՆԱՐԿԵԼ ԸՍՏ ԿԱՆԽԱԴՐՎԱԾԻ"</string>
- <string name="workspace_cling_title" msgid="5626202359865825661">"Կառավարեք ձեր տարածությունը"</string>
- <string name="workspace_cling_move_item" msgid="528201129978005352">"Հպեք և պահեք հետնաշերտի վրա՝ պաստառները, վիջեթներն ու կարգավորումները կառավարելու համար:"</string>
<string name="workspace_cling_longpress_title" msgid="9173998993909018310">"Պաստառներ, վիջեթներ և կարգավորումներ"</string>
<string name="workspace_cling_longpress_description" msgid="4119994475505235248">"Հարմարեցնելու համար հպեք և պահեք հետնաշերտի վրա"</string>
<string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"ՀԱՍԿԱՆԱԼԻ Է"</string>
- <string name="folder_cling_title" msgid="3894908818693254164">"Ահա մի պանակ"</string>
- <string name="folder_cling_create_folder" msgid="6158215559475836131">"Նման պանակ ստեղծելու համար հպեք և պահեք որևէ ծրագրի վրա, ապա տեղաշարժեք այն մեկ ուրիշ ծրագրի վրա:"</string>
- <string name="cling_dismiss" msgid="8962359497601507581">"Լավ"</string>
<string name="folder_opened" msgid="94695026776264709">"Թղթապանակը բաց է, <xliff:g id="WIDTH">%1$d</xliff:g>-ից <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
<string name="folder_tap_to_close" msgid="1884479294466410023">"Հպեք՝ պանակը փակելու համար"</string>
<string name="folder_tap_to_rename" msgid="9191075570492871147">"Հպեք՝ վերանվանումը պահելու համար"</string>
@@ -111,14 +68,34 @@
<string name="widget_button_text" msgid="2880537293434387943">"Վիջեթներ"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"Պաստառներ"</string>
<string name="settings_button_text" msgid="8119458837558863227">"Կարգավորումներ"</string>
- <string name="package_state_enqueued" msgid="6227252464303085641">"Առկախ է"</string>
- <string name="package_state_downloading" msgid="4088770468458724721">"Ներբեռնվում է"</string>
- <string name="package_state_installing" msgid="7588193972189849870">"Տեղադրվում է"</string>
+ <string name="allow_rotation_title" msgid="2118706734511831751">"Թույլ տալ պարբերական կրկնությունը"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Անհայտ է"</string>
- <string name="package_state_error" msgid="7672093962724223588">"Չի վերականգնվել"</string>
- <string name="abandoned_clean_all" msgid="5256770727689657618">"Հեռացնել բոլորը"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Հեռացնել"</string>
<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="action_add_to_workspace" msgid="8902165848117513641">"Ավելացնել Հիմնական էկրանին"</string>
+ <string name="action_move_here" msgid="2170188780612570250">"Տեղափոխել տարրն այստեղ"</string>
+ <string name="item_added_to_workspace" msgid="4211073925752213539">"Տարրն ավելացվեց հիմնական էկրանին"</string>
+ <string name="item_removed" msgid="851119963877842327">"Տարրը հեռացվեց"</string>
+ <string name="action_move" msgid="4339390619886385032">"Տեղափոխել տարրը"</string>
+ <string name="move_to_empty_cell" msgid="2833711483015685619">"Տեղափոխել տող <xliff:g id="NUMBER_0">%1$s</xliff:g> սյունակ <xliff:g id="NUMBER_1">%2$s</xliff:g>"</string>
+ <string name="move_to_position" msgid="6750008980455459790">"Տեղափոխել դիրք <xliff:g id="NUMBER">%1$s</xliff:g>"</string>
+ <string name="move_to_hotseat_position" msgid="6295412897075147808">"Տեղափոխել նախընտրած դիրք՝ <xliff:g id="NUMBER">%1$s</xliff:g>"</string>
+ <string name="item_moved" msgid="4606538322571412879">"Տարրը տեղափոխվեց"</string>
+ <string name="add_to_folder" msgid="9040534766770853243">"Ավելացնել թղթապանակում՝ <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="add_to_folder_with_app" msgid="4534929978967147231">"Ավելացնել «<xliff:g id="NAME">%1$s</xliff:g>» պանակին"</string>
+ <string name="added_to_folder" msgid="4793259502305558003">"Տարրն ավելացվեց թղթապանակում"</string>
+ <string name="create_folder_with" msgid="4050141361160214248">"Ստեղծել թղթապանակ, օգտագործելով՝ <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="folder_created" msgid="6409794597405184510">"Թղթապանակը ստեղծվեց"</string>
+ <string name="action_move_to_workspace" msgid="1603837886334246317">"Տեղափոխել Հիմնական էկրան"</string>
+ <string name="action_move_screen_left" msgid="8854216831569401665">"Տեղափոխել էկրանը ձախ"</string>
+ <string name="action_move_screen_right" msgid="329334910274311123">"Տեղափոխել էկրանը աջ"</string>
+ <string name="screen_moved" msgid="266230079505650577">"Էկրանը տեղափոխվեց"</string>
+ <string name="action_resize" msgid="1802976324781771067">"Չափափոխել"</string>
+ <string name="action_increase_width" msgid="8773715375078513326">"Ավելացնել լայնությունը"</string>
+ <string name="action_increase_height" msgid="459390020612501122">"Ավելացնել բարձրությունը"</string>
+ <string name="action_decrease_width" msgid="1374549771083094654">"Նվազեցնել լայնությունը"</string>
+ <string name="action_decrease_height" msgid="282377193880900022">"Նվազեցնել բարձրությունը"</string>
+ <string name="widget_resized" msgid="9130327887929620">"Վիջեթի լայնությունը փոխվել է <xliff:g id="NUMBER_0">%1$s</xliff:g>-ի, իսկ բարձրությունը՝ <xliff:g id="NUMBER_1">%2$s</xliff:g>-ի"</string>
</resources>
diff --git a/res/values-in/strings.xml b/res/values-in/strings.xml
index b0c5d139d..c65254a2a 100644
--- a/res/values-in/strings.xml
+++ b/res/values-in/strings.xml
@@ -20,57 +20,27 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="application_name" msgid="5181331383435256801">"Launcher3"</string>
- <string name="home" msgid="7658288663002113681">"Layar Utama"</string>
- <string name="uid_name" msgid="7820867637514617527">"Aplikasi Inti Android"</string>
<string name="folder_name" msgid="7371454440695724752"></string>
+ <string name="work_folder_name" msgid="3753320833950115786">"Kantor"</string>
<string name="activity_not_found" msgid="8071924732094499514">"Aplikasi tidak dipasang."</string>
<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="widgets_tab_label" msgid="2921133187116603919">"Widget"</string>
- <string name="widget_adder" msgid="3201040140710381657">"Widget"</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="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
- <string name="external_drop_widget_error" msgid="3165821058322217155">"Tidak dapat melepas item ke layar Utama ini."</string>
- <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Pilih widget untuk membuat"</string>
- <string name="rename_folder_label" msgid="3727762225964550653">"Nama folder"</string>
- <string name="rename_folder_title" msgid="3771389277707820891">"Ganti nama folder"</string>
- <string name="rename_action" msgid="5559600076028658757">"Oke"</string>
- <string name="cancel_action" msgid="7009134900002915310">"Batal"</string>
- <string name="menu_item_add_item" msgid="1264911265836810421">"Tambahkan ke layar Utama"</string>
- <string name="group_applications" msgid="3797214114206693605">"Aplikasi"</string>
- <string name="group_shortcuts" msgid="6012256992764410535">"Pintasan"</string>
- <string name="group_widgets" msgid="1569030723286851002">"Widget"</string>
- <string name="completely_out_of_space" msgid="6106288382070760318">"Tidak ada ruang lagi di layar Utama Anda."</string>
+ <string name="all_apps_search_bar_hint" msgid="7084713969757597256">"Telusuri Apps"</string>
+ <string name="all_apps_loading_message" msgid="7557140873644765180">"Memuat Aplikasi..."</string>
+ <string name="all_apps_no_search_results" msgid="6332185285860416787">"Tidak ditemukan Aplikasi yang cocok dengan \"<xliff:g id="QUERY">%1$s</xliff:g>\""</string>
<string name="out_of_space" msgid="4691004494942118364">"Tidak ada ruang lagi pada layar Utama ini."</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"Tidak ada ruang tersisa di baki Favorit"</string>
- <string name="invalid_hotseat_item" msgid="5779907847267573691">"Widget ini terlalu besar untuk baki Favorit"</string>
- <string name="shortcut_installed" msgid="1701742129426969556">"Pintasan \"<xliff:g id="NAME">%s</xliff:g>\" sudah dibuat."</string>
- <string name="shortcut_uninstalled" msgid="8176767991305701821">"Pintasan \"<xliff:g id="NAME">%s</xliff:g>\" telah dihapus."</string>
- <string name="shortcut_duplicate" msgid="9167217446062498127">"Pintasan \"<xliff:g id="NAME">%s</xliff:g>\" sudah ada."</string>
- <string name="title_select_shortcut" msgid="6680642571148153868">"Pilih pintasan"</string>
- <string name="title_select_application" msgid="3280812711670683644">"Pilih aplikasi"</string>
<string name="all_apps_button_label" msgid="9110807029020582876">"Aplikasi"</string>
<string name="all_apps_home_button_label" msgid="252062713717058851">"Layar Utama"</string>
- <string name="delete_zone_label_workspace" msgid="4009607676751398685">"Hapus"</string>
- <string name="delete_zone_label_all_apps" msgid="8083826390278958980">"Copot pemasangan"</string>
<string name="delete_target_label" msgid="1822697352535677073">"Hapus"</string>
<string name="delete_target_uninstall_label" msgid="5100785476250872595">"Copot pemasangan"</string>
<string name="info_target_label" msgid="8053346143994679532">"Info aplikasi"</string>
- <string name="accessibility_all_apps_button" msgid="2603132375383800483">"Aplikasi"</string>
- <string name="accessibility_delete_button" msgid="6466114477993744621">"Hapus"</string>
- <string name="delete_zone_label_all_apps_system_app" msgid="449755632749610895">"Copot pemasangan pembaruan"</string>
- <string name="cab_menu_delete_app" msgid="7435191475867183689">"Copot aplikasi"</string>
- <string name="cab_menu_app_info" msgid="8593722221450362342">"Detail aplikasi"</string>
- <string name="cab_app_selection_text" msgid="374688303047985416">"1 aplikasi dipilih"</string>
- <string name="cab_widget_selection_text" msgid="1833458597831541241">"1 widget dipilih"</string>
- <string name="cab_folder_selection_text" msgid="7999992513806132118">"1 folder dipilih"</string>
- <string name="cab_shortcut_selection_text" msgid="2103811025667946450">"1 pintasan dipilih"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"memasang pintasan"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"Mengizinkan aplikasi menambahkan pintasan tanpa campur tangan pengguna."</string>
- <string name="permlab_uninstall_shortcut" msgid="864595034498083837">"mencopot pemasangan pintasan"</string>
- <string name="permdesc_uninstall_shortcut" msgid="5134129545001836849">"Mengizinkan aplikasi menghapus pintasan tanpa campur tangan pengguna."</string>
<string name="permlab_read_settings" msgid="1941457408239617576">"membaca setelan dan pintasan layar Utama"</string>
<string name="permdesc_read_settings" msgid="5833423719057558387">"Mengizinkan aplikasi membaca setelan dan pintasan di layar Utama."</string>
<string name="permlab_write_settings" msgid="3574213698004620587">"menulis setelan dan pintasan layar Utama"</string>
@@ -78,30 +48,17 @@
<string name="gadget_error_text" msgid="6081085226050792095">"Masalah memuat widget"</string>
<string name="gadget_setup_text" msgid="8274003207686040488">"Siapkan"</string>
<string name="uninstall_system_app_text" msgid="4172046090762920660">"Ini adalah aplikasi sistem dan tidak dapat dicopot pemasangannya."</string>
- <string name="dream_name" msgid="1530253749244328964">"Rocket Launcher"</string>
<string name="folder_hint_text" msgid="6617836969016293992">"Folder Tanpa Nama"</string>
- <string name="workspace_description_format" msgid="2950174241104043327">"Layar utama %1$d"</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="apps_customize_apps_scroll_format" msgid="370005296147130238">"Laman aplikasi %1$d dari %2$d"</string>
- <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"Laman widget %1$d dari %2$d"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"Selamat Datang"</string>
- <string name="first_run_cling_description" msgid="6447072552696253358">"Serasa di rumah sendiri."</string>
- <string name="first_run_cling_custom_content_hint" msgid="6090628589029352439"></string>
- <string name="first_run_cling_search_bar_hint" msgid="5909062802402452582"></string>
- <string name="first_run_cling_create_screens_hint" msgid="6950729526680114157">"Buat lebih banyak layar untuk aplikasi dan folder"</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>
<string name="migration_cling_copy_apps" msgid="946331230090919440">"IKON SALIN"</string>
<string name="migration_cling_use_default" msgid="2626475813981258626">"MULAI DARI AWAL"</string>
- <string name="workspace_cling_title" msgid="5626202359865825661">"Kelola ruang Anda"</string>
- <string name="workspace_cling_move_item" msgid="528201129978005352">"Sentuh lama latar belakang untuk mengelola wallpaper, widget, dan setelan."</string>
<string name="workspace_cling_longpress_title" msgid="9173998993909018310">"Wallpaper, widget, &amp; setelan"</string>
<string name="workspace_cling_longpress_description" msgid="4119994475505235248">"Sentuh &amp; tahan latar belakang untuk menyesuaikan"</string>
<string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"MENGERTI"</string>
- <string name="folder_cling_title" msgid="3894908818693254164">"Ini adalah folder"</string>
- <string name="folder_cling_create_folder" msgid="6158215559475836131">"Untuk membuat seperti yang ini, sentuh lama aplikasi, lalu pindahkan ke atas aplikasi lain."</string>
- <string name="cling_dismiss" msgid="8962359497601507581">"Oke"</string>
<string name="folder_opened" msgid="94695026776264709">"Folder dibuka, <xliff:g id="WIDTH">%1$d</xliff:g> x <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
<string name="folder_tap_to_close" msgid="1884479294466410023">"Sentuh untuk menutup folder"</string>
<string name="folder_tap_to_rename" msgid="9191075570492871147">"Sentuh untuk menyimpan ganti nama"</string>
@@ -111,14 +68,34 @@
<string name="widget_button_text" msgid="2880537293434387943">"Widget"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"Wallpaper"</string>
<string name="settings_button_text" msgid="8119458837558863227">"Setelan"</string>
- <string name="package_state_enqueued" msgid="6227252464303085641">"Menunggu"</string>
- <string name="package_state_downloading" msgid="4088770468458724721">"Mengunduh"</string>
- <string name="package_state_installing" msgid="7588193972189849870">"Memasang"</string>
+ <string name="allow_rotation_title" msgid="2118706734511831751">"Izinkan putaran"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Tidak dikenal"</string>
- <string name="package_state_error" msgid="7672093962724223588">"Tak dipulihkan"</string>
- <string name="abandoned_clean_all" msgid="5256770727689657618">"Buang Semua"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Buang"</string>
<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="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>
+ <string name="item_removed" msgid="851119963877842327">"Item dihapus"</string>
+ <string name="action_move" msgid="4339390619886385032">"Pindahkan item"</string>
+ <string name="move_to_empty_cell" msgid="2833711483015685619">"Pindahkan ke baris <xliff:g id="NUMBER_0">%1$s</xliff:g> kolom <xliff:g id="NUMBER_1">%2$s</xliff:g>"</string>
+ <string name="move_to_position" msgid="6750008980455459790">"PIndahkan ke posisi <xliff:g id="NUMBER">%1$s</xliff:g>"</string>
+ <string name="move_to_hotseat_position" msgid="6295412897075147808">"Pindahkan ke posisi favorit <xliff:g id="NUMBER">%1$s</xliff:g>"</string>
+ <string name="item_moved" msgid="4606538322571412879">"Item dipindahkan"</string>
+ <string name="add_to_folder" msgid="9040534766770853243">"Tambahkan ke folder: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="add_to_folder_with_app" msgid="4534929978967147231">"Tambahkan ke folder dengan <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="added_to_folder" msgid="4793259502305558003">"Item ditambahkan ke folder"</string>
+ <string name="create_folder_with" msgid="4050141361160214248">"Buat folder dengan: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="folder_created" msgid="6409794597405184510">"Folder dibuat"</string>
+ <string name="action_move_to_workspace" msgid="1603837886334246317">"Pindahkan ke layar Utama"</string>
+ <string name="action_move_screen_left" msgid="8854216831569401665">"Pindahkan layar ke kiri"</string>
+ <string name="action_move_screen_right" msgid="329334910274311123">"Pindahkan layar ke kanan"</string>
+ <string name="screen_moved" msgid="266230079505650577">"Layar dipindahkan"</string>
+ <string name="action_resize" msgid="1802976324781771067">"Ubah ukuran"</string>
+ <string name="action_increase_width" msgid="8773715375078513326">"Tambahi lebar"</string>
+ <string name="action_increase_height" msgid="459390020612501122">"Tambahi tinggi"</string>
+ <string name="action_decrease_width" msgid="1374549771083094654">"Kurangi lebar"</string>
+ <string name="action_decrease_height" msgid="282377193880900022">"Kurangi tinggi"</string>
+ <string name="widget_resized" msgid="9130327887929620">"Widget diubah ukurannya menjadi lebar <xliff:g id="NUMBER_0">%1$s</xliff:g> tinggi <xliff:g id="NUMBER_1">%2$s</xliff:g>"</string>
</resources>
diff --git a/res/values-is-rIS/strings.xml b/res/values-is-rIS/strings.xml
index a3fa0bc52..1d46cdc93 100644
--- a/res/values-is-rIS/strings.xml
+++ b/res/values-is-rIS/strings.xml
@@ -20,57 +20,27 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="application_name" msgid="5181331383435256801">"Launcher3"</string>
- <string name="home" msgid="7658288663002113681">"Heim"</string>
- <string name="uid_name" msgid="7820867637514617527">"Kjarnaforrit Android"</string>
<string name="folder_name" msgid="7371454440695724752"></string>
+ <string name="work_folder_name" msgid="3753320833950115786">"Vinna"</string>
<string name="activity_not_found" msgid="8071924732094499514">"Forritið er ekki uppsett."</string>
<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="widgets_tab_label" msgid="2921133187116603919">"Græjur"</string>
- <string name="widget_adder" msgid="3201040140710381657">"Græjur"</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="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
- <string name="external_drop_widget_error" msgid="3165821058322217155">"Ekki er hægt að sleppa atriði á þennan heimaskjá."</string>
- <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Veldu græju til að búa til"</string>
- <string name="rename_folder_label" msgid="3727762225964550653">"Möppuheiti"</string>
- <string name="rename_folder_title" msgid="3771389277707820891">"Endurnefna möppu"</string>
- <string name="rename_action" msgid="5559600076028658757">"Í lagi"</string>
- <string name="cancel_action" msgid="7009134900002915310">"Hætta við"</string>
- <string name="menu_item_add_item" msgid="1264911265836810421">"Bæta á heimaskjá"</string>
- <string name="group_applications" msgid="3797214114206693605">"Forrit"</string>
- <string name="group_shortcuts" msgid="6012256992764410535">"Flýtileiðir"</string>
- <string name="group_widgets" msgid="1569030723286851002">"Græjur"</string>
- <string name="completely_out_of_space" msgid="6106288382070760318">"Heimaskjáirnir þínir eru fullskipaðir."</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>
+ <string name="all_apps_no_search_results" msgid="6332185285860416787">"Ekki fundust forrit sem samsvara „<xliff:g id="QUERY">%1$s</xliff:g>“"</string>
<string name="out_of_space" msgid="4691004494942118364">"Ekki meira pláss á þessum heimaskjá."</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"Ekki meira pláss í bakka fyrir uppáhald"</string>
- <string name="invalid_hotseat_item" msgid="5779907847267573691">"Þessi græja er of stór fyrir bakkann fyrir uppáhald"</string>
- <string name="shortcut_installed" msgid="1701742129426969556">"Flýtileiðin „<xliff:g id="NAME">%s</xliff:g>“ var búin til."</string>
- <string name="shortcut_uninstalled" msgid="8176767991305701821">"Flýtileiðin „<xliff:g id="NAME">%s</xliff:g>“ var fjarlægð."</string>
- <string name="shortcut_duplicate" msgid="9167217446062498127">"Flýtileiðin „<xliff:g id="NAME">%s</xliff:g>“ er þegar til."</string>
- <string name="title_select_shortcut" msgid="6680642571148153868">"Veldu flýtileið"</string>
- <string name="title_select_application" msgid="3280812711670683644">"Veldu forrit"</string>
<string name="all_apps_button_label" msgid="9110807029020582876">"Forrit"</string>
<string name="all_apps_home_button_label" msgid="252062713717058851">"Heim"</string>
- <string name="delete_zone_label_workspace" msgid="4009607676751398685">"Fjarlægja"</string>
- <string name="delete_zone_label_all_apps" msgid="8083826390278958980">"Eyða"</string>
<string name="delete_target_label" msgid="1822697352535677073">"Fjarlægja"</string>
<string name="delete_target_uninstall_label" msgid="5100785476250872595">"Eyða"</string>
<string name="info_target_label" msgid="8053346143994679532">"Upplýsingar um forrit"</string>
- <string name="accessibility_all_apps_button" msgid="2603132375383800483">"Forrit"</string>
- <string name="accessibility_delete_button" msgid="6466114477993744621">"Fjarlægja"</string>
- <string name="delete_zone_label_all_apps_system_app" msgid="449755632749610895">"Fjarlægja uppfærslu"</string>
- <string name="cab_menu_delete_app" msgid="7435191475867183689">"Fjarlægja forrit"</string>
- <string name="cab_menu_app_info" msgid="8593722221450362342">"Upplýsingar um forrit"</string>
- <string name="cab_app_selection_text" msgid="374688303047985416">"1 forrit valið"</string>
- <string name="cab_widget_selection_text" msgid="1833458597831541241">"1 græja valin"</string>
- <string name="cab_folder_selection_text" msgid="7999992513806132118">"1 mappa valin"</string>
- <string name="cab_shortcut_selection_text" msgid="2103811025667946450">"1 flýtileið valin"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"setja upp flýtileiðir"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"Leyfir forriti að bæta við flýtileiðum án íhlutunar notanda."</string>
- <string name="permlab_uninstall_shortcut" msgid="864595034498083837">"fjarlægja flýtileiðir"</string>
- <string name="permdesc_uninstall_shortcut" msgid="5134129545001836849">"Leyfir forriti að fjarlægja flýtileiðir án íhlutunar notanda."</string>
<string name="permlab_read_settings" msgid="1941457408239617576">"lesa stillingar og flýtileiðir heimaskjás"</string>
<string name="permdesc_read_settings" msgid="5833423719057558387">"Leyfir forriti að lesa stillingar og flýtileiðir heimaskjás."</string>
<string name="permlab_write_settings" msgid="3574213698004620587">"skrifa stillingar og flýtileiðir heimaskjás"</string>
@@ -78,30 +48,17 @@
<string name="gadget_error_text" msgid="6081085226050792095">"Vandamál við að hlaða græju"</string>
<string name="gadget_setup_text" msgid="8274003207686040488">"Uppsetning"</string>
<string name="uninstall_system_app_text" msgid="4172046090762920660">"Þetta er kerfisforrit sem ekki er hægt að fjarlægja."</string>
- <string name="dream_name" msgid="1530253749244328964">"Eldflaugapallur"</string>
<string name="folder_hint_text" msgid="6617836969016293992">"Ónefnd mappa"</string>
- <string name="workspace_description_format" msgid="2950174241104043327">"Heimaskjár %1$d"</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="apps_customize_apps_scroll_format" msgid="370005296147130238">"Forritasíða %1$d af %2$d"</string>
- <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"Græjusíða %1$d af %2$d"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"Komdu fagnandi"</string>
- <string name="first_run_cling_description" msgid="6447072552696253358">"Komdu þér vel fyrir."</string>
- <string name="first_run_cling_custom_content_hint" msgid="6090628589029352439"></string>
- <string name="first_run_cling_search_bar_hint" msgid="5909062802402452582"></string>
- <string name="first_run_cling_create_screens_hint" msgid="6950729526680114157">"Búðu til fleiri skjái fyrir forrit og möppur"</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>
<string name="migration_cling_copy_apps" msgid="946331230090919440">"AFRITA TÁKN"</string>
<string name="migration_cling_use_default" msgid="2626475813981258626">"BYRJA UPP Á NÝTT"</string>
- <string name="workspace_cling_title" msgid="5626202359865825661">"Settu hlutina á sína staði"</string>
- <string name="workspace_cling_move_item" msgid="528201129978005352">"Haltu inni á bakgrunni til að stjórna veggfóðri, græjum og stillingum."</string>
<string name="workspace_cling_longpress_title" msgid="9173998993909018310">"Veggfóður, græjur og stillingar"</string>
<string name="workspace_cling_longpress_description" msgid="4119994475505235248">"Haltu fingri á bakgrunninum til að sérsníða hann"</string>
<string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"ÉG SKIL"</string>
- <string name="folder_cling_title" msgid="3894908818693254164">"Hér er mappa"</string>
- <string name="folder_cling_create_folder" msgid="6158215559475836131">"Til að búa til svona skaltu draga forrit yfir á annað forrit."</string>
- <string name="cling_dismiss" msgid="8962359497601507581">"Í lagi"</string>
<string name="folder_opened" msgid="94695026776264709">"Mappa opnuð, <xliff:g id="WIDTH">%1$d</xliff:g> sinnum <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
<string name="folder_tap_to_close" msgid="1884479294466410023">"Snertu til að loka möppunni"</string>
<string name="folder_tap_to_rename" msgid="9191075570492871147">"Snertu til að staðfesta nýtt heiti"</string>
@@ -111,14 +68,34 @@
<string name="widget_button_text" msgid="2880537293434387943">"Græjur"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"Veggfóður"</string>
<string name="settings_button_text" msgid="8119458837558863227">"Stillingar"</string>
- <string name="package_state_enqueued" msgid="6227252464303085641">"Bíður"</string>
- <string name="package_state_downloading" msgid="4088770468458724721">"Sækir"</string>
- <string name="package_state_installing" msgid="7588193972189849870">"Setur upp"</string>
+ <string name="allow_rotation_title" msgid="2118706734511831751">"Leyfa snúning"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Óþekkt"</string>
- <string name="package_state_error" msgid="7672093962724223588">"Ekki endurheimt"</string>
- <string name="abandoned_clean_all" msgid="5256770727689657618">"Fjarlægja öll"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Fjarlægja"</string>
<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="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>
+ <string name="item_removed" msgid="851119963877842327">"Atriði fjarlægt"</string>
+ <string name="action_move" msgid="4339390619886385032">"Færa atriði"</string>
+ <string name="move_to_empty_cell" msgid="2833711483015685619">"Færa í línu <xliff:g id="NUMBER_0">%1$s</xliff:g>, dálk <xliff:g id="NUMBER_1">%2$s</xliff:g>"</string>
+ <string name="move_to_position" msgid="6750008980455459790">"Færa í stöðu <xliff:g id="NUMBER">%1$s</xliff:g>"</string>
+ <string name="move_to_hotseat_position" msgid="6295412897075147808">"Færa í stöðu <xliff:g id="NUMBER">%1$s</xliff:g> á festisvæði"</string>
+ <string name="item_moved" msgid="4606538322571412879">"Atriði fært"</string>
+ <string name="add_to_folder" msgid="9040534766770853243">"Setja í möppu: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="add_to_folder_with_app" msgid="4534929978967147231">"Setja í möppu með <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="added_to_folder" msgid="4793259502305558003">"Atriði sett í möppu"</string>
+ <string name="create_folder_with" msgid="4050141361160214248">"Búa til möppu með: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="folder_created" msgid="6409794597405184510">"Mappa búin til"</string>
+ <string name="action_move_to_workspace" msgid="1603837886334246317">"Færa á heimaskjá"</string>
+ <string name="action_move_screen_left" msgid="8854216831569401665">"Færa skjá til vinstri"</string>
+ <string name="action_move_screen_right" msgid="329334910274311123">"Færa skjá til hægri"</string>
+ <string name="screen_moved" msgid="266230079505650577">"Skjár færður"</string>
+ <string name="action_resize" msgid="1802976324781771067">"Breyta stærð"</string>
+ <string name="action_increase_width" msgid="8773715375078513326">"Auka breidd"</string>
+ <string name="action_increase_height" msgid="459390020612501122">"Auka hæð"</string>
+ <string name="action_decrease_width" msgid="1374549771083094654">"Minnka breidd"</string>
+ <string name="action_decrease_height" msgid="282377193880900022">"Minnka hæð"</string>
+ <string name="widget_resized" msgid="9130327887929620">"Stærð græju breytt í <xliff:g id="NUMBER_0">%1$s</xliff:g> á breidd og <xliff:g id="NUMBER_1">%2$s</xliff:g> á hæð"</string>
</resources>
diff --git a/res/values-it/strings.xml b/res/values-it/strings.xml
index d78d0326d..02057a19c 100644
--- a/res/values-it/strings.xml
+++ b/res/values-it/strings.xml
@@ -20,57 +20,27 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="application_name" msgid="5181331383435256801">"Launcher3"</string>
- <string name="home" msgid="7658288663002113681">"Home page"</string>
- <string name="uid_name" msgid="7820867637514617527">"Applicazioni di base Android"</string>
<string name="folder_name" msgid="7371454440695724752"></string>
+ <string name="work_folder_name" msgid="3753320833950115786">"Lavoro"</string>
<string name="activity_not_found" msgid="8071924732094499514">"App non installata."</string>
<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="widgets_tab_label" msgid="2921133187116603919">"Widget"</string>
- <string name="widget_adder" msgid="3201040140710381657">"Widget"</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="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
- <string name="external_drop_widget_error" msgid="3165821058322217155">"Rilascio elemento in schermata Home non riuscito."</string>
- <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Scegli il widget da creare"</string>
- <string name="rename_folder_label" msgid="3727762225964550653">"Nome cartella"</string>
- <string name="rename_folder_title" msgid="3771389277707820891">"Rinomina cartella"</string>
- <string name="rename_action" msgid="5559600076028658757">"OK"</string>
- <string name="cancel_action" msgid="7009134900002915310">"Annulla"</string>
- <string name="menu_item_add_item" msgid="1264911265836810421">"Aggiungi a schermata Home"</string>
- <string name="group_applications" msgid="3797214114206693605">"App"</string>
- <string name="group_shortcuts" msgid="6012256992764410535">"Scorciatoie"</string>
- <string name="group_widgets" msgid="1569030723286851002">"Widget"</string>
- <string name="completely_out_of_space" msgid="6106288382070760318">"Spazio nelle schermate Home esaurito."</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>
+ <string name="all_apps_no_search_results" msgid="6332185285860416787">"Nessuna app trovata corrispondente a \"<xliff:g id="QUERY">%1$s</xliff:g>\""</string>
<string name="out_of_space" msgid="4691004494942118364">"Spazio nella schermata Home esaurito."</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"Spazio esaurito nella barra dei Preferiti"</string>
- <string name="invalid_hotseat_item" msgid="5779907847267573691">"Questo widget è troppo grande per la barra dei Preferiti"</string>
- <string name="shortcut_installed" msgid="1701742129426969556">"Scorciatoia \"<xliff:g id="NAME">%s</xliff:g>\" creata."</string>
- <string name="shortcut_uninstalled" msgid="8176767991305701821">"La scorciatoia \"<xliff:g id="NAME">%s</xliff:g>\" è stata rimossa."</string>
- <string name="shortcut_duplicate" msgid="9167217446062498127">"Scorciatoia \"<xliff:g id="NAME">%s</xliff:g>\" già presente."</string>
- <string name="title_select_shortcut" msgid="6680642571148153868">"Scegli scorciatoia"</string>
- <string name="title_select_application" msgid="3280812711670683644">"Scegli app"</string>
<string name="all_apps_button_label" msgid="9110807029020582876">"App"</string>
<string name="all_apps_home_button_label" msgid="252062713717058851">"Home page"</string>
- <string name="delete_zone_label_workspace" msgid="4009607676751398685">"Rimuovi"</string>
- <string name="delete_zone_label_all_apps" msgid="8083826390278958980">"Disinstalla"</string>
<string name="delete_target_label" msgid="1822697352535677073">"Rimuovi"</string>
<string name="delete_target_uninstall_label" msgid="5100785476250872595">"Disinstalla"</string>
<string name="info_target_label" msgid="8053346143994679532">"Informazioni app"</string>
- <string name="accessibility_all_apps_button" msgid="2603132375383800483">"App"</string>
- <string name="accessibility_delete_button" msgid="6466114477993744621">"Rimuovi"</string>
- <string name="delete_zone_label_all_apps_system_app" msgid="449755632749610895">"Disinstalla aggiornamento"</string>
- <string name="cab_menu_delete_app" msgid="7435191475867183689">"Disinstalla app"</string>
- <string name="cab_menu_app_info" msgid="8593722221450362342">"Dettagli sull\'app"</string>
- <string name="cab_app_selection_text" msgid="374688303047985416">"1 app selezionata"</string>
- <string name="cab_widget_selection_text" msgid="1833458597831541241">"1 widget selezionato"</string>
- <string name="cab_folder_selection_text" msgid="7999992513806132118">"1 cartella selezionata"</string>
- <string name="cab_shortcut_selection_text" msgid="2103811025667946450">"1 scorciatoia selezionata"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"aggiunta di scorciatoie"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"Consente a un\'app di aggiungere scorciatoie automaticamente."</string>
- <string name="permlab_uninstall_shortcut" msgid="864595034498083837">"eliminazione di scorciatoie"</string>
- <string name="permdesc_uninstall_shortcut" msgid="5134129545001836849">"Consente all\'app di rimuovere scorciatoie automaticamente."</string>
<string name="permlab_read_settings" msgid="1941457408239617576">"lettura di impostazioni e scorciatoie in Home"</string>
<string name="permdesc_read_settings" msgid="5833423719057558387">"Consente all\'app di leggere le impostazioni e le scorciatoie in Home."</string>
<string name="permlab_write_settings" msgid="3574213698004620587">"creazione di impostazioni e scorciatoie in Home"</string>
@@ -78,30 +48,17 @@
<string name="gadget_error_text" msgid="6081085226050792095">"Errore durante il caricamento del widget"</string>
<string name="gadget_setup_text" msgid="8274003207686040488">"Configurazione"</string>
<string name="uninstall_system_app_text" msgid="4172046090762920660">"Questa è un\'app di sistema e non può essere disinstallata."</string>
- <string name="dream_name" msgid="1530253749244328964">"Lanciamissili"</string>
<string name="folder_hint_text" msgid="6617836969016293992">"Cartella senza nome"</string>
- <string name="workspace_description_format" msgid="2950174241104043327">"Schermata Home %1$d"</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="apps_customize_apps_scroll_format" msgid="370005296147130238">"Pagina di applicazioni %1$d di %2$d"</string>
- <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"Pagina di widget %1$d di %2$d"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"Benvenuto"</string>
- <string name="first_run_cling_description" msgid="6447072552696253358">"Personalizza la schermata Home."</string>
- <string name="first_run_cling_custom_content_hint" msgid="6090628589029352439"></string>
- <string name="first_run_cling_search_bar_hint" msgid="5909062802402452582"></string>
- <string name="first_run_cling_create_screens_hint" msgid="6950729526680114157">"Creare più schermate per app e cartelle"</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>
<string name="migration_cling_copy_apps" msgid="946331230090919440">"COPIA ICONE"</string>
<string name="migration_cling_use_default" msgid="2626475813981258626">"RICOMINCIA"</string>
- <string name="workspace_cling_title" msgid="5626202359865825661">"Organizza il tuo spazio"</string>
- <string name="workspace_cling_move_item" msgid="528201129978005352">"Tocca e tieni premuto lo sfondo per gestire sfondi, widget e impostazioni."</string>
<string name="workspace_cling_longpress_title" msgid="9173998993909018310">"Sfondi, widget e impostazioni"</string>
<string name="workspace_cling_longpress_description" msgid="4119994475505235248">"Tocca lo sfondo e tieni premuto per personalizzare"</string>
<string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"OK"</string>
- <string name="folder_cling_title" msgid="3894908818693254164">"Ecco una cartella"</string>
- <string name="folder_cling_create_folder" msgid="6158215559475836131">"Per crearne una simile, tocca un\'app e tieni premuto, dopodiché spostala sopra un\'altra."</string>
- <string name="cling_dismiss" msgid="8962359497601507581">"OK"</string>
<string name="folder_opened" msgid="94695026776264709">"Cartella aperta, <xliff:g id="WIDTH">%1$d</xliff:g> per <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
<string name="folder_tap_to_close" msgid="1884479294466410023">"Tocca per chiudere la cartella"</string>
<string name="folder_tap_to_rename" msgid="9191075570492871147">"Tocca per salvare nuovo nome"</string>
@@ -111,14 +68,34 @@
<string name="widget_button_text" msgid="2880537293434387943">"Widget"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"Sfondi"</string>
<string name="settings_button_text" msgid="8119458837558863227">"Impostazioni"</string>
- <string name="package_state_enqueued" msgid="6227252464303085641">"In attesa"</string>
- <string name="package_state_downloading" msgid="4088770468458724721">"Download..."</string>
- <string name="package_state_installing" msgid="7588193972189849870">"Installazione..."</string>
+ <string name="allow_rotation_title" msgid="2118706734511831751">"Consenti rotazione"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Sconosciuto"</string>
- <string name="package_state_error" msgid="7672093962724223588">"Non ripristinato"</string>
- <string name="abandoned_clean_all" msgid="5256770727689657618">"Rimuovi tutto"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Rimuovi"</string>
<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="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>
+ <string name="item_removed" msgid="851119963877842327">"Elemento rimosso"</string>
+ <string name="action_move" msgid="4339390619886385032">"Sposta elemento"</string>
+ <string name="move_to_empty_cell" msgid="2833711483015685619">"Sposta a riga <xliff:g id="NUMBER_0">%1$s</xliff:g>, colonna <xliff:g id="NUMBER_1">%2$s</xliff:g>"</string>
+ <string name="move_to_position" msgid="6750008980455459790">"Sposta nella posizione <xliff:g id="NUMBER">%1$s</xliff:g>"</string>
+ <string name="move_to_hotseat_position" msgid="6295412897075147808">"Sposta nella posizione <xliff:g id="NUMBER">%1$s</xliff:g> dei preferiti"</string>
+ <string name="item_moved" msgid="4606538322571412879">"Elemento spostato"</string>
+ <string name="add_to_folder" msgid="9040534766770853243">"Aggiungi alla cartella: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="add_to_folder_with_app" msgid="4534929978967147231">"Aggiungi a cartella con <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="added_to_folder" msgid="4793259502305558003">"Elemento aggiunto alla cartella"</string>
+ <string name="create_folder_with" msgid="4050141361160214248">"Crea cartella con: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="folder_created" msgid="6409794597405184510">"Cartella creata"</string>
+ <string name="action_move_to_workspace" msgid="1603837886334246317">"Sposta nella schermata Home"</string>
+ <string name="action_move_screen_left" msgid="8854216831569401665">"Sposta schermata a sinistra"</string>
+ <string name="action_move_screen_right" msgid="329334910274311123">"Sposta schermata a destra"</string>
+ <string name="screen_moved" msgid="266230079505650577">"Schermata spostata"</string>
+ <string name="action_resize" msgid="1802976324781771067">"Ridimensiona"</string>
+ <string name="action_increase_width" msgid="8773715375078513326">"Aumenta larghezza"</string>
+ <string name="action_increase_height" msgid="459390020612501122">"Aumenta altezza"</string>
+ <string name="action_decrease_width" msgid="1374549771083094654">"Riduci larghezza"</string>
+ <string name="action_decrease_height" msgid="282377193880900022">"Riduci altezza"</string>
+ <string name="widget_resized" msgid="9130327887929620">"Widget ridimensionato a larghezza <xliff:g id="NUMBER_0">%1$s</xliff:g>, altezza <xliff:g id="NUMBER_1">%2$s</xliff:g>"</string>
</resources>
diff --git a/res/values-iw/strings.xml b/res/values-iw/strings.xml
index 61fb53efa..a8039f7c1 100644
--- a/res/values-iw/strings.xml
+++ b/res/values-iw/strings.xml
@@ -20,57 +20,27 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="application_name" msgid="5181331383435256801">"Launcher3"</string>
- <string name="home" msgid="7658288663002113681">"דף הבית"</string>
- <string name="uid_name" msgid="7820867637514617527">"‏אפליקציות הליבה של Android"</string>
<string name="folder_name" msgid="7371454440695724752"></string>
+ <string name="work_folder_name" msgid="3753320833950115786">"עבודה"</string>
<string name="activity_not_found" msgid="8071924732094499514">"האפליקציה לא מותקנת."</string>
<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="widgets_tab_label" msgid="2921133187116603919">"רכיבי ווידג\'ט"</string>
- <string name="widget_adder" msgid="3201040140710381657">"רכיבי ווידג\'ט"</string>
<string name="toggle_weight_watcher" msgid="5645299835184636119">"הצג זכרון"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"גע נגיעה רציפה בווידג\'ט כדי לבחור בו."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
- <string name="external_drop_widget_error" msgid="3165821058322217155">"לא ניתן היה לשחרר את הפריט במסך דף הבית הזה."</string>
- <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"בחר ווידג\'ט ליצירה"</string>
- <string name="rename_folder_label" msgid="3727762225964550653">"שם תיקיה"</string>
- <string name="rename_folder_title" msgid="3771389277707820891">"שנה את שם התיקיה"</string>
- <string name="rename_action" msgid="5559600076028658757">"אישור"</string>
- <string name="cancel_action" msgid="7009134900002915310">"בטל"</string>
- <string name="menu_item_add_item" msgid="1264911265836810421">"הוסף למסך דף הבית"</string>
- <string name="group_applications" msgid="3797214114206693605">"אפליקציות"</string>
- <string name="group_shortcuts" msgid="6012256992764410535">"קיצורי דרך"</string>
- <string name="group_widgets" msgid="1569030723286851002">"רכיבי ווידג\'ט"</string>
- <string name="completely_out_of_space" msgid="6106288382070760318">"אין יותר מקום במסכי דף הבית."</string>
+ <string name="all_apps_search_bar_hint" msgid="7084713969757597256">"חפש אפליקציות"</string>
+ <string name="all_apps_loading_message" msgid="7557140873644765180">"טוען אפליקציות…"</string>
+ <string name="all_apps_no_search_results" msgid="6332185285860416787">"לא נמצאו אפליקציות התואמות ל-\"<xliff:g id="QUERY">%1$s</xliff:g>\""</string>
<string name="out_of_space" msgid="4691004494942118364">"אין עוד מקום במסך דף הבית הזה."</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"אין עוד מקום במגש המועדפים"</string>
- <string name="invalid_hotseat_item" msgid="5779907847267573691">"הווידג\'ט הזה גדול מדי עבור מגש המועדפים."</string>
- <string name="shortcut_installed" msgid="1701742129426969556">"קיצור הדרך \'<xliff:g id="NAME">%s</xliff:g>\' נוצר."</string>
- <string name="shortcut_uninstalled" msgid="8176767991305701821">"קיצור הדרך \'<xliff:g id="NAME">%s</xliff:g>\' הוסר."</string>
- <string name="shortcut_duplicate" msgid="9167217446062498127">"קיצור הדרך \'<xliff:g id="NAME">%s</xliff:g>\' כבר קיים."</string>
- <string name="title_select_shortcut" msgid="6680642571148153868">"בחר קיצור דרך"</string>
- <string name="title_select_application" msgid="3280812711670683644">"בחר אפליקציה"</string>
<string name="all_apps_button_label" msgid="9110807029020582876">"אפליקציות"</string>
<string name="all_apps_home_button_label" msgid="252062713717058851">"דף הבית"</string>
- <string name="delete_zone_label_workspace" msgid="4009607676751398685">"הסר"</string>
- <string name="delete_zone_label_all_apps" msgid="8083826390278958980">"הסר התקנה"</string>
<string name="delete_target_label" msgid="1822697352535677073">"הסר"</string>
<string name="delete_target_uninstall_label" msgid="5100785476250872595">"הסר התקנה"</string>
<string name="info_target_label" msgid="8053346143994679532">"פרטי אפליקציה"</string>
- <string name="accessibility_all_apps_button" msgid="2603132375383800483">"אפליקציות"</string>
- <string name="accessibility_delete_button" msgid="6466114477993744621">"הסר"</string>
- <string name="delete_zone_label_all_apps_system_app" msgid="449755632749610895">"הסר את התקנת העדכון"</string>
- <string name="cab_menu_delete_app" msgid="7435191475867183689">"הסר את התקנת האפליקציה"</string>
- <string name="cab_menu_app_info" msgid="8593722221450362342">"פרטי האפליקציה"</string>
- <string name="cab_app_selection_text" msgid="374688303047985416">"נבחרה אפליקציה אחת"</string>
- <string name="cab_widget_selection_text" msgid="1833458597831541241">"נבחר ווידג\'ט אחד"</string>
- <string name="cab_folder_selection_text" msgid="7999992513806132118">"נבחרה תיקיה אחת"</string>
- <string name="cab_shortcut_selection_text" msgid="2103811025667946450">"נבחר קיצור דרך אחד"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"התקן קיצורי דרך"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"מאפשר לאפליקציה להוסיף קיצורי דרך ללא התערבות המשתמש."</string>
- <string name="permlab_uninstall_shortcut" msgid="864595034498083837">"הסר התקנה של קיצורי דרך"</string>
- <string name="permdesc_uninstall_shortcut" msgid="5134129545001836849">"מאפשר לאפליקציה להסיר קיצורי דרך ללא התערבות המשתמש."</string>
<string name="permlab_read_settings" msgid="1941457408239617576">"קרא הגדרות וקיצורי דרך של דף הבית"</string>
<string name="permdesc_read_settings" msgid="5833423719057558387">"מאפשר לאפליקציה לקרוא את ההגדרות וקיצורי הדרך בדף הבית."</string>
<string name="permlab_write_settings" msgid="3574213698004620587">"כתוב הגדרות וקיצורי דרך של דף הבית"</string>
@@ -78,30 +48,17 @@
<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>
- <string name="dream_name" msgid="1530253749244328964">"Rocket Launcher"</string>
<string name="folder_hint_text" msgid="6617836969016293992">"תיקיה ללא שם"</string>
- <string name="workspace_description_format" msgid="2950174241104043327">"‏מסך דף הבית %1$d"</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="apps_customize_apps_scroll_format" msgid="370005296147130238">"‏דף אפליקציות %1$d מתוך %2$d"</string>
- <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"‏דף רכיבי ווידג\'ט ‏%1$d מתוך %2$d"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"ברוכים הבאים"</string>
- <string name="first_run_cling_description" msgid="6447072552696253358">"להרגיש בבית."</string>
- <string name="first_run_cling_custom_content_hint" msgid="6090628589029352439"></string>
- <string name="first_run_cling_search_bar_hint" msgid="5909062802402452582"></string>
- <string name="first_run_cling_create_screens_hint" msgid="6950729526680114157">"צור מסכים נוספים עבור אפליקציות ותיקיות"</string>
<string name="migration_cling_title" msgid="9181776667882933767">"העתקת סמלי האפליקציות שלך"</string>
<string name="migration_cling_description" msgid="2752413805582227644">"האם לייבא סמלים ותיקיות ממסכי דף הבית הישנים שלך?"</string>
<string name="migration_cling_copy_apps" msgid="946331230090919440">"העתק סמלים"</string>
<string name="migration_cling_use_default" msgid="2626475813981258626">"התחל דף חדש"</string>
- <string name="workspace_cling_title" msgid="5626202359865825661">"ארגן את אזור העבודה שלך"</string>
- <string name="workspace_cling_move_item" msgid="528201129978005352">"גע נגיעה רציפה ברקע כדי לנהל את הטפט, רכיבי הווידג\'ט וההגדרות."</string>
<string name="workspace_cling_longpress_title" msgid="9173998993909018310">"טפטים, ווידג\'טים והגדרות"</string>
<string name="workspace_cling_longpress_description" msgid="4119994475505235248">"גע והחזק ברקע לביצוע התאמה אישית"</string>
<string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"הבנתי"</string>
- <string name="folder_cling_title" msgid="3894908818693254164">"הנה תיקייה"</string>
- <string name="folder_cling_create_folder" msgid="6158215559475836131">"כדי ליצור תיקייה כזו, גע נגיעה רציפה באפליקציה, ולאחר מכן גרור ושחרר אותו על-גבי אפליקציה אחרת."</string>
- <string name="cling_dismiss" msgid="8962359497601507581">"אישור"</string>
<string name="folder_opened" msgid="94695026776264709">"תיקיה פתוחה, <xliff:g id="WIDTH">%1$d</xliff:g> על <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
<string name="folder_tap_to_close" msgid="1884479294466410023">"גע כדי לסגור את התיקיה"</string>
<string name="folder_tap_to_rename" msgid="9191075570492871147">"גע כדי לשמור את שינוי השם"</string>
@@ -111,14 +68,34 @@
<string name="widget_button_text" msgid="2880537293434387943">"רכיבי ווידג\'ט"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"טפטים"</string>
<string name="settings_button_text" msgid="8119458837558863227">"הגדרות"</string>
- <string name="package_state_enqueued" msgid="6227252464303085641">"ממתין"</string>
- <string name="package_state_downloading" msgid="4088770468458724721">"מוריד"</string>
- <string name="package_state_installing" msgid="7588193972189849870">"מתקין"</string>
+ <string name="allow_rotation_title" msgid="2118706734511831751">"אפשרות סיבוב"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"לא ידוע"</string>
- <string name="package_state_error" msgid="7672093962724223588">"לא שוחזרה"</string>
- <string name="abandoned_clean_all" msgid="5256770727689657618">"הסר את הכל"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"הסר"</string>
<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="action_add_to_workspace" msgid="8902165848117513641">"הוסף למסך דף הבית"</string>
+ <string name="action_move_here" msgid="2170188780612570250">"העבר את הפריט לכאן"</string>
+ <string name="item_added_to_workspace" msgid="4211073925752213539">"הפריט הועבר אל מסך דף הבית"</string>
+ <string name="item_removed" msgid="851119963877842327">"הפריט הוסר"</string>
+ <string name="action_move" msgid="4339390619886385032">"העבר את הפריט"</string>
+ <string name="move_to_empty_cell" msgid="2833711483015685619">"העבר אל שורה <xliff:g id="NUMBER_0">%1$s</xliff:g> עמודה <xliff:g id="NUMBER_1">%2$s</xliff:g>"</string>
+ <string name="move_to_position" msgid="6750008980455459790">"העבר אל מיקום <xliff:g id="NUMBER">%1$s</xliff:g>"</string>
+ <string name="move_to_hotseat_position" msgid="6295412897075147808">"העבר אל מיקום <xliff:g id="NUMBER">%1$s</xliff:g> במועדפים"</string>
+ <string name="item_moved" msgid="4606538322571412879">"הפריט הועבר"</string>
+ <string name="add_to_folder" msgid="9040534766770853243">"הוסף לתיקייה: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="add_to_folder_with_app" msgid="4534929978967147231">"העבר אל התיקייה עם <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="added_to_folder" msgid="4793259502305558003">"הפריט נוסף לתיקייה"</string>
+ <string name="create_folder_with" msgid="4050141361160214248">"צור תיקייה עם: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="folder_created" msgid="6409794597405184510">"התיקייה נוצרה"</string>
+ <string name="action_move_to_workspace" msgid="1603837886334246317">"העבר אל מסך דף הבית"</string>
+ <string name="action_move_screen_left" msgid="8854216831569401665">"הזז את המסך שמאלה"</string>
+ <string name="action_move_screen_right" msgid="329334910274311123">"הזז את המסך ימינה"</string>
+ <string name="screen_moved" msgid="266230079505650577">"המסך הועבר"</string>
+ <string name="action_resize" msgid="1802976324781771067">"שנה גודל"</string>
+ <string name="action_increase_width" msgid="8773715375078513326">"הגדל רוחב"</string>
+ <string name="action_increase_height" msgid="459390020612501122">"הגדל גובה"</string>
+ <string name="action_decrease_width" msgid="1374549771083094654">"הקטן רוחב"</string>
+ <string name="action_decrease_height" msgid="282377193880900022">"הקטן גובה"</string>
+ <string name="widget_resized" msgid="9130327887929620">"גודל הווידג\'ט שונה - רוחב <xliff:g id="NUMBER_0">%1$s</xliff:g> גובה <xliff:g id="NUMBER_1">%2$s</xliff:g>"</string>
</resources>
diff --git a/res/values-ja/strings.xml b/res/values-ja/strings.xml
index ec872b8a9..ba58d88ef 100644
--- a/res/values-ja/strings.xml
+++ b/res/values-ja/strings.xml
@@ -20,57 +20,27 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="application_name" msgid="5181331383435256801">"Launcher3"</string>
- <string name="home" msgid="7658288663002113681">"ホーム"</string>
- <string name="uid_name" msgid="7820867637514617527">"Android Core Apps"</string>
<string name="folder_name" msgid="7371454440695724752"></string>
+ <string name="work_folder_name" msgid="3753320833950115786">"仕事用"</string>
<string name="activity_not_found" msgid="8071924732094499514">"このアプリはインストールされていません。"</string>
<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="widgets_tab_label" msgid="2921133187116603919">"ウィジェット"</string>
- <string name="widget_adder" msgid="3201040140710381657">"ウィジェット"</string>
<string name="toggle_weight_watcher" msgid="5645299835184636119">"メモリーを表示"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"ウィジェットを追加するには押し続けます。"</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$dx%2$d"</string>
- <string name="external_drop_widget_error" msgid="3165821058322217155">"このホーム画面にアイテムをドロップできませんでした"</string>
- <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"作成するウィジェットの選択"</string>
- <string name="rename_folder_label" msgid="3727762225964550653">"フォルダ名"</string>
- <string name="rename_folder_title" msgid="3771389277707820891">"フォルダ名を変更"</string>
- <string name="rename_action" msgid="5559600076028658757">"OK"</string>
- <string name="cancel_action" msgid="7009134900002915310">"キャンセル"</string>
- <string name="menu_item_add_item" msgid="1264911265836810421">"ホーム画面に追加"</string>
- <string name="group_applications" msgid="3797214114206693605">"アプリ"</string>
- <string name="group_shortcuts" msgid="6012256992764410535">"ショートカット"</string>
- <string name="group_widgets" msgid="1569030723286851002">"ウィジェット"</string>
- <string name="completely_out_of_space" msgid="6106288382070760318">"ホーム画面に空きスペースがありません。"</string>
+ <string name="all_apps_search_bar_hint" msgid="7084713969757597256">"アプリを検索"</string>
+ <string name="all_apps_loading_message" msgid="7557140873644765180">"アプリを読み込んでいます…"</string>
+ <string name="all_apps_no_search_results" msgid="6332185285860416787">"「<xliff:g id="QUERY">%1$s</xliff:g>」に一致するアプリは見つかりませんでした"</string>
<string name="out_of_space" msgid="4691004494942118364">"このホーム画面に空きスペースがありません。"</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"お気に入りトレイに空きスペースがありません"</string>
- <string name="invalid_hotseat_item" msgid="5779907847267573691">"このウィジェットはお気に入りトレイには大きすぎます"</string>
- <string name="shortcut_installed" msgid="1701742129426969556">"ショートカット「<xliff:g id="NAME">%s</xliff:g>」を作成しました。"</string>
- <string name="shortcut_uninstalled" msgid="8176767991305701821">"ショートカット「<xliff:g id="NAME">%s</xliff:g>」を削除しました。"</string>
- <string name="shortcut_duplicate" msgid="9167217446062498127">"ショートカット「<xliff:g id="NAME">%s</xliff:g>」は既に存在します。"</string>
- <string name="title_select_shortcut" msgid="6680642571148153868">"ショートカットを選択"</string>
- <string name="title_select_application" msgid="3280812711670683644">"アプリを選択"</string>
<string name="all_apps_button_label" msgid="9110807029020582876">"アプリ"</string>
<string name="all_apps_home_button_label" msgid="252062713717058851">"ホーム"</string>
- <string name="delete_zone_label_workspace" msgid="4009607676751398685">"削除"</string>
- <string name="delete_zone_label_all_apps" msgid="8083826390278958980">"アンインストール"</string>
<string name="delete_target_label" msgid="1822697352535677073">"削除"</string>
<string name="delete_target_uninstall_label" msgid="5100785476250872595">"アンインストール"</string>
<string name="info_target_label" msgid="8053346143994679532">"アプリ情報"</string>
- <string name="accessibility_all_apps_button" msgid="2603132375383800483">"アプリ"</string>
- <string name="accessibility_delete_button" msgid="6466114477993744621">"削除"</string>
- <string name="delete_zone_label_all_apps_system_app" msgid="449755632749610895">"更新をアンインストール"</string>
- <string name="cab_menu_delete_app" msgid="7435191475867183689">"アプリをアンインストール"</string>
- <string name="cab_menu_app_info" msgid="8593722221450362342">"アプリの詳細"</string>
- <string name="cab_app_selection_text" msgid="374688303047985416">"1つのアプリが選択されています"</string>
- <string name="cab_widget_selection_text" msgid="1833458597831541241">"1つのウィジェットが選択されています"</string>
- <string name="cab_folder_selection_text" msgid="7999992513806132118">"1つのフォルダが選択されています"</string>
- <string name="cab_shortcut_selection_text" msgid="2103811025667946450">"1つのショートカットが選択されています"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"ショートカットのインストール"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"ユーザー操作なしでショートカットを追加することをアプリに許可します。"</string>
- <string name="permlab_uninstall_shortcut" msgid="864595034498083837">"ショートカットのアンインストール"</string>
- <string name="permdesc_uninstall_shortcut" msgid="5134129545001836849">"ユーザー操作なしでショートカットを削除することをアプリに許可します。"</string>
<string name="permlab_read_settings" msgid="1941457408239617576">"ホームの設定とショートカットの読み取り"</string>
<string name="permdesc_read_settings" msgid="5833423719057558387">"ホームの設定とショートカットの読み取りをアプリに許可します。"</string>
<string name="permlab_write_settings" msgid="3574213698004620587">"ホームの設定とショートカットの書き込み"</string>
@@ -78,30 +48,17 @@
<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>
- <string name="dream_name" msgid="1530253749244328964">"Rocket Launcher"</string>
<string name="folder_hint_text" msgid="6617836969016293992">"名前のないフォルダ"</string>
- <string name="workspace_description_format" msgid="2950174241104043327">"ホーム画面: %1$d"</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="apps_customize_apps_scroll_format" msgid="370005296147130238">"アプリの%1$d/%2$dページ"</string>
- <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"ウィジェットの%1$d/%2$dページ"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"ようこそ"</string>
- <string name="first_run_cling_description" msgid="6447072552696253358">"ホームをカスタマイズします。"</string>
- <string name="first_run_cling_custom_content_hint" msgid="6090628589029352439"></string>
- <string name="first_run_cling_search_bar_hint" msgid="5909062802402452582"></string>
- <string name="first_run_cling_create_screens_hint" msgid="6950729526680114157">"アプリとフォルダの画面をもっと作成します"</string>
<string name="migration_cling_title" msgid="9181776667882933767">"アプリのアイコンをコピー"</string>
<string name="migration_cling_description" msgid="2752413805582227644">"古いホーム画面からアイコンとフォルダをインポートしますか?"</string>
<string name="migration_cling_copy_apps" msgid="946331230090919440">"アイコンをコピー"</string>
<string name="migration_cling_use_default" msgid="2626475813981258626">"初期状態にリセットする"</string>
- <string name="workspace_cling_title" msgid="5626202359865825661">"スペースを整理"</string>
- <string name="workspace_cling_move_item" msgid="528201129978005352">"壁紙、ウィジェット、設定を管理するには、背景を押し続けます。"</string>
<string name="workspace_cling_longpress_title" msgid="9173998993909018310">"壁紙、ウィジェット、設定"</string>
<string name="workspace_cling_longpress_description" msgid="4119994475505235248">"カスタマイズするにはバックグラウンドを押し続けます"</string>
<string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"OK"</string>
- <string name="folder_cling_title" msgid="3894908818693254164">"これがフォルダです"</string>
- <string name="folder_cling_create_folder" msgid="6158215559475836131">"これと同じフォルダを作成するには、アプリを押し続けてから別のアプリの上に移動します。"</string>
- <string name="cling_dismiss" msgid="8962359497601507581">"OK"</string>
<string name="folder_opened" msgid="94695026776264709">"フォルダが開いています。<xliff:g id="WIDTH">%1$d</xliff:g>x<xliff:g id="HEIGHT">%2$d</xliff:g>の大きさです"</string>
<string name="folder_tap_to_close" msgid="1884479294466410023">"タップしてフォルダを閉じます"</string>
<string name="folder_tap_to_rename" msgid="9191075570492871147">"タップして名前の変更を保存します"</string>
@@ -111,14 +68,34 @@
<string name="widget_button_text" msgid="2880537293434387943">"ウィジェット"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"壁紙"</string>
<string name="settings_button_text" msgid="8119458837558863227">"設定"</string>
- <string name="package_state_enqueued" msgid="6227252464303085641">"待機中"</string>
- <string name="package_state_downloading" msgid="4088770468458724721">"ダウンロード中"</string>
- <string name="package_state_installing" msgid="7588193972189849870">"インストール中"</string>
+ <string name="allow_rotation_title" msgid="2118706734511831751">"回転を許可"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"不明"</string>
- <string name="package_state_error" msgid="7672093962724223588">"復元失敗"</string>
- <string name="abandoned_clean_all" msgid="5256770727689657618">"すべて削除"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"削除"</string>
<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="action_add_to_workspace" msgid="8902165848117513641">"ホーム画面に追加"</string>
+ <string name="action_move_here" msgid="2170188780612570250">"アイテムをここに移動"</string>
+ <string name="item_added_to_workspace" msgid="4211073925752213539">"アイテムをホーム画面に追加しました"</string>
+ <string name="item_removed" msgid="851119963877842327">"アイテムを削除しました"</string>
+ <string name="action_move" msgid="4339390619886385032">"アイテムを移動"</string>
+ <string name="move_to_empty_cell" msgid="2833711483015685619">"行<xliff:g id="NUMBER_0">%1$s</xliff:g>、列<xliff:g id="NUMBER_1">%2$s</xliff:g>に移動"</string>
+ <string name="move_to_position" msgid="6750008980455459790">"位置<xliff:g id="NUMBER">%1$s</xliff:g>に移動"</string>
+ <string name="move_to_hotseat_position" msgid="6295412897075147808">"お気に入りの位置<xliff:g id="NUMBER">%1$s</xliff:g>に移動"</string>
+ <string name="item_moved" msgid="4606538322571412879">"アイテムを移動しました"</string>
+ <string name="add_to_folder" msgid="9040534766770853243">"フォルダ「<xliff:g id="NAME">%1$s</xliff:g>」に追加"</string>
+ <string name="add_to_folder_with_app" msgid="4534929978967147231">"<xliff:g id="NAME">%1$s</xliff:g>のあるフォルダに追加"</string>
+ <string name="added_to_folder" msgid="4793259502305558003">"アイテムをフォルダに追加しました"</string>
+ <string name="create_folder_with" msgid="4050141361160214248">"「<xliff:g id="NAME">%1$s</xliff:g>」フォルダを作成"</string>
+ <string name="folder_created" msgid="6409794597405184510">"フォルダを作成しました"</string>
+ <string name="action_move_to_workspace" msgid="1603837886334246317">"ホーム画面に移動"</string>
+ <string name="action_move_screen_left" msgid="8854216831569401665">"画面を左に移動"</string>
+ <string name="action_move_screen_right" msgid="329334910274311123">"画面を右に移動"</string>
+ <string name="screen_moved" msgid="266230079505650577">"画面を移動しました"</string>
+ <string name="action_resize" msgid="1802976324781771067">"サイズを変更"</string>
+ <string name="action_increase_width" msgid="8773715375078513326">"幅を広くする"</string>
+ <string name="action_increase_height" msgid="459390020612501122">"高さを高くする"</string>
+ <string name="action_decrease_width" msgid="1374549771083094654">"幅を狭くする"</string>
+ <string name="action_decrease_height" msgid="282377193880900022">"高さを低くする"</string>
+ <string name="widget_resized" msgid="9130327887929620">"ウィジェットのサイズを幅<xliff:g id="NUMBER_0">%1$s</xliff:g>、高さ<xliff:g id="NUMBER_1">%2$s</xliff:g>に変更しました"</string>
</resources>
diff --git a/res/values-ka-rGE/strings.xml b/res/values-ka-rGE/strings.xml
index b96d3d267..07030d866 100644
--- a/res/values-ka-rGE/strings.xml
+++ b/res/values-ka-rGE/strings.xml
@@ -20,57 +20,27 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="application_name" msgid="5181331383435256801">"Launcher3"</string>
- <string name="home" msgid="7658288663002113681">"მთავარი"</string>
- <string name="uid_name" msgid="7820867637514617527">"Android-ის ბირთვის აპები"</string>
<string name="folder_name" msgid="7371454440695724752"></string>
+ <string name="work_folder_name" msgid="3753320833950115786">"სამუშაო"</string>
<string name="activity_not_found" msgid="8071924732094499514">"აპი არ არის დაყენებული."</string>
<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="widgets_tab_label" msgid="2921133187116603919">"ვიჯეტები"</string>
- <string name="widget_adder" msgid="3201040140710381657">"ვიჯეტები"</string>
<string name="toggle_weight_watcher" msgid="5645299835184636119">"Mem-ის ჩვენება"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"შეეხეთ და დააყოვნეთ ვიჯეტის ასარჩევად."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
- <string name="external_drop_widget_error" msgid="3165821058322217155">"ერთეულის მთავარ ეკრანზე ჩაგდება ვერ მოხერხდა."</string>
- <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"აირჩიეთ ვიჯეტი შესაქმნელად"</string>
- <string name="rename_folder_label" msgid="3727762225964550653">"საქაღალდის სახელი"</string>
- <string name="rename_folder_title" msgid="3771389277707820891">"საქაღალდის გადარქმევა"</string>
- <string name="rename_action" msgid="5559600076028658757">"კარგი"</string>
- <string name="cancel_action" msgid="7009134900002915310">"გაუქმება"</string>
- <string name="menu_item_add_item" msgid="1264911265836810421">"მთავარ ეკრანზე დამატება"</string>
- <string name="group_applications" msgid="3797214114206693605">"აპები"</string>
- <string name="group_shortcuts" msgid="6012256992764410535">"მალსახმობები"</string>
- <string name="group_widgets" msgid="1569030723286851002">"ვიჯეტები"</string>
- <string name="completely_out_of_space" msgid="6106288382070760318">"მთავარ ეკრანებზე ადგილი აღარ არის."</string>
+ <string name="all_apps_search_bar_hint" msgid="7084713969757597256">"აპების ძიება"</string>
+ <string name="all_apps_loading_message" msgid="7557140873644765180">"აპები იტვირთება..."</string>
+ <string name="all_apps_no_search_results" msgid="6332185285860416787">"„<xliff:g id="QUERY">%1$s</xliff:g>“-ის თანხვედრი აპები არ მოიძებნა"</string>
<string name="out_of_space" msgid="4691004494942118364">"ამ მთავარ ეკრანზე ადგილი აღარ არის."</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"რჩეულების თაროზე ადგილი არ არის"</string>
- <string name="invalid_hotseat_item" msgid="5779907847267573691">"ეს ვიჯეტი ძალიან დიდია რჩეულების თაროსთვის"</string>
- <string name="shortcut_installed" msgid="1701742129426969556">"შეიქმნა მალსახმობი „<xliff:g id="NAME">%s</xliff:g>“."</string>
- <string name="shortcut_uninstalled" msgid="8176767991305701821">"მასლახმობი „<xliff:g id="NAME">%s</xliff:g>“ წაშლილია."</string>
- <string name="shortcut_duplicate" msgid="9167217446062498127">"მალსახმობი „<xliff:g id="NAME">%s</xliff:g>“ უკვე არსებობს."</string>
- <string name="title_select_shortcut" msgid="6680642571148153868">"აირჩიეთ მალსახმობი"</string>
- <string name="title_select_application" msgid="3280812711670683644">"აირჩიეთ აპი"</string>
<string name="all_apps_button_label" msgid="9110807029020582876">"აპები"</string>
<string name="all_apps_home_button_label" msgid="252062713717058851">"მთავარი"</string>
- <string name="delete_zone_label_workspace" msgid="4009607676751398685">"წაშლა"</string>
- <string name="delete_zone_label_all_apps" msgid="8083826390278958980">"დეინსტალაცია"</string>
<string name="delete_target_label" msgid="1822697352535677073">"წაშლა"</string>
<string name="delete_target_uninstall_label" msgid="5100785476250872595">"დეინსტალაცია"</string>
<string name="info_target_label" msgid="8053346143994679532">"აპის შესახებ"</string>
- <string name="accessibility_all_apps_button" msgid="2603132375383800483">"აპები"</string>
- <string name="accessibility_delete_button" msgid="6466114477993744621">"წაშლა"</string>
- <string name="delete_zone_label_all_apps_system_app" msgid="449755632749610895">"განახლების დეინსტალაცია"</string>
- <string name="cab_menu_delete_app" msgid="7435191475867183689">"აპის დეინსტალაცია"</string>
- <string name="cab_menu_app_info" msgid="8593722221450362342">"აპის შესახებ"</string>
- <string name="cab_app_selection_text" msgid="374688303047985416">"არჩეულია 1 აპი"</string>
- <string name="cab_widget_selection_text" msgid="1833458597831541241">"არჩეულია 1 ვიჯეტი"</string>
- <string name="cab_folder_selection_text" msgid="7999992513806132118">"არჩეულია 1 საქაღალდე"</string>
- <string name="cab_shortcut_selection_text" msgid="2103811025667946450">"არჩეულია 1 მალსახმობი"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"მალსახმობების დაყენება"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"აპისთვის მალსახმობების დამოუკიდებლად დამატების უფლების მიცემა."</string>
- <string name="permlab_uninstall_shortcut" msgid="864595034498083837">"მალსახმობების წაშლა"</string>
- <string name="permdesc_uninstall_shortcut" msgid="5134129545001836849">"აპისთვის მალსახმობების დამოუკიდებლად წაშლის უფლების მიცემა."</string>
<string name="permlab_read_settings" msgid="1941457408239617576">"მთავარი ეკრანის პარამეტრებისა და მალსახმობების წაკითხვა"</string>
<string name="permdesc_read_settings" msgid="5833423719057558387">"აპისთვის მთავარი ეკრანის პარამეტრებისა და მალსახმობების წაკითხვის უფლების მიცემა."</string>
<string name="permlab_write_settings" msgid="3574213698004620587">"მთავარი ეკრანის პარამეტრებისა და მალსახმობების ჩაწერა"</string>
@@ -78,30 +48,17 @@
<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>
- <string name="dream_name" msgid="1530253749244328964">"ფეიერვერკი"</string>
<string name="folder_hint_text" msgid="6617836969016293992">"უსახელო საქაღალდე"</string>
- <string name="workspace_description_format" msgid="2950174241104043327">"მთავარი ეკრანი %1$d"</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="apps_customize_apps_scroll_format" msgid="370005296147130238">"აპების გვერდი %1$d, %2$d-დან"</string>
- <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"ვიჯეტების გვერდი %1$d, %2$d-დან"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"მოგესალმებით"</string>
- <string name="first_run_cling_description" msgid="6447072552696253358">"იგრძენით თავი საკუთარ სახლში"</string>
- <string name="first_run_cling_custom_content_hint" msgid="6090628589029352439"></string>
- <string name="first_run_cling_search_bar_hint" msgid="5909062802402452582"></string>
- <string name="first_run_cling_create_screens_hint" msgid="6950729526680114157">"აპებისა და საქაღალდეებისთვის კიდევ ერთი ეკრანის შექმნა"</string>
<string name="migration_cling_title" msgid="9181776667882933767">"თქვენი აპის ხატულების კოპირება"</string>
<string name="migration_cling_description" msgid="2752413805582227644">"გსურთ, ძველი მთავარი ეკრანიდან ხატულების და საქაღ. იმპორტი?"</string>
<string name="migration_cling_copy_apps" msgid="946331230090919440">"ხატულების კოპირება"</string>
<string name="migration_cling_use_default" msgid="2626475813981258626">"სტანდარტული განლაგება"</string>
- <string name="workspace_cling_title" msgid="5626202359865825661">"თქვენი სივრცის ორგანიზება"</string>
- <string name="workspace_cling_move_item" msgid="528201129978005352">"თუ გსურთ ფონების, ვიჯეტების და პარამეტრების მართვა, შეეხეთ და არ აუშვათ ფონს."</string>
<string name="workspace_cling_longpress_title" msgid="9173998993909018310">"ფონები, ვიჯეტები, &amp; პარამეტრები"</string>
<string name="workspace_cling_longpress_description" msgid="4119994475505235248">"მოსარგებად შეეხეთ &amp; დააყოვნეთ ფონზე"</string>
<string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"გასაგებია"</string>
- <string name="folder_cling_title" msgid="3894908818693254164">"აი, საქაღალდე"</string>
- <string name="folder_cling_create_folder" msgid="6158215559475836131">"ასეთის შესაქმნელად, შეეხეთ და დააყოვნეთ აპზე, ხოლო შემდეგ გადააჩოჩეთ შემდეგზე."</string>
- <string name="cling_dismiss" msgid="8962359497601507581">"კარგი"</string>
<string name="folder_opened" msgid="94695026776264709">"საქაღალდე გახსნილია, <xliff:g id="WIDTH">%1$d</xliff:g> x <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
<string name="folder_tap_to_close" msgid="1884479294466410023">"შეეხეთ საქაღალდის დასახურად"</string>
<string name="folder_tap_to_rename" msgid="9191075570492871147">"შეეხეთ ახალი სახელის შესანახად"</string>
@@ -111,14 +68,34 @@
<string name="widget_button_text" msgid="2880537293434387943">"ვიჯეტები"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"ფონები"</string>
<string name="settings_button_text" msgid="8119458837558863227">"პარამეტრები"</string>
- <string name="package_state_enqueued" msgid="6227252464303085641">"მოცდა..."</string>
- <string name="package_state_downloading" msgid="4088770468458724721">"ჩამოტვირთვა..."</string>
- <string name="package_state_installing" msgid="7588193972189849870">"ინსტალაცია..."</string>
+ <string name="allow_rotation_title" msgid="2118706734511831751">"როტაციის დაშვება"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"უცნობი"</string>
- <string name="package_state_error" msgid="7672093962724223588">"არ აღდგა"</string>
- <string name="abandoned_clean_all" msgid="5256770727689657618">"ყველას ამოშლა"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"ამოშლა"</string>
<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="action_add_to_workspace" msgid="8902165848117513641">"მთავარ ეკრანზე დამატება"</string>
+ <string name="action_move_here" msgid="2170188780612570250">"ერთეულის გადაადგილება აქ"</string>
+ <string name="item_added_to_workspace" msgid="4211073925752213539">"ერთეული დაემატა მთავარ ეკრანს"</string>
+ <string name="item_removed" msgid="851119963877842327">"ერთეული წაიშალა"</string>
+ <string name="action_move" msgid="4339390619886385032">"ერთეულის გადაადგილება"</string>
+ <string name="move_to_empty_cell" msgid="2833711483015685619">"გადატანა რიგში <xliff:g id="NUMBER_0">%1$s</xliff:g> სვეტში <xliff:g id="NUMBER_1">%2$s</xliff:g>"</string>
+ <string name="move_to_position" msgid="6750008980455459790">"გადატანა <xliff:g id="NUMBER">%1$s</xliff:g> პოზიციაზე"</string>
+ <string name="move_to_hotseat_position" msgid="6295412897075147808">"გადატანა რჩეულთა პოზიციაზე <xliff:g id="NUMBER">%1$s</xliff:g>"</string>
+ <string name="item_moved" msgid="4606538322571412879">"ერთეული გადაადგილდა"</string>
+ <string name="add_to_folder" msgid="9040534766770853243">"საქაღალდეში დამატება: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="add_to_folder_with_app" msgid="4534929978967147231">"საქაღალდეში დამატება <xliff:g id="NAME">%1$s</xliff:g>-ით"</string>
+ <string name="added_to_folder" msgid="4793259502305558003">"ერთეული დაემატა საქაღალდეს"</string>
+ <string name="create_folder_with" msgid="4050141361160214248">"საქაღალდის შექმნა ერთეულით: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="folder_created" msgid="6409794597405184510">"საქაღალდე შექმნილია"</string>
+ <string name="action_move_to_workspace" msgid="1603837886334246317">"მთავარ ეკრანზე გადატანა"</string>
+ <string name="action_move_screen_left" msgid="8854216831569401665">"ეკრანის გადატანა მარცხნივ"</string>
+ <string name="action_move_screen_right" msgid="329334910274311123">"ეკრანის გადატანა მარჯვნით"</string>
+ <string name="screen_moved" msgid="266230079505650577">"ეკრანი გადაადგილდა"</string>
+ <string name="action_resize" msgid="1802976324781771067">"ზომის შეცვლა"</string>
+ <string name="action_increase_width" msgid="8773715375078513326">"სიგანის გაზრდა"</string>
+ <string name="action_increase_height" msgid="459390020612501122">"სიმაღლის გაზრდა"</string>
+ <string name="action_decrease_width" msgid="1374549771083094654">"სიგანის შემცირება"</string>
+ <string name="action_decrease_height" msgid="282377193880900022">"სიმაღლის შემცირება"</string>
+ <string name="widget_resized" msgid="9130327887929620">"ვიჯეტის ზომები შეიცვალა: სიგანე <xliff:g id="NUMBER_0">%1$s</xliff:g> სიმაღლე <xliff:g id="NUMBER_1">%2$s</xliff:g>"</string>
</resources>
diff --git a/res/values-kk-rKZ/strings.xml b/res/values-kk-rKZ/strings.xml
index c5b5a62f6..e79c9ce98 100644
--- a/res/values-kk-rKZ/strings.xml
+++ b/res/values-kk-rKZ/strings.xml
@@ -20,57 +20,27 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="application_name" msgid="5181331383435256801">"Launcher3"</string>
- <string name="home" msgid="7658288663002113681">"Негізгі"</string>
- <string name="uid_name" msgid="7820867637514617527">"Android Core қолданбалары"</string>
<string name="folder_name" msgid="7371454440695724752"></string>
+ <string name="work_folder_name" msgid="3753320833950115786">"Жұмыс"</string>
<string name="activity_not_found" msgid="8071924732094499514">"Қолданба орнатылмаған."</string>
<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="widgets_tab_label" msgid="2921133187116603919">"Виджеттер"</string>
- <string name="widget_adder" msgid="3201040140710381657">"Виджеттер"</string>
<string name="toggle_weight_watcher" msgid="5645299835184636119">"Жадты көрсету"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"Виджетті таңдау үшін түртіп, мықтап ұстаңыз."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
- <string name="external_drop_widget_error" msgid="3165821058322217155">"Элементті осы Негізгі Экранға тастау орындалмады."</string>
- <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Жасақтау үшін виджет таңдау"</string>
- <string name="rename_folder_label" msgid="3727762225964550653">"Қалта атауы"</string>
- <string name="rename_folder_title" msgid="3771389277707820891">"Қалтаның атауын өзгерту"</string>
- <string name="rename_action" msgid="5559600076028658757">"Жарайды"</string>
- <string name="cancel_action" msgid="7009134900002915310">"Өшіру"</string>
- <string name="menu_item_add_item" msgid="1264911265836810421">"Негізгі экранға қосу"</string>
- <string name="group_applications" msgid="3797214114206693605">"Қолданбалар"</string>
- <string name="group_shortcuts" msgid="6012256992764410535">"Төте пернелер"</string>
- <string name="group_widgets" msgid="1569030723286851002">"Виджеттер"</string>
- <string name="completely_out_of_space" msgid="6106288382070760318">"Негізгі экранда орын жоқ."</string>
+ <string name="all_apps_search_bar_hint" msgid="7084713969757597256">"Қолданбаларды іздеу"</string>
+ <string name="all_apps_loading_message" msgid="7557140873644765180">"Қолданбалар жүктелуде…"</string>
+ <string name="all_apps_no_search_results" msgid="6332185285860416787">"«<xliff:g id="QUERY">%1$s</xliff:g>» сұрауына сәйкес келетін қолданбалар жоқ"</string>
<string name="out_of_space" msgid="4691004494942118364">"Бұл Негізгі экранда орын қалмады."</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"Қалаулылар науасында орын қалмады"</string>
- <string name="invalid_hotseat_item" msgid="5779907847267573691">"Бұл виджет Қалаулылар науасы үшін тым үлкен"</string>
- <string name="shortcut_installed" msgid="1701742129426969556">"\"<xliff:g id="NAME">%s</xliff:g>\" төте пернесі жасақталды."</string>
- <string name="shortcut_uninstalled" msgid="8176767991305701821">"\"<xliff:g id="NAME">%s</xliff:g>\" төте пернесі алынды."</string>
- <string name="shortcut_duplicate" msgid="9167217446062498127">"\"<xliff:g id="NAME">%s</xliff:g>\" төте пернесі бұрыннан бар."</string>
- <string name="title_select_shortcut" msgid="6680642571148153868">"Төте перне таңдау"</string>
- <string name="title_select_application" msgid="3280812711670683644">"Қолданба таңдау"</string>
<string name="all_apps_button_label" msgid="9110807029020582876">"Қолданбалар"</string>
<string name="all_apps_home_button_label" msgid="252062713717058851">"Негізгі"</string>
- <string name="delete_zone_label_workspace" msgid="4009607676751398685">"Алып тастау"</string>
- <string name="delete_zone_label_all_apps" msgid="8083826390278958980">"Алмау"</string>
<string name="delete_target_label" msgid="1822697352535677073">"Алып тастау"</string>
<string name="delete_target_uninstall_label" msgid="5100785476250872595">"Алмау"</string>
<string name="info_target_label" msgid="8053346143994679532">"Қолданба ақпары"</string>
- <string name="accessibility_all_apps_button" msgid="2603132375383800483">"Қолданбалар"</string>
- <string name="accessibility_delete_button" msgid="6466114477993744621">"Алып тастау"</string>
- <string name="delete_zone_label_all_apps_system_app" msgid="449755632749610895">"Жаңартуды алмау"</string>
- <string name="cab_menu_delete_app" msgid="7435191475867183689">"Қолданбаны алып тастау"</string>
- <string name="cab_menu_app_info" msgid="8593722221450362342">"Қолданба туралы толығырақ"</string>
- <string name="cab_app_selection_text" msgid="374688303047985416">"1 қолданба таңдалған"</string>
- <string name="cab_widget_selection_text" msgid="1833458597831541241">"1 виджет таңдалған"</string>
- <string name="cab_folder_selection_text" msgid="7999992513806132118">"1 қалта таңдалған"</string>
- <string name="cab_shortcut_selection_text" msgid="2103811025667946450">"1 төте перне таңдалған"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"төте пернелерді орнату"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"Қолданбаға пайдаланушының қатысуынсыз төте пернелерді қосу мүмкіндігін береді."</string>
- <string name="permlab_uninstall_shortcut" msgid="864595034498083837">"төте пернелерді алып тастау"</string>
- <string name="permdesc_uninstall_shortcut" msgid="5134129545001836849">"Қолданбаға пайдаланушының қатысуынсыз төте пернелерді алу мүмкіндігін береді."</string>
<string name="permlab_read_settings" msgid="1941457408239617576">"Негізгі экрандағы параметрлер мен төте пернелерді оқу"</string>
<string name="permdesc_read_settings" msgid="5833423719057558387">"Қолданбаға Негізгі экрандағы параметрлер мен төте пернелерді оқу мүмкіндігін береді."</string>
<string name="permlab_write_settings" msgid="3574213698004620587">"Негізгі экран параметрлері мен төте пернелерін жазу"</string>
@@ -78,30 +48,17 @@
<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>
- <string name="dream_name" msgid="1530253749244328964">"Rocket Launcher"</string>
<string name="folder_hint_text" msgid="6617836969016293992">"Атауы жоқ қалта"</string>
- <string name="workspace_description_format" msgid="2950174241104043327">"%1$d негізгі экран"</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="apps_customize_apps_scroll_format" msgid="370005296147130238">"%1$d қолданба беті, барлығы %2$d"</string>
- <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"%1$d виджет беті, барлығы %2$d"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"Қош келдіңіз"</string>
- <string name="first_run_cling_description" msgid="6447072552696253358">"Өзіңізді ыңғайлы сезініңіз."</string>
- <string name="first_run_cling_custom_content_hint" msgid="6090628589029352439"></string>
- <string name="first_run_cling_search_bar_hint" msgid="5909062802402452582"></string>
- <string name="first_run_cling_create_screens_hint" msgid="6950729526680114157">"Қолданбалар мен қалталар үшін көбірек экрандар жасау"</string>
<string name="migration_cling_title" msgid="9181776667882933767">"Қолданба таңбаларын көшіру"</string>
<string name="migration_cling_description" msgid="2752413805582227644">"Бұрынғы негізгі экрандарыңыздағы таңбалар мен қалталар импортталсын ба?"</string>
<string name="migration_cling_copy_apps" msgid="946331230090919440">"ТАҢБАЛАРДЫ КӨШІРУ"</string>
<string name="migration_cling_use_default" msgid="2626475813981258626">"ЖАҢАДАН БАСТАУ"</string>
- <string name="workspace_cling_title" msgid="5626202359865825661">"Кеңістікті реттеу"</string>
- <string name="workspace_cling_move_item" msgid="528201129978005352">"Артқы фонды, виджеттерді және параметрлерді басқару үшін артқы шебін түртіп, мықтап ұстаңыз."</string>
<string name="workspace_cling_longpress_title" msgid="9173998993909018310">"Тұсқағаздар, виджеттер және параметрлер"</string>
<string name="workspace_cling_longpress_description" msgid="4119994475505235248">"Теңшеу үшін фонды түртіп, ұстап тұрыңыз"</string>
<string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"ТҮСІНДІМ"</string>
- <string name="folder_cling_title" msgid="3894908818693254164">"Міне, қалта."</string>
- <string name="folder_cling_create_folder" msgid="6158215559475836131">"Осы сияқты қалта жасау үшін, қолданбаны түртіп, мықтап ұстаңыз, одан кейін екіншісінің үстінен жылжытыңыз."</string>
- <string name="cling_dismiss" msgid="8962359497601507581">"Жарайды"</string>
<string name="folder_opened" msgid="94695026776264709">"Қалта ашылды, <xliff:g id="WIDTH">%1$d</xliff:g> және <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
<string name="folder_tap_to_close" msgid="1884479294466410023">"Қалтаны жабу үшін түртіңіз"</string>
<string name="folder_tap_to_rename" msgid="9191075570492871147">"Өзгертілген атауын сақтау үшін түртіңіз"</string>
@@ -111,14 +68,34 @@
<string name="widget_button_text" msgid="2880537293434387943">"Виджеттер"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"Артқы фондар"</string>
<string name="settings_button_text" msgid="8119458837558863227">"Параметрлер"</string>
- <string name="package_state_enqueued" msgid="6227252464303085641">"Күтілуде"</string>
- <string name="package_state_downloading" msgid="4088770468458724721">"Жүктелуде"</string>
- <string name="package_state_installing" msgid="7588193972189849870">"Орнатылуда"</string>
+ <string name="allow_rotation_title" msgid="2118706734511831751">"Айналуға рұқсат ету"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Белгісіз"</string>
- <string name="package_state_error" msgid="7672093962724223588">"Қалп. кел-меді"</string>
- <string name="abandoned_clean_all" msgid="5256770727689657618">"Барлығын алып тастау"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Алып тастау"</string>
<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="action_add_to_workspace" msgid="8902165848117513641">"Негізгі экранға қосу"</string>
+ <string name="action_move_here" msgid="2170188780612570250">"Элементті мұнда жылжыту"</string>
+ <string name="item_added_to_workspace" msgid="4211073925752213539">"Элемент негізгі экранға қосылды"</string>
+ <string name="item_removed" msgid="851119963877842327">"Элемент жойылды"</string>
+ <string name="action_move" msgid="4339390619886385032">"Элементті жылжыту"</string>
+ <string name="move_to_empty_cell" msgid="2833711483015685619">"<xliff:g id="NUMBER_0">%1$s</xliff:g>-жол, <xliff:g id="NUMBER_1">%2$s</xliff:g>-бағанға жылжыту"</string>
+ <string name="move_to_position" msgid="6750008980455459790">"<xliff:g id="NUMBER">%1$s</xliff:g>-орынға жылжыту"</string>
+ <string name="move_to_hotseat_position" msgid="6295412897075147808">"<xliff:g id="NUMBER">%1$s</xliff:g> нөмірлі таңдаулы орынға жылжыту"</string>
+ <string name="item_moved" msgid="4606538322571412879">"Элемент жылжытылды"</string>
+ <string name="add_to_folder" msgid="9040534766770853243">"Қалтаға қосу: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="add_to_folder_with_app" msgid="4534929978967147231">"<xliff:g id="NAME">%1$s</xliff:g> бар қалтаға қосу"</string>
+ <string name="added_to_folder" msgid="4793259502305558003">"Элемент қалтаға қосылды"</string>
+ <string name="create_folder_with" msgid="4050141361160214248">"Мына бар қалтаны жасау: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="folder_created" msgid="6409794597405184510">"Қалта жасалды"</string>
+ <string name="action_move_to_workspace" msgid="1603837886334246317">"Негізгі экранға жылжыту"</string>
+ <string name="action_move_screen_left" msgid="8854216831569401665">"Экранды солға жылжыту"</string>
+ <string name="action_move_screen_right" msgid="329334910274311123">"Экранды оңға жылжыту"</string>
+ <string name="screen_moved" msgid="266230079505650577">"Экран жылжытылды"</string>
+ <string name="action_resize" msgid="1802976324781771067">"Өлшемін өзгерту"</string>
+ <string name="action_increase_width" msgid="8773715375078513326">"Енін арттыру"</string>
+ <string name="action_increase_height" msgid="459390020612501122">"Биіктігін арттыру"</string>
+ <string name="action_decrease_width" msgid="1374549771083094654">"Енін азайту"</string>
+ <string name="action_decrease_height" msgid="282377193880900022">"Биіктігін азайту"</string>
+ <string name="widget_resized" msgid="9130327887929620">"Виджет өлшемінің ені <xliff:g id="NUMBER_0">%1$s</xliff:g>, биіктігі <xliff:g id="NUMBER_1">%2$s</xliff:g> болып өзгертілді"</string>
</resources>
diff --git a/res/values-km-rKH/strings.xml b/res/values-km-rKH/strings.xml
index 670ac70b5..9f7f53717 100644
--- a/res/values-km-rKH/strings.xml
+++ b/res/values-km-rKH/strings.xml
@@ -20,57 +20,27 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="application_name" msgid="5181331383435256801">"Launcher3"</string>
- <string name="home" msgid="7658288663002113681">"ដើម"</string>
- <string name="uid_name" msgid="7820867637514617527">"កម្មវិធី​​សំខាន់​ៗ​របស់ Android"</string>
<string name="folder_name" msgid="7371454440695724752"></string>
+ <string name="work_folder_name" msgid="3753320833950115786">"ការងារ"</string>
<string name="activity_not_found" msgid="8071924732094499514">"មិន​បាន​ដំឡើង​កម្មវិធី។"</string>
<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="widgets_tab_label" msgid="2921133187116603919">"ធាតុ​ក្រាហ្វិក"</string>
- <string name="widget_adder" msgid="3201040140710381657">"ធាតុ​ក្រាហ្វិក"</string>
<string name="toggle_weight_watcher" msgid="5645299835184636119">"បង្ហាញ​ Mem"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"ប៉ះ &amp; សង្កត់ ដើម្បី​ជ្រើស​ធាតុ​ក្រាហ្វិក។"</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
- <string name="external_drop_widget_error" msgid="3165821058322217155">"មិន​អាច​ទម្លាក់​ធាតុ​លើ​អេក្រង់​ដើម​នេះ​ទេ"</string>
- <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"ជ្រើស​ធាតុ​ក្រាហ្វិក ដើម្បី​​​បង្កើត"</string>
- <string name="rename_folder_label" msgid="3727762225964550653">"ឈ្មោះ​ថត"</string>
- <string name="rename_folder_title" msgid="3771389277707820891">"ប្ដូរ​ឈ្មោះ​ថត"</string>
- <string name="rename_action" msgid="5559600076028658757">"យល់ព្រម"</string>
- <string name="cancel_action" msgid="7009134900002915310">"បោះបង់"</string>
- <string name="menu_item_add_item" msgid="1264911265836810421">"បន្ថែម​ទៅ​អេក្រង់​ដើម"</string>
- <string name="group_applications" msgid="3797214114206693605">"កម្មវិធី"</string>
- <string name="group_shortcuts" msgid="6012256992764410535">"ផ្លូវកាត់"</string>
- <string name="group_widgets" msgid="1569030723286851002">"ធាតុ​ក្រាហ្វិក"</string>
- <string name="completely_out_of_space" msgid="6106288382070760318">"គ្មាន​បន្ទប់​នៅ​លើ​អេក្រង់​ដើម​រស់​អ្នក​ទៀត​ទេ។"</string>
+ <string name="all_apps_search_bar_hint" msgid="7084713969757597256">"ស្វែងរកកម្មវិធី"</string>
+ <string name="all_apps_loading_message" msgid="7557140873644765180">"កំពុងដំណើរការកម្មវិធី..."</string>
+ <string name="all_apps_no_search_results" msgid="6332185285860416787">"គ្មានកម្មវិធីដែលត្រូវជាមួយ \"<xliff:g id="QUERY">%1$s</xliff:g>\" ទេ"</string>
<string name="out_of_space" msgid="4691004494942118364">"គ្មាន​បន្ទប់​នៅ​លើ​អេក្រង់​ដើម​នេះ​ទៀត​ទេ។"</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"គ្មាន​បន្ទប់​​ក្នុង​ថាស​និយម​ប្រើ"</string>
- <string name="invalid_hotseat_item" msgid="5779907847267573691">"ធាតុ​ក្រាហ្វិក​នេះ​ធំ​ពេក​សម្រាប់​ថាស​និយម​ប្រើ"</string>
- <string name="shortcut_installed" msgid="1701742129426969556">"បាន​បង្កើត​ផ្លូវកាត់ \"<xliff:g id="NAME">%s</xliff:g>\" ។"</string>
- <string name="shortcut_uninstalled" msgid="8176767991305701821">"បាន​លុប​ផ្លូវកាត់ \"<xliff:g id="NAME">%s</xliff:g>\" ។"</string>
- <string name="shortcut_duplicate" msgid="9167217446062498127">"មាន​ផ្លូវកាត់ \"<xliff:g id="NAME">%s</xliff:g>\" រួច​ហើយ។"</string>
- <string name="title_select_shortcut" msgid="6680642571148153868">"ជ្រើស​ផ្លូវកាត់"</string>
- <string name="title_select_application" msgid="3280812711670683644">"ជ្រើស​កម្មវិធី"</string>
<string name="all_apps_button_label" msgid="9110807029020582876">"កម្មវិធី"</string>
<string name="all_apps_home_button_label" msgid="252062713717058851">"ដើម"</string>
- <string name="delete_zone_label_workspace" msgid="4009607676751398685">"លុប​ចេញ"</string>
- <string name="delete_zone_label_all_apps" msgid="8083826390278958980">"លុប"</string>
<string name="delete_target_label" msgid="1822697352535677073">"លុប​ចេញ"</string>
<string name="delete_target_uninstall_label" msgid="5100785476250872595">"លុប"</string>
<string name="info_target_label" msgid="8053346143994679532">"ព័ត៌មាន​កម្មវិធី"</string>
- <string name="accessibility_all_apps_button" msgid="2603132375383800483">"កម្មវិធី"</string>
- <string name="accessibility_delete_button" msgid="6466114477993744621">"លុប​ចេញ"</string>
- <string name="delete_zone_label_all_apps_system_app" msgid="449755632749610895">"លុប​បច្ចុប្បន្នភាព"</string>
- <string name="cab_menu_delete_app" msgid="7435191475867183689">"លុប​កម្មវិធី"</string>
- <string name="cab_menu_app_info" msgid="8593722221450362342">"ព័ត៌មាន​លម្អិត​កម្មវិធី"</string>
- <string name="cab_app_selection_text" msgid="374688303047985416">"បាន​ជ្រើស​កម្មវិធី ១"</string>
- <string name="cab_widget_selection_text" msgid="1833458597831541241">"បាន​ជ្រើស​ធាតុ ១"</string>
- <string name="cab_folder_selection_text" msgid="7999992513806132118">"បាន​ជ្រើស​ថត ១"</string>
- <string name="cab_shortcut_selection_text" msgid="2103811025667946450">"បាន​ជ្រើស​ផ្លូវកាត់ ១"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"ដំឡើង​ផ្លូវកាត់"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"អនុញ្ញាត​ឲ្យ​កម្មវិធី​បន្ថែម​ផ្លូវកាត់​ ដោយ​មិន​ចាំបាច់​​អំពើ​ពី​អ្នក​ប្រើ។"</string>
- <string name="permlab_uninstall_shortcut" msgid="864595034498083837">"លុប​ផ្លូវកាត់"</string>
- <string name="permdesc_uninstall_shortcut" msgid="5134129545001836849">"អនុញ្ញាត​ឲ្យ​កម្មវិធី​លុប​ផ្លូវកាត់​ដោយ​មិន​ចាំបាច់​អំពើ​ពី​អ្នក​ប្រើ។"</string>
<string name="permlab_read_settings" msgid="1941457408239617576">"អាន​ការ​កំណត់​ និង​ផ្លូវកាត់​​អេក្រង់​ដើម"</string>
<string name="permdesc_read_settings" msgid="5833423719057558387">"អនុញ្ញាត​ឲ្យ​កម្មវិធី​អាន​ការ​កំណត់ និង​ផ្លូវកាត់​ក្នុង​អេក្រង់​ដើម។"</string>
<string name="permlab_write_settings" msgid="3574213698004620587">"សរសេរ​ការ​កំណត់ ​និង​ផ្លូវកាត់​​លើ​អេក្រង់​ដើម"</string>
@@ -78,30 +48,17 @@
<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>
- <string name="dream_name" msgid="1530253749244328964">"កម្មវិធី​ចាប់ផ្ដើម​រ៉ូកែត"</string>
<string name="folder_hint_text" msgid="6617836969016293992">"ថត​គ្មាន​ឈ្មោះ"</string>
- <string name="workspace_description_format" msgid="2950174241104043327">"អេក្រង់​ដើម %1$d"</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="apps_customize_apps_scroll_format" msgid="370005296147130238">"ទំព័រ​កម្មវិធី %1$d នៃ %2$d"</string>
- <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"ទំព័រ​ធាតុ​ក្រាហ្វិក ​%1$d នៃ %2$d"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"សូម​ស្វាគមន៍​"</string>
- <string name="first_run_cling_description" msgid="6447072552696253358">"ធ្វើ​ដោយ​ខ្លួន​ឯង​នៅ​លើ​អេក្រង់​ដើម។"</string>
- <string name="first_run_cling_custom_content_hint" msgid="6090628589029352439"></string>
- <string name="first_run_cling_search_bar_hint" msgid="5909062802402452582"></string>
- <string name="first_run_cling_create_screens_hint" msgid="6950729526680114157">"បង្កើត​អេក្រង់​ច្រើន​សម្រាប់​កម្មវិធី​ ​និង​ថតឯកសារ"</string>
<string name="migration_cling_title" msgid="9181776667882933767">"ចម្លង​រូបតំណាង​កម្មវិធី​របស់​អ្នក"</string>
<string name="migration_cling_description" msgid="2752413805582227644">"នាំចូល​រូបតំណាង និង​ថត​ពី​អេក្រង់​ដើម​ចាស់​របស់​អ្នក?"</string>
<string name="migration_cling_copy_apps" msgid="946331230090919440">"រូប​តំណាង​ច្បាប់​ចម្លង"</string>
<string name="migration_cling_use_default" msgid="2626475813981258626">"ចាប់ផ្ដើម​ធ្វើ​ឲ្យ​ស្រស់"</string>
- <string name="workspace_cling_title" msgid="5626202359865825661">"រៀបចំ​ចន្លោះ​របស់​អ្នក"</string>
- <string name="workspace_cling_move_item" msgid="528201129978005352">"ប៉ះ &amp; សង្កត់​លើ​ផ្ទៃ​ខាង​ក្រោម ដើម្បី​គ្រប់គ្រង​ផ្ទាំង​រូបភាព, ធាតុ​ក្រាហ្វិក និង​ការ​កំណត់។"</string>
<string name="workspace_cling_longpress_title" msgid="9173998993909018310">"ផ្ទាំងរូបភាព,ធាតុក្រាហ្វិក &amp; ការកំណត់"</string>
<string name="workspace_cling_longpress_description" msgid="4119994475505235248">"ប៉ះ &amp; សង្កត់​ផ្ទៃ​ខាង​ក្រោយ​ដើម្បី​ប្ដូរ​តាម​​តម្រូវ​ការ"</string>
<string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"យល់​ហើយ"</string>
- <string name="folder_cling_title" msgid="3894908818693254164">"នេះ​ជា​ថត"</string>
- <string name="folder_cling_create_folder" msgid="6158215559475836131">"ដើម្បី​បង្កើត​មួយ​ដូច​នេះ ប៉ះ &amp; សង្កត់​​លើ​កម្មវិធី បន្ទាប់​មក​ផ្លាស់ទី​វា​ទៅ​លើ​ធាតុ​មួយ​ផ្សេង​ទៀត។"</string>
- <string name="cling_dismiss" msgid="8962359497601507581">"យល់ព្រម"</string>
<string name="folder_opened" msgid="94695026776264709">"បាន​បើក​ថត <xliff:g id="WIDTH">%1$d</xliff:g> ដោយ <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
<string name="folder_tap_to_close" msgid="1884479294466410023">"ប៉ះ ដើម្បី​បិទ​ថត"</string>
<string name="folder_tap_to_rename" msgid="9191075570492871147">"ប៉ះ ដើម្បី​រក្សាទុក​ការ​ប្ដូរ​ឈ្មោះ"</string>
@@ -111,14 +68,34 @@
<string name="widget_button_text" msgid="2880537293434387943">"ធាតុ​ក្រាហ្វិក"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"ផ្ទាំង​រូបភាព"</string>
<string name="settings_button_text" msgid="8119458837558863227">"ការកំណត់"</string>
- <string name="package_state_enqueued" msgid="6227252464303085641">"រង់ចាំ"</string>
- <string name="package_state_downloading" msgid="4088770468458724721">"​ទាញ​យក"</string>
- <string name="package_state_installing" msgid="7588193972189849870">"ដំឡើង"</string>
+ <string name="allow_rotation_title" msgid="2118706734511831751">"អនុញ្ញាតឲ្យបង្វិល"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"មិន​ស្គាល់"</string>
- <string name="package_state_error" msgid="7672093962724223588">"មិនបាន​​ស្តា​រ"</string>
- <string name="abandoned_clean_all" msgid="5256770727689657618">"លុបចេញ​​​ទាំងអស់"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"លុបចេញ"</string>
<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="action_add_to_workspace" msgid="8902165848117513641">"បន្ថែមទៅអេក្រង់ដើម"</string>
+ <string name="action_move_here" msgid="2170188780612570250">"ផ្លាស់ធាតុមកទីនេះ"</string>
+ <string name="item_added_to_workspace" msgid="4211073925752213539">"ធាតុដែលត្រូវបានបន្ថែមទៅអេក្រង់ដើម"</string>
+ <string name="item_removed" msgid="851119963877842327">"ធាតុដែលបានដកចេញ"</string>
+ <string name="action_move" msgid="4339390619886385032">"ផ្លាស់ទីធាតុ"</string>
+ <string name="move_to_empty_cell" msgid="2833711483015685619">"ផ្លាស់ទីទៅជួរដេកទី <xliff:g id="NUMBER_0">%1$s</xliff:g> ជួរឈរទី <xliff:g id="NUMBER_1">%2$s</xliff:g>"</string>
+ <string name="move_to_position" msgid="6750008980455459790">"ផ្លាស់ទីទៅទីតាំង <xliff:g id="NUMBER">%1$s</xliff:g>"</string>
+ <string name="move_to_hotseat_position" msgid="6295412897075147808">"ផ្លាស់ទីទៅការចូលចិត្តទីតាំងទី <xliff:g id="NUMBER">%1$s</xliff:g>"</string>
+ <string name="item_moved" msgid="4606538322571412879">"បានផ្លាស់ទីធាតុ"</string>
+ <string name="add_to_folder" msgid="9040534766770853243">"បន្ថែមទៅថតឯកសារ៖ <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="add_to_folder_with_app" msgid="4534929978967147231">"បន្ថែមទៅថតឯកសារដែលមានឈ្មោះ <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="added_to_folder" msgid="4793259502305558003">"បានបន្ថែមធាតុទៅថតឯកសារ"</string>
+ <string name="create_folder_with" msgid="4050141361160214248">"បង្កើតថតឯកសារជាមួយ៖ <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="folder_created" msgid="6409794597405184510">"បានបង្កើតថតឯកសារ"</string>
+ <string name="action_move_to_workspace" msgid="1603837886334246317">"ផ្លាស់ទៅអេក្រង់ដើម"</string>
+ <string name="action_move_screen_left" msgid="8854216831569401665">"រំកិលអេក្រង់ទៅខាងឆ្វេង"</string>
+ <string name="action_move_screen_right" msgid="329334910274311123">"រំកិលអេក្រង់ទៅខាងស្តាំ"</string>
+ <string name="screen_moved" msgid="266230079505650577">"អេក្រង់ដែលបានផ្លាស់ទី"</string>
+ <string name="action_resize" msgid="1802976324781771067">"ប្ដូរទំហំ"</string>
+ <string name="action_increase_width" msgid="8773715375078513326">"បង្កើនទទឹង"</string>
+ <string name="action_increase_height" msgid="459390020612501122">"បង្កើនកម្ពស់"</string>
+ <string name="action_decrease_width" msgid="1374549771083094654">"បន្ថយទទឹង"</string>
+ <string name="action_decrease_height" msgid="282377193880900022">"បន្ថយកម្ពស់"</string>
+ <string name="widget_resized" msgid="9130327887929620">"ធាតុក្រាហ្វិកដែលបានប្តូរទំហំទៅទទឹងប្រវែង <xliff:g id="NUMBER_0">%1$s</xliff:g> កម្ពស់ប្រវែង <xliff:g id="NUMBER_1">%2$s</xliff:g>"</string>
</resources>
diff --git a/res/values-kn-rIN/strings.xml b/res/values-kn-rIN/strings.xml
index 7a070511d..5cd8792dd 100644
--- a/res/values-kn-rIN/strings.xml
+++ b/res/values-kn-rIN/strings.xml
@@ -20,57 +20,27 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="application_name" msgid="5181331383435256801">"ಲಾಂಚರ್3"</string>
- <string name="home" msgid="7658288663002113681">"ಮುಖಪುಟ"</string>
- <string name="uid_name" msgid="7820867637514617527">"Android Core ಅಪ್ಲಿಕೇಶನ್‌ಗಳು"</string>
<string name="folder_name" msgid="7371454440695724752"></string>
+ <string name="work_folder_name" msgid="3753320833950115786">"ಕೆಲಸ"</string>
<string name="activity_not_found" msgid="8071924732094499514">"ಅಪ್ಲಿಕೇಶನ್‌ ಅನ್ನು ಸ್ಥಾಪಿಸಲಾಗಿಲ್ಲ"</string>
<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="widgets_tab_label" msgid="2921133187116603919">"ವಿಜೆಟ್‌ಗಳು"</string>
- <string name="widget_adder" msgid="3201040140710381657">"ವಿಜೆಟ್‌ಗಳು"</string>
<string name="toggle_weight_watcher" msgid="5645299835184636119">"ಸ್ಮರಣೆ ತೋರಿಸು"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"ವಿಜೆಟ್ ಅನ್ನು ಆರಿಸಿಕೊಳ್ಳಲು ಸ್ಪರ್ಶಿಸಿ &amp; ಹಿಡಿದುಕೊಳ್ಳಿ."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
- <string name="external_drop_widget_error" msgid="3165821058322217155">"ಈ ಮುಖಪುಟದ ಪರದೆಯಲ್ಲಿ ಐಟಂ ಅನ್ನು ಬಿಡಲು ಸಾಧ್ಯವಾಗಲಿಲ್ಲ."</string>
- <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"ರಚಿಸಲು ವಿಜೆಟ್‌ ಆಯ್ಕೆಮಾಡಿ"</string>
- <string name="rename_folder_label" msgid="3727762225964550653">"ಫೋಲ್ಡರ್ ಹೆಸರು"</string>
- <string name="rename_folder_title" msgid="3771389277707820891">"ಫೋಲ್ಡರ್ ಅನ್ನು ಮರುಹೆಸರಿಸಿ"</string>
- <string name="rename_action" msgid="5559600076028658757">"ಸರಿ"</string>
- <string name="cancel_action" msgid="7009134900002915310">"ರದ್ದುಮಾಡು"</string>
- <string name="menu_item_add_item" msgid="1264911265836810421">"ಮುಖಪುಟಕ್ಕೆ ಸೇರಿಸು"</string>
- <string name="group_applications" msgid="3797214114206693605">"ಅಪ್ಲಿಕೇಶನ್‌ಗಳು"</string>
- <string name="group_shortcuts" msgid="6012256992764410535">"ಶಾರ್ಟ್‌ಕಟ್‌ಗಳು"</string>
- <string name="group_widgets" msgid="1569030723286851002">"ವಿಜೆಟ್‌ಗಳು"</string>
- <string name="completely_out_of_space" msgid="6106288382070760318">"ನಿಮ್ಮ ಮುಖಪುಟದ ಪರದೆಗಳಲ್ಲಿ ಯಾವುದೇ ಸ್ಥಳಾವಕಾಶವಿಲ್ಲ"</string>
+ <string name="all_apps_search_bar_hint" msgid="7084713969757597256">"ಅಪ್ಲಿಕೇಷನ್‌ಗಳನ್ನು ಹುಡುಕಿ"</string>
+ <string name="all_apps_loading_message" msgid="7557140873644765180">"ಅಪ್ಲಿಕೇಶನ್‌ಗಳನ್ನು ಲೋಡ್ ಮಾಡಲಾಗುತ್ತಿದೆ..."</string>
+ <string name="all_apps_no_search_results" msgid="6332185285860416787">"\"<xliff:g id="QUERY">%1$s</xliff:g>\" ಹೊಂದಿಕೆಯ ಯಾವುದೇ ಅಪ್ಲಿಕೇಶನ್‌ಗಳು ಕಂಡುಬಂದಿಲ್ಲ"</string>
<string name="out_of_space" msgid="4691004494942118364">"ಈ ಮುಖಪುಟದ ಪರದೆಯಲ್ಲಿ ಹೆಚ್ಚು ಸ್ಥಳಾವಕಾಶವಿಲ್ಲ."</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"ಮೆಚ್ಚಿನವುಗಳ ಟ್ರೇನಲ್ಲಿ ಹೆಚ್ಚಿನ ಸ್ಥಳಾವಕಾಶವಿಲ್ಲ"</string>
- <string name="invalid_hotseat_item" msgid="5779907847267573691">"ಮೆಚ್ಚಿನವುಗಳ ಟ್ರೇಗೆ ಈ ವಿಜೆಟ್‌ ತುಂಬಾ ದೊಡ್ಡದಾಗಿದೆ"</string>
- <string name="shortcut_installed" msgid="1701742129426969556">"ಶಾರ್ಟ್‌ಕಟ್‌ \"<xliff:g id="NAME">%s</xliff:g>\" ಅನ್ನು ರಚಿಸಲಾಗಿದೆ."</string>
- <string name="shortcut_uninstalled" msgid="8176767991305701821">"ಶಾರ್ಟ್‌ಕಟ್‌ \"<xliff:g id="NAME">%s</xliff:g>\" ಅನ್ನು ತೆಗೆದುಹಾಕಲಾಗಿದೆ."</string>
- <string name="shortcut_duplicate" msgid="9167217446062498127">"ಶಾರ್ಟ್‌ಕಟ್‌ \"<xliff:g id="NAME">%s</xliff:g>\" ಈಗಾಗಲೇ ಅಸ್ತಿತ್ವದಲ್ಲಿದೆ."</string>
- <string name="title_select_shortcut" msgid="6680642571148153868">"ಶಾರ್ಟ್‌ಕಟ್‌ ಆರಿಸಿ"</string>
- <string name="title_select_application" msgid="3280812711670683644">"ಅಪ್ಲಿಕೇಶನ್ ಆಯ್ಕೆಮಾಡಿ"</string>
<string name="all_apps_button_label" msgid="9110807029020582876">"ಅಪ್ಲಿಕೇಶನ್‌ಗಳು"</string>
<string name="all_apps_home_button_label" msgid="252062713717058851">"ಮುಖಪುಟ"</string>
- <string name="delete_zone_label_workspace" msgid="4009607676751398685">"ತೆಗೆದುಹಾಕು"</string>
- <string name="delete_zone_label_all_apps" msgid="8083826390278958980">"ಅಸ್ಥಾಪಿಸು"</string>
<string name="delete_target_label" msgid="1822697352535677073">"ತೆಗೆದುಹಾಕು"</string>
<string name="delete_target_uninstall_label" msgid="5100785476250872595">"ಅಸ್ಥಾಪಿಸು"</string>
<string name="info_target_label" msgid="8053346143994679532">"ಅಪ್ಲಿಕೇಶನ್ ಮಾಹಿತಿ"</string>
- <string name="accessibility_all_apps_button" msgid="2603132375383800483">"ಅಪ್ಲಿಕೇಶನ್‌ಗಳು"</string>
- <string name="accessibility_delete_button" msgid="6466114477993744621">"ತೆಗೆದುಹಾಕು"</string>
- <string name="delete_zone_label_all_apps_system_app" msgid="449755632749610895">"ನವೀಕರಣವನ್ನು ಅಸ್ಥಾಪಿಸು"</string>
- <string name="cab_menu_delete_app" msgid="7435191475867183689">"ಅಪ್ಲಿಕೇಶನ್ ಅಸ್ಥಾಪಿಸು"</string>
- <string name="cab_menu_app_info" msgid="8593722221450362342">"ಅಪ್ಲಿಕೇಶನ್ ವಿವರಗಳು"</string>
- <string name="cab_app_selection_text" msgid="374688303047985416">"1 ಅಪ್ಲಿಕೇಶನ್‌ ಅನ್ನು ಆಯ್ಕೆ ಮಾಡಲಾಗಿದೆ"</string>
- <string name="cab_widget_selection_text" msgid="1833458597831541241">"1 ವಿಜೆಟ್‌ ಆಯ್ಕೆಮಾಡಲಾಗಿದೆ"</string>
- <string name="cab_folder_selection_text" msgid="7999992513806132118">"1 ಫೋಲ್ಡರ್‌ ಅನ್ನು ಆಯ್ಕೆ ಮಾಡಲಾಗಿದೆ"</string>
- <string name="cab_shortcut_selection_text" msgid="2103811025667946450">"1 ಶಾರ್ಟ್‌ಕಟ್‌ ಆಯ್ಕೆ ಮಾಡಲಾಗಿದೆ"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"ಶಾರ್ಟ್‌ಕಟ್‌ಗಳನ್ನು ಸ್ಥಾಪಿಸಿ"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"ಬಳಕೆದಾರರ ಹಸ್ತಕ್ಷೇಪವಿಲ್ಲದೆ ಶಾರ್ಟ್‌ಕಟ್‌ಗಳನ್ನು ಸೇರಿಸಲು ಅಪ್ಲಿಕೇಶನ್‌ಗೆ ಅನುಮತಿಸುತ್ತದೆ."</string>
- <string name="permlab_uninstall_shortcut" msgid="864595034498083837">"ಶಾರ್ಟ್‌ಕಟ್‌ಗಳನ್ನು ಅಸ್ಥಾಪಿಸಿ"</string>
- <string name="permdesc_uninstall_shortcut" msgid="5134129545001836849">"ಬಳಕೆದಾರರ ಹಸ್ತಕ್ಷೇಪವಿಲ್ಲದೆ ಶಾರ್ಟ್‌ಕಟ್‌ಗಳನ್ನು ತೆಗೆದುಹಾಕಲು ಅಪ್ಲಿಕೇಶನ್‌ಗೆ ಅನುಮತಿ ನೀಡುತ್ತದೆ."</string>
<string name="permlab_read_settings" msgid="1941457408239617576">"ಮುಖಪುಟದ ಸೆಟ್ಟಿಂಗ್‌ಗಳು ಮತ್ತು ಶಾರ್ಟ್‌ಕಟ್‌ಗಳನ್ನು ಓದಿ"</string>
<string name="permdesc_read_settings" msgid="5833423719057558387">"ಮುಖಪುಟದಲ್ಲಿ ಸೆಟ್ಟಿಂಗ್‌ಗಳು ಮತ್ತು ಶಾರ್ಟ್‌ಕಟ್‌ಗಳನ್ನು ಓದಲು ಅಪ್ಲಿಕೇಶನ್‌ಗೆ ಅನುಮತಿ ನೀಡುತ್ತದೆ."</string>
<string name="permlab_write_settings" msgid="3574213698004620587">"ಮುಖಪುಟದ ಸೆಟ್ಟಿಂಗ್‌ಗಳು ಮತ್ತು ಶಾರ್ಟ್‌ಕಟ್‌ಗಳನ್ನು ಬರೆಯಿರಿ"</string>
@@ -78,30 +48,17 @@
<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>
- <string name="dream_name" msgid="1530253749244328964">"ರಾಕೆಟ್ ಲಾಂಚರ್"</string>
<string name="folder_hint_text" msgid="6617836969016293992">"ಹೆಸರಿಲ್ಲದ ಫೋಲ್ಡರ್"</string>
- <string name="workspace_description_format" msgid="2950174241104043327">"ಮುಖಪುಟದ ಪರದೆ %1$d"</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="apps_customize_apps_scroll_format" msgid="370005296147130238">"%2$d ರಲ್ಲಿ %1$d ಅಪ್ಲಿಕೇಶನ್ ಪುಟ"</string>
- <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"%2$d ರಲ್ಲಿ %1$d ವಿಜೆಟ್‌ಗಳ ಪುಟ"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"ಸುಸ್ವಾಗತ"</string>
- <string name="first_run_cling_description" msgid="6447072552696253358">"ನಿಮ್ಮ ಮನೆಯಂತೆ ಭಾವಿಸಿ."</string>
- <string name="first_run_cling_custom_content_hint" msgid="6090628589029352439"></string>
- <string name="first_run_cling_search_bar_hint" msgid="5909062802402452582"></string>
- <string name="first_run_cling_create_screens_hint" msgid="6950729526680114157">"ಅಪ್ಲಿಕೇಶನ್‌ಗಳು ಮತ್ತು ಫೋಲ್ಡರ್‌ಗಳಿಗಾಗಿ ಇನ್ನಷ್ಟು ಪರದೆಗಳನ್ನು ರಚಿಸಿ"</string>
<string name="migration_cling_title" msgid="9181776667882933767">"ಅಪ್ಲಿಕೇಶನ್‌ ಐಕಾನ್‌ ನಕಲಿಸು"</string>
<string name="migration_cling_description" msgid="2752413805582227644">"ನಿಮ್ಮ ಹಳೆಯ ಮುಖಪುಟದ ಪರದೆಗಳಿಂದ ಐಕಾನ್‌ಗಳು ಮತ್ತು ಫೋಲ್ಡರ್‌ಗಳನ್ನು ಆಮದು ಮಾಡಿಕೊಳ್ಳುವುದೇ?"</string>
<string name="migration_cling_copy_apps" msgid="946331230090919440">"ಐಕಾನ್‌ಗಳನ್ನು ನಕಲಿಸು"</string>
<string name="migration_cling_use_default" msgid="2626475813981258626">"ಹೊಸದಾಗಿ ಪ್ರಾರಂಭಿಸು"</string>
- <string name="workspace_cling_title" msgid="5626202359865825661">"ನಿಮ್ಮ ಸ್ಥಳವನ್ನು ವ್ಯವಸ್ಥಿತಗೊಳಿಸಿ"</string>
- <string name="workspace_cling_move_item" msgid="528201129978005352">"ವಾಲ್‌ಪೇಪರ್‌, ವಿಜೆಟ್‌ಗಳು ಮತ್ತು ಸೆಟ್ಟಿಂಗ್‌ಗಳನ್ನು ನಿರ್ವಹಿಸಲು ಹಿನ್ನೆಲೆಯನ್ನು ಸ್ಪರ್ಶಿಸಿ &amp; ಹಿಡಿದುಕೊಳ್ಳಿ."</string>
<string name="workspace_cling_longpress_title" msgid="9173998993909018310">"ವಾಲ್‌ಪೇಪರ್‌ಗಳು, ವಿಜೆಟ್‌ಗಳು, &amp; ಸೆಟ್ಟಿಂಗ್‌ಗಳು"</string>
<string name="workspace_cling_longpress_description" msgid="4119994475505235248">"ಕಸ್ಟಮೈಸ್ ಮಾಡಲು ಹಿನ್ನೆಲೆಯನ್ನು ಸ್ಪರ್ಶಿಸಿ &amp; ಒತ್ತಿ ಹಿಡಿಯಿರಿ"</string>
<string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"ಅರ್ಥವಾಯಿತು"</string>
- <string name="folder_cling_title" msgid="3894908818693254164">"ಇಲ್ಲೊಂದು ಫೋಲ್ಡರ್ ಇದೆ"</string>
- <string name="folder_cling_create_folder" msgid="6158215559475836131">"ಈ ರೀತಿ ರಚಿಸಲು, ಸ್ಪರ್ಶಿಸಿ &amp; ಆಪ್‌ ಹಿಡಿದುಕೊಂಡು ಮತ್ತೊಂದರ ಮೇಲೆ ಸರಿಸಿ."</string>
- <string name="cling_dismiss" msgid="8962359497601507581">"ಸರಿ"</string>
<string name="folder_opened" msgid="94695026776264709">"ಫೋಲ್ಡರ್ ತೆರೆಯಲಾಗಿದೆ, <xliff:g id="WIDTH">%1$d</xliff:g> ಬೈ <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
<string name="folder_tap_to_close" msgid="1884479294466410023">"ಫೋಲ್ಡರ್‌ ಮುಚ್ಚಲು ಸ್ಪರ್ಶಿಸಿ"</string>
<string name="folder_tap_to_rename" msgid="9191075570492871147">"ಮರುಹೆಸರನ್ನು ಉಳಿಸಲು ಸ್ಪರ್ಶಿಸಿ"</string>
@@ -111,14 +68,34 @@
<string name="widget_button_text" msgid="2880537293434387943">"ವಿಜೆಟ್‌ಗಳು"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"ವಾಲ್‌ಪೇಪರ್‌ಗಳು"</string>
<string name="settings_button_text" msgid="8119458837558863227">"ಸೆಟ್ಟಿಂಗ್‌ಗಳು"</string>
- <string name="package_state_enqueued" msgid="6227252464303085641">"ನಿರೀಕ್ಷಿಸಲಾಗುತ್ತಿದೆ"</string>
- <string name="package_state_downloading" msgid="4088770468458724721">"ಡೌನ್‌ಲೋಡ್ ಮಾಡಲಾಗುತ್ತಿದೆ"</string>
- <string name="package_state_installing" msgid="7588193972189849870">"ಸ್ಥಾಪಿಸಲಾಗುತ್ತಿದೆ"</string>
+ <string name="allow_rotation_title" msgid="2118706734511831751">"ತಿರುಗಿಸುವಿಕೆಯನ್ನು ಅನುಮತಿಸಿ"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"ಅಜ್ಞಾತ"</string>
- <string name="package_state_error" msgid="7672093962724223588">"ಇನ್ನೂ ಪುನಃಸ್ಥಾಪಿಸಲಾಗಿಲ್ಲ"</string>
- <string name="abandoned_clean_all" msgid="5256770727689657618">"ಎಲ್ಲವನ್ನೂ ತೆಗೆದುಹಾಕಿ"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"ತೆಗೆದುಹಾಕಿ"</string>
<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="action_add_to_workspace" msgid="8902165848117513641">"ಮುಖಪುಟಕ್ಕೆ ಸೇರಿಸು"</string>
+ <string name="action_move_here" msgid="2170188780612570250">"ಐಟಂ ಇಲ್ಲಿಗೆ ಸರಿಸಿ"</string>
+ <string name="item_added_to_workspace" msgid="4211073925752213539">"ಮುಖಪುಟ ಪರದೆಗೆ ಐಟಂ ಸೇರಿಸಲಾಗಿದೆ"</string>
+ <string name="item_removed" msgid="851119963877842327">"ಐಟಂ ತೆಗೆದುಹಾಕಲಾಗಿದೆ"</string>
+ <string name="action_move" msgid="4339390619886385032">"ಐಟಂ ಸರಿಸಿ"</string>
+ <string name="move_to_empty_cell" msgid="2833711483015685619">"<xliff:g id="NUMBER_0">%1$s</xliff:g> ಸಾಲು <xliff:g id="NUMBER_1">%2$s</xliff:g> ಕಾಲಮ್‌ಗೆ ಸರಿಸಿ"</string>
+ <string name="move_to_position" msgid="6750008980455459790">"<xliff:g id="NUMBER">%1$s</xliff:g> ಸ್ಥಾನಕ್ಕೆ ಸರಿಸಿ"</string>
+ <string name="move_to_hotseat_position" msgid="6295412897075147808">"ಮೆಚ್ಚಿನ <xliff:g id="NUMBER">%1$s</xliff:g> ಸ್ಥಾನಕ್ಕೆ ಸರಿಸಿ"</string>
+ <string name="item_moved" msgid="4606538322571412879">"ಐಟಂ ಸರಿಸಲಾಗಿದೆ"</string>
+ <string name="add_to_folder" msgid="9040534766770853243">"ಫೋಲ್ಡರ್‌ಗೆ ಸೇರಿಸಿ: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="add_to_folder_with_app" msgid="4534929978967147231">"<xliff:g id="NAME">%1$s</xliff:g> ಮೂಲಕ ಫೋಲ್ಡರ್‌ಗೆ ಸೇರಿಸಿ"</string>
+ <string name="added_to_folder" msgid="4793259502305558003">"ಐಟಂ ಅನ್ನು ಫೋಲ್ಡರ್‌ಗೆ ಸೇರಿಸಲಾಗಿದೆ"</string>
+ <string name="create_folder_with" msgid="4050141361160214248">"ಇದನ್ನು ಬಳಸಿಕೊಂಡು ಫೋಲ್ಡರ್ ರಚಿಸಿ: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="folder_created" msgid="6409794597405184510">"ಫೋಲ್ಡರ್ ರಚಿಸಲಾಗಿದೆ"</string>
+ <string name="action_move_to_workspace" msgid="1603837886334246317">"ಮುಖಪುಟಕ್ಕೆ ಸರಿಸಿ"</string>
+ <string name="action_move_screen_left" msgid="8854216831569401665">"ಪರದೆಯನ್ನು ಎಡಕ್ಕೆ ಸರಿಸಿ"</string>
+ <string name="action_move_screen_right" msgid="329334910274311123">"ಪರದೆಯನ್ನು ಬಲಕ್ಕೆ ಸರಿಸಿ"</string>
+ <string name="screen_moved" msgid="266230079505650577">"ಪರದೆ ಸರಿಸಲಾಗಿದೆ"</string>
+ <string name="action_resize" msgid="1802976324781771067">"ಮರುಗಾತ್ರ"</string>
+ <string name="action_increase_width" msgid="8773715375078513326">"ಅಗಲವನ್ನು ಹೆಚ್ಚು ಮಾಡಿ"</string>
+ <string name="action_increase_height" msgid="459390020612501122">"ಎತ್ತರವನ್ನು ಹೆಚ್ಚು ಮಾಡಿ"</string>
+ <string name="action_decrease_width" msgid="1374549771083094654">"ಅಗಲವನ್ನು ಕಡಿಮೆ ಮಾಡಿ"</string>
+ <string name="action_decrease_height" msgid="282377193880900022">"ಎತ್ತರವನ್ನು ಕಡಿಮೆ ಮಾಡಿ"</string>
+ <string name="widget_resized" msgid="9130327887929620">"ವಿಜೆಟ್ ಅನ್ನು <xliff:g id="NUMBER_0">%1$s</xliff:g> ಅಗಲ <xliff:g id="NUMBER_1">%2$s</xliff:g> ಎತ್ತರಕ್ಕೆ ಮರುಗಾತ್ರಗೊಳಿಸಲಾಗಿದೆ"</string>
</resources>
diff --git a/res/values-ko/strings.xml b/res/values-ko/strings.xml
index c73b431bd..fa445acca 100644
--- a/res/values-ko/strings.xml
+++ b/res/values-ko/strings.xml
@@ -20,57 +20,27 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="application_name" msgid="5181331383435256801">"Launcher3"</string>
- <string name="home" msgid="7658288663002113681">"홈"</string>
- <string name="uid_name" msgid="7820867637514617527">"Android 핵심 앱"</string>
<string name="folder_name" msgid="7371454440695724752"></string>
+ <string name="work_folder_name" msgid="3753320833950115786">"업무"</string>
<string name="activity_not_found" msgid="8071924732094499514">"앱이 설치되지 않았습니다."</string>
<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="widgets_tab_label" msgid="2921133187116603919">"위젯"</string>
- <string name="widget_adder" msgid="3201040140710381657">"위젯"</string>
<string name="toggle_weight_watcher" msgid="5645299835184636119">"메모리 표시"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"위젯을 선택하려면 길게 터치하세요."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d×%2$d"</string>
- <string name="external_drop_widget_error" msgid="3165821058322217155">"홈 화면에 항목을 놓을 수 없습니다."</string>
- <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"만들 위젯 선택"</string>
- <string name="rename_folder_label" msgid="3727762225964550653">"폴더 이름"</string>
- <string name="rename_folder_title" msgid="3771389277707820891">"폴더 이름 바꾸기"</string>
- <string name="rename_action" msgid="5559600076028658757">"확인"</string>
- <string name="cancel_action" msgid="7009134900002915310">"취소"</string>
- <string name="menu_item_add_item" msgid="1264911265836810421">"홈 화면에 추가"</string>
- <string name="group_applications" msgid="3797214114206693605">"앱"</string>
- <string name="group_shortcuts" msgid="6012256992764410535">"바로가기"</string>
- <string name="group_widgets" msgid="1569030723286851002">"위젯"</string>
- <string name="completely_out_of_space" msgid="6106288382070760318">"홈 화면에 더 이상 공간이 없습니다."</string>
+ <string name="all_apps_search_bar_hint" msgid="7084713969757597256">"앱 검색"</string>
+ <string name="all_apps_loading_message" msgid="7557140873644765180">"앱 로드 중..."</string>
+ <string name="all_apps_no_search_results" msgid="6332185285860416787">"\'<xliff:g id="QUERY">%1$s</xliff:g>\'와(과) 일치하는 앱이 없습니다."</string>
<string name="out_of_space" msgid="4691004494942118364">"홈 화면에 더 이상 공간이 없습니다."</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"즐겨찾기 트레이에 더 이상 공간이 없습니다."</string>
- <string name="invalid_hotseat_item" msgid="5779907847267573691">"위젯이 너무 커서 즐겨찾기 트레이에 들어갈 수 없습니다."</string>
- <string name="shortcut_installed" msgid="1701742129426969556">"바로가기(\'<xliff:g id="NAME">%s</xliff:g>\')가 생성되었습니다."</string>
- <string name="shortcut_uninstalled" msgid="8176767991305701821">"바로가기(\'<xliff:g id="NAME">%s</xliff:g>\')가 삭제되었습니다."</string>
- <string name="shortcut_duplicate" msgid="9167217446062498127">"바로가기(\'<xliff:g id="NAME">%s</xliff:g>\')가 이미 있습니다."</string>
- <string name="title_select_shortcut" msgid="6680642571148153868">"바로가기 선택"</string>
- <string name="title_select_application" msgid="3280812711670683644">"앱 선택"</string>
<string name="all_apps_button_label" msgid="9110807029020582876">"앱"</string>
<string name="all_apps_home_button_label" msgid="252062713717058851">"홈"</string>
- <string name="delete_zone_label_workspace" msgid="4009607676751398685">"삭제"</string>
- <string name="delete_zone_label_all_apps" msgid="8083826390278958980">"제거"</string>
<string name="delete_target_label" msgid="1822697352535677073">"삭제"</string>
<string name="delete_target_uninstall_label" msgid="5100785476250872595">"제거"</string>
<string name="info_target_label" msgid="8053346143994679532">"앱 정보"</string>
- <string name="accessibility_all_apps_button" msgid="2603132375383800483">"앱"</string>
- <string name="accessibility_delete_button" msgid="6466114477993744621">"삭제"</string>
- <string name="delete_zone_label_all_apps_system_app" msgid="449755632749610895">"업데이트 제거"</string>
- <string name="cab_menu_delete_app" msgid="7435191475867183689">"앱 제거"</string>
- <string name="cab_menu_app_info" msgid="8593722221450362342">"앱 세부정보"</string>
- <string name="cab_app_selection_text" msgid="374688303047985416">"앱 1개 선택됨"</string>
- <string name="cab_widget_selection_text" msgid="1833458597831541241">"위젯 1개 선택됨"</string>
- <string name="cab_folder_selection_text" msgid="7999992513806132118">"폴더 1개 선택됨"</string>
- <string name="cab_shortcut_selection_text" msgid="2103811025667946450">"바로가기 1개 선택됨"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"바로가기 설치"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"앱이 사용자의 작업 없이 바로가기를 추가할 수 있도록 합니다."</string>
- <string name="permlab_uninstall_shortcut" msgid="864595034498083837">"바로가기 제거"</string>
- <string name="permdesc_uninstall_shortcut" msgid="5134129545001836849">"앱이 사용자의 작업 없이 바로가기를 삭제할 수 있도록 합니다."</string>
<string name="permlab_read_settings" msgid="1941457408239617576">"홈 설정 및 바로가기 읽기"</string>
<string name="permdesc_read_settings" msgid="5833423719057558387">"앱이 홈에 있는 설정 및 바로가기를 읽을 수 있도록 합니다."</string>
<string name="permlab_write_settings" msgid="3574213698004620587">"홈 설정 및 바로가기 쓰기"</string>
@@ -78,30 +48,17 @@
<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>
- <string name="dream_name" msgid="1530253749244328964">"로켓 실행기"</string>
<string name="folder_hint_text" msgid="6617836969016293992">"이름이 없는 폴더"</string>
- <string name="workspace_description_format" msgid="2950174241104043327">"홈 화면 %1$d"</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="apps_customize_apps_scroll_format" msgid="370005296147130238">"앱 페이지 %1$d/%2$d"</string>
- <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"위젯 페이지 %1$d/%2$d"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"환영합니다."</string>
- <string name="first_run_cling_description" msgid="6447072552696253358">"편리한 사용 환경을 만드세요."</string>
- <string name="first_run_cling_custom_content_hint" msgid="6090628589029352439"></string>
- <string name="first_run_cling_search_bar_hint" msgid="5909062802402452582"></string>
- <string name="first_run_cling_create_screens_hint" msgid="6950729526680114157">"앱 및 폴더를 표시할 화면 더 만들기"</string>
<string name="migration_cling_title" msgid="9181776667882933767">"앱 아이콘 복사"</string>
<string name="migration_cling_description" msgid="2752413805582227644">"이전 메인 스크린에서 아이콘과 폴더를 가져오시겠습니까?"</string>
<string name="migration_cling_copy_apps" msgid="946331230090919440">"아이콘 복사"</string>
<string name="migration_cling_use_default" msgid="2626475813981258626">"새로 시작"</string>
- <string name="workspace_cling_title" msgid="5626202359865825661">"공간 관리하기"</string>
- <string name="workspace_cling_move_item" msgid="528201129978005352">"배경화면, 위젯, 설정을 관리하려면 백그라운드를 길게 터치합니다."</string>
<string name="workspace_cling_longpress_title" msgid="9173998993909018310">"배경화면, 위젯, 설정"</string>
<string name="workspace_cling_longpress_description" msgid="4119994475505235248">"백그라운드를 길게 터치하여 맞춤설정합니다."</string>
<string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"확인"</string>
- <string name="folder_cling_title" msgid="3894908818693254164">"폴더"</string>
- <string name="folder_cling_create_folder" msgid="6158215559475836131">"폴더를 만들려면 앱을 길게 터치한 다음 다른 앱 위에 올려 놓으세요."</string>
- <string name="cling_dismiss" msgid="8962359497601507581">"확인"</string>
<string name="folder_opened" msgid="94695026776264709">"폴더 열림(<xliff:g id="WIDTH">%1$d</xliff:g>X<xliff:g id="HEIGHT">%2$d</xliff:g>)"</string>
<string name="folder_tap_to_close" msgid="1884479294466410023">"터치하여 폴더를 닫음"</string>
<string name="folder_tap_to_rename" msgid="9191075570492871147">"터치하여 바꾼 이름을 저장"</string>
@@ -111,14 +68,34 @@
<string name="widget_button_text" msgid="2880537293434387943">"위젯"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"배경화면"</string>
<string name="settings_button_text" msgid="8119458837558863227">"설정"</string>
- <string name="package_state_enqueued" msgid="6227252464303085641">"대기 중"</string>
- <string name="package_state_downloading" msgid="4088770468458724721">"다운로드 중"</string>
- <string name="package_state_installing" msgid="7588193972189849870">"설치 중"</string>
+ <string name="allow_rotation_title" msgid="2118706734511831751">"회전 허용"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"알 수 없음"</string>
- <string name="package_state_error" msgid="7672093962724223588">"복원되지 않음"</string>
- <string name="abandoned_clean_all" msgid="5256770727689657618">"모두 삭제"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"삭제"</string>
<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="action_add_to_workspace" msgid="8902165848117513641">"메인 스크린에 추가"</string>
+ <string name="action_move_here" msgid="2170188780612570250">"여기에 항목을 이동"</string>
+ <string name="item_added_to_workspace" msgid="4211073925752213539">"메인 스크린에 항목 추가됨"</string>
+ <string name="item_removed" msgid="851119963877842327">"항목 삭제됨"</string>
+ <string name="action_move" msgid="4339390619886385032">"항목 이동"</string>
+ <string name="move_to_empty_cell" msgid="2833711483015685619">"<xliff:g id="NUMBER_0">%1$s</xliff:g>행 <xliff:g id="NUMBER_1">%2$s</xliff:g>열로 이동"</string>
+ <string name="move_to_position" msgid="6750008980455459790">"<xliff:g id="NUMBER">%1$s</xliff:g>번 위치로 이동"</string>
+ <string name="move_to_hotseat_position" msgid="6295412897075147808">"즐겨찾는 <xliff:g id="NUMBER">%1$s</xliff:g>번 위치로 이동"</string>
+ <string name="item_moved" msgid="4606538322571412879">"항목을 이동했습니다."</string>
+ <string name="add_to_folder" msgid="9040534766770853243">"폴더에 추가: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="add_to_folder_with_app" msgid="4534929978967147231">"<xliff:g id="NAME">%1$s</xliff:g>이(가) 포함된 폴더에 추가"</string>
+ <string name="added_to_folder" msgid="4793259502305558003">"항목이 폴더에 추가되었습니다."</string>
+ <string name="create_folder_with" msgid="4050141361160214248">"다음이 포함된 폴더 만들기: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="folder_created" msgid="6409794597405184510">"폴더를 만들었습니다."</string>
+ <string name="action_move_to_workspace" msgid="1603837886334246317">"메인 스크린으로 이동"</string>
+ <string name="action_move_screen_left" msgid="8854216831569401665">"화면을 왼쪽으로 이동"</string>
+ <string name="action_move_screen_right" msgid="329334910274311123">"화면을 오른쪽으로 이동"</string>
+ <string name="screen_moved" msgid="266230079505650577">"화면 이동됨"</string>
+ <string name="action_resize" msgid="1802976324781771067">"크기 조정"</string>
+ <string name="action_increase_width" msgid="8773715375078513326">"폭 늘리기"</string>
+ <string name="action_increase_height" msgid="459390020612501122">"높이 늘리기"</string>
+ <string name="action_decrease_width" msgid="1374549771083094654">"폭 줄이기"</string>
+ <string name="action_decrease_height" msgid="282377193880900022">"높이 줄이기"</string>
+ <string name="widget_resized" msgid="9130327887929620">"폭 <xliff:g id="NUMBER_0">%1$s</xliff:g>, 높이 <xliff:g id="NUMBER_1">%2$s</xliff:g>로 위젯 크기 조정됨"</string>
</resources>
diff --git a/res/values-ky-rKG/strings.xml b/res/values-ky-rKG/strings.xml
index a8a605b26..20787489e 100644
--- a/res/values-ky-rKG/strings.xml
+++ b/res/values-ky-rKG/strings.xml
@@ -20,57 +20,27 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="application_name" msgid="5181331383435256801">"Launcher3"</string>
- <string name="home" msgid="7658288663002113681">"Үйгө"</string>
- <string name="uid_name" msgid="7820867637514617527">"Android Core колдонмолору"</string>
<string name="folder_name" msgid="7371454440695724752"></string>
+ <string name="work_folder_name" msgid="3753320833950115786">"Жумуш"</string>
<string name="activity_not_found" msgid="8071924732094499514">"Колдонмо орнотулган эмес."</string>
<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="widgets_tab_label" msgid="2921133187116603919">"Виджеттер"</string>
- <string name="widget_adder" msgid="3201040140710381657">"Виджеттер"</string>
<string name="toggle_weight_watcher" msgid="5645299835184636119">"Мемди көргөзүү"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"Виджетти тандаш үчүн, басып туруңуз"</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
- <string name="external_drop_widget_error" msgid="3165821058322217155">"Муну бул Үй экранына ыргытуу мүмкүн эмес."</string>
- <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Түзүлүүчү виджетти тандаңыз"</string>
- <string name="rename_folder_label" msgid="3727762225964550653">"Фолдердин аты"</string>
- <string name="rename_folder_title" msgid="3771389277707820891">"Фолдердин атын өзгөртүү"</string>
- <string name="rename_action" msgid="5559600076028658757">"OK"</string>
- <string name="cancel_action" msgid="7009134900002915310">"Жокко чыгаруу"</string>
- <string name="menu_item_add_item" msgid="1264911265836810421">"Үй экранына кошуу"</string>
- <string name="group_applications" msgid="3797214114206693605">"Колдонмолор"</string>
- <string name="group_shortcuts" msgid="6012256992764410535">"Тез чакырмалар"</string>
- <string name="group_widgets" msgid="1569030723286851002">"Виджеттер"</string>
- <string name="completely_out_of_space" msgid="6106288382070760318">"Үй экрандарыңызда бош орун калган жок."</string>
+ <string name="all_apps_search_bar_hint" msgid="7084713969757597256">"Колдонмолорду издөө"</string>
+ <string name="all_apps_loading_message" msgid="7557140873644765180">"Колдонмолор жүктөлүүдө…"</string>
+ <string name="all_apps_no_search_results" msgid="6332185285860416787">"\"<xliff:g id="QUERY">%1$s</xliff:g>\" дал келген колдонмолор табылган жок"</string>
<string name="out_of_space" msgid="4691004494942118364">"Бул Үй экранында бош орун жок."</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"Тандамалдар тайпасында орун калган жок"</string>
- <string name="invalid_hotseat_item" msgid="5779907847267573691">"Бул виджет Тандамалдар үчүн өтө чоң"</string>
- <string name="shortcut_installed" msgid="1701742129426969556">"\"<xliff:g id="NAME">%s</xliff:g>\" тез чакырмасы түзүлдү."</string>
- <string name="shortcut_uninstalled" msgid="8176767991305701821">"\"<xliff:g id="NAME">%s</xliff:g>\" тез чакырмасы алынып салынды."</string>
- <string name="shortcut_duplicate" msgid="9167217446062498127">"\"<xliff:g id="NAME">%s</xliff:g>\" тез чакырмасы бар."</string>
- <string name="title_select_shortcut" msgid="6680642571148153868">"Тез чакырма тандоо"</string>
- <string name="title_select_application" msgid="3280812711670683644">"Колдонмо тандоо"</string>
<string name="all_apps_button_label" msgid="9110807029020582876">"Колдонмолор"</string>
<string name="all_apps_home_button_label" msgid="252062713717058851">"Үйгө"</string>
- <string name="delete_zone_label_workspace" msgid="4009607676751398685">"Алып салуу"</string>
- <string name="delete_zone_label_all_apps" msgid="8083826390278958980">"Чечип салуу"</string>
<string name="delete_target_label" msgid="1822697352535677073">"Алып салуу"</string>
<string name="delete_target_uninstall_label" msgid="5100785476250872595">"Чечип салуу"</string>
<string name="info_target_label" msgid="8053346143994679532">"Колдонмо тууралуу"</string>
- <string name="accessibility_all_apps_button" msgid="2603132375383800483">"Колдонмолор"</string>
- <string name="accessibility_delete_button" msgid="6466114477993744621">"Алып салуу"</string>
- <string name="delete_zone_label_all_apps_system_app" msgid="449755632749610895">"Жаңыртууну чечип салуу"</string>
- <string name="cab_menu_delete_app" msgid="7435191475867183689">"Колдонмону чечип салуу"</string>
- <string name="cab_menu_app_info" msgid="8593722221450362342">"Колдонмонун кеңири маалыматтары"</string>
- <string name="cab_app_selection_text" msgid="374688303047985416">"1 колдонмо тандалды"</string>
- <string name="cab_widget_selection_text" msgid="1833458597831541241">"1 виджет тандалды"</string>
- <string name="cab_folder_selection_text" msgid="7999992513806132118">"1 фолдер тандалды"</string>
- <string name="cab_shortcut_selection_text" msgid="2103811025667946450">"1 тез чакырма тандалды"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"тез чакырмаларды орнотуу"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"Колдонмого колдонуучуга кайрылбастан тез чакырма кошууга уруксат берет."</string>
- <string name="permlab_uninstall_shortcut" msgid="864595034498083837">"тез чакырмаларды жок кылуу"</string>
- <string name="permdesc_uninstall_shortcut" msgid="5134129545001836849">"Колдонмого колдонуучуга кайрылбастан тез чакырмаларды жок кылууга уруксат берет."</string>
<string name="permlab_read_settings" msgid="1941457408239617576">"Үйдүн тууралоолорун жана тез чакырмаларын окуу"</string>
<string name="permdesc_read_settings" msgid="5833423719057558387">"Колдонмого Үйдүн тууралоолорун жана тез чакырмаларын окууга уруксат берет."</string>
<string name="permlab_write_settings" msgid="3574213698004620587">"Үйдүн тууралоолорун жана тез чакырмаларын жазуу"</string>
@@ -78,30 +48,17 @@
<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>
- <string name="dream_name" msgid="1530253749244328964">"Rocket Launcher"</string>
<string name="folder_hint_text" msgid="6617836969016293992">"Аты жок фолдер"</string>
- <string name="workspace_description_format" msgid="2950174241104043327">"Үй экраны %1$d"</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="apps_customize_apps_scroll_format" msgid="370005296147130238">"Колдонмолор барагы %2$d ичинен %1$d"</string>
- <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"Виджеттер барагы %2$d ичинен %1$d"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"Кош келиңиз"</string>
- <string name="first_run_cling_description" msgid="6447072552696253358">"Өзүңүздү үйүңүздөгүдөй эркин сезиңиз."</string>
- <string name="first_run_cling_custom_content_hint" msgid="6090628589029352439"></string>
- <string name="first_run_cling_search_bar_hint" msgid="5909062802402452582"></string>
- <string name="first_run_cling_create_screens_hint" msgid="6950729526680114157">"Колдонмолор жана фолдерлер үчүн кошумча экрандарды түзүңүз"</string>
<string name="migration_cling_title" msgid="9181776667882933767">"Колдонмоңуздун сүрөтчөлөрүн көчүрүү"</string>
<string name="migration_cling_description" msgid="2752413805582227644">"Эски үй экрандарыңыздан сүрөтчөлөр жана фолдерлер импорттолсунбу?"</string>
<string name="migration_cling_copy_apps" msgid="946331230090919440">"СҮРӨТЧӨЛӨРДҮ КӨЧҮРҮҮ"</string>
<string name="migration_cling_use_default" msgid="2626475813981258626">"ТАЗАСЫН БАШТОО"</string>
- <string name="workspace_cling_title" msgid="5626202359865825661">"Өз мейкиндигиңизди уюштуруңуз"</string>
- <string name="workspace_cling_move_item" msgid="528201129978005352">"Тушкагаздарды, виджеттерди жана тууралоолорду башкаруу үчүн фонду басып туруңуз."</string>
<string name="workspace_cling_longpress_title" msgid="9173998993909018310">"Тушкагаздар, виджеттер &amp; жөндөөлөр"</string>
<string name="workspace_cling_longpress_description" msgid="4119994475505235248">"Өзгөчөлөштүрүү үчүн фонго тийип &amp; коё бербей туруңуз"</string>
<string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"ТҮШҮНДҮМ"</string>
- <string name="folder_cling_title" msgid="3894908818693254164">"Мынакей фолдер"</string>
- <string name="folder_cling_create_folder" msgid="6158215559475836131">"Башкасын түзүш үчүн колдонмону басып туруп, башканын жанына жылдырыңыз."</string>
- <string name="cling_dismiss" msgid="8962359497601507581">"OK"</string>
<string name="folder_opened" msgid="94695026776264709">"Фолдер ачылды, туурасы <xliff:g id="WIDTH">%1$d</xliff:g>, бийиктиги <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
<string name="folder_tap_to_close" msgid="1884479294466410023">"Фолдерди жабыш үчүн тийиңиз"</string>
<string name="folder_tap_to_rename" msgid="9191075570492871147">"Тийип, аттын өзгөртүлүшүн сактаңыз"</string>
@@ -111,14 +68,34 @@
<string name="widget_button_text" msgid="2880537293434387943">"Виджеттер"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"Тушкагаздар"</string>
<string name="settings_button_text" msgid="8119458837558863227">"Тууралоолор"</string>
- <string name="package_state_enqueued" msgid="6227252464303085641">"Күтүүдө"</string>
- <string name="package_state_downloading" msgid="4088770468458724721">"Жүктөлп алнууда"</string>
- <string name="package_state_installing" msgid="7588193972189849870">"Орнотулууда"</string>
+ <string name="allow_rotation_title" msgid="2118706734511831751">"Айлантууга уруксат берүү"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Белгисиз"</string>
- <string name="package_state_error" msgid="7672093962724223588">"Калыбн келт. жок"</string>
- <string name="abandoned_clean_all" msgid="5256770727689657618">"Баарын алып салуу"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Алып салуу"</string>
<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="action_add_to_workspace" msgid="8902165848117513641">"Башкы экранга кошуу"</string>
+ <string name="action_move_here" msgid="2170188780612570250">"Бул нерсени бул жерге жылдыруу"</string>
+ <string name="item_added_to_workspace" msgid="4211073925752213539">"Башкы экранга кошулду"</string>
+ <string name="item_removed" msgid="851119963877842327">"Жоюлду"</string>
+ <string name="action_move" msgid="4339390619886385032">"Муну жылдыруу"</string>
+ <string name="move_to_empty_cell" msgid="2833711483015685619">"<xliff:g id="NUMBER_0">%1$s</xliff:g> катарга <xliff:g id="NUMBER_1">%2$s</xliff:g> тилкеге жылдыруу"</string>
+ <string name="move_to_position" msgid="6750008980455459790">"<xliff:g id="NUMBER">%1$s</xliff:g> орунга жылдыруу"</string>
+ <string name="move_to_hotseat_position" msgid="6295412897075147808">"Сүйүктүүлөргө <xliff:g id="NUMBER">%1$s</xliff:g> жылдыруу"</string>
+ <string name="item_moved" msgid="4606538322571412879">"Нерсе жылдырылды"</string>
+ <string name="add_to_folder" msgid="9040534766770853243">"Куржунга кошуу: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="add_to_folder_with_app" msgid="4534929978967147231">"<xliff:g id="NAME">%1$s</xliff:g> куржунуна кошуу"</string>
+ <string name="added_to_folder" msgid="4793259502305558003">"Нерсе куржунга кошулду"</string>
+ <string name="create_folder_with" msgid="4050141361160214248">"Төмөнкү менен куржун түзүү: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="folder_created" msgid="6409794597405184510">"Куржун түзүлдү"</string>
+ <string name="action_move_to_workspace" msgid="1603837886334246317">"Башкы экранга жылдыруу"</string>
+ <string name="action_move_screen_left" msgid="8854216831569401665">"Экранды солго жылдыруу"</string>
+ <string name="action_move_screen_right" msgid="329334910274311123">"Экранды оңго жылдыруу"</string>
+ <string name="screen_moved" msgid="266230079505650577">"Экран жылдырылды"</string>
+ <string name="action_resize" msgid="1802976324781771067">"Өлчөмүн өзгөртүү"</string>
+ <string name="action_increase_width" msgid="8773715375078513326">"Кеңейтүү"</string>
+ <string name="action_increase_height" msgid="459390020612501122">"Бийиктетүү"</string>
+ <string name="action_decrease_width" msgid="1374549771083094654">"Ичкертүү"</string>
+ <string name="action_decrease_height" msgid="282377193880900022">"Жапыздатуу"</string>
+ <string name="widget_resized" msgid="9130327887929620">"Виджеттин кеңдиги <xliff:g id="NUMBER_0">%1$s</xliff:g> бийиктиги <xliff:g id="NUMBER_1">%2$s</xliff:g> болду"</string>
</resources>
diff --git a/res/values-land/dimens.xml b/res/values-land/dimens.xml
index 1b3418154..06a99842e 100644
--- a/res/values-land/dimens.xml
+++ b/res/values-land/dimens.xml
@@ -18,9 +18,4 @@
<!-- QSB -->
<dimen name="toolbar_button_vertical_padding">8dip</dimen>
<dimen name="toolbar_button_horizontal_padding">0dip</dimen>
-
-<!-- AppsCustomize -->
- <dimen name="apps_customize_tab_bar_height">42dp</dimen>
- <integer name="apps_customize_widget_cell_count_x">3</integer>
- <integer name="apps_customize_widget_cell_count_y">2</integer>
</resources>
diff --git a/res/values-land/styles.xml b/res/values-land/styles.xml
index 8a255c91b..c5a76d595 100644
--- a/res/values-land/styles.xml
+++ b/res/values-land/styles.xml
@@ -28,7 +28,7 @@
</style>
<!-- This style applies to the drop target when it is shown in the sidebar -->
- <style name="DropTargetButton" parent="DropTargetButton.Base">
+ <style name="DropTargetButton" parent="DropTargetButtonBase">
<item name="android:layout_height">wrap_content</item>
<item name="android:gravity">center</item>
<item name="android:drawablePadding">0dp</item>
diff --git a/res/values-lo-rLA/strings.xml b/res/values-lo-rLA/strings.xml
index 1beb049e2..dff2612ba 100644
--- a/res/values-lo-rLA/strings.xml
+++ b/res/values-lo-rLA/strings.xml
@@ -20,57 +20,27 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="application_name" msgid="5181331383435256801">"Launcher3"</string>
- <string name="home" msgid="7658288663002113681">"ໜ້າຫຼັກ"</string>
- <string name="uid_name" msgid="7820867637514617527">"ແອັບພລິເຄຊັນຫຼັກຂອງ Android"</string>
<string name="folder_name" msgid="7371454440695724752"></string>
+ <string name="work_folder_name" msgid="3753320833950115786">"ວຽກ"</string>
<string name="activity_not_found" msgid="8071924732094499514">"ແອັບຯບໍ່ໄດ້ຖືກຕິດຕັ້ງ."</string>
<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="widgets_tab_label" msgid="2921133187116603919">"ວິດເຈັດ"</string>
- <string name="widget_adder" msgid="3201040140710381657">"ວິດເຈັດ"</string>
<string name="toggle_weight_watcher" msgid="5645299835184636119">"ສະແດງຄວາມຈຳ"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"ສຳພັດຄ້າງໄວ້ ເພື່ອຈັບວິດເຈັດ."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
- <string name="external_drop_widget_error" msgid="3165821058322217155">"ບໍ່ສາມາດວາງລາຍການໃສ່ໜ້າຈໍຫຼັກນີ້ໄດ້"</string>
- <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"ເລືອກວິດເຈັດເພື່ອສ້າງມັນ"</string>
- <string name="rename_folder_label" msgid="3727762225964550653">"ຊື່ໂຟນເດີ"</string>
- <string name="rename_folder_title" msgid="3771389277707820891">"ປ່ຽນຊື່ໂຟນເດີ"</string>
- <string name="rename_action" msgid="5559600076028658757">"ຕົກລົງ"</string>
- <string name="cancel_action" msgid="7009134900002915310">"ຍົກ​ເລີກ​"</string>
- <string name="menu_item_add_item" msgid="1264911265836810421">"ເພີ່ມໃສ່ໜ້າຈໍຫຼັກ"</string>
- <string name="group_applications" msgid="3797214114206693605">"ແອັບຯ"</string>
- <string name="group_shortcuts" msgid="6012256992764410535">"ທາງລັດ"</string>
- <string name="group_widgets" msgid="1569030723286851002">"ວິດເຈັດ"</string>
- <string name="completely_out_of_space" msgid="6106288382070760318">"ບໍ່ມີຫ້ອງເຫຼືອໃນໜ້າຈໍຫຼັກຂອງທ່ານ."</string>
+ <string name="all_apps_search_bar_hint" msgid="7084713969757597256">"ຊອກຫາແອັບ"</string>
+ <string name="all_apps_loading_message" msgid="7557140873644765180">"​ກຳ​ລັງ​ໂຫລດ​ແອັບ..."</string>
+ <string name="all_apps_no_search_results" msgid="6332185285860416787">"ບໍ່​ພົບ​ແອັບ​ໃດ​ທີ່​ກົງ​ກັນ \"<xliff:g id="QUERY">%1$s</xliff:g>\""</string>
<string name="out_of_space" msgid="4691004494942118364">"ບໍ່ມີຫ້ອງເຫຼືອໃນໜ້າຈໍຫຼັກນີ້."</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"ບໍ່ມີບ່ອນຫວ່າງໃນຖາດສຳລັບເກັບສິ່ງທີ່ໃຊ້ເປັນປະຈຳ"</string>
- <string name="invalid_hotseat_item" msgid="5779907847267573691">"ວິດເຈັດນີ້ໃຫຍ່ເກີນໄປທີ່ຈະເກັບໄວ້ໃນຖາດເກັບສິ່ງທີ່ໃຊ້ເປັນປະຈຳ"</string>
- <string name="shortcut_installed" msgid="1701742129426969556">"ທາງລັດ \"<xliff:g id="NAME">%s</xliff:g>\" ຖືກສ້າງແລ້ວ."</string>
- <string name="shortcut_uninstalled" msgid="8176767991305701821">"ທາງລັດ \"<xliff:g id="NAME">%s</xliff:g>\" ຖືກລຶບແລ້ວ."</string>
- <string name="shortcut_duplicate" msgid="9167217446062498127">"ທາງລັດ \"<xliff:g id="NAME">%s</xliff:g>\" ມີຢູ່ແລ້ວ."</string>
- <string name="title_select_shortcut" msgid="6680642571148153868">"ເລືອກທາງລັດ"</string>
- <string name="title_select_application" msgid="3280812711670683644">"ເລືອກແອັບຯ"</string>
<string name="all_apps_button_label" msgid="9110807029020582876">"ແອັບຯ"</string>
<string name="all_apps_home_button_label" msgid="252062713717058851">"ໜ້າຫຼັກ"</string>
- <string name="delete_zone_label_workspace" msgid="4009607676751398685">"ລຶບ"</string>
- <string name="delete_zone_label_all_apps" msgid="8083826390278958980">"ຖອນ​ການ​ຕິດ​ຕັ້ງ"</string>
<string name="delete_target_label" msgid="1822697352535677073">"ລຶບ"</string>
<string name="delete_target_uninstall_label" msgid="5100785476250872595">"ຖອນ​ການ​ຕິດ​ຕັ້ງ"</string>
<string name="info_target_label" msgid="8053346143994679532">"ຂໍ້ມູນແອັບຯ"</string>
- <string name="accessibility_all_apps_button" msgid="2603132375383800483">"ແອັບຯ"</string>
- <string name="accessibility_delete_button" msgid="6466114477993744621">"ລຶບ"</string>
- <string name="delete_zone_label_all_apps_system_app" msgid="449755632749610895">"ຖອນອັບເດດ"</string>
- <string name="cab_menu_delete_app" msgid="7435191475867183689">"ຖອນແອັບຯ"</string>
- <string name="cab_menu_app_info" msgid="8593722221450362342">"ລາຍລະອຽດແອັບຯ"</string>
- <string name="cab_app_selection_text" msgid="374688303047985416">"1 ແອັບຯຖືກເລືອກ"</string>
- <string name="cab_widget_selection_text" msgid="1833458597831541241">"1 ວິດເຈັດຖືກເລືອກ"</string>
- <string name="cab_folder_selection_text" msgid="7999992513806132118">"1 ໂຟນເດີຖືກເລືອກ"</string>
- <string name="cab_shortcut_selection_text" msgid="2103811025667946450">"1 ທາງລັດຖືກເລືອກ"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"ຕິດຕັ້ງທາງລັດ"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"ອະນຸຍາດໃຫ້ແອັບຯ ເພີ່ມທາງລັດໂດຍບໍ່ຕ້ອງຮັບການຢືນຢັນຈາກຜູ່ໃຊ້."</string>
- <string name="permlab_uninstall_shortcut" msgid="864595034498083837">"ຖອນທາງລັດ"</string>
- <string name="permdesc_uninstall_shortcut" msgid="5134129545001836849">"ອະນຸຍາດໃຫ້ແອັບຯດັ່ງກ່າວ ລຶບທາງລັດໂດຍບໍ່ຕ້ອງຮັບການຢືນຢັນຈາກຜູ່ໃຊ້."</string>
<string name="permlab_read_settings" msgid="1941457408239617576">"ອ່ານການຕັ້ງຄ່າໜ້າຫຼັກ ແລະທາງລັດ"</string>
<string name="permdesc_read_settings" msgid="5833423719057558387">"ອະນຸຍາດໃຫ້ແອັບຯດັ່ງກ່າວອ່ານການຕັ້ງຄ່າ ແລະທາງລັດໃນໜ້າຫຼັກ."</string>
<string name="permlab_write_settings" msgid="3574213698004620587">"ຂຽນການຕັ້ງຄ່າໜ້າຫຼັກ ແລະທາງລັດ"</string>
@@ -78,30 +48,17 @@
<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>
- <string name="dream_name" msgid="1530253749244328964">"Rocket Launcher"</string>
<string name="folder_hint_text" msgid="6617836969016293992">"ໂຟນເດີຍັງບໍ່ຖືກຕັ້ງຊື່"</string>
- <string name="workspace_description_format" msgid="2950174241104043327">"ໜ້າຈໍຫຼັກ %1$d"</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="apps_customize_apps_scroll_format" msgid="370005296147130238">"ແອັບຯໜ້າ %1$d ໃນ %2$d"</string>
- <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"ວິດເຈັດໜ້າ %1$d ໃນ %2$d"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"ຍິນດີຕ້ອນຮັບ"</string>
- <string name="first_run_cling_description" msgid="6447072552696253358">"ເຮັດໂຕໃຫ້ຄືຢູ່ໃນບ້ານ"</string>
- <string name="first_run_cling_custom_content_hint" msgid="6090628589029352439"></string>
- <string name="first_run_cling_search_bar_hint" msgid="5909062802402452582"></string>
- <string name="first_run_cling_create_screens_hint" msgid="6950729526680114157">"ສ້າງຈໍເພີ່ມເຕີມສຳລັບແອັບຯ ແລະໂຟນເດີ"</string>
<string name="migration_cling_title" msgid="9181776667882933767">"ສຳເນົາໄອຄອນແອັບຯຂອງທ່ານ"</string>
<string name="migration_cling_description" msgid="2752413805582227644">"ນຳເຂົ້າໄອຄອນ ແລະ ໂຟນເດີຈາກໂຮມສະກຣີນອັນເກົ່າຂອງທ່ານບໍ່?"</string>
<string name="migration_cling_copy_apps" msgid="946331230090919440">"ສຳເນົາໄອຄອນ"</string>
<string name="migration_cling_use_default" msgid="2626475813981258626">"ເລີ່ມຕົ້ນໃໝ່"</string>
- <string name="workspace_cling_title" msgid="5626202359865825661">"ຈັດການພື້ນທີ່ຂອງທ່ານ"</string>
- <string name="workspace_cling_move_item" msgid="528201129978005352">"ແຕະຄ້າງໄວ້ທີ່ພາບພື້ນຫຼັງເພື່ອຈັດການພາບພື້ນຫຼັງ, ວິດເຈັດແລະການຕັ້ງຄ່າ."</string>
<string name="workspace_cling_longpress_title" msgid="9173998993909018310">"​ຮູບ​ພື້ນຫຼັງ, ວິດເຈັດ, &amp; ​ການ​ຕັ້ງ​ຄ່າ"</string>
<string name="workspace_cling_longpress_description" msgid="4119994475505235248">"ແຕະທີ່​ພາບ​ພື້ນ​ຫລັງ​ຄ້າງ​ໄວ້​ເພື່ອ​ປັບ​ແຕ່ງ"</string>
<string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"ເຂົ້າໃຈແລ້ວ"</string>
- <string name="folder_cling_title" msgid="3894908818693254164">"ນີ້ແມ່ນໂຟນເດີ"</string>
- <string name="folder_cling_create_folder" msgid="6158215559475836131">"ເພື່ອ​ສ້າງ​ອັນໃໝ່​ແບບນີ້ ໃຫ້​ແຕະ​ຄ້າງ​ໄວ້​ທີ່​ແອັບຯ​ທີ່​ຕ້ອງການ​ຍ້າຍ​ແລ້ວ​ລາກ​ມັນ​ໄປ​ຫາ​ໂຕ​ອື່ນ."</string>
- <string name="cling_dismiss" msgid="8962359497601507581">"ຕົກລົງ"</string>
<string name="folder_opened" msgid="94695026776264709">"ເປີດໂຟນເດີແລ້ວ, <xliff:g id="WIDTH">%1$d</xliff:g> ຄູນ <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
<string name="folder_tap_to_close" msgid="1884479294466410023">"ສຳພັດເພື່ອປິດໂຟນເດີ"</string>
<string name="folder_tap_to_rename" msgid="9191075570492871147">"ສຳພັດເພື່ອບັນທຶກການປ່ຽນຊື່"</string>
@@ -111,14 +68,34 @@
<string name="widget_button_text" msgid="2880537293434387943">"ວິດເຈັດ"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"ພາບພື້ນຫຼັງ"</string>
<string name="settings_button_text" msgid="8119458837558863227">"ການຕັ້ງຄ່າ"</string>
- <string name="package_state_enqueued" msgid="6227252464303085641">"ກຳ​ລັງ​ລໍ​ຖ້າ"</string>
- <string name="package_state_downloading" msgid="4088770468458724721">"ກຳລັງດາວໂຫລດ"</string>
- <string name="package_state_installing" msgid="7588193972189849870">"​ກຳ​ລັງ​ຕິດ​ຕັ້ງ"</string>
+ <string name="allow_rotation_title" msgid="2118706734511831751">"ອະ​ນຸ​ຍາດ​ການ​ໝຸນ"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"​ບໍ່​ຮູ້​ຈັກ"</string>
- <string name="package_state_error" msgid="7672093962724223588">"ບໍ່​ໄດ້​ກູ້​ຂໍ້ມູນ​ມາ​ເທື່ອ"</string>
- <string name="abandoned_clean_all" msgid="5256770727689657618">"ລຶບ​ທັງ​ໝົດ"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"ລຶບ​"</string>
<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="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>
+ <string name="item_removed" msgid="851119963877842327">"ເອົາ​ລາຍ​ການ​ອອກ​ໄປ​ແລ້ວ"</string>
+ <string name="action_move" msgid="4339390619886385032">"ຍ້າຍ​ລາຍ​ການ"</string>
+ <string name="move_to_empty_cell" msgid="2833711483015685619">"ຍ້າຍ​ໄປ​ໃສ່​ແຖວ <xliff:g id="NUMBER_0">%1$s</xliff:g> ຖັນ <xliff:g id="NUMBER_1">%2$s</xliff:g>"</string>
+ <string name="move_to_position" msgid="6750008980455459790">"ຍ້າຍ​ໄປ​ໃສ່​ຕຳ​ແໜ່ງ <xliff:g id="NUMBER">%1$s</xliff:g>"</string>
+ <string name="move_to_hotseat_position" msgid="6295412897075147808">"ຍ້າຍ​ໄປ​ໃສ່​ຕຳ​ແໜ່ງ​ທີ່​ມັກ <xliff:g id="NUMBER">%1$s</xliff:g>"</string>
+ <string name="item_moved" msgid="4606538322571412879">"ຍ້າຍ​ລາຍ​ການ​ແລ້ວ"</string>
+ <string name="add_to_folder" msgid="9040534766770853243">"ເພີ່ມ​ໃສ່​ໂຟ​ລ​ເດີ: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="add_to_folder_with_app" msgid="4534929978967147231">"ເພີ່ມ​ໃສ່​ໂຟ​ລ​ເດີ​ດ້ວຍ <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="added_to_folder" msgid="4793259502305558003">"ເພີ່ມ​ລາຍ​ການ​ໃສ່​ໂຟ​ລ​ເດີ​ແລ້ວ"</string>
+ <string name="create_folder_with" msgid="4050141361160214248">"ສ້າງ​ໂຟ​ລ​ເດີ​ກັບ: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="folder_created" msgid="6409794597405184510">"ສ້າງ​ໂຟ​ລ​ເດີ​ແລ້ວ"</string>
+ <string name="action_move_to_workspace" msgid="1603837886334246317">"ຍ້າຍ​ໄປ​ໃສ່​ໜ້າ​ຈໍ​ຫຼັກ"</string>
+ <string name="action_move_screen_left" msgid="8854216831569401665">"ຍ້າຍ​ໜ້າ​ຈໍ​ໄປ​ທາງ​ຊ້າຍ"</string>
+ <string name="action_move_screen_right" msgid="329334910274311123">"ຍ້າຍ​ໜ້າ​ຈໍ​ໄປ​ທາງ​ຂວາ"</string>
+ <string name="screen_moved" msgid="266230079505650577">"ຍ້າຍ​ໜ້າ​ຈໍ​ແລ້ວ"</string>
+ <string name="action_resize" msgid="1802976324781771067">"ປັບຂະໜາດ"</string>
+ <string name="action_increase_width" msgid="8773715375078513326">"ເພີ່ມ​ລວງ​ກ້​ວາງ​ຂຶ້ນ"</string>
+ <string name="action_increase_height" msgid="459390020612501122">"ເພີ່ມ​ລວງ​ສູງ​ຂຶ້ນ"</string>
+ <string name="action_decrease_width" msgid="1374549771083094654">"ຫຼຸດ​ລວງ​ກ້​ວາງ​ລົງ"</string>
+ <string name="action_decrease_height" msgid="282377193880900022">"ຫຼຸດ​ລວງ​ສູງ​ລົງ"</string>
+ <string name="widget_resized" msgid="9130327887929620">"ປ່ຽນ​ຂະ​ໜາດ​ວິດ​ເຈັດ​ເປັນ​ລວງ​ກ້​ວາງ <xliff:g id="NUMBER_0">%1$s</xliff:g> ລວງ​ສູງ <xliff:g id="NUMBER_1">%2$s</xliff:g> ແລ້ວ"</string>
</resources>
diff --git a/res/values-lt/strings.xml b/res/values-lt/strings.xml
index 897c2fd9f..b5c0832dc 100644
--- a/res/values-lt/strings.xml
+++ b/res/values-lt/strings.xml
@@ -20,57 +20,27 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="application_name" msgid="5181331383435256801">"Launcher3"</string>
- <string name="home" msgid="7658288663002113681">"Pagrindinis"</string>
- <string name="uid_name" msgid="7820867637514617527">"Pagrindinės „Android“ programos"</string>
<string name="folder_name" msgid="7371454440695724752"></string>
+ <string name="work_folder_name" msgid="3753320833950115786">"Darbas"</string>
<string name="activity_not_found" msgid="8071924732094499514">"Programa neįdiegta."</string>
<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="widgets_tab_label" msgid="2921133187116603919">"Valdikliai"</string>
- <string name="widget_adder" msgid="3201040140710381657">"Valdikliai"</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="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
- <string name="external_drop_widget_error" msgid="3165821058322217155">"Nepavyko nuvilkti elemento į šį pagrindinį ekraną."</string>
- <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Pasirinkite norimą kurti valdiklį"</string>
- <string name="rename_folder_label" msgid="3727762225964550653">"Aplanko pavadinimas"</string>
- <string name="rename_folder_title" msgid="3771389277707820891">"Pervardyti aplanką"</string>
- <string name="rename_action" msgid="5559600076028658757">"Gerai"</string>
- <string name="cancel_action" msgid="7009134900002915310">"Atšaukti"</string>
- <string name="menu_item_add_item" msgid="1264911265836810421">"Pridėti prie pagrindinio ekrano"</string>
- <string name="group_applications" msgid="3797214114206693605">"Programos"</string>
- <string name="group_shortcuts" msgid="6012256992764410535">"Spartieji klavišai"</string>
- <string name="group_widgets" msgid="1569030723286851002">"Valdikliai"</string>
- <string name="completely_out_of_space" msgid="6106288382070760318">"Pagrindiniuose ekranuose vietos nebėra."</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>
+ <string name="all_apps_no_search_results" msgid="6332185285860416787">"Nerasta jokių užklausą „<xliff:g id="QUERY">%1$s</xliff:g>“ atitinkančių programų"</string>
<string name="out_of_space" msgid="4691004494942118364">"Šiame pagrindiniame ekrane vietos nebėra."</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"Mėgstamiausių dėkle nebėra vietos"</string>
- <string name="invalid_hotseat_item" msgid="5779907847267573691">"Mėgstamiausių dėklui šis valdiklis per didelis."</string>
- <string name="shortcut_installed" msgid="1701742129426969556">"Spartusis klavišas „<xliff:g id="NAME">%s</xliff:g>“ sukurtas."</string>
- <string name="shortcut_uninstalled" msgid="8176767991305701821">"Spartusis klavišas „<xliff:g id="NAME">%s</xliff:g>“ pašalintas."</string>
- <string name="shortcut_duplicate" msgid="9167217446062498127">"Spartusis klavišas „<xliff:g id="NAME">%s</xliff:g>“ jau yra."</string>
- <string name="title_select_shortcut" msgid="6680642571148153868">"Pasirinkite spartųjį klavišą"</string>
- <string name="title_select_application" msgid="3280812711670683644">"Pasirinkite programą"</string>
<string name="all_apps_button_label" msgid="9110807029020582876">"Programos"</string>
<string name="all_apps_home_button_label" msgid="252062713717058851">"Pagrindinis"</string>
- <string name="delete_zone_label_workspace" msgid="4009607676751398685">"Pašalinti"</string>
- <string name="delete_zone_label_all_apps" msgid="8083826390278958980">"Pašalinti"</string>
<string name="delete_target_label" msgid="1822697352535677073">"Pašalinti"</string>
<string name="delete_target_uninstall_label" msgid="5100785476250872595">"Pašalinti"</string>
<string name="info_target_label" msgid="8053346143994679532">"Programos informacija"</string>
- <string name="accessibility_all_apps_button" msgid="2603132375383800483">"Programos"</string>
- <string name="accessibility_delete_button" msgid="6466114477993744621">"Pašalinti"</string>
- <string name="delete_zone_label_all_apps_system_app" msgid="449755632749610895">"Pašalinti naujinį"</string>
- <string name="cab_menu_delete_app" msgid="7435191475867183689">"Pašalinti programą"</string>
- <string name="cab_menu_app_info" msgid="8593722221450362342">"Išsami programos informacija"</string>
- <string name="cab_app_selection_text" msgid="374688303047985416">"Pasirinkta 1 programa"</string>
- <string name="cab_widget_selection_text" msgid="1833458597831541241">"Pasirinktas 1 valdiklis"</string>
- <string name="cab_folder_selection_text" msgid="7999992513806132118">"Pasirinktas 1 aplankas"</string>
- <string name="cab_shortcut_selection_text" msgid="2103811025667946450">"Pasirinktas 1 spartusis klavišas"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"įdiegti sparčiuosius klavišus"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"Programai leidžiama pridėti sparčiuosius klavišus be naudotojo įsikišimo."</string>
- <string name="permlab_uninstall_shortcut" msgid="864595034498083837">"pašalinti sparčiuosius klavišus"</string>
- <string name="permdesc_uninstall_shortcut" msgid="5134129545001836849">"Programai leidžiama pašalinti sparčiuosius klavišus be naudotojo įsikišimo."</string>
<string name="permlab_read_settings" msgid="1941457408239617576">"skaityti pagrindinio puslapio nustatymus ir sparčiuosius klavišus"</string>
<string name="permdesc_read_settings" msgid="5833423719057558387">"Programai leidžiama skaityti pagrindinio puslapio nustatymus ir sparčiuosius klavišus."</string>
<string name="permlab_write_settings" msgid="3574213698004620587">"rašyti pagrindinio puslapio nustatymus ir sparčiuosius klavišus"</string>
@@ -78,30 +48,17 @@
<string name="gadget_error_text" msgid="6081085226050792095">"Problema įkeliant valdiklį"</string>
<string name="gadget_setup_text" msgid="8274003207686040488">"Sąranka"</string>
<string name="uninstall_system_app_text" msgid="4172046090762920660">"Tai sistemos programa ir jos negalima pašalinti."</string>
- <string name="dream_name" msgid="1530253749244328964">"Rocket Launcher"</string>
<string name="folder_hint_text" msgid="6617836969016293992">"Aplankas be pavadinimo"</string>
- <string name="workspace_description_format" msgid="2950174241104043327">"%1$d pagrindinis ekranas"</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="apps_customize_apps_scroll_format" msgid="370005296147130238">"%1$d programų psl. iš %2$d"</string>
- <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"%1$d valdiklių psl. iš %2$d"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"Sveiki"</string>
- <string name="first_run_cling_description" msgid="6447072552696253358">"Jauskitės kaip namie."</string>
- <string name="first_run_cling_custom_content_hint" msgid="6090628589029352439"></string>
- <string name="first_run_cling_search_bar_hint" msgid="5909062802402452582"></string>
- <string name="first_run_cling_create_screens_hint" msgid="6950729526680114157">"Sukurkite daugiau programų ir aplankų ekrano kopijų"</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>
<string name="migration_cling_copy_apps" msgid="946331230090919440">"KOPIJUOTI PIKTOGRAMAS"</string>
<string name="migration_cling_use_default" msgid="2626475813981258626">"PRADĖTI IŠ NAUJO"</string>
- <string name="workspace_cling_title" msgid="5626202359865825661">"Tvarkykite savo vietą"</string>
- <string name="workspace_cling_move_item" msgid="528201129978005352">"Palieskite ir laikykite foną, jei norite tvarkyti ekrano foną, valdiklius ir nustatymus."</string>
<string name="workspace_cling_longpress_title" msgid="9173998993909018310">"Ekrano fonai, valdikliai ir nustatymai"</string>
<string name="workspace_cling_longpress_description" msgid="4119994475505235248">"Jei norite tinkinti, palieskite ir palaikykite foną"</string>
<string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"SUPRATAU"</string>
- <string name="folder_cling_title" msgid="3894908818693254164">"Štai aplankas"</string>
- <string name="folder_cling_create_folder" msgid="6158215559475836131">"Kad sukurtumėte tokį patį, palieskite ir laikykite programą, tada perkelkite ją virš kitos programos."</string>
- <string name="cling_dismiss" msgid="8962359497601507581">"Gerai"</string>
<string name="folder_opened" msgid="94695026776264709">"Atidarytas aplankas, <xliff:g id="WIDTH">%1$d</xliff:g> ir <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
<string name="folder_tap_to_close" msgid="1884479294466410023">"Palieskite, kad uždarytumėte aplanką"</string>
<string name="folder_tap_to_rename" msgid="9191075570492871147">"Palieskite, kad išsaugotumėte naują pavadinimą"</string>
@@ -111,14 +68,34 @@
<string name="widget_button_text" msgid="2880537293434387943">"Valdikliai"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"Ekrano fonai"</string>
<string name="settings_button_text" msgid="8119458837558863227">"Nustatymai"</string>
- <string name="package_state_enqueued" msgid="6227252464303085641">"Laukiama"</string>
- <string name="package_state_downloading" msgid="4088770468458724721">"Atsisiunčiama"</string>
- <string name="package_state_installing" msgid="7588193972189849870">"Diegiama"</string>
+ <string name="allow_rotation_title" msgid="2118706734511831751">"Leisti kaitaliojimą"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Nežinoma"</string>
- <string name="package_state_error" msgid="7672093962724223588">"Neatkurta"</string>
- <string name="abandoned_clean_all" msgid="5256770727689657618">"Pašalinti viską"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Pašalinti"</string>
<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="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>
+ <string name="item_removed" msgid="851119963877842327">"Elementas perkeltas"</string>
+ <string name="action_move" msgid="4339390619886385032">"Perkelti elementą"</string>
+ <string name="move_to_empty_cell" msgid="2833711483015685619">"Perkelti į <xliff:g id="NUMBER_0">%1$s</xliff:g> eilutę, <xliff:g id="NUMBER_1">%2$s</xliff:g> stulpelį"</string>
+ <string name="move_to_position" msgid="6750008980455459790">"Perkelti į <xliff:g id="NUMBER">%1$s</xliff:g> poziciją"</string>
+ <string name="move_to_hotseat_position" msgid="6295412897075147808">"Perkelti į <xliff:g id="NUMBER">%1$s</xliff:g> mėgstamiausių poziciją"</string>
+ <string name="item_moved" msgid="4606538322571412879">"Elementas perkeltas"</string>
+ <string name="add_to_folder" msgid="9040534766770853243">"Pridėti prie aplanko: „<xliff:g id="NAME">%1$s</xliff:g>“"</string>
+ <string name="add_to_folder_with_app" msgid="4534929978967147231">"Pridėti prie aplanko su „<xliff:g id="NAME">%1$s</xliff:g>“"</string>
+ <string name="added_to_folder" msgid="4793259502305558003">"Elementas pridėtas prie aplanko"</string>
+ <string name="create_folder_with" msgid="4050141361160214248">"Kurti aplanką naudojant: „<xliff:g id="NAME">%1$s</xliff:g>“"</string>
+ <string name="folder_created" msgid="6409794597405184510">"Aplankas sukurtas"</string>
+ <string name="action_move_to_workspace" msgid="1603837886334246317">"Perkelti į pagrindinį ekraną"</string>
+ <string name="action_move_screen_left" msgid="8854216831569401665">"Perkelti ekraną į kairę"</string>
+ <string name="action_move_screen_right" msgid="329334910274311123">"Perkelti ekraną į dešinę"</string>
+ <string name="screen_moved" msgid="266230079505650577">"Ekranas perkeltas"</string>
+ <string name="action_resize" msgid="1802976324781771067">"Pakeisti dydį"</string>
+ <string name="action_increase_width" msgid="8773715375078513326">"Padidinti plotį"</string>
+ <string name="action_increase_height" msgid="459390020612501122">"Padidinti aukštį"</string>
+ <string name="action_decrease_width" msgid="1374549771083094654">"Sumažinti plotį"</string>
+ <string name="action_decrease_height" msgid="282377193880900022">"Sumažinti aukštį"</string>
+ <string name="widget_resized" msgid="9130327887929620">"Valdiklio dydis pakeistas: plotis – <xliff:g id="NUMBER_0">%1$s</xliff:g>, aukštis – <xliff:g id="NUMBER_1">%2$s</xliff:g>"</string>
</resources>
diff --git a/res/values-lv/strings.xml b/res/values-lv/strings.xml
index 13a47606d..432bda443 100644
--- a/res/values-lv/strings.xml
+++ b/res/values-lv/strings.xml
@@ -20,57 +20,27 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="application_name" msgid="5181331383435256801">"Launcher3"</string>
- <string name="home" msgid="7658288663002113681">"Sākums"</string>
- <string name="uid_name" msgid="7820867637514617527">"Android pamatlietotnes"</string>
<string name="folder_name" msgid="7371454440695724752"></string>
+ <string name="work_folder_name" msgid="3753320833950115786">"Darbs"</string>
<string name="activity_not_found" msgid="8071924732094499514">"Lietotne nav instalēta."</string>
<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="widgets_tab_label" msgid="2921133187116603919">"Logrīki"</string>
- <string name="widget_adder" msgid="3201040140710381657">"Logrīki"</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="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
- <string name="external_drop_widget_error" msgid="3165821058322217155">"Nevarēja nomest vienumu šajā sākuma ekrānā."</string>
- <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Izveidojamā logrīka izvēle"</string>
- <string name="rename_folder_label" msgid="3727762225964550653">"Mapes nosaukums"</string>
- <string name="rename_folder_title" msgid="3771389277707820891">"Mapes pārdēvēšana"</string>
- <string name="rename_action" msgid="5559600076028658757">"Labi"</string>
- <string name="cancel_action" msgid="7009134900002915310">"Atcelt"</string>
- <string name="menu_item_add_item" msgid="1264911265836810421">"Pievienošana sākuma ekrānam"</string>
- <string name="group_applications" msgid="3797214114206693605">"Lietotnes"</string>
- <string name="group_shortcuts" msgid="6012256992764410535">"Saīsnes"</string>
- <string name="group_widgets" msgid="1569030723286851002">"Logrīki"</string>
- <string name="completely_out_of_space" msgid="6106288382070760318">"Sākuma ekrānos vairs nav vietas."</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>
+ <string name="all_apps_no_search_results" msgid="6332185285860416787">"Vaicājumam “<xliff:g id="QUERY">%1$s</xliff:g>” neatbilda neviena lietotne."</string>
<string name="out_of_space" msgid="4691004494942118364">"Šajā sākuma ekrānā vairs nav vietas."</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"Izlases joslā vairs nav vietas."</string>
- <string name="invalid_hotseat_item" msgid="5779907847267573691">"Šis logrīks ir pārāk liels izlases joslai."</string>
- <string name="shortcut_installed" msgid="1701742129426969556">"Tika izveidota saīsne “<xliff:g id="NAME">%s</xliff:g>”."</string>
- <string name="shortcut_uninstalled" msgid="8176767991305701821">"Tika noņemta saīsne “<xliff:g id="NAME">%s</xliff:g>”."</string>
- <string name="shortcut_duplicate" msgid="9167217446062498127">"Saīsne “<xliff:g id="NAME">%s</xliff:g>” jau pastāv."</string>
- <string name="title_select_shortcut" msgid="6680642571148153868">"Saīsnes izvēle"</string>
- <string name="title_select_application" msgid="3280812711670683644">"Lietotnes izvēle"</string>
<string name="all_apps_button_label" msgid="9110807029020582876">"Lietotnes"</string>
<string name="all_apps_home_button_label" msgid="252062713717058851">"Sākums"</string>
- <string name="delete_zone_label_workspace" msgid="4009607676751398685">"Noņemt"</string>
- <string name="delete_zone_label_all_apps" msgid="8083826390278958980">"Atinstalēt"</string>
<string name="delete_target_label" msgid="1822697352535677073">"Noņemt"</string>
<string name="delete_target_uninstall_label" msgid="5100785476250872595">"Atinstalēt"</string>
<string name="info_target_label" msgid="8053346143994679532">"Lietotnes informācija"</string>
- <string name="accessibility_all_apps_button" msgid="2603132375383800483">"Lietotnes"</string>
- <string name="accessibility_delete_button" msgid="6466114477993744621">"Noņemt"</string>
- <string name="delete_zone_label_all_apps_system_app" msgid="449755632749610895">"Atinstalēt atjauninājumu"</string>
- <string name="cab_menu_delete_app" msgid="7435191475867183689">"Atinstalēt lietotni"</string>
- <string name="cab_menu_app_info" msgid="8593722221450362342">"Lietotnes informācija"</string>
- <string name="cab_app_selection_text" msgid="374688303047985416">"Atlasīta 1 lietotne"</string>
- <string name="cab_widget_selection_text" msgid="1833458597831541241">"Atlasīts 1 logrīks"</string>
- <string name="cab_folder_selection_text" msgid="7999992513806132118">"Atlasīta 1 mape"</string>
- <string name="cab_shortcut_selection_text" msgid="2103811025667946450">"Atlasīta 1 saīsne"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"instalēt saīsnes"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"Ļauj lietotnei pievienot saīsnes, nejautājot lietotājam."</string>
- <string name="permlab_uninstall_shortcut" msgid="864595034498083837">"atinstalēt saīsnes"</string>
- <string name="permdesc_uninstall_shortcut" msgid="5134129545001836849">"Ļauj lietotnei noņemt saīsnes, nejautājot lietotājam."</string>
<string name="permlab_read_settings" msgid="1941457408239617576">"lasīt sākuma ekrāna iestatījumus un saīsnes"</string>
<string name="permdesc_read_settings" msgid="5833423719057558387">"Ļauj lietotnei lasīt iestatījumus un saīsnes sākuma ekrānā."</string>
<string name="permlab_write_settings" msgid="3574213698004620587">"rakstīt sākuma ekrāna iestatījumus un saīsnes"</string>
@@ -78,30 +48,17 @@
<string name="gadget_error_text" msgid="6081085226050792095">"Ielādējot logrīku, radās problēma."</string>
<string name="gadget_setup_text" msgid="8274003207686040488">"Notiek iestatīšana"</string>
<string name="uninstall_system_app_text" msgid="4172046090762920660">"Šī ir sistēmas lietotne, un to nevar atinstalēt."</string>
- <string name="dream_name" msgid="1530253749244328964">"Rocket Launcher"</string>
<string name="folder_hint_text" msgid="6617836969016293992">"Mape bez nosaukuma"</string>
- <string name="workspace_description_format" msgid="2950174241104043327">"Sākuma ekrāns: %1$d"</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="apps_customize_apps_scroll_format" msgid="370005296147130238">"%1$d. lietotņu lapa no %2$d"</string>
- <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"%1$d. logrīku lapa no %2$d"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"Laipni lūdzam!"</string>
- <string name="first_run_cling_description" msgid="6447072552696253358">"Informācija par pamatfunkcijām"</string>
- <string name="first_run_cling_custom_content_hint" msgid="6090628589029352439"></string>
- <string name="first_run_cling_search_bar_hint" msgid="5909062802402452582"></string>
- <string name="first_run_cling_create_screens_hint" msgid="6950729526680114157">"Izveidojiet vairāk ekrānu lietotnēm un mapēm."</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>
<string name="migration_cling_copy_apps" msgid="946331230090919440">"KOPĒT IKONAS"</string>
<string name="migration_cling_use_default" msgid="2626475813981258626">"SĀKT NO SĀKUMA"</string>
- <string name="workspace_cling_title" msgid="5626202359865825661">"Kārtojiet savu darbvietu"</string>
- <string name="workspace_cling_move_item" msgid="528201129978005352">"Pieskarieties fonam un turiet to, lai pārvaldītu fona tapeti, logrīkus un iestatījumus."</string>
<string name="workspace_cling_longpress_title" msgid="9173998993909018310">"Fona tapetes, logrīki un iestatījumi"</string>
<string name="workspace_cling_longpress_description" msgid="4119994475505235248">"Lai pielāgotu, pieskarieties fonam un turiet to nospiestu."</string>
<string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"SAPRATU!"</string>
- <string name="folder_cling_title" msgid="3894908818693254164">"Lūk, mape!"</string>
- <string name="folder_cling_create_folder" msgid="6158215559475836131">"Lai izveidotu tādu pašu, pieskarieties lietotnei un turiet to, pēc tam pārvietojiet to virs citas lietotnes."</string>
- <string name="cling_dismiss" msgid="8962359497601507581">"Labi"</string>
<string name="folder_opened" msgid="94695026776264709">"Atvērta mape: <xliff:g id="WIDTH">%1$d</xliff:g> x <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
<string name="folder_tap_to_close" msgid="1884479294466410023">"Pieskarieties, lai aizvērtu mapi."</string>
<string name="folder_tap_to_rename" msgid="9191075570492871147">"Pieskarieties, lai saglabātu pārdēvēto nosaukumu."</string>
@@ -111,14 +68,34 @@
<string name="widget_button_text" msgid="2880537293434387943">"Logrīki"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"Fona tapetes"</string>
<string name="settings_button_text" msgid="8119458837558863227">"Iestatījumi"</string>
- <string name="package_state_enqueued" msgid="6227252464303085641">"Gaida"</string>
- <string name="package_state_downloading" msgid="4088770468458724721">"Lejupielādē"</string>
- <string name="package_state_installing" msgid="7588193972189849870">"Instalē"</string>
+ <string name="allow_rotation_title" msgid="2118706734511831751">"Rotācijas atļauja"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Nezināma"</string>
- <string name="package_state_error" msgid="7672093962724223588">"Nav atjaunota"</string>
- <string name="abandoned_clean_all" msgid="5256770727689657618">"Noņemt visas"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Noņemt"</string>
<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="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>
+ <string name="item_removed" msgid="851119963877842327">"Vienums noņemts"</string>
+ <string name="action_move" msgid="4339390619886385032">"Pārvietot vienumu"</string>
+ <string name="move_to_empty_cell" msgid="2833711483015685619">"Pārvietot uz <xliff:g id="NUMBER_0">%1$s</xliff:g>. rindu, <xliff:g id="NUMBER_1">%2$s</xliff:g>. kolonnu"</string>
+ <string name="move_to_position" msgid="6750008980455459790">"Pārvietot uz <xliff:g id="NUMBER">%1$s</xliff:g>. pozīciju"</string>
+ <string name="move_to_hotseat_position" msgid="6295412897075147808">"Pārvietot uz <xliff:g id="NUMBER">%1$s</xliff:g>. izlases pozīciju"</string>
+ <string name="item_moved" msgid="4606538322571412879">"Vienums pārvietots"</string>
+ <string name="add_to_folder" msgid="9040534766770853243">"Pievienot mapei: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="add_to_folder_with_app" msgid="4534929978967147231">"Pievienot mapei, kurā ir <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="added_to_folder" msgid="4793259502305558003">"Vienums pievienots mapei"</string>
+ <string name="create_folder_with" msgid="4050141361160214248">"Izveidot mapi ar: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="folder_created" msgid="6409794597405184510">"Mape izveidota"</string>
+ <string name="action_move_to_workspace" msgid="1603837886334246317">"Pārvietot uz sākuma ekrānu"</string>
+ <string name="action_move_screen_left" msgid="8854216831569401665">"Pārvietot ekrānu pa kreisi"</string>
+ <string name="action_move_screen_right" msgid="329334910274311123">"Pārvietot ekrānu pa labi"</string>
+ <string name="screen_moved" msgid="266230079505650577">"Ekrāns pārvietots"</string>
+ <string name="action_resize" msgid="1802976324781771067">"Mainīt lielumu"</string>
+ <string name="action_increase_width" msgid="8773715375078513326">"Palielināt platumu"</string>
+ <string name="action_increase_height" msgid="459390020612501122">"Palielināt augstumu"</string>
+ <string name="action_decrease_width" msgid="1374549771083094654">"Samazināt platumu"</string>
+ <string name="action_decrease_height" msgid="282377193880900022">"Samazināt augstumu"</string>
+ <string name="widget_resized" msgid="9130327887929620">"Logrīka lielums mainīts — platums: <xliff:g id="NUMBER_0">%1$s</xliff:g>, augstums: <xliff:g id="NUMBER_1">%2$s</xliff:g>."</string>
</resources>
diff --git a/res/values-mk-rMK/strings.xml b/res/values-mk-rMK/strings.xml
index dcc55d7b7..8c276e3f0 100644
--- a/res/values-mk-rMK/strings.xml
+++ b/res/values-mk-rMK/strings.xml
@@ -20,57 +20,27 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="application_name" msgid="5181331383435256801">"Launcher3"</string>
- <string name="home" msgid="7658288663002113681">"Почетна страница"</string>
- <string name="uid_name" msgid="7820867637514617527">"Основни апликации на Android"</string>
<string name="folder_name" msgid="7371454440695724752"></string>
+ <string name="work_folder_name" msgid="3753320833950115786">"Работа"</string>
<string name="activity_not_found" msgid="8071924732094499514">"Апликацијата не е инсталирана."</string>
<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="widgets_tab_label" msgid="2921133187116603919">"Виџети"</string>
- <string name="widget_adder" msgid="3201040140710381657">"Виџети"</string>
<string name="toggle_weight_watcher" msgid="5645299835184636119">"Прикажи „Мени“"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"Допри и задржи за да се избере виџетот."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
- <string name="external_drop_widget_error" msgid="3165821058322217155">"Не можеше да се спушти елемент на овој екран на почетната страница."</string>
- <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Избери виџет за да се создаде"</string>
- <string name="rename_folder_label" msgid="3727762225964550653">"Име на папка"</string>
- <string name="rename_folder_title" msgid="3771389277707820891">"Преименувај папка"</string>
- <string name="rename_action" msgid="5559600076028658757">"Во ред"</string>
- <string name="cancel_action" msgid="7009134900002915310">"Откажи"</string>
- <string name="menu_item_add_item" msgid="1264911265836810421">"Додај во екран на почетна страница"</string>
- <string name="group_applications" msgid="3797214114206693605">"Апликации"</string>
- <string name="group_shortcuts" msgid="6012256992764410535">"Кратенки"</string>
- <string name="group_widgets" msgid="1569030723286851002">"Виџети"</string>
- <string name="completely_out_of_space" msgid="6106288382070760318">"Нема повеќе простор на вашите екрани на почетна страница."</string>
+ <string name="all_apps_search_bar_hint" msgid="7084713969757597256">"Пребарување апликации"</string>
+ <string name="all_apps_loading_message" msgid="7557140873644765180">"Се вчитуваат апликации…"</string>
+ <string name="all_apps_no_search_results" msgid="6332185285860416787">"Не се најдени апликации што одговараат на „<xliff:g id="QUERY">%1$s</xliff:g>“"</string>
<string name="out_of_space" msgid="4691004494942118364">"Нема повеќе простор на овој екран на почетната страница."</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"Нема повеќе простор на лентата „Омилени“"</string>
- <string name="invalid_hotseat_item" msgid="5779907847267573691">"Овој виџет е премногу голем за лентата „Омилени“"</string>
- <string name="shortcut_installed" msgid="1701742129426969556">"Кратенката „<xliff:g id="NAME">%s</xliff:g>“ е создадена."</string>
- <string name="shortcut_uninstalled" msgid="8176767991305701821">"Кратенката „<xliff:g id="NAME">%s</xliff:g>“ е отстранета."</string>
- <string name="shortcut_duplicate" msgid="9167217446062498127">"Кратенката „<xliff:g id="NAME">%s</xliff:g>“ веќе постои."</string>
- <string name="title_select_shortcut" msgid="6680642571148153868">"Избери кратенка"</string>
- <string name="title_select_application" msgid="3280812711670683644">"Избери апликација"</string>
<string name="all_apps_button_label" msgid="9110807029020582876">"Апликации"</string>
<string name="all_apps_home_button_label" msgid="252062713717058851">"Почетна страница"</string>
- <string name="delete_zone_label_workspace" msgid="4009607676751398685">"Отстрани"</string>
- <string name="delete_zone_label_all_apps" msgid="8083826390278958980">"Деинсталирај"</string>
<string name="delete_target_label" msgid="1822697352535677073">"Отстрани"</string>
<string name="delete_target_uninstall_label" msgid="5100785476250872595">"Деинсталирај"</string>
<string name="info_target_label" msgid="8053346143994679532">"Информации за апликацијата"</string>
- <string name="accessibility_all_apps_button" msgid="2603132375383800483">"Апликации"</string>
- <string name="accessibility_delete_button" msgid="6466114477993744621">"Отстрани"</string>
- <string name="delete_zone_label_all_apps_system_app" msgid="449755632749610895">"Деинсталирај ажурирање"</string>
- <string name="cab_menu_delete_app" msgid="7435191475867183689">"Деинсталирај апликација"</string>
- <string name="cab_menu_app_info" msgid="8593722221450362342">"Детали за апликација"</string>
- <string name="cab_app_selection_text" msgid="374688303047985416">"1 апликација е избрана"</string>
- <string name="cab_widget_selection_text" msgid="1833458597831541241">"1 виџет е избран"</string>
- <string name="cab_folder_selection_text" msgid="7999992513806132118">"1 папка е избрана"</string>
- <string name="cab_shortcut_selection_text" msgid="2103811025667946450">"1 кратенка е избрана"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"инсталирај кратенки"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"Овозможува апликацијата да додава кратенки без интервенција на корисникот."</string>
- <string name="permlab_uninstall_shortcut" msgid="864595034498083837">"деинсталирај кратенки"</string>
- <string name="permdesc_uninstall_shortcut" msgid="5134129545001836849">"Овозможува апликацијата да ги отстрани кратенките без интервенција на корисникот."</string>
<string name="permlab_read_settings" msgid="1941457408239617576">"прочитај подесувања и кратенки на почетна страница"</string>
<string name="permdesc_read_settings" msgid="5833423719057558387">"Овозможува апликацијата да ги менува подесувањата и кратенките на почетната страница."</string>
<string name="permlab_write_settings" msgid="3574213698004620587">"напиши подесувања и кратенки на почетна страница"</string>
@@ -78,30 +48,17 @@
<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>
- <string name="dream_name" msgid="1530253749244328964">"Rocket Launcher"</string>
<string name="folder_hint_text" msgid="6617836969016293992">"Неименувана папка"</string>
- <string name="workspace_description_format" msgid="2950174241104043327">"Екран на почетна страница %1$d"</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="apps_customize_apps_scroll_format" msgid="370005296147130238">"Страница на апликации %1$d од %2$d"</string>
- <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"Страница на виџети %1$d од %2$d"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"Добредојдовте"</string>
- <string name="first_run_cling_description" msgid="6447072552696253358">"Чувствувајте се како дома."</string>
- <string name="first_run_cling_custom_content_hint" msgid="6090628589029352439"></string>
- <string name="first_run_cling_search_bar_hint" msgid="5909062802402452582"></string>
- <string name="first_run_cling_create_screens_hint" msgid="6950729526680114157">"Создади повеќе екрани за апликации и папки"</string>
<string name="migration_cling_title" msgid="9181776667882933767">"Копирај икони за апликација"</string>
<string name="migration_cling_description" msgid="2752413805582227644">"Зачувај икони и папки од твоите стари почетни страни?"</string>
<string name="migration_cling_copy_apps" msgid="946331230090919440">"КОПИРАЈ ИКОНИ"</string>
<string name="migration_cling_use_default" msgid="2626475813981258626">"СТАРТУВАЈ ОД ПОЧЕТОК"</string>
- <string name="workspace_cling_title" msgid="5626202359865825661">"Организирајте го вашиот простор"</string>
- <string name="workspace_cling_move_item" msgid="528201129978005352">"Допри и задржи ја заднината за управување со тапети, виџети и подесувања."</string>
<string name="workspace_cling_longpress_title" msgid="9173998993909018310">"Тапети, додатоци и поставки"</string>
<string name="workspace_cling_longpress_description" msgid="4119994475505235248">"Допрете и задржете на заднината за да приспособите"</string>
<string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"СФАТИВ"</string>
- <string name="folder_cling_title" msgid="3894908818693254164">"Еве папка"</string>
- <string name="folder_cling_create_folder" msgid="6158215559475836131">"За да создадете ваква, допрете и држете ја апликацијата, а потоа поместете ја врз другата."</string>
- <string name="cling_dismiss" msgid="8962359497601507581">"Во ред"</string>
<string name="folder_opened" msgid="94695026776264709">"Отворена е папка, <xliff:g id="WIDTH">%1$d</xliff:g> на <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
<string name="folder_tap_to_close" msgid="1884479294466410023">"Допри за да се затвори папката"</string>
<string name="folder_tap_to_rename" msgid="9191075570492871147">"Допри за да се зачува преименувањето"</string>
@@ -111,14 +68,34 @@
<string name="widget_button_text" msgid="2880537293434387943">"Виџети"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"Тапети"</string>
<string name="settings_button_text" msgid="8119458837558863227">"Подесувања"</string>
- <string name="package_state_enqueued" msgid="6227252464303085641">"На чекање"</string>
- <string name="package_state_downloading" msgid="4088770468458724721">"Се презема"</string>
- <string name="package_state_installing" msgid="7588193972189849870">"Се инсталира"</string>
+ <string name="allow_rotation_title" msgid="2118706734511831751">"Дозволи ротација"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Непознато"</string>
- <string name="package_state_error" msgid="7672093962724223588">"Не е обновено"</string>
- <string name="abandoned_clean_all" msgid="5256770727689657618">"Отстрани ги сите"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Отстрани"</string>
<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="action_add_to_workspace" msgid="8902165848117513641">"Додај на Почетен екран"</string>
+ <string name="action_move_here" msgid="2170188780612570250">"Премести ја ставката овде"</string>
+ <string name="item_added_to_workspace" msgid="4211073925752213539">"Ставката е додадена на почетниот екран"</string>
+ <string name="item_removed" msgid="851119963877842327">"Ставката е отстранета"</string>
+ <string name="action_move" msgid="4339390619886385032">"Премести ја ставката"</string>
+ <string name="move_to_empty_cell" msgid="2833711483015685619">"Премести во ред <xliff:g id="NUMBER_0">%1$s</xliff:g> колона <xliff:g id="NUMBER_1">%2$s</xliff:g>"</string>
+ <string name="move_to_position" msgid="6750008980455459790">"Премести на место <xliff:g id="NUMBER">%1$s</xliff:g>"</string>
+ <string name="move_to_hotseat_position" msgid="6295412897075147808">"Премести на место <xliff:g id="NUMBER">%1$s</xliff:g> во омилени"</string>
+ <string name="item_moved" msgid="4606538322571412879">"Ставката е преместена"</string>
+ <string name="add_to_folder" msgid="9040534766770853243">"Додај во папката: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="add_to_folder_with_app" msgid="4534929978967147231">"Додај во папка со <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="added_to_folder" msgid="4793259502305558003">"Ставката е додадена во папката"</string>
+ <string name="create_folder_with" msgid="4050141361160214248">"Создај папка со: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="folder_created" msgid="6409794597405184510">"Папката е создадена"</string>
+ <string name="action_move_to_workspace" msgid="1603837886334246317">"Премести на Почетен екран"</string>
+ <string name="action_move_screen_left" msgid="8854216831569401665">"Движи го екранот налево"</string>
+ <string name="action_move_screen_right" msgid="329334910274311123">"Движи го екранот надесно"</string>
+ <string name="screen_moved" msgid="266230079505650577">"Екранот е преместен"</string>
+ <string name="action_resize" msgid="1802976324781771067">"Промени големина"</string>
+ <string name="action_increase_width" msgid="8773715375078513326">"Зголеми ширина"</string>
+ <string name="action_increase_height" msgid="459390020612501122">"Зголеми висина"</string>
+ <string name="action_decrease_width" msgid="1374549771083094654">"Намали ширина"</string>
+ <string name="action_decrease_height" msgid="282377193880900022">"Намали висина"</string>
+ <string name="widget_resized" msgid="9130327887929620">"Големината на виџетот е променета на ширина <xliff:g id="NUMBER_0">%1$s</xliff:g> висина <xliff:g id="NUMBER_1">%2$s</xliff:g>"</string>
</resources>
diff --git a/res/values-ml-rIN/strings.xml b/res/values-ml-rIN/strings.xml
index 87788442d..59ad153a8 100644
--- a/res/values-ml-rIN/strings.xml
+++ b/res/values-ml-rIN/strings.xml
@@ -20,57 +20,27 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="application_name" msgid="5181331383435256801">"Launcher3"</string>
- <string name="home" msgid="7658288663002113681">"ഹോം"</string>
- <string name="uid_name" msgid="7820867637514617527">"Android Core അപ്ലിക്കേഷനുകൾ"</string>
<string name="folder_name" msgid="7371454440695724752"></string>
+ <string name="work_folder_name" msgid="3753320833950115786">"ഔദ്യോഗികം"</string>
<string name="activity_not_found" msgid="8071924732094499514">"അപ്ലിക്കേഷൻ ഇൻസ്‌റ്റാളുചെ‌യ്‌തിട്ടില്ല."</string>
<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="widgets_tab_label" msgid="2921133187116603919">"വിജറ്റുകൾ"</string>
- <string name="widget_adder" msgid="3201040140710381657">"വിജറ്റുകൾ"</string>
<string name="toggle_weight_watcher" msgid="5645299835184636119">"മെമ്മറി കാണിക്കുക"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"ഒരു വിജറ്റ് ചേർക്കുന്നതിന് അത് സ്‌പർശിച്ച് പിടിക്കുക."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
- <string name="external_drop_widget_error" msgid="3165821058322217155">"ഹോം സ്‌ക്രീനിൽ ഇനം വലിച്ചിടാനായില്ല."</string>
- <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"സൃഷ്‌ടിക്കുന്നതിന് വിജറ്റ് തിരഞ്ഞെടുക്കുക"</string>
- <string name="rename_folder_label" msgid="3727762225964550653">"ഫോൾഡറിന്റെ പേര്"</string>
- <string name="rename_folder_title" msgid="3771389277707820891">"ഫോൾഡറിന്റെ പേരുമാറ്റുക"</string>
- <string name="rename_action" msgid="5559600076028658757">"ശരി"</string>
- <string name="cancel_action" msgid="7009134900002915310">"റദ്ദാക്കുക"</string>
- <string name="menu_item_add_item" msgid="1264911265836810421">"ഹോം സ്ക്രീനിൽ ചേർക്കുക"</string>
- <string name="group_applications" msgid="3797214114206693605">"അപ്ലിക്കേഷനുകൾ"</string>
- <string name="group_shortcuts" msgid="6012256992764410535">"കുറുക്കുവഴികൾ"</string>
- <string name="group_widgets" msgid="1569030723286851002">"വിജറ്റുകൾ"</string>
- <string name="completely_out_of_space" msgid="6106288382070760318">"നിങ്ങളുടെ ഹോം സ്‌ക്രീനുകളിൽ സ്ഥലമില്ല."</string>
+ <string name="all_apps_search_bar_hint" msgid="7084713969757597256">"ആപ്പ്‌സ് തിരയുക"</string>
+ <string name="all_apps_loading_message" msgid="7557140873644765180">"ആപ്പ്‌സ് ലോഡുചെയ്യുന്നു..."</string>
+ <string name="all_apps_no_search_results" msgid="6332185285860416787">"\"<xliff:g id="QUERY">%1$s</xliff:g>\" എന്നതുമായി പൊരുത്തപ്പെടുന്ന ആപ്പ്‌സൊന്നും കണ്ടെത്തിയില്ല"</string>
<string name="out_of_space" msgid="4691004494942118364">"ഈ ഹോം സ്‌ക്രീനിൽ ഒഴിവൊന്നുമില്ല."</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"പ്രിയപ്പെട്ടവയുടെ ട്രേയിൽ ഒഴിവൊന്നുമില്ല"</string>
- <string name="invalid_hotseat_item" msgid="5779907847267573691">"ഈ വിജറ്റ് പ്രിയപ്പെട്ടവയുടെ ട്രേയിൽ ഉൾക്കൊള്ളിക്കാവുന്നതിലും വളരെ വലുതാണ്"</string>
- <string name="shortcut_installed" msgid="1701742129426969556">"കുറുക്കുവഴി \"<xliff:g id="NAME">%s</xliff:g>\" സൃഷ്‌ടിച്ചു."</string>
- <string name="shortcut_uninstalled" msgid="8176767991305701821">"കുറുക്കുവഴി \"<xliff:g id="NAME">%s</xliff:g>\" നീക്കംചെയ്‌തു."</string>
- <string name="shortcut_duplicate" msgid="9167217446062498127">"കുറുക്കുവഴി \"<xliff:g id="NAME">%s</xliff:g>\" ഇതിനകം നിലവിലുണ്ട്."</string>
- <string name="title_select_shortcut" msgid="6680642571148153868">"കുറുക്കുവഴി തിരഞ്ഞെടുക്കുക"</string>
- <string name="title_select_application" msgid="3280812711670683644">"അപ്ലിക്കേഷൻ തിരഞ്ഞെടുക്കുക"</string>
<string name="all_apps_button_label" msgid="9110807029020582876">"അപ്ലിക്കേഷനുകൾ"</string>
<string name="all_apps_home_button_label" msgid="252062713717058851">"ഹോം"</string>
- <string name="delete_zone_label_workspace" msgid="4009607676751398685">"നീക്കംചെയ്യുക"</string>
- <string name="delete_zone_label_all_apps" msgid="8083826390278958980">"അണ്‍ഇസ്റ്റാളുചെയ്യുക"</string>
<string name="delete_target_label" msgid="1822697352535677073">"നീക്കംചെയ്യുക"</string>
<string name="delete_target_uninstall_label" msgid="5100785476250872595">"അണ്‍ഇസ്റ്റാളുചെയ്യുക"</string>
<string name="info_target_label" msgid="8053346143994679532">"ആപ്പ് വിവരം"</string>
- <string name="accessibility_all_apps_button" msgid="2603132375383800483">"അപ്ലിക്കേഷനുകൾ"</string>
- <string name="accessibility_delete_button" msgid="6466114477993744621">"നീക്കംചെയ്യുക"</string>
- <string name="delete_zone_label_all_apps_system_app" msgid="449755632749610895">"അപ്‌ഡേറ്റ് അൺഇൻസ്റ്റാളുചെയ്യുക"</string>
- <string name="cab_menu_delete_app" msgid="7435191475867183689">"അപ്ലിക്കേഷൻ അൺഇൻസ്റ്റാളുചെയ്യുക"</string>
- <string name="cab_menu_app_info" msgid="8593722221450362342">"അപ്ലിക്കേഷൻ വിശദാംശങ്ങൾ"</string>
- <string name="cab_app_selection_text" msgid="374688303047985416">"ഒരു അപ്ലിക്കേഷൻ തിരഞ്ഞെടുത്തു"</string>
- <string name="cab_widget_selection_text" msgid="1833458597831541241">"ഒരു വിജറ്റ് തിരഞ്ഞെടുത്തു"</string>
- <string name="cab_folder_selection_text" msgid="7999992513806132118">"ഒരു ഫോൾഡർ തിരഞ്ഞെടുത്തു"</string>
- <string name="cab_shortcut_selection_text" msgid="2103811025667946450">"ഒരു കുറുക്കുവഴി തിരഞ്ഞെടുത്തു"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"കുറുക്കുവഴികൾ ഇൻസ്റ്റാളുചെയ്യുക"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"ഉപയോക്തൃ ഇടപെടൽ ഇല്ലാതെ കുറുക്കുവഴികൾ ചേർക്കാൻ അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു."</string>
- <string name="permlab_uninstall_shortcut" msgid="864595034498083837">"കുറുക്കുവഴികൾ അൺഇൻസ്റ്റാളുചെയ്യുക"</string>
- <string name="permdesc_uninstall_shortcut" msgid="5134129545001836849">"ഉപയോക്തൃ ഇടപെടൽ ഇല്ലാതെ കുറുക്കുവഴികൾ നീക്കംചെയ്യാൻ അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു."</string>
<string name="permlab_read_settings" msgid="1941457408239617576">"ഹോം ക്രമീകരണങ്ങളും കുറുക്കുവഴികളും റീഡുചെയ്യുക"</string>
<string name="permdesc_read_settings" msgid="5833423719057558387">"ഹോമിലെ ക്രമീകരണങ്ങളും കുറുക്കുവഴികളും റീഡുചെയ്യാൻ അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു."</string>
<string name="permlab_write_settings" msgid="3574213698004620587">"ഹോം ക്രമീകരണങ്ങളും കുറുക്കുവഴികളും റൈറ്റുചെയ്യുക"</string>
@@ -78,30 +48,17 @@
<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>
- <string name="dream_name" msgid="1530253749244328964">"റോക്കറ്റ് ലോഞ്ചർ"</string>
<string name="folder_hint_text" msgid="6617836969016293992">"പേരുനൽകാത്ത ഫോൾഡർ"</string>
- <string name="workspace_description_format" msgid="2950174241104043327">"ഹോം സ്‌ക്രീൻ %1$d"</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="apps_customize_apps_scroll_format" msgid="370005296147130238">"അപ്ലിക്കേഷനുകളുടെ പേജ് %1$d / %2$d"</string>
- <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"വിജറ്റുകളുടെ പേജ് %1$d / %2$d"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"സ്വാഗതം"</string>
- <string name="first_run_cling_description" msgid="6447072552696253358">"ഹോം നിങ്ങളുടേതാക്കി മാറ്റുക."</string>
- <string name="first_run_cling_custom_content_hint" msgid="6090628589029352439"></string>
- <string name="first_run_cling_search_bar_hint" msgid="5909062802402452582"></string>
- <string name="first_run_cling_create_screens_hint" msgid="6950729526680114157">"അപ്ലിക്കേഷനുകൾക്കും ഫോൾഡറുകൾക്കും വേണ്ടി കൂടുതൽ സ്‌ക്രീനുകൾ സൃഷ്‌ടിക്കുക"</string>
<string name="migration_cling_title" msgid="9181776667882933767">"നിങ്ങളുടെ അപ്ലിക്കേഷൻ ഐക്കണുകൾ പകർത്തുക"</string>
<string name="migration_cling_description" msgid="2752413805582227644">"നിങ്ങളുടെ പഴയ ഹോം സ്ക്രീനുകളിൽ നിന്ന് ഐക്കണുകളും ഫോൾഡറുകളും ഇമ്പോർട്ടുചെയ്യണോ?"</string>
<string name="migration_cling_copy_apps" msgid="946331230090919440">"ഐക്കണുകൾ പകർത്തുക"</string>
<string name="migration_cling_use_default" msgid="2626475813981258626">"പുതുതായി ആരംഭിക്കുക"</string>
- <string name="workspace_cling_title" msgid="5626202359865825661">"നിങ്ങളുടെ ഇടം ഓർഗനൈസുചെയ്യുക"</string>
- <string name="workspace_cling_move_item" msgid="528201129978005352">"വാൾപേപ്പർ, വിജറ്റുകൾ, ക്രമീകരണങ്ങൾ എന്നിവ നിയന്ത്രിക്കുന്നതിന് പശ്ചാത്തലം സ്‌പർശിച്ച് പിടിക്കുക."</string>
<string name="workspace_cling_longpress_title" msgid="9173998993909018310">"വാൾപേപ്പറുകൾ, വിജറ്റുകൾ, ക്രമീകരണങ്ങൾ എന്നിവ"</string>
<string name="workspace_cling_longpress_description" msgid="4119994475505235248">"ഇഷ്‌ടാനുസൃതമാക്കുന്നതിന് പശ്‌ചാത്തലം സ്‌പർശിച്ചുപിടിക്കുക"</string>
<string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"മനസ്സിലായി"</string>
- <string name="folder_cling_title" msgid="3894908818693254164">"ഇവിടെയൊരു ഫോൾഡർ ഉണ്ട്"</string>
- <string name="folder_cling_create_folder" msgid="6158215559475836131">"ഇതുപോലൊന്ന് സൃഷ്‌ടിക്കുന്നതിന്, ഒരു അപ്ലിക്കേഷൻ സ്‌പർശിച്ച് പിടിച്ചുകൊണ്ട് അത് മറ്റൊന്നിലേക്ക് നീക്കുക."</string>
- <string name="cling_dismiss" msgid="8962359497601507581">"ശരി"</string>
<string name="folder_opened" msgid="94695026776264709">"ഫോൾഡർ തുറന്നു, <xliff:g id="WIDTH">%1$d</xliff:g> / <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
<string name="folder_tap_to_close" msgid="1884479294466410023">"ഫോൾഡർ അടയ്ക്കാൻ സ്‌പർശിക്കുക"</string>
<string name="folder_tap_to_rename" msgid="9191075570492871147">"പേരുമാറ്റം സംരക്ഷിക്കുന്നതിന് സ്‌പർശിക്കുക"</string>
@@ -111,14 +68,34 @@
<string name="widget_button_text" msgid="2880537293434387943">"വിജറ്റുകൾ"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"വാൾപേപ്പറുകൾ"</string>
<string name="settings_button_text" msgid="8119458837558863227">"ക്രമീകരണങ്ങൾ"</string>
- <string name="package_state_enqueued" msgid="6227252464303085641">"കാത്തിരിക്കുന്നു"</string>
- <string name="package_state_downloading" msgid="4088770468458724721">"ഡൗൺലോഡുചെയ്യുന്നു"</string>
- <string name="package_state_installing" msgid="7588193972189849870">"ഇൻസ്‌റ്റാൾ ചെയ്യുന്നു"</string>
+ <string name="allow_rotation_title" msgid="2118706734511831751">"തിരിക്കൽ അനുവദിക്കുക"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"അജ്ഞാതം"</string>
- <string name="package_state_error" msgid="7672093962724223588">"പുനഃസ്ഥാപിച്ചിട്ടില്ല"</string>
- <string name="abandoned_clean_all" msgid="5256770727689657618">"എല്ലാം നീക്കം ചെയ്യുക"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"നീക്കംചെയ്യുക"</string>
<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="action_add_to_workspace" msgid="8902165848117513641">"ഹോം സ്ക്രീനിൽ ചേർക്കുക"</string>
+ <string name="action_move_here" msgid="2170188780612570250">"ഇനം ഇവിടേക്ക് നീക്കുക"</string>
+ <string name="item_added_to_workspace" msgid="4211073925752213539">"ഹോം സ്‌ക്രീനിൽ ഇനം ചേർത്തു"</string>
+ <string name="item_removed" msgid="851119963877842327">"ഇനം നീക്കംചെയ്‌തു"</string>
+ <string name="action_move" msgid="4339390619886385032">"ഇനം നീക്കുക"</string>
+ <string name="move_to_empty_cell" msgid="2833711483015685619">"വരി <xliff:g id="NUMBER_0">%1$s</xliff:g> നിര <xliff:g id="NUMBER_1">%2$s</xliff:g>-ലേക്ക് നീക്കുക"</string>
+ <string name="move_to_position" msgid="6750008980455459790">"<xliff:g id="NUMBER">%1$s</xliff:g>-ലേക്ക് നീക്കുക"</string>
+ <string name="move_to_hotseat_position" msgid="6295412897075147808">"ഇഷ്‌ടമുള്ള <xliff:g id="NUMBER">%1$s</xliff:g> സ്ഥാനത്തേക്ക് നീക്കുക"</string>
+ <string name="item_moved" msgid="4606538322571412879">"ഇനം നീക്കി"</string>
+ <string name="add_to_folder" msgid="9040534766770853243">"ഫോൾഡറിൽ ചേർക്കുക: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="add_to_folder_with_app" msgid="4534929978967147231">"<xliff:g id="NAME">%1$s</xliff:g> ഉള്ള ഫോൾഡറിൽ ചേർക്കുക"</string>
+ <string name="added_to_folder" msgid="4793259502305558003">"ഫോൾഡറിൽ ഇനം ചേർത്തു"</string>
+ <string name="create_folder_with" msgid="4050141361160214248">"ഇതുപയോഗിച്ച് ഫോൾഡർ സൃഷ്‌ടിക്കുക: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="folder_created" msgid="6409794597405184510">"ഫോൾഡർ സൃഷ്‌ടിച്ചു"</string>
+ <string name="action_move_to_workspace" msgid="1603837886334246317">"ഹോം സ്‌ക്രീനിലേക്ക് നീക്കുക"</string>
+ <string name="action_move_screen_left" msgid="8854216831569401665">"സ്‌ക്രീൻ ഇടത്തേക്ക് നീക്കുക"</string>
+ <string name="action_move_screen_right" msgid="329334910274311123">"സ്‌ക്രീൻ വലത്തേക്ക് നീക്കുക"</string>
+ <string name="screen_moved" msgid="266230079505650577">"സ്‌ക്രീൻ നീക്കി"</string>
+ <string name="action_resize" msgid="1802976324781771067">"വലുപ്പംമാറ്റുക"</string>
+ <string name="action_increase_width" msgid="8773715375078513326">"വീതി കൂട്ടുക"</string>
+ <string name="action_increase_height" msgid="459390020612501122">"ഉയരം കൂട്ടുക"</string>
+ <string name="action_decrease_width" msgid="1374549771083094654">"വീതി കുറയ്‌ക്കുക"</string>
+ <string name="action_decrease_height" msgid="282377193880900022">"ഉയരം കുറയ്‌ക്കുക"</string>
+ <string name="widget_resized" msgid="9130327887929620">"വീതി <xliff:g id="NUMBER_0">%1$s</xliff:g> ഉയരം <xliff:g id="NUMBER_1">%2$s</xliff:g>-ലേക്ക് വിഡ്‌ജെറ്റിന്റെ വലുപ്പം മാറ്റി"</string>
</resources>
diff --git a/res/values-mn-rMN/strings.xml b/res/values-mn-rMN/strings.xml
index f258b4c8d..fafb37b2c 100644
--- a/res/values-mn-rMN/strings.xml
+++ b/res/values-mn-rMN/strings.xml
@@ -20,57 +20,27 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="application_name" msgid="5181331383435256801">"Launcher3"</string>
- <string name="home" msgid="7658288663002113681">"Нүүр"</string>
- <string name="uid_name" msgid="7820867637514617527">"Андройд үндсэн апп"</string>
<string name="folder_name" msgid="7371454440695724752"></string>
+ <string name="work_folder_name" msgid="3753320833950115786">"Ажил"</string>
<string name="activity_not_found" msgid="8071924732094499514">"Апп суугаагүй байна."</string>
<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="widgets_tab_label" msgid="2921133187116603919">"Виджет"</string>
- <string name="widget_adder" msgid="3201040140710381657">"Виджет"</string>
<string name="toggle_weight_watcher" msgid="5645299835184636119">"Мем харуулах"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"Виджетийг авах бол хүрээд барина уу."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
- <string name="external_drop_widget_error" msgid="3165821058322217155">"Энэ Нүүр дэлгэцэнд буулгах боломжгүй."</string>
- <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Үүсгэх виджетээ сонгоно уу"</string>
- <string name="rename_folder_label" msgid="3727762225964550653">"Фолдерын нэр"</string>
- <string name="rename_folder_title" msgid="3771389277707820891">"Фолдерын нэр өөрчлөх"</string>
- <string name="rename_action" msgid="5559600076028658757">"Тийм"</string>
- <string name="cancel_action" msgid="7009134900002915310">"Цуцлах"</string>
- <string name="menu_item_add_item" msgid="1264911265836810421">"Нүүр дэлгэцэнд нэмэх"</string>
- <string name="group_applications" msgid="3797214114206693605">"Апп"</string>
- <string name="group_shortcuts" msgid="6012256992764410535">"Товчлол"</string>
- <string name="group_widgets" msgid="1569030723286851002">"Виджет"</string>
- <string name="completely_out_of_space" msgid="6106288382070760318">"Таны Нүүр дэлгэц зайгүй."</string>
+ <string name="all_apps_search_bar_hint" msgid="7084713969757597256">"Апп хайх"</string>
+ <string name="all_apps_loading_message" msgid="7557140873644765180">"Аппликейшныг ачаалж байна..."</string>
+ <string name="all_apps_no_search_results" msgid="6332185285860416787">"\"<xliff:g id="QUERY">%1$s</xliff:g>\"-тай нийцэх апп олдсонгүй"</string>
<string name="out_of_space" msgid="4691004494942118364">"Энэ Нүүр дэлгэц зайгүй."</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"\"Дуртай\" трей дээр өөр зай байхгүй байна"</string>
- <string name="invalid_hotseat_item" msgid="5779907847267573691">"Энэ виджет трей дээр хэт томдож байна"</string>
- <string name="shortcut_installed" msgid="1701742129426969556">"\"<xliff:g id="NAME">%s</xliff:g>\" товчлол үүсэв."</string>
- <string name="shortcut_uninstalled" msgid="8176767991305701821">"\"<xliff:g id="NAME">%s</xliff:g>\" товчлол устгагдав."</string>
- <string name="shortcut_duplicate" msgid="9167217446062498127">"\"<xliff:g id="NAME">%s</xliff:g>\" товчлол өмнө үүссэн байна."</string>
- <string name="title_select_shortcut" msgid="6680642571148153868">"Товчлол сонгох"</string>
- <string name="title_select_application" msgid="3280812711670683644">"Апп сонгох"</string>
<string name="all_apps_button_label" msgid="9110807029020582876">"Апп"</string>
<string name="all_apps_home_button_label" msgid="252062713717058851">"Нүүр"</string>
- <string name="delete_zone_label_workspace" msgid="4009607676751398685">"Устгах"</string>
- <string name="delete_zone_label_all_apps" msgid="8083826390278958980">"Устгах"</string>
<string name="delete_target_label" msgid="1822697352535677073">"Устгах"</string>
<string name="delete_target_uninstall_label" msgid="5100785476250872595">"Устгах"</string>
<string name="info_target_label" msgid="8053346143994679532">"Апп мэдээлэл"</string>
- <string name="accessibility_all_apps_button" msgid="2603132375383800483">"Апп"</string>
- <string name="accessibility_delete_button" msgid="6466114477993744621">"Устгах"</string>
- <string name="delete_zone_label_all_apps_system_app" msgid="449755632749610895">"Шинэчлэлийг устгах"</string>
- <string name="cab_menu_delete_app" msgid="7435191475867183689">"Апп устгах"</string>
- <string name="cab_menu_app_info" msgid="8593722221450362342">"Апп дэлгэрэнгүй"</string>
- <string name="cab_app_selection_text" msgid="374688303047985416">"1 апп сонгогдсон"</string>
- <string name="cab_widget_selection_text" msgid="1833458597831541241">"1 виджет сонгогдсон"</string>
- <string name="cab_folder_selection_text" msgid="7999992513806132118">"1 фолдер сонгогдсон"</string>
- <string name="cab_shortcut_selection_text" msgid="2103811025667946450">"1 товчлол сонгогдсон"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"товчлол суулгах"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"Апп нь хэрэглэгчийн оролцоогүйгээр товчлолыг нэмэж чадна"</string>
- <string name="permlab_uninstall_shortcut" msgid="864595034498083837">"товчлолыг устгах"</string>
- <string name="permdesc_uninstall_shortcut" msgid="5134129545001836849">"Апп нь хэрэглэгчийн оролцоогүйгээр товчлолыг устгаж чадна"</string>
<string name="permlab_read_settings" msgid="1941457408239617576">"Нүүрний тохиргоо болон товчлолыг унших"</string>
<string name="permdesc_read_settings" msgid="5833423719057558387">"Апп нь Нүүрэндэх товчлол болон тохиргоог уншиж чадна."</string>
<string name="permlab_write_settings" msgid="3574213698004620587">"Нүүрний тохиргоо болон товчлолыг бичих"</string>
@@ -78,30 +48,17 @@
<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>
- <string name="dream_name" msgid="1530253749244328964">"Пуужин хөөргөгч"</string>
<string name="folder_hint_text" msgid="6617836969016293992">"Нэргүй фолдер"</string>
- <string name="workspace_description_format" msgid="2950174241104043327">"Нүүр дэлгэц %1$d"</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="apps_customize_apps_scroll_format" msgid="370005296147130238">"%2$d-н %1$d апп хуудас"</string>
- <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"%2$d-н %1$d виджет хуудас"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"Тавтай морилно уу"</string>
- <string name="first_run_cling_description" msgid="6447072552696253358">"Гэртээ байгаа мэт тухлаарай."</string>
- <string name="first_run_cling_custom_content_hint" msgid="6090628589029352439"></string>
- <string name="first_run_cling_search_bar_hint" msgid="5909062802402452582"></string>
- <string name="first_run_cling_create_screens_hint" msgid="6950729526680114157">"Апп болон фолдеруудад зориулан өөр дэлгэцүүд үүсгээрэй"</string>
<string name="migration_cling_title" msgid="9181776667882933767">"Таны апп дүрсүүдийг хуулах"</string>
<string name="migration_cling_description" msgid="2752413805582227644">"Таны хуучин Үндсэн дэлгэц дээрх дүрсүүдийг импорт хийх үү?"</string>
<string name="migration_cling_copy_apps" msgid="946331230090919440">"ДҮРСҮҮДИЙГ ХУУЛАХ"</string>
<string name="migration_cling_use_default" msgid="2626475813981258626">"ШИНЭЭР ЭХЛЭХ"</string>
- <string name="workspace_cling_title" msgid="5626202359865825661">"Өөрийнхөө зайг тохируулаарай"</string>
- <string name="workspace_cling_move_item" msgid="528201129978005352">"Арын дэвсгэр дээр хүрээд &amp; дарснаар ханын зураг, виджет болон тохиргоог өөрчилж болно."</string>
<string name="workspace_cling_longpress_title" msgid="9173998993909018310">"Дэвсгэр зураг, виджет, &amp; тохиргоо"</string>
<string name="workspace_cling_longpress_description" msgid="4119994475505235248">"Тааруулахын тулд арын дэлгэцэнд хүрээд &amp; барина уу"</string>
<string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"Ойлголоо"</string>
- <string name="folder_cling_title" msgid="3894908818693254164">"Фолдер энд байна"</string>
- <string name="folder_cling_create_folder" msgid="6158215559475836131">"Үүнтэй адилханыг үүсгэхийн тулд апп дээр хүрч &amp; бариад нөгөөхийн дээр зөөнө үү."</string>
- <string name="cling_dismiss" msgid="8962359497601507581">"Тийм"</string>
<string name="folder_opened" msgid="94695026776264709">"<xliff:g id="WIDTH">%1$d</xliff:g> <xliff:g id="HEIGHT">%2$d</xliff:g> фолдер нээгдэв"</string>
<string name="folder_tap_to_close" msgid="1884479294466410023">"Фолдер хаах бол хүрнэ үү"</string>
<string name="folder_tap_to_rename" msgid="9191075570492871147">"Шинэ нэрийг хадгалах бол хүрнэ үү"</string>
@@ -111,14 +68,34 @@
<string name="widget_button_text" msgid="2880537293434387943">"Виджет"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"Ханын зураг"</string>
<string name="settings_button_text" msgid="8119458837558863227">"Тохиргоо"</string>
- <string name="package_state_enqueued" msgid="6227252464303085641">"Хүлээж байна"</string>
- <string name="package_state_downloading" msgid="4088770468458724721">"Татаж авч байна"</string>
- <string name="package_state_installing" msgid="7588193972189849870">"Суулгаж байна"</string>
+ <string name="allow_rotation_title" msgid="2118706734511831751">"Эргүүлэхийг зөвшөөрөх"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Тодорхойгүй"</string>
- <string name="package_state_error" msgid="7672093962724223588">"Сэргээгээгүй"</string>
- <string name="abandoned_clean_all" msgid="5256770727689657618">"Бүгдийг устгах"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Устгах"</string>
<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="action_add_to_workspace" msgid="8902165848117513641">"Нүүр дэлгэц нэмэх"</string>
+ <string name="action_move_here" msgid="2170188780612570250">"Энд байршуулах"</string>
+ <string name="item_added_to_workspace" msgid="4211073925752213539">"Нүүр дэлгэцэнд нэмсэн зүйл"</string>
+ <string name="item_removed" msgid="851119963877842327">"Арилгасан зүйл"</string>
+ <string name="action_move" msgid="4339390619886385032">"Зөөх"</string>
+ <string name="move_to_empty_cell" msgid="2833711483015685619">"<xliff:g id="NUMBER_0">%1$s</xliff:g> мөр <xliff:g id="NUMBER_1">%2$s</xliff:g> баганад зөөх"</string>
+ <string name="move_to_position" msgid="6750008980455459790">"Байршил <xliff:g id="NUMBER">%1$s</xliff:g>-д зөөх"</string>
+ <string name="move_to_hotseat_position" msgid="6295412897075147808">"Дуртай байршил болох <xliff:g id="NUMBER">%1$s</xliff:g>-д зөөх"</string>
+ <string name="item_moved" msgid="4606538322571412879">"Зөөвөрлөсөн зүйл"</string>
+ <string name="add_to_folder" msgid="9040534766770853243">"Хавтас: <xliff:g id="NAME">%1$s</xliff:g> руу нэм"</string>
+ <string name="add_to_folder_with_app" msgid="4534929978967147231">"<xliff:g id="NAME">%1$s</xliff:g>-тай хавтас нэмэх"</string>
+ <string name="added_to_folder" msgid="4793259502305558003">"Хавтсанд нэмэгдсэн зүйл"</string>
+ <string name="create_folder_with" msgid="4050141361160214248">"Хавтсыг: <xliff:g id="NAME">%1$s</xliff:g> нэрээр үүсгэ"</string>
+ <string name="folder_created" msgid="6409794597405184510">"Үүсгэсэн хавтас"</string>
+ <string name="action_move_to_workspace" msgid="1603837886334246317">"Нүүр дэлгэц рүү зөөх"</string>
+ <string name="action_move_screen_left" msgid="8854216831569401665">"Дэлгэцийг зүүн тийш зөөх"</string>
+ <string name="action_move_screen_right" msgid="329334910274311123">"Дэлгэцийг баруун тийш зөөх"</string>
+ <string name="screen_moved" msgid="266230079505650577">"Дэлгэцийг зөөсөн"</string>
+ <string name="action_resize" msgid="1802976324781771067">"Хэмжээг өөрчлөх"</string>
+ <string name="action_increase_width" msgid="8773715375078513326">"Өргөсгөх"</string>
+ <string name="action_increase_height" msgid="459390020612501122">"Өндөрсгөх"</string>
+ <string name="action_decrease_width" msgid="1374549771083094654">"Нарийсгах"</string>
+ <string name="action_decrease_height" msgid="282377193880900022">"Намсгах"</string>
+ <string name="widget_resized" msgid="9130327887929620">"Виджэтийн өргөн <xliff:g id="NUMBER_0">%1$s</xliff:g>, өндөр <xliff:g id="NUMBER_1">%2$s</xliff:g> болсон"</string>
</resources>
diff --git a/res/values-mr-rIN/strings.xml b/res/values-mr-rIN/strings.xml
index 098e83023..657010d6c 100644
--- a/res/values-mr-rIN/strings.xml
+++ b/res/values-mr-rIN/strings.xml
@@ -20,57 +20,27 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="application_name" msgid="5181331383435256801">"Launcher3"</string>
- <string name="home" msgid="7658288663002113681">"मुख्‍यपृष्‍ठ"</string>
- <string name="uid_name" msgid="7820867637514617527">"Android Core Apps"</string>
<string name="folder_name" msgid="7371454440695724752"></string>
+ <string name="work_folder_name" msgid="3753320833950115786">"कार्य"</string>
<string name="activity_not_found" msgid="8071924732094499514">"अॅप स्थापित केलेला नाही."</string>
<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="widgets_tab_label" msgid="2921133187116603919">"विजेट"</string>
- <string name="widget_adder" msgid="3201040140710381657">"विजेट"</string>
<string name="toggle_weight_watcher" msgid="5645299835184636119">"Mem दर्शवा"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"विजेट निवडण्यासाठी स्पर्श करा आणि धरून ठेवा."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
- <string name="external_drop_widget_error" msgid="3165821058322217155">"या मुख्य स्क्रीनवर आयटम ड्रॉप करू शकलो नाही."</string>
- <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"तयार करण्यासाठी विजेट निवडा"</string>
- <string name="rename_folder_label" msgid="3727762225964550653">"फोल्डर नाव"</string>
- <string name="rename_folder_title" msgid="3771389277707820891">"फोल्डरचे नाव बदला"</string>
- <string name="rename_action" msgid="5559600076028658757">"ठीक"</string>
- <string name="cancel_action" msgid="7009134900002915310">"रद्द करा"</string>
- <string name="menu_item_add_item" msgid="1264911265836810421">"मुख्य स्क्रीनवर जोडा"</string>
- <string name="group_applications" msgid="3797214114206693605">"अॅप्स"</string>
- <string name="group_shortcuts" msgid="6012256992764410535">"शॉर्टकट"</string>
- <string name="group_widgets" msgid="1569030723286851002">"विजेट"</string>
- <string name="completely_out_of_space" msgid="6106288382070760318">"आपल्या मुख्य स्क्रीनवर अधिक जागा नाही."</string>
+ <string name="all_apps_search_bar_hint" msgid="7084713969757597256">"अॅप्स शोधा"</string>
+ <string name="all_apps_loading_message" msgid="7557140873644765180">"अॅप्स लोड करीत आहे..."</string>
+ <string name="all_apps_no_search_results" msgid="6332185285860416787">"\"<xliff:g id="QUERY">%1$s</xliff:g>\" शी जुळणारे कोणतेही अॅप्स आढळले नाहीत"</string>
<string name="out_of_space" msgid="4691004494942118364">"या मुख्य स्क्रीनवर आणखी जागा नाही."</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"आवडीच्या ट्रे मध्ये आणखी जागा नाही"</string>
- <string name="invalid_hotseat_item" msgid="5779907847267573691">"हे विजेट आवडत्या ट्रे साठी खूप मोठे आहे"</string>
- <string name="shortcut_installed" msgid="1701742129426969556">"\"<xliff:g id="NAME">%s</xliff:g>\" शॉर्टकट तयार केला."</string>
- <string name="shortcut_uninstalled" msgid="8176767991305701821">"\"<xliff:g id="NAME">%s</xliff:g>\" शॉर्टकट काढला."</string>
- <string name="shortcut_duplicate" msgid="9167217446062498127">"\"<xliff:g id="NAME">%s</xliff:g>\" शॉर्टकट आधीपासून अस्तित्वात आहे."</string>
- <string name="title_select_shortcut" msgid="6680642571148153868">"शॉर्टकट निवडा"</string>
- <string name="title_select_application" msgid="3280812711670683644">"अॅप निवडा"</string>
<string name="all_apps_button_label" msgid="9110807029020582876">"अॅप्स"</string>
<string name="all_apps_home_button_label" msgid="252062713717058851">"मुख्‍यपृष्‍ठ"</string>
- <string name="delete_zone_label_workspace" msgid="4009607676751398685">"काढा"</string>
- <string name="delete_zone_label_all_apps" msgid="8083826390278958980">"विस्थापित करा"</string>
<string name="delete_target_label" msgid="1822697352535677073">"काढा"</string>
<string name="delete_target_uninstall_label" msgid="5100785476250872595">"विस्थापित करा"</string>
<string name="info_target_label" msgid="8053346143994679532">"अॅप माहिती"</string>
- <string name="accessibility_all_apps_button" msgid="2603132375383800483">"अॅप्स"</string>
- <string name="accessibility_delete_button" msgid="6466114477993744621">"काढा"</string>
- <string name="delete_zone_label_all_apps_system_app" msgid="449755632749610895">"अद्यतन विस्थापित करा"</string>
- <string name="cab_menu_delete_app" msgid="7435191475867183689">"अॅप विस्थापित करा"</string>
- <string name="cab_menu_app_info" msgid="8593722221450362342">"अॅप तपशील"</string>
- <string name="cab_app_selection_text" msgid="374688303047985416">"1 अॅप निवडला"</string>
- <string name="cab_widget_selection_text" msgid="1833458597831541241">"1 विजेट निवडले"</string>
- <string name="cab_folder_selection_text" msgid="7999992513806132118">"1 फोल्डर निवडले"</string>
- <string name="cab_shortcut_selection_text" msgid="2103811025667946450">"1 शॉर्टकट निवडला"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"शॉर्टकट स्‍थापित करा"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"वापरकर्ता हस्तक्षेपाशिवाय शॉर्टकट जोडण्यास अॅप ला अनुमती देते."</string>
- <string name="permlab_uninstall_shortcut" msgid="864595034498083837">"शॉर्टकट विस्‍थापित करा"</string>
- <string name="permdesc_uninstall_shortcut" msgid="5134129545001836849">"वापरकर्ता हस्तक्षेपाशिवाय शॉर्टकट काढण्यास अॅप ला अनुमती देते."</string>
<string name="permlab_read_settings" msgid="1941457408239617576">"मुख्यपृष्ठ सेटिंग्ज आणि शॉर्टकट वाचा"</string>
<string name="permdesc_read_settings" msgid="5833423719057558387">"मुख्यपृष्ठातील सेटिंग्ज आणि शॉर्टकट वाचण्यास अॅप ला अनुमती देते."</string>
<string name="permlab_write_settings" msgid="3574213698004620587">"मुख्यपृष्ठ सेटिंग्ज आणि शॉर्टकट लिहा"</string>
@@ -78,30 +48,17 @@
<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>
- <string name="dream_name" msgid="1530253749244328964">"रॉकेट लाँचर"</string>
<string name="folder_hint_text" msgid="6617836969016293992">"अनामित फोल्डर"</string>
- <string name="workspace_description_format" msgid="2950174241104043327">"मुख्य स्क्रीन %1$d"</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="apps_customize_apps_scroll_format" msgid="370005296147130238">"%2$d पैकी %1$d Apps पृष्ठ"</string>
- <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"%2$d पैकी %1$d विजेट पृष्ठ"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"सुस्वागतम"</string>
- <string name="first_run_cling_description" msgid="6447072552696253358">"जसे पाहिजे तसे वापरा."</string>
- <string name="first_run_cling_custom_content_hint" msgid="6090628589029352439"></string>
- <string name="first_run_cling_search_bar_hint" msgid="5909062802402452582"></string>
- <string name="first_run_cling_create_screens_hint" msgid="6950729526680114157">"अॅप्स आणि फोल्डरसाठी आणखी स्क्रीन तयार करा"</string>
<string name="migration_cling_title" msgid="9181776667882933767">"आपली अॅप चिन्हे कॉपी करा"</string>
<string name="migration_cling_description" msgid="2752413805582227644">"आपल्या जुन्या मुख्य स्क्रीनवरून चिन्हे आणि फोल्डर आयात करायची?"</string>
<string name="migration_cling_copy_apps" msgid="946331230090919440">"चिन्हे कॉपी करा"</string>
<string name="migration_cling_use_default" msgid="2626475813981258626">"नव्याने प्रारंभ करा"</string>
- <string name="workspace_cling_title" msgid="5626202359865825661">"आपले स्थान व्यवस्थापित करा"</string>
- <string name="workspace_cling_move_item" msgid="528201129978005352">"वॉलपेपर, विजेट आणि सेटिंग्ज व्यवस्थापित करण्यासाठी पार्श्वभूमीस स्पर्श करा आणि धरून ठेवा."</string>
<string name="workspace_cling_longpress_title" msgid="9173998993909018310">"वॉलपेपर, विजेट आणि सेटिंग्ज"</string>
<string name="workspace_cling_longpress_description" msgid="4119994475505235248">"सानुकूल करण्यासाठी पार्श्वभूमीस स्पर्श करा आणि धरुन ठेवा"</string>
<string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"समजले"</string>
- <string name="folder_cling_title" msgid="3894908818693254164">"येथे एक फोल्डर आहे"</string>
- <string name="folder_cling_create_folder" msgid="6158215559475836131">"यासारखे एखादे तयार करण्यासाठी अॅप ला स्पर्श करा आणि धरून ठेवा, नंतर तो दुसर्‍यावर हलवा."</string>
- <string name="cling_dismiss" msgid="8962359497601507581">"ठीक"</string>
<string name="folder_opened" msgid="94695026776264709">"फोल्डर उघडले, <xliff:g id="WIDTH">%1$d</xliff:g> बाय <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
<string name="folder_tap_to_close" msgid="1884479294466410023">"फोल्डर बंद करण्यासाठी स्पर्श करा"</string>
<string name="folder_tap_to_rename" msgid="9191075570492871147">"नवे नाव जतन करण्यासाठी स्पर्श करा"</string>
@@ -111,14 +68,34 @@
<string name="widget_button_text" msgid="2880537293434387943">"विजेट"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"वॉलपेपर"</string>
<string name="settings_button_text" msgid="8119458837558863227">"सेटिंग्ज"</string>
- <string name="package_state_enqueued" msgid="6227252464303085641">"प्रतीक्षारत"</string>
- <string name="package_state_downloading" msgid="4088770468458724721">"डाउनलोड करत आहे"</string>
- <string name="package_state_installing" msgid="7588193972189849870">"स्थापित करत आहे"</string>
+ <string name="allow_rotation_title" msgid="2118706734511831751">"फिरविण्‍यास अनुमती द्या"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"अज्ञात"</string>
- <string name="package_state_error" msgid="7672093962724223588">"पुनर्स्थापित झाले नाही"</string>
- <string name="abandoned_clean_all" msgid="5256770727689657618">"सर्व काढा"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"काढा"</string>
<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="action_add_to_workspace" msgid="8902165848117513641">"मुख्य स्क्रीनवर जोडा"</string>
+ <string name="action_move_here" msgid="2170188780612570250">"आयटम येथे हलवा"</string>
+ <string name="item_added_to_workspace" msgid="4211073925752213539">"आयटम मुख्य स्क्रीनवर जोडला"</string>
+ <string name="item_removed" msgid="851119963877842327">"आयटम काढला"</string>
+ <string name="action_move" msgid="4339390619886385032">"आयटम हलवा"</string>
+ <string name="move_to_empty_cell" msgid="2833711483015685619">"पंक्ति <xliff:g id="NUMBER_0">%1$s</xliff:g> स्तंभ <xliff:g id="NUMBER_1">%2$s</xliff:g> मध्ये हलवा"</string>
+ <string name="move_to_position" msgid="6750008980455459790">"<xliff:g id="NUMBER">%1$s</xliff:g> स्थानावर हलवा"</string>
+ <string name="move_to_hotseat_position" msgid="6295412897075147808">"आवडत्या <xliff:g id="NUMBER">%1$s</xliff:g> स्थानावर हलवा"</string>
+ <string name="item_moved" msgid="4606538322571412879">"आयटम हलविला"</string>
+ <string name="add_to_folder" msgid="9040534766770853243">"फोल्‍डरवर जोडा: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="add_to_folder_with_app" msgid="4534929978967147231">"<xliff:g id="NAME">%1$s</xliff:g> सह फोल्डरमध्ये जोडा"</string>
+ <string name="added_to_folder" msgid="4793259502305558003">"फोल्‍डरमध्‍ये आयटम जोडले"</string>
+ <string name="create_folder_with" msgid="4050141361160214248">"यासह फोल्‍डर तयार करा: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="folder_created" msgid="6409794597405184510">"फोल्‍डर तयार केले"</string>
+ <string name="action_move_to_workspace" msgid="1603837886334246317">"मुख्य स्क्रीनवर हलवा"</string>
+ <string name="action_move_screen_left" msgid="8854216831569401665">"स्क्रीन डावीकडे हलवा"</string>
+ <string name="action_move_screen_right" msgid="329334910274311123">"स्क्रीन उजवीकडे हलवा"</string>
+ <string name="screen_moved" msgid="266230079505650577">"स्क्रीन हलविली"</string>
+ <string name="action_resize" msgid="1802976324781771067">"आकार बदला"</string>
+ <string name="action_increase_width" msgid="8773715375078513326">"रूंदी वाढवा"</string>
+ <string name="action_increase_height" msgid="459390020612501122">"उंची वाढवा"</string>
+ <string name="action_decrease_width" msgid="1374549771083094654">"रुंदी कमी करा"</string>
+ <string name="action_decrease_height" msgid="282377193880900022">"उंची कमी करा"</string>
+ <string name="widget_resized" msgid="9130327887929620">"विजेटचा आकार रुंदी <xliff:g id="NUMBER_0">%1$s</xliff:g> उंची <xliff:g id="NUMBER_1">%2$s</xliff:g> मध्ये बदलला"</string>
</resources>
diff --git a/res/values-ms-rMY/strings.xml b/res/values-ms-rMY/strings.xml
index 532b6ad8b..0c6a5f501 100644
--- a/res/values-ms-rMY/strings.xml
+++ b/res/values-ms-rMY/strings.xml
@@ -20,57 +20,27 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="application_name" msgid="5181331383435256801">"Launcher3"</string>
- <string name="home" msgid="7658288663002113681">"Laman Utama"</string>
- <string name="uid_name" msgid="7820867637514617527">"Apl Teras Android"</string>
<string name="folder_name" msgid="7371454440695724752"></string>
+ <string name="work_folder_name" msgid="3753320833950115786">"Kerja"</string>
<string name="activity_not_found" msgid="8071924732094499514">"Apl tidak dipasang."</string>
<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="widgets_tab_label" msgid="2921133187116603919">"Widget"</string>
- <string name="widget_adder" msgid="3201040140710381657">"Widget"</string>
<string name="toggle_weight_watcher" msgid="5645299835184636119">"Papar Mem"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"Sentuh &amp; tahan untuk mengambil widget."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
- <string name="external_drop_widget_error" msgid="3165821058322217155">"Tidak dapat melepaskan item pada Skrin Utama."</string>
- <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Pilih widget yang hendak dibuat"</string>
- <string name="rename_folder_label" msgid="3727762225964550653">"Nama folder"</string>
- <string name="rename_folder_title" msgid="3771389277707820891">"Namakan semula folder"</string>
- <string name="rename_action" msgid="5559600076028658757">"OK"</string>
- <string name="cancel_action" msgid="7009134900002915310">"Batal"</string>
- <string name="menu_item_add_item" msgid="1264911265836810421">"Tambah ke skrin Laman Utama"</string>
- <string name="group_applications" msgid="3797214114206693605">"Apl"</string>
- <string name="group_shortcuts" msgid="6012256992764410535">"Pintasan"</string>
- <string name="group_widgets" msgid="1569030723286851002">"Widget"</string>
- <string name="completely_out_of_space" msgid="6106288382070760318">"Tiada lagi ruang pada skrin Laman Utama anda."</string>
+ <string name="all_apps_search_bar_hint" msgid="7084713969757597256">"Cari Apl"</string>
+ <string name="all_apps_loading_message" msgid="7557140873644765180">"Memuatkan Apl…"</string>
+ <string name="all_apps_no_search_results" msgid="6332185285860416787">"Tiada Apl yang ditemui sepadan dengan \"<xliff:g id="QUERY">%1$s</xliff:g>\""</string>
<string name="out_of_space" msgid="4691004494942118364">"Tiada lagi ruang pada skrin Laman Utama ini."</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"Tiada ruang dalam dulang Kegemaran lagi"</string>
- <string name="invalid_hotseat_item" msgid="5779907847267573691">"Widget ini terlalu besar untuk dulang Kegemaran"</string>
- <string name="shortcut_installed" msgid="1701742129426969556">"Pintasan \"<xliff:g id="NAME">%s</xliff:g>\" telah dibuat."</string>
- <string name="shortcut_uninstalled" msgid="8176767991305701821">"Pintasan \"<xliff:g id="NAME">%s</xliff:g>\" telah dialih keluar."</string>
- <string name="shortcut_duplicate" msgid="9167217446062498127">"Pintasan \"<xliff:g id="NAME">%s</xliff:g>\" sudah wujud."</string>
- <string name="title_select_shortcut" msgid="6680642571148153868">"Pilih jalan pintas"</string>
- <string name="title_select_application" msgid="3280812711670683644">"Pilih apl"</string>
<string name="all_apps_button_label" msgid="9110807029020582876">"Apl"</string>
<string name="all_apps_home_button_label" msgid="252062713717058851">"Laman Utama"</string>
- <string name="delete_zone_label_workspace" msgid="4009607676751398685">"Alih keluar"</string>
- <string name="delete_zone_label_all_apps" msgid="8083826390278958980">"Nyahpasang"</string>
<string name="delete_target_label" msgid="1822697352535677073">"Alih keluar"</string>
<string name="delete_target_uninstall_label" msgid="5100785476250872595">"Nyahpasang"</string>
<string name="info_target_label" msgid="8053346143994679532">"Maklumat apl"</string>
- <string name="accessibility_all_apps_button" msgid="2603132375383800483">"Apl"</string>
- <string name="accessibility_delete_button" msgid="6466114477993744621">"Alih keluar"</string>
- <string name="delete_zone_label_all_apps_system_app" msgid="449755632749610895">"Nyahpasang kemas kini"</string>
- <string name="cab_menu_delete_app" msgid="7435191475867183689">"Nyahpasang apl"</string>
- <string name="cab_menu_app_info" msgid="8593722221450362342">"Butiran apl"</string>
- <string name="cab_app_selection_text" msgid="374688303047985416">"1 apl dipilih"</string>
- <string name="cab_widget_selection_text" msgid="1833458597831541241">"1 widget dipilih"</string>
- <string name="cab_folder_selection_text" msgid="7999992513806132118">"1 folder dipilih"</string>
- <string name="cab_shortcut_selection_text" msgid="2103811025667946450">"1 pintasan dipilih"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"pasang pintasan"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"Membenarkan apl menambah pintasan tanpa campur tangan pengguna."</string>
- <string name="permlab_uninstall_shortcut" msgid="864595034498083837">"nyahpasang pintasan"</string>
- <string name="permdesc_uninstall_shortcut" msgid="5134129545001836849">"Membenarkan apl mengalih keluar pintasan tanpa campur tangan pengguna."</string>
<string name="permlab_read_settings" msgid="1941457408239617576">"baca tetapan dan pintasan Laman Utama"</string>
<string name="permdesc_read_settings" msgid="5833423719057558387">"Membenarkan apl membaca tetapan dan pintasan di Laman Utama."</string>
<string name="permlab_write_settings" msgid="3574213698004620587">"tulis tetapan dan pintasan Laman Utama"</string>
@@ -78,30 +48,17 @@
<string name="gadget_error_text" msgid="6081085226050792095">"Masalah memuatkan widget"</string>
<string name="gadget_setup_text" msgid="8274003207686040488">"Persediaan"</string>
<string name="uninstall_system_app_text" msgid="4172046090762920660">"Ini ialah apl sistem dan tidak boleh dinyahpasang."</string>
- <string name="dream_name" msgid="1530253749244328964">"Pelancar Roket"</string>
<string name="folder_hint_text" msgid="6617836969016293992">"Folder Tanpa Nama"</string>
- <string name="workspace_description_format" msgid="2950174241104043327">"Skrin Laman Utama %1$d"</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="apps_customize_apps_scroll_format" msgid="370005296147130238">"Halaman apl %1$d daripada %2$d"</string>
- <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"Halaman widget %1$d daripada %2$d"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"Selamat datang"</string>
- <string name="first_run_cling_description" msgid="6447072552696253358">"Buat seperti berada di rumah sendiri."</string>
- <string name="first_run_cling_custom_content_hint" msgid="6090628589029352439"></string>
- <string name="first_run_cling_search_bar_hint" msgid="5909062802402452582"></string>
- <string name="first_run_cling_create_screens_hint" msgid="6950729526680114157">"Buat lebih banyak skrin untuk apl dan folder"</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>
<string name="migration_cling_copy_apps" msgid="946331230090919440">"SALIN IKON"</string>
<string name="migration_cling_use_default" msgid="2626475813981258626">"MULAKAN YANG BAHARU"</string>
- <string name="workspace_cling_title" msgid="5626202359865825661">"Susun ruang anda"</string>
- <string name="workspace_cling_move_item" msgid="528201129978005352">"Sentuh &amp; tahan latar belakang untuk mengurus kertas dinding, widget dan tetapan."</string>
<string name="workspace_cling_longpress_title" msgid="9173998993909018310">"Kertas dinding, widget &amp; tetapan"</string>
<string name="workspace_cling_longpress_description" msgid="4119994475505235248">"Sentuh &amp; tahan latar belakang untuk memperibadikan"</string>
<string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"FAHAM"</string>
- <string name="folder_cling_title" msgid="3894908818693254164">"Ini ada folder"</string>
- <string name="folder_cling_create_folder" msgid="6158215559475836131">"Untuk membuat satu folder seperti ini, sentuh &amp; tahan apl, kemudian alihkan ke atas folder lain."</string>
- <string name="cling_dismiss" msgid="8962359497601507581">"OK"</string>
<string name="folder_opened" msgid="94695026776264709">"Folder dibuka, <xliff:g id="WIDTH">%1$d</xliff:g> kali <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
<string name="folder_tap_to_close" msgid="1884479294466410023">"Sentuh untuk menutup folder"</string>
<string name="folder_tap_to_rename" msgid="9191075570492871147">"Sentuh untuk menyimpan penamaan semula"</string>
@@ -111,14 +68,34 @@
<string name="widget_button_text" msgid="2880537293434387943">"Widget"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"Kertas dinding"</string>
<string name="settings_button_text" msgid="8119458837558863227">"Tetapan"</string>
- <string name="package_state_enqueued" msgid="6227252464303085641">"Menunggu"</string>
- <string name="package_state_downloading" msgid="4088770468458724721">"Memuat turun"</string>
- <string name="package_state_installing" msgid="7588193972189849870">"Memasang"</string>
+ <string name="allow_rotation_title" msgid="2118706734511831751">"Benarkan putaran"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Tidak diketahui"</string>
- <string name="package_state_error" msgid="7672093962724223588">"Tak dipulihkan"</string>
- <string name="abandoned_clean_all" msgid="5256770727689657618">"Buang Semua"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Alih keluar"</string>
<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="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>
+ <string name="item_removed" msgid="851119963877842327">"Item dialih keluar"</string>
+ <string name="action_move" msgid="4339390619886385032">"Alihkan Item"</string>
+ <string name="move_to_empty_cell" msgid="2833711483015685619">"Alihkan ke baris <xliff:g id="NUMBER_0">%1$s</xliff:g> lajur <xliff:g id="NUMBER_1">%2$s</xliff:g>"</string>
+ <string name="move_to_position" msgid="6750008980455459790">"Alihkan ke kedudukan <xliff:g id="NUMBER">%1$s</xliff:g>"</string>
+ <string name="move_to_hotseat_position" msgid="6295412897075147808">"Alihkan ke kedudukan kegemaran <xliff:g id="NUMBER">%1$s</xliff:g>"</string>
+ <string name="item_moved" msgid="4606538322571412879">"Item dialihkan"</string>
+ <string name="add_to_folder" msgid="9040534766770853243">"Tambahkan pada folder: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="add_to_folder_with_app" msgid="4534929978967147231">"Tambahkan pada folder dengan <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="added_to_folder" msgid="4793259502305558003">"Item ditambahkan pada folder"</string>
+ <string name="create_folder_with" msgid="4050141361160214248">"Buat folder dengan: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="folder_created" msgid="6409794597405184510">"Folder dibuat"</string>
+ <string name="action_move_to_workspace" msgid="1603837886334246317">"Alihkan ke Skrin Utama"</string>
+ <string name="action_move_screen_left" msgid="8854216831569401665">"Alihkan skrin ke kiri"</string>
+ <string name="action_move_screen_right" msgid="329334910274311123">"Alihkan skrin ke kanan"</string>
+ <string name="screen_moved" msgid="266230079505650577">"Skrin dialihkan"</string>
+ <string name="action_resize" msgid="1802976324781771067">"Ubah saiz"</string>
+ <string name="action_increase_width" msgid="8773715375078513326">"Tambahkan kelebaran"</string>
+ <string name="action_increase_height" msgid="459390020612501122">"Tambahkan ketinggian"</string>
+ <string name="action_decrease_width" msgid="1374549771083094654">"Kurangkan kelebaran"</string>
+ <string name="action_decrease_height" msgid="282377193880900022">"Kurangkan ketinggian"</string>
+ <string name="widget_resized" msgid="9130327887929620">"Saiz widget diubah menjadi <xliff:g id="NUMBER_0">%1$s</xliff:g> lebar <xliff:g id="NUMBER_1">%2$s</xliff:g> tinggi"</string>
</resources>
diff --git a/res/values-ms/strings.xml b/res/values-ms/strings.xml
index f50a5db5b..7335605c8 100644
--- a/res/values-ms/strings.xml
+++ b/res/values-ms/strings.xml
@@ -20,95 +20,34 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="application_name" msgid="8424725141379931883">"Pelancar"</string>
- <string name="home" msgid="5921706419368316758">"Laman Utama"</string>
- <string name="uid_name" msgid="3371120195364560632">"Apl Teras Android"</string>
<string name="folder_name" msgid="8551881338202938211"></string>
- <string name="chooser_wallpaper" msgid="6063168087625352235">"Pilih kertas dinding dari"</string>
<string name="wallpaper_instructions" msgid="4215640646180727542">"Tetapkan kertas dinding"</string>
<string name="pick_wallpaper" msgid="5630222540525626723">"Kertas dinding"</string>
<string name="activity_not_found" msgid="217823393239365967">"Aplikasi tidak dipasang."</string>
- <string name="widgets_tab_label" msgid="9145860100000983599">"Widget"</string>
<string name="long_press_widget_to_add" msgid="7395697462851217506">"Sentuh &amp; tahan untuk mengambil widget."</string>
- <string name="market" msgid="2652226429823445833">"Kedai"</string>
<string name="widget_dims_format" msgid="1386418557719032947">"%1$d × %2$d"</string>
- <string name="external_drop_widget_error" msgid="2285187188524172774">"Tidak dapat melepaskan item pada skrin Utama ini."</string>
- <string name="external_drop_widget_pick_title" msgid="7040647073452295370">"Pilih widget untuk dibuat"</string>
- <string name="rename_folder_label" msgid="5646236631298452787">"Nama folder"</string>
- <string name="rename_folder_title" msgid="4544573104191526550">"Namakan semula folder"</string>
- <string name="rename_action" msgid="6016003384693240896">"OK"</string>
- <string name="cancel_action" msgid="3811860427489435048">"Batal"</string>
- <string name="menu_item_add_item" msgid="6233177331075781114">"Tambah ke Skrin utama"</string>
- <string name="group_applications" msgid="2103752818818161976">"Aplikasi"</string>
- <string name="group_shortcuts" msgid="9133529424900391877">"Pintasan"</string>
- <string name="group_widgets" msgid="6704978494073105844">"Widget"</string>
- <string name="completely_out_of_space" msgid="1759078539443491182">"Tiada lagi ruang pada skrin Utama anda."</string>
<string name="out_of_space" msgid="8365249326091984698">"Tiada lagi ruang pada skrin Utama ini"</string>
<string name="hotseat_out_of_space" msgid="6304886797358479361">"Tiada lagi ruang pada kerusi panas."</string>
- <string name="invalid_hotseat_item" msgid="6545340627805449250">"Widget ini terlalu besar untuk kerusi panas."</string>
- <string name="shortcut_installed" msgid="7071557296331322355">"Pintasan \"<xliff:g id="NAME">%s</xliff:g>\" diwujudkan."</string>
- <string name="shortcut_uninstalled" msgid="2129499669449749995">"Pintasan \"<xliff:g id="NAME">%s</xliff:g>\" telah dialih keluar."</string>
- <string name="shortcut_duplicate" msgid="4757756326465060694">"Pintasan \"<xliff:g id="NAME">%s</xliff:g>\" sudah pun wujud."</string>
- <string name="title_select_shortcut" msgid="1873670208166882222">"Pilih pintasan"</string>
- <string name="title_select_application" msgid="1793455815754848652">"Pilih aplikasi"</string>
<string name="all_apps_button_label" msgid="2578400570124163469">"Apl"</string>
<string name="all_apps_home_button_label" msgid="1022222300329398558">"Laman Utama"</string>
- <string name="delete_zone_label_workspace" msgid="7153615831493049150">"Alih keluar"</string>
- <string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Nyahpasang"</string>
<string name="delete_target_label" msgid="665300185123139530">"Alih keluar"</string>
<string name="delete_target_uninstall_label" msgid="748894921183769150">"Nyahpasang"</string>
<string name="info_target_label" msgid="4019495079517426980">"Maklumat apl"</string>
- <string name="accessibility_search_button" msgid="816822994629942611">"Carian"</string>
- <string name="accessibility_voice_search_button" msgid="3938249215065842475">"Carian Suara"</string>
- <string name="accessibility_all_apps_button" msgid="8803738611398979849">"Aplikasi"</string>
- <string name="accessibility_delete_button" msgid="3628162007991023603">"Alih keluar"</string>
- <string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Nyahpasang kemas kini"</string>
- <string name="menu_add" msgid="3065046628354640854">"Tambah"</string>
- <string name="menu_manage_apps" msgid="2308685199463588895">"Mengurus apl"</string>
- <string name="menu_wallpaper" msgid="5837429080911269832">"Kertas dinding"</string>
- <string name="menu_search" msgid="4826514464423239041">"Cari"</string>
- <string name="menu_notifications" msgid="6424587053194766192">"Pemberitahuan"</string>
- <string name="menu_settings" msgid="3946232973327980394">"Tetapan sistem"</string>
- <string name="menu_help" msgid="4901160661634590633">"Bantuan"</string>
- <string name="cab_menu_delete_app" msgid="4089398025537640349">"Nyahpasang aplikasi"</string>
- <string name="cab_menu_app_info" msgid="914548323652698884">"Butiran aplikasi"</string>
- <string name="cab_app_selection_text" msgid="6378522164293415735">"1 aplikasi dipilih"</string>
- <string name="cab_widget_selection_text" msgid="962527270506951955">"1 widget dipilih"</string>
- <string name="cab_folder_selection_text" msgid="8916111874189565067">"1 folder dipilih"</string>
- <string name="cab_shortcut_selection_text" msgid="8115847384500412878">"1 pintasan dipilih"</string>
<string name="permlab_install_shortcut" msgid="1201690825493376489">"pasang pintasan"</string>
<string name="permdesc_install_shortcut" msgid="8634424803272077038">"Membenarkan aplikasi menambah pintasan tanpa campur tangan pengguna."</string>
- <string name="permlab_uninstall_shortcut" msgid="7696645932555926449">"nyahpasang pintasan"</string>
- <string name="permdesc_uninstall_shortcut" msgid="274355570620220977">"Membenarkan apl mengalih keluar pintasan tanpa campur tangan pengguna."</string>
<string name="permlab_read_settings" msgid="3452408290738106747">"membaca tetapan dan pintasan Laman Utama"</string>
<string name="permdesc_read_settings" msgid="5788109303585403679">"Membenarkan apl membaca tetapan dan pintasan di Laman Utama."</string>
<string name="permlab_write_settings" msgid="1360567537236705628">"menulis tetapan dan pintasan Laman Utama"</string>
<string name="permdesc_write_settings" msgid="8530105489115785531">"Membenarkan apl menukar tetapan dan pintasan di Laman Utama."</string>
<string name="gadget_error_text" msgid="8359351016167075858">"Masalah memuatkan widget"</string>
<string name="uninstall_system_app_text" msgid="6429814133777046491">"Ini adalah aplikasi sistem dan tidak boleh dinyahpasang."</string>
- <string name="dream_name" msgid="2847171357608437154">"Pelancar Roket"</string>
<string name="folder_hint_text" msgid="8633351560105748141">"Folder Tanpa Nama"</string>
- <string name="workspace_description_format" msgid="2968608205939373034">"Skrin utama %1$d"</string>
<string name="default_scroll_format" msgid="4057140866420001240">"Halaman %1$d dari %2$d"</string>
<string name="workspace_scroll_format" msgid="1704767047951143301">"Skrin utama %1$d dari %2$d"</string>
- <string name="apps_customize_apps_scroll_format" msgid="5494241912377704885">"Halaman apl %1$d dari %2$d"</string>
- <string name="apps_customize_widgets_scroll_format" msgid="5383009742241717437">"Halaman widget %1$d dari %2$d"</string>
- <string name="workspace_cling_title" msgid="738396473989890567">"Buat diri anda seperti di rumah"</string>
- <string name="workspace_cling_move_item" msgid="791013895761065070">"Anda boleh meletakkan aplikasi kegemaran anda di sini."</string>
- <string name="workspace_cling_open_all_apps" msgid="2459977609848572588">"Untuk melihat semua aplikasi anda, sentuh bulatan."</string>
- <string name="all_apps_cling_title" msgid="2559734712581447107">"Pilih beberapa aplikasi"</string>
- <string name="all_apps_cling_add_item" msgid="5665035103260318891">"Untuk menambahkan aplikasi pada skrin Utama anda, sentuh &amp; tahankannya."</string>
- <string name="folder_cling_title" msgid="4308949882377840953">"Susun aplikasi anda dengan folder"</string>
- <string name="folder_cling_move_item" msgid="270598675060435169">"Untuk memindahkan aplikasi, sentuh &amp; tahankannya."</string>
- <string name="folder_cling_create_folder" msgid="8352867485656129478">"Untuk membuat folder baharu pada skrin Utama anda, tindihkan satu aplikasi di atas yang lain."</string>
- <string name="cling_dismiss" msgid="2780907108735868381">"OK"</string>
<string name="folder_opened" msgid="1262064100943801533">"Folder dibuka, <xliff:g id="WIDTH">%1$d</xliff:g> kali <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
<string name="folder_tap_to_close" msgid="1335478160661137579">"Sentuh untuk menutup folder"</string>
<string name="folder_tap_to_rename" msgid="5201612989905472442">"Sentuh untuk menyimpan penamaan semula"</string>
<string name="folder_closed" msgid="3130534551370511932">"Folder ditutup"</string>
<string name="folder_renamed" msgid="7951233572858053642">"Folder dinamakan semula kepada <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="folder_name_format" msgid="3051680259794759037">"Folder: <xliff:g id="NAME">%1$s</xliff:g>"</string>
- <string name="custom_workspace_cling_title_1" msgid="1433009175359948587"></string>
- <string name="custom_workspace_cling_description_1" msgid="6875529190849858047"></string>
- <string name="custom_workspace_cling_title_2" msgid="5516006164661020362"></string>
- <string name="custom_workspace_cling_description_2" msgid="2758258454975288377"></string>
</resources>
diff --git a/res/values-my-rMM/strings.xml b/res/values-my-rMM/strings.xml
index 544ecdc7a..19ec3a6ff 100644
--- a/res/values-my-rMM/strings.xml
+++ b/res/values-my-rMM/strings.xml
@@ -20,57 +20,27 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="application_name" msgid="5181331383435256801">"Launcher၃"</string>
- <string name="home" msgid="7658288663002113681">"ပင်မစာမျက်နှာ"</string>
- <string name="uid_name" msgid="7820867637514617527">"Androidပင်မ အပ်ပလီကေးရှင်းများ"</string>
<string name="folder_name" msgid="7371454440695724752"></string>
+ <string name="work_folder_name" msgid="3753320833950115786">"အလုပ်"</string>
<string name="activity_not_found" msgid="8071924732094499514">"အပ်ပလီကေးရှင်း မထည့်သွင်းထားပါ"</string>
<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="widgets_tab_label" msgid="2921133187116603919">"ဝဒ်ဂျက်များ"</string>
- <string name="widget_adder" msgid="3201040140710381657">"ဝဒ်ဂျက်များ"</string>
<string name="toggle_weight_watcher" msgid="5645299835184636119">"Mem ကိုပြရန်"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"ဝဒ်ဂျက်တစ်ခုကို ကောက်ယူရန် ဖိနှိပ်ထားပါ"</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
- <string name="external_drop_widget_error" msgid="3165821058322217155">"ပင်မမျက်နှာစာတွင် အရာများ ချ လို့ မရတော့ပါ"</string>
- <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"ဝဒ်ဂျက်တစ်ခုအား ပြုဖန်တီးရန် ရွေးပါ"</string>
- <string name="rename_folder_label" msgid="3727762225964550653">"အကန့်အမည်"</string>
- <string name="rename_folder_title" msgid="3771389277707820891">"အကန့်အမည်ပြောင်းရန်"</string>
- <string name="rename_action" msgid="5559600076028658757">"ကောင်းပြီ"</string>
- <string name="cancel_action" msgid="7009134900002915310">"ထားတော့"</string>
- <string name="menu_item_add_item" msgid="1264911265836810421">"ပင်မမျက်နှာစာသို့ ထည့်ပါ"</string>
- <string name="group_applications" msgid="3797214114206693605">"အပ်ပလီကေးရှင်းများ"</string>
- <string name="group_shortcuts" msgid="6012256992764410535">"အတိုကောက်မှတ်သားမှုများ"</string>
- <string name="group_widgets" msgid="1569030723286851002">"ဝဒ်ဂျက်များ"</string>
- <string name="completely_out_of_space" msgid="6106288382070760318">"ပင်မမျက်နှာစာတွင် နေရာလွတ် မကျန်တော့ပါ"</string>
+ <string name="all_apps_search_bar_hint" msgid="7084713969757597256">"ရှာဖွေမှု Appများ"</string>
+ <string name="all_apps_loading_message" msgid="7557140873644765180">"App များ ရယူနေစဉ်..."</string>
+ <string name="all_apps_no_search_results" msgid="6332185285860416787">"\"<xliff:g id="QUERY">%1$s</xliff:g>\" နှင့်ကိုက်ညီသည့် အပ်ဖ်များမတွေ့ပါ"</string>
<string name="out_of_space" msgid="4691004494942118364">"ဤပင်မမျက်နှာစာတွင် နေရာလွတ် မကျန်တော့ပါ"</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"အနှစ်သက်ဆုံးများ ထားရာတွင် နေရာလွတ် မကျန်တော့ပါ"</string>
- <string name="invalid_hotseat_item" msgid="5779907847267573691">"ဤဝဒ်ဂျက်မှာ အနှစ်သက်ဆုံးအရာများထားရာနေရာ အတွက် ကြီးလွန်းနေပါသည်"</string>
- <string name="shortcut_installed" msgid="1701742129426969556">"အတိုကောက်မှတ်သားမှု \"<xliff:g id="NAME">%s</xliff:g>\" ကို ပြုလုပ်ပြီးပါပြီ"</string>
- <string name="shortcut_uninstalled" msgid="8176767991305701821">"အတိုကောက်မှတ်သားမှု \"<xliff:g id="NAME">%s</xliff:g>\" ကို ဖယ်ရှားပြီးပါပြီ"</string>
- <string name="shortcut_duplicate" msgid="9167217446062498127">"အတိုကောက်မှတ်သားမှု \"<xliff:g id="NAME">%s</xliff:g>\" ရှိပြီးသား ဖြစ်နေပါသည်"</string>
- <string name="title_select_shortcut" msgid="6680642571148153868">"အတိုကောက်မှတ်သားမှုကို ရွေးရန်"</string>
- <string name="title_select_application" msgid="3280812711670683644">"အပလီကေးရှင်း တစ်ခုခုကို ရွေးချယ်ပါ"</string>
<string name="all_apps_button_label" msgid="9110807029020582876">"အပ်ပလီကေးရှင်းများ"</string>
<string name="all_apps_home_button_label" msgid="252062713717058851">"ပင်မစာမျက်နှာ"</string>
- <string name="delete_zone_label_workspace" msgid="4009607676751398685">"ဖယ်ရှာခြင်း"</string>
- <string name="delete_zone_label_all_apps" msgid="8083826390278958980">"ဖယ်ရှားခြင်း"</string>
<string name="delete_target_label" msgid="1822697352535677073">"ဖယ်ရှာခြင်း"</string>
<string name="delete_target_uninstall_label" msgid="5100785476250872595">"ဖယ်ရှားခြင်း"</string>
<string name="info_target_label" msgid="8053346143994679532">"အပ်ပလီကေးရှင်း အချက်အလက်များ"</string>
- <string name="accessibility_all_apps_button" msgid="2603132375383800483">"အပ်ပလီကေးရှင်းများ"</string>
- <string name="accessibility_delete_button" msgid="6466114477993744621">"ဖယ်ရှာခြင်း"</string>
- <string name="delete_zone_label_all_apps_system_app" msgid="449755632749610895">"အဆင့်မြှင့်ခြင်းကို ဖယ်ရှားပါ"</string>
- <string name="cab_menu_delete_app" msgid="7435191475867183689">"အပ်ပလီကေးရှင်းကို ဖယ်ရှားပါ"</string>
- <string name="cab_menu_app_info" msgid="8593722221450362342">"အပ်ပလီကေးရှင်း အသေးစိတ် အချက်အလက်"</string>
- <string name="cab_app_selection_text" msgid="374688303047985416">"အပ်ပလီကေးရှင်းတစ်ခု ရွေးချယ်ထားပြီး"</string>
- <string name="cab_widget_selection_text" msgid="1833458597831541241">"ဝဒ်ဂျက်တစ်ခု ရွေးချယ်ထားပြီး"</string>
- <string name="cab_folder_selection_text" msgid="7999992513806132118">"အကန့် တစ်ခု ရွေးချယ်ထားပြီး"</string>
- <string name="cab_shortcut_selection_text" msgid="2103811025667946450">"အတိုကောက်မှတ်သားမှုတစ်ခု ရွေးချယ်ထားပြီး"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"အတိုကောက်မှတ်သားမှုများအား ထည့်သွင်းခြင်း"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"အသုံးပြုသူ လုပ်ဆောင်မှုမရှိပဲ အပ်ပလီကေးရှင်းကို အတိုကောက်မှတ်သားမှုများ ပြုလုပ်ခွင့် ပေးခြင်း"</string>
- <string name="permlab_uninstall_shortcut" msgid="864595034498083837">"အတိုကောက်မှတ်သားမှုများ ဖယ်ထုတ်ခြင်း"</string>
- <string name="permdesc_uninstall_shortcut" msgid="5134129545001836849">"အပ်ပလီကေးရှင်းအား အသုံးပြုသူ မပါဝင်ပဲ အတိုကောက်မှတ်သားမှုများ ဖယ်ရှားခွင့် ပြုခြင်း"</string>
<string name="permlab_read_settings" msgid="1941457408239617576">"ပင်မမျက်နှာစာ အပြင်အဆင် နှင့် အတိုကောက်မှတ်သားမှုများအား ဖတ်ခြင်း"</string>
<string name="permdesc_read_settings" msgid="5833423719057558387">"ပင်မမျက်နှာစာတွင်ရှိသော အပြင်အဆင်နှင့် အတိုကောက်မှတ်သားမှုများကို အပ်ပလီကေးရှင်းအား ဖတ်ခွင့်ပြုခြင်း"</string>
<string name="permlab_write_settings" msgid="3574213698004620587">"ပင်မမျက်နှာစာ အပြင်အဆင် နှင့် အတိုကောက်မှတ်သားမှုများအား ရေးသားခြင်း"</string>
@@ -78,30 +48,17 @@
<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>
- <string name="dream_name" msgid="1530253749244328964">"ဒုံပျံ ပစ်လွှတ်သောအရာ"</string>
<string name="folder_hint_text" msgid="6617836969016293992">"အမည်မရှိအကန့်"</string>
- <string name="workspace_description_format" msgid="2950174241104043327">"ပင်မစာမျက်နှာ %1$d"</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="apps_customize_apps_scroll_format" msgid="370005296147130238">"အပ်ပလီကေးရှင်းပြ စာမျက်နှာ %1$d မှ %2$d"</string>
- <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"ဝဒ်ဂျက်ပြ စာမျက်နှာ %1$d မှ %2$d"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"မင်္ဂလာပါ"</string>
- <string name="first_run_cling_description" msgid="6447072552696253358">"ကိုယ့်အိမ်လို သဘောထားပါ"</string>
- <string name="first_run_cling_custom_content_hint" msgid="6090628589029352439"></string>
- <string name="first_run_cling_search_bar_hint" msgid="5909062802402452582"></string>
- <string name="first_run_cling_create_screens_hint" msgid="6950729526680114157">"အပ်ပလီကေးရှင်း နှင့် အကန့်များအတွက် ဖန်သားပြင်မှာ ထပ်ထည့်ပါ"</string>
<string name="migration_cling_title" msgid="9181776667882933767">"အပ်ပလီကေးရှင်းပုံညွှန်းများကို ကူးယူပါ"</string>
<string name="migration_cling_description" msgid="2752413805582227644">"ပင်မစာမျက်နှာအဟောင်းမှ ပုံညွှန်းများ နှင့် အကန့်များကို ယူလာပါမလား"</string>
<string name="migration_cling_copy_apps" msgid="946331230090919440">"COPY ICONS"</string>
<string name="migration_cling_use_default" msgid="2626475813981258626">"START FRESH"</string>
- <string name="workspace_cling_title" msgid="5626202359865825661">"စနစ်တကျဖြစ်အောင် ပြုလုပ်ပါ"</string>
- <string name="workspace_cling_move_item" msgid="528201129978005352">"နောက်ခံကို ဖိကိုင်၍ နောက်ခံပုံ၊ဝဒ်ဂျက်များ၊အပြင်အဆင်များကို ထိန်းချုပ်ပါ"</string>
<string name="workspace_cling_longpress_title" msgid="9173998993909018310">"နောက်ခံများ၊ ဝီဂျက်များ&amp; ဆက်တင်များ"</string>
<string name="workspace_cling_longpress_description" msgid="4119994475505235248">"နောက်ခံကို စိတ်တိုင်းကျ ပြုလုပ်ရန် ထိလျက် &amp; ကိုင်ထားပါ"</string>
<string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"ရပြီ"</string>
- <string name="folder_cling_title" msgid="3894908818693254164">"ဒီမှာ အကန့်တစ်ခုဖြစ်ပါသည်"</string>
- <string name="folder_cling_create_folder" msgid="6158215559475836131">"ဤကဲ့သို့လုပ်ရန်အတွက်၊ အပ်ပလီကေးရှင်းတစ်ခုကို ဖိကိုင်ပြီး နောက်တစ်ခုပေါ်သို့ ရွှေ့လိုက်ပါ"</string>
- <string name="cling_dismiss" msgid="8962359497601507581">"ကောင်းပြီ"</string>
<string name="folder_opened" msgid="94695026776264709">"ဖွင့်ထားသောအကန့်, <xliff:g id="WIDTH">%1$d</xliff:g> နှင့် <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
<string name="folder_tap_to_close" msgid="1884479294466410023">"အကန့်ကို ပိတ်ရန် ဖိကိုင်ပါ"</string>
<string name="folder_tap_to_rename" msgid="9191075570492871147">"အမည်ပြောင်းခြင်း အတည်ပြုရန် ဖိကိုင်ပါ"</string>
@@ -111,14 +68,34 @@
<string name="widget_button_text" msgid="2880537293434387943">"ဝဒ်ဂျက်များ"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"နောက်ခံများ"</string>
<string name="settings_button_text" msgid="8119458837558863227">"အပြင်အဆင်များ"</string>
- <string name="package_state_enqueued" msgid="6227252464303085641">"စောင့်နေ"</string>
- <string name="package_state_downloading" msgid="4088770468458724721">"ဒေါင်းလုဒ် လုပ်နေ"</string>
- <string name="package_state_installing" msgid="7588193972189849870">"တပ်ဆင်နေ"</string>
+ <string name="allow_rotation_title" msgid="2118706734511831751">"လှည့်ရန် ခွင့်ပြုမည်"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"မသိရ"</string>
- <string name="package_state_error" msgid="7672093962724223588">"ပြန်မဖေါ်ခဲ့"</string>
- <string name="abandoned_clean_all" msgid="5256770727689657618">"အားလုံး ဖယ်ရှားရန်"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"ဖယ်ရှားရန်"</string>
<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="action_add_to_workspace" msgid="8902165848117513641">"ပင်မမျက်နှာစာသို့ ထည့်ပါ"</string>
+ <string name="action_move_here" msgid="2170188780612570250">"၎င်းအား ဤသို့ ရွှေ့ပါ"</string>
+ <string name="item_added_to_workspace" msgid="4211073925752213539">"ပင်မ ဖန်မျက်နှာပြင်သို့ ထည့်ပြီး၏"</string>
+ <string name="item_removed" msgid="851119963877842327">"၎င်းအား ဖယ်ရှားပြီး၏"</string>
+ <string name="action_move" msgid="4339390619886385032">"၎င်းအား ရွှေ့ပါ"</string>
+ <string name="move_to_empty_cell" msgid="2833711483015685619">"အတန်း <xliff:g id="NUMBER_0">%1$s</xliff:g> အတိုင် <xliff:g id="NUMBER_1">%2$s</xliff:g> သို့ ရွှေ့ပါ"</string>
+ <string name="move_to_position" msgid="6750008980455459790">"<xliff:g id="NUMBER">%1$s</xliff:g> သို့ နေရာရွှေ့ပါ"</string>
+ <string name="move_to_hotseat_position" msgid="6295412897075147808">"စိတ်ကြိုက်နေရာ <xliff:g id="NUMBER">%1$s</xliff:g> သို့ ရွှေ့ပါ"</string>
+ <string name="item_moved" msgid="4606538322571412879">"၎င်းအားရွှေ့ပြီး"</string>
+ <string name="add_to_folder" msgid="9040534766770853243">"ဖိုလ်ဒါသို့ ထည့်ရန်- <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="add_to_folder_with_app" msgid="4534929978967147231">"<xliff:g id="NAME">%1$s</xliff:g> အမည်ရှိ ဖိုလ်ဒါသို့ ထည့်ပြီး၏"</string>
+ <string name="added_to_folder" msgid="4793259502305558003">"ဖိုလ်ဒါသို့ ထည့်ပြီး"</string>
+ <string name="create_folder_with" msgid="4050141361160214248">"ဖိုလ်ဒါ ပြုလုပ်ရန်- <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="folder_created" msgid="6409794597405184510">"ဖိုလ်ဒါ ပြုလုပ်ပြီး"</string>
+ <string name="action_move_to_workspace" msgid="1603837886334246317">"ပင်မမျက်နှာပြင်သို့ ရွှေ့ပါ"</string>
+ <string name="action_move_screen_left" msgid="8854216831569401665">"မျက်နှာပြင် ဘယ်ဘက်သို့ ရွှေ့ပါ"</string>
+ <string name="action_move_screen_right" msgid="329334910274311123">"မျက်နှာပြင် ညာဘက်သို့ ရွှေ့ပါ"</string>
+ <string name="screen_moved" msgid="266230079505650577">"ဖန်မျက်နှာပြင် ပြောင်းရွှေ့ပြီး၏"</string>
+ <string name="action_resize" msgid="1802976324781771067">"အရွယ်အစားပြောင်းပါ"</string>
+ <string name="action_increase_width" msgid="8773715375078513326">"အကျယ်အား တိုးပါ"</string>
+ <string name="action_increase_height" msgid="459390020612501122">"အမြင့်အား တိုးပါ"</string>
+ <string name="action_decrease_width" msgid="1374549771083094654">"အကျယ်အား လျှော့ပါ"</string>
+ <string name="action_decrease_height" msgid="282377193880900022">"အမြင့်အား လျှော့ပါ"</string>
+ <string name="widget_resized" msgid="9130327887929620">"Widget အား အကျယ် <xliff:g id="NUMBER_0">%1$s</xliff:g> အမြင့် <xliff:g id="NUMBER_1">%2$s</xliff:g> အရွယ်အစားပြန်လည်ချိန်ညှိပြီး၏"</string>
</resources>
diff --git a/res/values-nb/strings.xml b/res/values-nb/strings.xml
index a9bbe08ca..21b87c894 100644
--- a/res/values-nb/strings.xml
+++ b/res/values-nb/strings.xml
@@ -20,57 +20,27 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="application_name" msgid="5181331383435256801">"Launcher3"</string>
- <string name="home" msgid="7658288663002113681">"Startside"</string>
- <string name="uid_name" msgid="7820867637514617527">"Kjerneapper for Android"</string>
<string name="folder_name" msgid="7371454440695724752"></string>
+ <string name="work_folder_name" msgid="3753320833950115786">"Jobb"</string>
<string name="activity_not_found" msgid="8071924732094499514">"Appen er ikke installert."</string>
<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="widgets_tab_label" msgid="2921133187116603919">"Moduler"</string>
- <string name="widget_adder" msgid="3201040140710381657">"Moduler"</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="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
- <string name="external_drop_widget_error" msgid="3165821058322217155">"Kunne ikke slippe elementet på denne startsiden."</string>
- <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Velg modul for oppretting"</string>
- <string name="rename_folder_label" msgid="3727762225964550653">"Mappenavn"</string>
- <string name="rename_folder_title" msgid="3771389277707820891">"Gi mappen nytt navn"</string>
- <string name="rename_action" msgid="5559600076028658757">"OK"</string>
- <string name="cancel_action" msgid="7009134900002915310">"Avbryt"</string>
- <string name="menu_item_add_item" msgid="1264911265836810421">"Legg til på startsiden"</string>
- <string name="group_applications" msgid="3797214114206693605">"Apper"</string>
- <string name="group_shortcuts" msgid="6012256992764410535">"Snarveier"</string>
- <string name="group_widgets" msgid="1569030723286851002">"Moduler"</string>
- <string name="completely_out_of_space" msgid="6106288382070760318">"Ikke mer plass på startsidene dine."</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>
+ <string name="all_apps_no_search_results" msgid="6332185285860416787">"Fant ingen apper som samsvarer med «<xliff:g id="QUERY">%1$s</xliff:g>»"</string>
<string name="out_of_space" msgid="4691004494942118364">"Denne startsiden er full."</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"Favoritter-skuffen er full"</string>
- <string name="invalid_hotseat_item" msgid="5779907847267573691">"Denne modulen er for stor for Favoritter-skuffen."</string>
- <string name="shortcut_installed" msgid="1701742129426969556">"Snarveien «<xliff:g id="NAME">%s</xliff:g>» er opprettet."</string>
- <string name="shortcut_uninstalled" msgid="8176767991305701821">"Snarveien «<xliff:g id="NAME">%s</xliff:g>» er fjernet."</string>
- <string name="shortcut_duplicate" msgid="9167217446062498127">"Snarveien «<xliff:g id="NAME">%s</xliff:g>» fins allerede."</string>
- <string name="title_select_shortcut" msgid="6680642571148153868">"Valg av snarvei"</string>
- <string name="title_select_application" msgid="3280812711670683644">"Velg app"</string>
<string name="all_apps_button_label" msgid="9110807029020582876">"Apper"</string>
<string name="all_apps_home_button_label" msgid="252062713717058851">"Startside"</string>
- <string name="delete_zone_label_workspace" msgid="4009607676751398685">"Fjern"</string>
- <string name="delete_zone_label_all_apps" msgid="8083826390278958980">"Avinstaller"</string>
<string name="delete_target_label" msgid="1822697352535677073">"Fjern"</string>
<string name="delete_target_uninstall_label" msgid="5100785476250872595">"Avinstaller"</string>
<string name="info_target_label" msgid="8053346143994679532">"App-info"</string>
- <string name="accessibility_all_apps_button" msgid="2603132375383800483">"Apper"</string>
- <string name="accessibility_delete_button" msgid="6466114477993744621">"Fjern"</string>
- <string name="delete_zone_label_all_apps_system_app" msgid="449755632749610895">"Avinstaller oppdateringen"</string>
- <string name="cab_menu_delete_app" msgid="7435191475867183689">"Avinstaller appen"</string>
- <string name="cab_menu_app_info" msgid="8593722221450362342">"Informasjon om appen"</string>
- <string name="cab_app_selection_text" msgid="374688303047985416">"Én app er valgt"</string>
- <string name="cab_widget_selection_text" msgid="1833458597831541241">"Én modul er valgt"</string>
- <string name="cab_folder_selection_text" msgid="7999992513806132118">"Én mappe er valgt"</string>
- <string name="cab_shortcut_selection_text" msgid="2103811025667946450">"Én snarvei er valgt"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"installere snarveier"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"Gir apper tillatelse til å legge til snarveier uten innblanding fra brukeren."</string>
- <string name="permlab_uninstall_shortcut" msgid="864595034498083837">"avinstallere snarveier"</string>
- <string name="permdesc_uninstall_shortcut" msgid="5134129545001836849">"Lar appen fjerne snarveier uten innblanding fra brukeren."</string>
<string name="permlab_read_settings" msgid="1941457408239617576">"lese startsideinnstillinger og -snarveier"</string>
<string name="permdesc_read_settings" msgid="5833423719057558387">"Lar appen lese innstillingene og snarveiene på startsiden."</string>
<string name="permlab_write_settings" msgid="3574213698004620587">"angi startsideinnstillinger og -snarveier"</string>
@@ -78,30 +48,17 @@
<string name="gadget_error_text" msgid="6081085226050792095">"Problem ved innlasting av modul"</string>
<string name="gadget_setup_text" msgid="8274003207686040488">"Konfigurering"</string>
<string name="uninstall_system_app_text" msgid="4172046090762920660">"Dette er en systemapp som ikke kan avinstalleres."</string>
- <string name="dream_name" msgid="1530253749244328964">"Rocket Launcher"</string>
<string name="folder_hint_text" msgid="6617836969016293992">"Mappe uten navn"</string>
- <string name="workspace_description_format" msgid="2950174241104043327">"Startside %1$d"</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="apps_customize_apps_scroll_format" msgid="370005296147130238">"Appside %1$d av %2$d"</string>
- <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"Modulside %1$d av %2$d"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"Velkommen"</string>
- <string name="first_run_cling_description" msgid="6447072552696253358">"Føl deg som hjemme."</string>
- <string name="first_run_cling_custom_content_hint" msgid="6090628589029352439"></string>
- <string name="first_run_cling_search_bar_hint" msgid="5909062802402452582"></string>
- <string name="first_run_cling_create_screens_hint" msgid="6950729526680114157">"Opprett flere sider for apper og mapper"</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>
<string name="migration_cling_copy_apps" msgid="946331230090919440">"KOPIÉR IKONENE"</string>
<string name="migration_cling_use_default" msgid="2626475813981258626">"START PÅ NYTT"</string>
- <string name="workspace_cling_title" msgid="5626202359865825661">"Organiser plassen din"</string>
- <string name="workspace_cling_move_item" msgid="528201129978005352">"Trykk og hold på bakgrunnen for å administrere bakgrunnen, moduler og innstillinger."</string>
<string name="workspace_cling_longpress_title" msgid="9173998993909018310">"Bakgrunner, moduler og innstillinger"</string>
<string name="workspace_cling_longpress_description" msgid="4119994475505235248">"Trykk og hold på bakgrunnen for å tilpasse den"</string>
<string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"SKJØNNER"</string>
- <string name="folder_cling_title" msgid="3894908818693254164">"Dette er en mappe"</string>
- <string name="folder_cling_create_folder" msgid="6158215559475836131">"For å opprette en som denne, trykker og holder du på en app og flytter den over en annen."</string>
- <string name="cling_dismiss" msgid="8962359497601507581">"OK"</string>
<string name="folder_opened" msgid="94695026776264709">"Mappen er åpnet – <xliff:g id="WIDTH">%1$d</xliff:g> ganger <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
<string name="folder_tap_to_close" msgid="1884479294466410023">"Trykk for å lukke mappen"</string>
<string name="folder_tap_to_rename" msgid="9191075570492871147">"Trykk for å lagre det nye navnet"</string>
@@ -111,14 +68,34 @@
<string name="widget_button_text" msgid="2880537293434387943">"Moduler"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"Bakgrunner"</string>
<string name="settings_button_text" msgid="8119458837558863227">"Innstillinger"</string>
- <string name="package_state_enqueued" msgid="6227252464303085641">"Venter …"</string>
- <string name="package_state_downloading" msgid="4088770468458724721">"Laster ned …"</string>
- <string name="package_state_installing" msgid="7588193972189849870">"Installerer …"</string>
+ <string name="allow_rotation_title" msgid="2118706734511831751">"Tillat rotasjon"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Ukjent"</string>
- <string name="package_state_error" msgid="7672093962724223588">"Ikke gjenoppr."</string>
- <string name="abandoned_clean_all" msgid="5256770727689657618">"Fjern alle"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Fjern"</string>
<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="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>
+ <string name="item_removed" msgid="851119963877842327">"Elementet er fjernet"</string>
+ <string name="action_move" msgid="4339390619886385032">"Flytt elementet"</string>
+ <string name="move_to_empty_cell" msgid="2833711483015685619">"Flytt til rad <xliff:g id="NUMBER_0">%1$s</xliff:g>, kolonne <xliff:g id="NUMBER_1">%2$s</xliff:g>"</string>
+ <string name="move_to_position" msgid="6750008980455459790">"Flytt til posisjon <xliff:g id="NUMBER">%1$s</xliff:g>"</string>
+ <string name="move_to_hotseat_position" msgid="6295412897075147808">"Flytt til posisjonen for favoritter <xliff:g id="NUMBER">%1$s</xliff:g>"</string>
+ <string name="item_moved" msgid="4606538322571412879">"Elementet er flyttet"</string>
+ <string name="add_to_folder" msgid="9040534766770853243">"Legg til i mappe: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="add_to_folder_with_app" msgid="4534929978967147231">"Legg til mappen med <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="added_to_folder" msgid="4793259502305558003">"Elementet er lagt til i mappen"</string>
+ <string name="create_folder_with" msgid="4050141361160214248">"Opprett mappe med: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="folder_created" msgid="6409794597405184510">"Mappen er opprettet"</string>
+ <string name="action_move_to_workspace" msgid="1603837886334246317">"Flytt til startskjermen"</string>
+ <string name="action_move_screen_left" msgid="8854216831569401665">"Flytt skjermen til venstre"</string>
+ <string name="action_move_screen_right" msgid="329334910274311123">"Flytt skjermen til høyre"</string>
+ <string name="screen_moved" msgid="266230079505650577">"Skjermen er flyttet"</string>
+ <string name="action_resize" msgid="1802976324781771067">"Endre størrelse"</string>
+ <string name="action_increase_width" msgid="8773715375078513326">"Øk bredden"</string>
+ <string name="action_increase_height" msgid="459390020612501122">"Øk høyden"</string>
+ <string name="action_decrease_width" msgid="1374549771083094654">"Reduser bredden"</string>
+ <string name="action_decrease_height" msgid="282377193880900022">"Reduser høyden"</string>
+ <string name="widget_resized" msgid="9130327887929620">"Størrelsen på modulen er endret til bredde <xliff:g id="NUMBER_0">%1$s</xliff:g> og høyde <xliff:g id="NUMBER_1">%2$s</xliff:g>"</string>
</resources>
diff --git a/res/values-ne-rNP/strings.xml b/res/values-ne-rNP/strings.xml
index 4c72ebb63..dd3b3f310 100644
--- a/res/values-ne-rNP/strings.xml
+++ b/res/values-ne-rNP/strings.xml
@@ -20,57 +20,27 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="application_name" msgid="5181331383435256801">"Launcher3"</string>
- <string name="home" msgid="7658288663002113681">"गृह"</string>
- <string name="uid_name" msgid="7820867637514617527">"Android मूल अनुप्रयोगहरू"</string>
<string name="folder_name" msgid="7371454440695724752"></string>
+ <string name="work_folder_name" msgid="3753320833950115786">"कार्य"</string>
<string name="activity_not_found" msgid="8071924732094499514">"अनुप्रयोग स्थापित छैन।"</string>
<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="widgets_tab_label" msgid="2921133187116603919">"विजेटहरू"</string>
- <string name="widget_adder" msgid="3201040140710381657">"विजेटहरू"</string>
<string name="toggle_weight_watcher" msgid="5645299835184636119">"Mem देखाउनुहोस्"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"एउटा विजेटलाई टिप्नको लागि टच गरेर होल्ड गर्नुहोस्।"</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
- <string name="external_drop_widget_error" msgid="3165821058322217155">"यो गृह स्क्रिनमा वस्तु खसाउन सकिँदैन।"</string>
- <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"सृजना गर्नको लागि विजेट छान्नुहोस्"</string>
- <string name="rename_folder_label" msgid="3727762225964550653">"फोल्डरको नाम"</string>
- <string name="rename_folder_title" msgid="3771389277707820891">"फोल्डरलाई पुनःनामाकरण गर्नुहोस्"</string>
- <string name="rename_action" msgid="5559600076028658757">"ठिक छ"</string>
- <string name="cancel_action" msgid="7009134900002915310">"रद्द गर्नुहोस्"</string>
- <string name="menu_item_add_item" msgid="1264911265836810421">"गृह स्क्रिनमा थप्नुहोस्"</string>
- <string name="group_applications" msgid="3797214114206693605">"अनुप्रयोगहरू"</string>
- <string name="group_shortcuts" msgid="6012256992764410535">"सर्टकटहरू"</string>
- <string name="group_widgets" msgid="1569030723286851002">"विजेटहरू"</string>
- <string name="completely_out_of_space" msgid="6106288382070760318">"यो गृह स्क्रिनहरूमा कुनै थप ठाउँ छैन"</string>
+ <string name="all_apps_search_bar_hint" msgid="7084713969757597256">"अनुप्रयोगहरू खोज्नुहोस्"</string>
+ <string name="all_apps_loading_message" msgid="7557140873644765180">"अनुप्रयोगहरू लोड गरिँदै..."</string>
+ <string name="all_apps_no_search_results" msgid="6332185285860416787">"\"<xliff:g id="QUERY">%1$s</xliff:g>\" सँग मिल्दो कुनै अनुप्रयोगहरू फेला परेनन्"</string>
<string name="out_of_space" msgid="4691004494942118364">"यो गृह स्क्रिनमा कुनै थप ठाउँ छैन।"</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"मनपर्ने ट्रे अब कुनै ठाँउ छैन"</string>
- <string name="invalid_hotseat_item" msgid="5779907847267573691">"यो विजेट मनपर्ने ट्रे को लागि निकै ठूलो छ"</string>
- <string name="shortcut_installed" msgid="1701742129426969556">"सर्टकट \"<xliff:g id="NAME">%s</xliff:g>\" सिर्जित गरियो।"</string>
- <string name="shortcut_uninstalled" msgid="8176767991305701821">"सर्टकट \"<xliff:g id="NAME">%s</xliff:g>\" हटाइयो।"</string>
- <string name="shortcut_duplicate" msgid="9167217446062498127">"सर्टकट \"<xliff:g id="NAME">%s</xliff:g>\" पहिल्यै अवस्थित छ।"</string>
- <string name="title_select_shortcut" msgid="6680642571148153868">"सर्टकट छान्नुहोस्"</string>
- <string name="title_select_application" msgid="3280812711670683644">"अनुप्रयोग छनौट गर्नुहोस्"</string>
<string name="all_apps_button_label" msgid="9110807029020582876">"अनुप्रयोगहरू"</string>
<string name="all_apps_home_button_label" msgid="252062713717058851">"गृह"</string>
- <string name="delete_zone_label_workspace" msgid="4009607676751398685">"हटाउनुहोस्"</string>
- <string name="delete_zone_label_all_apps" msgid="8083826390278958980">"हटाउनुहोस्"</string>
<string name="delete_target_label" msgid="1822697352535677073">"हटाउनुहोस्"</string>
<string name="delete_target_uninstall_label" msgid="5100785476250872595">"हटाउनुहोस्"</string>
<string name="info_target_label" msgid="8053346143994679532">"अनुप्रयोग जानकारी"</string>
- <string name="accessibility_all_apps_button" msgid="2603132375383800483">"अनुप्रयोगहरू"</string>
- <string name="accessibility_delete_button" msgid="6466114477993744621">"हटाउनुहोस्"</string>
- <string name="delete_zone_label_all_apps_system_app" msgid="449755632749610895">"अद्यावधिक अस्थापित गर्नुहोस्"</string>
- <string name="cab_menu_delete_app" msgid="7435191475867183689">"अनुप्रयोग अस्थापना गर्नुहोस्"</string>
- <string name="cab_menu_app_info" msgid="8593722221450362342">"अनुप्रयोग विवरणहरु"</string>
- <string name="cab_app_selection_text" msgid="374688303047985416">"१ अनुप्रयोग चयन गरियो"</string>
- <string name="cab_widget_selection_text" msgid="1833458597831541241">"१ विजेट चयन गरियो"</string>
- <string name="cab_folder_selection_text" msgid="7999992513806132118">"१ फोल्डर चयन गरियो"</string>
- <string name="cab_shortcut_selection_text" msgid="2103811025667946450">"१ सर्टकट चयन गरियो"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"सर्टकट स्थापना गर्नेहोस्"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"प्रयोगकर्ताको हस्तक्षेप बिना एउटा अनुप्रयोगलाई सर्टकटमा थप्नको लागि अनुमति दिनुहोस्।"</string>
- <string name="permlab_uninstall_shortcut" msgid="864595034498083837">"सर्टकटहरूको स्थापन रद्द गर्नुहोस्"</string>
- <string name="permdesc_uninstall_shortcut" msgid="5134129545001836849">"अनुप्रयोगलाई उपयोगकर्ताको हस्तक्षेप बिना सर्टकटहरूलाई हटाउन अनुमति दिनुहोस्।"</string>
<string name="permlab_read_settings" msgid="1941457408239617576">"गृह सेटिङहरू र सर्टकटहरू पढ्नुहोस्"</string>
<string name="permdesc_read_settings" msgid="5833423719057558387">"गृहमा एउटा अनुप्रयोगलाई सेटिङहरू र सर्टकटहरू पढ्न अनुमति दिनुहोस्।"</string>
<string name="permlab_write_settings" msgid="3574213698004620587">"गृह सेटिङहरू र सर्टकटहरू लेख्नुहोस्"</string>
@@ -78,32 +48,17 @@
<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>
- <string name="dream_name" msgid="1530253749244328964">"रकेट लन्चर"</string>
<string name="folder_hint_text" msgid="6617836969016293992">"बेनाम फोल्डर"</string>
- <string name="workspace_description_format" msgid="2950174241104043327">"गृह स्क्रिन %1$d"</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="apps_customize_apps_scroll_format" msgid="370005296147130238">"अनुप्रयोग पृष्ठ %2$d को %1$d"</string>
- <!-- String.format failed for translation -->
- <!-- no translation found for apps_customize_widgets_scroll_format (3106209519974971521) -->
- <skip />
<string name="first_run_cling_title" msgid="2459738000155917941">"स्वागतम"</string>
- <string name="first_run_cling_description" msgid="6447072552696253358">"गृह आरामसँग बस्नुहोस्"</string>
- <string name="first_run_cling_custom_content_hint" msgid="6090628589029352439"></string>
- <string name="first_run_cling_search_bar_hint" msgid="5909062802402452582"></string>
- <string name="first_run_cling_create_screens_hint" msgid="6950729526680114157">"अनुप्रयोगहरु र फोल्डरहरुलाई थप स्क्रीनहरु सिर्जना गर्नुहोस्"</string>
<string name="migration_cling_title" msgid="9181776667882933767">"तपाईँको अनुप्रयोग आईकनको प्रतिलिप गर्नुहोस्"</string>
<string name="migration_cling_description" msgid="2752413805582227644">"आफ्नो पुरानो गृह स्क्रीनबाट अाईकन र फोल्डरहरू आयात गर्नुहोस्?"</string>
<string name="migration_cling_copy_apps" msgid="946331230090919440">"ICONS प्रतिलिप गर्नुहोस्"</string>
<string name="migration_cling_use_default" msgid="2626475813981258626">"START FRESH"</string>
- <string name="workspace_cling_title" msgid="5626202359865825661">"आफ्नो ठाउँ व्यवस्थापन गर्नुहोस्"</string>
- <string name="workspace_cling_move_item" msgid="528201129978005352">"वालपेपर, विजेट र सेटिङ्स प्रबन्ध गर्न पृष्ठभूमिलाई टच गरेर होल्ड गर्नुहोस्।"</string>
<string name="workspace_cling_longpress_title" msgid="9173998993909018310">"वालपेपरहरू, विजेट; सेटिङहरू"</string>
<string name="workspace_cling_longpress_description" msgid="4119994475505235248">"छुनुहोस् ; अनुकूलन पृष्ठभूमि होल्ड गर्नुहोस्"</string>
<string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"बुझियो"</string>
- <string name="folder_cling_title" msgid="3894908818693254164">"यहाँ एउटा फोल्डर छ"</string>
- <string name="folder_cling_create_folder" msgid="6158215559475836131">"यस्तै एक किसिमका सिर्जना गर्न, अनुप्रयोगलाई टच गरेर होल्ड गर्नुहोस्, त्यसपछि यसलाई अर्को माथि सार्नुहोस्।"</string>
- <string name="cling_dismiss" msgid="8962359497601507581">"ठिक छ"</string>
<string name="folder_opened" msgid="94695026776264709">"फोल्डर खुल्यो <xliff:g id="WIDTH">%1$d</xliff:g> बाट <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
<string name="folder_tap_to_close" msgid="1884479294466410023">"फोल्डर बन्द गर्नको लागि टच गर्नुहोस्"</string>
<string name="folder_tap_to_rename" msgid="9191075570492871147">"पुन: नामाकरण बचत गर्न टच गर्नुहोस्।"</string>
@@ -113,14 +68,34 @@
<string name="widget_button_text" msgid="2880537293434387943">"विजेटहरू"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"वालपेपरहरु"</string>
<string name="settings_button_text" msgid="8119458837558863227">"सेटिंङहरू"</string>
- <string name="package_state_enqueued" msgid="6227252464303085641">"पर्खँदै"</string>
- <string name="package_state_downloading" msgid="4088770468458724721">"डाउनलोड हुँदै"</string>
- <string name="package_state_installing" msgid="7588193972189849870">"स्थापना गर्दै"</string>
+ <string name="allow_rotation_title" msgid="2118706734511831751">"परिक्रमणलाई अनुमति दिनुहोस्"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"अज्ञात"</string>
- <string name="package_state_error" msgid="7672093962724223588">"पुनर्स्थापित भएन"</string>
- <string name="abandoned_clean_all" msgid="5256770727689657618">"सबै हटाउनुहोस्"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"हटाउनुहोस्"</string>
<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="action_add_to_workspace" msgid="8902165848117513641">"गृह स्क्रिनमा थप्नुहोस्"</string>
+ <string name="action_move_here" msgid="2170188780612570250">"वस्तु यहाँ सार्नुहोस्"</string>
+ <string name="item_added_to_workspace" msgid="4211073925752213539">"वस्तु गृह स्क्रिनमा थपियो"</string>
+ <string name="item_removed" msgid="851119963877842327">"वस्तु हटाइयो"</string>
+ <string name="action_move" msgid="4339390619886385032">"वस्तु सार्नुहोस्"</string>
+ <string name="move_to_empty_cell" msgid="2833711483015685619">"पङ्क्ति <xliff:g id="NUMBER_0">%1$s</xliff:g> स्तम्भ <xliff:g id="NUMBER_1">%2$s</xliff:g> मा सार्नुहोस्"</string>
+ <string name="move_to_position" msgid="6750008980455459790">"स्थिति <xliff:g id="NUMBER">%1$s</xliff:g> मा सार्नुहोस्"</string>
+ <string name="move_to_hotseat_position" msgid="6295412897075147808">"मनपर्ने स्थिति <xliff:g id="NUMBER">%1$s</xliff:g> मा सार्नुहोस्"</string>
+ <string name="item_moved" msgid="4606538322571412879">"वस्तु सारियो"</string>
+ <string name="add_to_folder" msgid="9040534766770853243">"फोल्डर: <xliff:g id="NAME">%1$s</xliff:g> मा थप्नुहोस्"</string>
+ <string name="add_to_folder_with_app" msgid="4534929978967147231">"फोल्डरमा <xliff:g id="NAME">%1$s</xliff:g> सँग थप्नुहोस्"</string>
+ <string name="added_to_folder" msgid="4793259502305558003">"वस्तु फोल्डरमा थपियो"</string>
+ <string name="create_folder_with" msgid="4050141361160214248">"<xliff:g id="NAME">%1$s</xliff:g>: मार्फत फोल्डर सिर्जना गर्नुहोस्"</string>
+ <string name="folder_created" msgid="6409794597405184510">"फोल्डर सिर्जना गरियो"</string>
+ <string name="action_move_to_workspace" msgid="1603837886334246317">"गृह स्क्रिनमा सार्नुहोस्"</string>
+ <string name="action_move_screen_left" msgid="8854216831569401665">"स्क्रिनलाई बायाँ सार्नुहोस्"</string>
+ <string name="action_move_screen_right" msgid="329334910274311123">"स्क्रिनलाई दायाँ सार्नुहोस्"</string>
+ <string name="screen_moved" msgid="266230079505650577">"स्क्रिन सारियो"</string>
+ <string name="action_resize" msgid="1802976324781771067">"पुनःआकार मिलाउनुहोस्"</string>
+ <string name="action_increase_width" msgid="8773715375078513326">"चौडाइ बढाउनुहोस्"</string>
+ <string name="action_increase_height" msgid="459390020612501122">"उँचाइ बढाउनुहोस्"</string>
+ <string name="action_decrease_width" msgid="1374549771083094654">"चौडाइ घटाउनुहोस्"</string>
+ <string name="action_decrease_height" msgid="282377193880900022">"उँचाइ घटाउनुहोस्"</string>
+ <string name="widget_resized" msgid="9130327887929620">"विजेट चौडाइ <xliff:g id="NUMBER_0">%1$s</xliff:g> उचाइ <xliff:g id="NUMBER_1">%2$s</xliff:g> मा पुनः आकार मिलाइयो"</string>
</resources>
diff --git a/res/values-nl/strings.xml b/res/values-nl/strings.xml
index 2a21bd647..fcbe375e7 100644
--- a/res/values-nl/strings.xml
+++ b/res/values-nl/strings.xml
@@ -20,57 +20,27 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="application_name" msgid="5181331383435256801">"Launcher3"</string>
- <string name="home" msgid="7658288663002113681">"Startpagina"</string>
- <string name="uid_name" msgid="7820867637514617527">"Android-kernapps"</string>
<string name="folder_name" msgid="7371454440695724752"></string>
+ <string name="work_folder_name" msgid="3753320833950115786">"Werk"</string>
<string name="activity_not_found" msgid="8071924732094499514">"App is niet geïnstalleerd."</string>
<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="widgets_tab_label" msgid="2921133187116603919">"Widgets"</string>
- <string name="widget_adder" msgid="3201040140710381657">"Widgets"</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="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
- <string name="external_drop_widget_error" msgid="3165821058322217155">"Kan item niet neerzetten in dit startscherm."</string>
- <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Widget selecteren om te maken"</string>
- <string name="rename_folder_label" msgid="3727762225964550653">"Mapnaam"</string>
- <string name="rename_folder_title" msgid="3771389277707820891">"Naam van map wijzigen"</string>
- <string name="rename_action" msgid="5559600076028658757">"OK"</string>
- <string name="cancel_action" msgid="7009134900002915310">"Annuleren"</string>
- <string name="menu_item_add_item" msgid="1264911265836810421">"Toevoegen aan startscherm"</string>
- <string name="group_applications" msgid="3797214114206693605">"Apps"</string>
- <string name="group_shortcuts" msgid="6012256992764410535">"Snelkoppelingen"</string>
- <string name="group_widgets" msgid="1569030723286851002">"Widgets"</string>
- <string name="completely_out_of_space" msgid="6106288382070760318">"Er is geen ruimte meer op uw startschermen."</string>
+ <string name="all_apps_search_bar_hint" msgid="7084713969757597256">"Apps zoeken"</string>
+ <string name="all_apps_loading_message" msgid="7557140873644765180">"Apps laden…"</string>
+ <string name="all_apps_no_search_results" msgid="6332185285860416787">"Er zijn geen apps gevonden die overeenkomen met \'<xliff:g id="QUERY">%1$s</xliff:g>\'"</string>
<string name="out_of_space" msgid="4691004494942118364">"Er is geen ruimte meer op dit startscherm."</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"Geen ruimte meer in het vak \'Favorieten\'"</string>
- <string name="invalid_hotseat_item" msgid="5779907847267573691">"Deze widget is te groot voor het vak \'Favorieten\'"</string>
- <string name="shortcut_installed" msgid="1701742129426969556">"Snelkoppeling \'<xliff:g id="NAME">%s</xliff:g>\' is gemaakt."</string>
- <string name="shortcut_uninstalled" msgid="8176767991305701821">"Snelkoppeling \'<xliff:g id="NAME">%s</xliff:g>\' is verwijderd."</string>
- <string name="shortcut_duplicate" msgid="9167217446062498127">"Snelkoppeling \'<xliff:g id="NAME">%s</xliff:g>\' bestaat al."</string>
- <string name="title_select_shortcut" msgid="6680642571148153868">"Snelkoppeling selecteren"</string>
- <string name="title_select_application" msgid="3280812711670683644">"App selecteren"</string>
<string name="all_apps_button_label" msgid="9110807029020582876">"Apps"</string>
<string name="all_apps_home_button_label" msgid="252062713717058851">"Startpagina"</string>
- <string name="delete_zone_label_workspace" msgid="4009607676751398685">"Verwijderen"</string>
- <string name="delete_zone_label_all_apps" msgid="8083826390278958980">"Verwijderen"</string>
<string name="delete_target_label" msgid="1822697352535677073">"Verwijderen"</string>
<string name="delete_target_uninstall_label" msgid="5100785476250872595">"Verwijderen"</string>
<string name="info_target_label" msgid="8053346143994679532">"App-info"</string>
- <string name="accessibility_all_apps_button" msgid="2603132375383800483">"Apps"</string>
- <string name="accessibility_delete_button" msgid="6466114477993744621">"Verwijderen"</string>
- <string name="delete_zone_label_all_apps_system_app" msgid="449755632749610895">"Update verwijderen"</string>
- <string name="cab_menu_delete_app" msgid="7435191475867183689">"App verwijderen"</string>
- <string name="cab_menu_app_info" msgid="8593722221450362342">"App-details"</string>
- <string name="cab_app_selection_text" msgid="374688303047985416">"1 app geselecteerd"</string>
- <string name="cab_widget_selection_text" msgid="1833458597831541241">"1 widget geselecteerd"</string>
- <string name="cab_folder_selection_text" msgid="7999992513806132118">"1 map geselecteerd"</string>
- <string name="cab_shortcut_selection_text" msgid="2103811025667946450">"1 snelkoppeling geselecteerd"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"Snelkoppelingen instellen"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"Een app toestaan snelkoppelingen toe te voegen zonder tussenkomst van de gebruiker."</string>
- <string name="permlab_uninstall_shortcut" msgid="864595034498083837">"snelkoppelingen verwijderen"</string>
- <string name="permdesc_uninstall_shortcut" msgid="5134129545001836849">"De app toestaan snelkoppelingen te verwijderen zonder tussenkomst van de gebruiker."</string>
<string name="permlab_read_settings" msgid="1941457408239617576">"instellingen en snelkoppelingen op de startpagina lezen"</string>
<string name="permdesc_read_settings" msgid="5833423719057558387">"De app toestaan de instellingen en snelkoppelingen op de startpagina te lezen."</string>
<string name="permlab_write_settings" msgid="3574213698004620587">"instellingen en snelkoppelingen op de startpagina schrijven"</string>
@@ -78,30 +48,17 @@
<string name="gadget_error_text" msgid="6081085226050792095">"Probleem bij het laden van widget"</string>
<string name="gadget_setup_text" msgid="8274003207686040488">"Configuratie"</string>
<string name="uninstall_system_app_text" msgid="4172046090762920660">"Dit is een systeemapp die niet kan worden verwijderd."</string>
- <string name="dream_name" msgid="1530253749244328964">"Rocket Launcher"</string>
<string name="folder_hint_text" msgid="6617836969016293992">"Naamloze map"</string>
- <string name="workspace_description_format" msgid="2950174241104043327">"Startscherm %1$d"</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="apps_customize_apps_scroll_format" msgid="370005296147130238">"App-pagina %1$d van %2$d"</string>
- <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"Widgetpagina %1$d van %2$d"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"Welkom"</string>
- <string name="first_run_cling_description" msgid="6447072552696253358">"Personaliseer uw startscherm."</string>
- <string name="first_run_cling_custom_content_hint" msgid="6090628589029352439"></string>
- <string name="first_run_cling_search_bar_hint" msgid="5909062802402452582"></string>
- <string name="first_run_cling_create_screens_hint" msgid="6950729526680114157">"Meer schermen maken voor apps en mappen"</string>
<string name="migration_cling_title" msgid="9181776667882933767">"Uw app-pictogrammen kopiëren"</string>
<string name="migration_cling_description" msgid="2752413805582227644">"Pictogrammen en mappen importeren uit uw oude startschermen?"</string>
<string name="migration_cling_copy_apps" msgid="946331230090919440">"PICTOGRAMMEN KOPIËREN"</string>
<string name="migration_cling_use_default" msgid="2626475813981258626">"OPNIEUW BEGINNEN"</string>
- <string name="workspace_cling_title" msgid="5626202359865825661">"Uw ruimte indelen"</string>
- <string name="workspace_cling_move_item" msgid="528201129978005352">"Blijf de achtergrond aanraken om de achtergrond, widgets en instellingen te beheren."</string>
<string name="workspace_cling_longpress_title" msgid="9173998993909018310">"Achtergronden, widgets en instellingen"</string>
<string name="workspace_cling_longpress_description" msgid="4119994475505235248">"Blijf de achtergrond aanraken om deze aan te passen"</string>
<string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"OK"</string>
- <string name="folder_cling_title" msgid="3894908818693254164">"Dit is een map"</string>
- <string name="folder_cling_create_folder" msgid="6158215559475836131">"Als u een map zoals deze wilt maken, blijft u een app aanraken en schuift u deze boven op een andere app."</string>
- <string name="cling_dismiss" msgid="8962359497601507581">"OK"</string>
<string name="folder_opened" msgid="94695026776264709">"Map geopend, <xliff:g id="WIDTH">%1$d</xliff:g> bij <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
<string name="folder_tap_to_close" msgid="1884479294466410023">"Raak dit aan om de map te sluiten"</string>
<string name="folder_tap_to_rename" msgid="9191075570492871147">"Raak dit aan om de gewijzigde naam op te slaan"</string>
@@ -111,14 +68,34 @@
<string name="widget_button_text" msgid="2880537293434387943">"Widgets"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"Achtergronden"</string>
<string name="settings_button_text" msgid="8119458837558863227">"Instellingen"</string>
- <string name="package_state_enqueued" msgid="6227252464303085641">"Wachten"</string>
- <string name="package_state_downloading" msgid="4088770468458724721">"Downloaden"</string>
- <string name="package_state_installing" msgid="7588193972189849870">"Installeren"</string>
+ <string name="allow_rotation_title" msgid="2118706734511831751">"Draaien toestaan"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Onbekend"</string>
- <string name="package_state_error" msgid="7672093962724223588">"Niet hersteld"</string>
- <string name="abandoned_clean_all" msgid="5256770727689657618">"Alles verwijderen"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Verwijderen"</string>
<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. U kunt het pictogram verwijderen of de app zoeken en handmatig installeren."</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>
+ <string name="item_removed" msgid="851119963877842327">"Item verwijderd"</string>
+ <string name="action_move" msgid="4339390619886385032">"Item verplaatsen"</string>
+ <string name="move_to_empty_cell" msgid="2833711483015685619">"Verplaatsen naar rij <xliff:g id="NUMBER_0">%1$s</xliff:g>, kolom <xliff:g id="NUMBER_1">%2$s</xliff:g>"</string>
+ <string name="move_to_position" msgid="6750008980455459790">"Verplaatsen naar positie <xliff:g id="NUMBER">%1$s</xliff:g>"</string>
+ <string name="move_to_hotseat_position" msgid="6295412897075147808">"Verplaatsen naar positie <xliff:g id="NUMBER">%1$s</xliff:g> voor favorieten"</string>
+ <string name="item_moved" msgid="4606538322571412879">"Item verplaatst"</string>
+ <string name="add_to_folder" msgid="9040534766770853243">"Toevoegen aan map: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="add_to_folder_with_app" msgid="4534929978967147231">"Toevoegen aan map met <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="added_to_folder" msgid="4793259502305558003">"Item toegevoegd aan map"</string>
+ <string name="create_folder_with" msgid="4050141361160214248">"Map maken met: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="folder_created" msgid="6409794597405184510">"Map gemaakt"</string>
+ <string name="action_move_to_workspace" msgid="1603837886334246317">"Verplaatsen naar startscherm"</string>
+ <string name="action_move_screen_left" msgid="8854216831569401665">"Scherm naar links verplaatsen"</string>
+ <string name="action_move_screen_right" msgid="329334910274311123">"Scherm naar rechts verplaatsen"</string>
+ <string name="screen_moved" msgid="266230079505650577">"Scherm verplaatst"</string>
+ <string name="action_resize" msgid="1802976324781771067">"Formaat aanpassen"</string>
+ <string name="action_increase_width" msgid="8773715375078513326">"Breedte vergroten"</string>
+ <string name="action_increase_height" msgid="459390020612501122">"Hoogte vergroten"</string>
+ <string name="action_decrease_width" msgid="1374549771083094654">"Breedte verkleinen"</string>
+ <string name="action_decrease_height" msgid="282377193880900022">"Hoogte verkleinen"</string>
+ <string name="widget_resized" msgid="9130327887929620">"Formaat van widget gewijzigd in breedte <xliff:g id="NUMBER_0">%1$s</xliff:g> en hoogte <xliff:g id="NUMBER_1">%2$s</xliff:g>"</string>
</resources>
diff --git a/res/values-pa-rIN/strings.xml b/res/values-pa-rIN/strings.xml
index fbb27b3a1..d510dc7fa 100644
--- a/res/values-pa-rIN/strings.xml
+++ b/res/values-pa-rIN/strings.xml
@@ -20,57 +20,27 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="application_name" msgid="5181331383435256801">"ਲਾਂਚਰ3"</string>
- <string name="home" msgid="7658288663002113681">"ਹੋਮ"</string>
- <string name="uid_name" msgid="7820867637514617527">"Android Core ਐਪਸ"</string>
<string name="folder_name" msgid="7371454440695724752"></string>
+ <string name="work_folder_name" msgid="3753320833950115786">"ਦਫ਼ਤਰ"</string>
<string name="activity_not_found" msgid="8071924732094499514">"ਐਪ ਇੰਸਟੌਲ ਨਹੀਂ ਕੀਤਾ ਹੋਇਆ ਹੈ।"</string>
<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="widgets_tab_label" msgid="2921133187116603919">"ਵਿਜੇਟਸ"</string>
- <string name="widget_adder" msgid="3201040140710381657">"ਵਿਜੇਟਸ"</string>
<string name="toggle_weight_watcher" msgid="5645299835184636119">"ਮੈਮ ਦਿਖਾਓ"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"ਇੱਕ ਵਿਜੇਟ ਚੁਣਨ ਲਈ ਛੋਹਵੋT &amp; ਹੋਲਡ ਕਰੋ।"</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
- <string name="external_drop_widget_error" msgid="3165821058322217155">"ਇਸ ਹੋਮ ਸਕ੍ਰੀਨ ਤੇ ਆਈਟਮ ਡ੍ਰੌਪ ਨਹੀਂ ਕਰ ਸਕਿਆ।"</string>
- <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"ਬਣਾਉਣ ਲਈ ਵਿਜੇਟ ਚੁਣੋ"</string>
- <string name="rename_folder_label" msgid="3727762225964550653">"ਫੋਲਡਰ ਨਾਮ"</string>
- <string name="rename_folder_title" msgid="3771389277707820891">"ਫੋਲਡਰ ਨੂੰ ਦੁਬਾਰਾ ਨਾਮ ਦਿਓ"</string>
- <string name="rename_action" msgid="5559600076028658757">"ਠੀਕ"</string>
- <string name="cancel_action" msgid="7009134900002915310">"ਰੱਦ ਕਰੋ"</string>
- <string name="menu_item_add_item" msgid="1264911265836810421">"ਹੋਮ ਸਕ੍ਰੀਨ ਵਿੱਚ ਜੋੜੋ"</string>
- <string name="group_applications" msgid="3797214114206693605">"ਐਪਸ"</string>
- <string name="group_shortcuts" msgid="6012256992764410535">"ਸ਼ੌਰਟਕਟਸ"</string>
- <string name="group_widgets" msgid="1569030723286851002">"ਵਿਜੇਟਸ"</string>
- <string name="completely_out_of_space" msgid="6106288382070760318">"ਤੁਹਾਡੀਆਂ ਹੋਮ ਸਕ੍ਰੀਨਾਂ ਤੇ ਹੋਰ ਖਾਲੀ ਸਥਾਨ ਨਹੀਂ ਹੈ।"</string>
+ <string name="all_apps_search_bar_hint" msgid="7084713969757597256">"ਐਪਸ ਖੋਜੋ"</string>
+ <string name="all_apps_loading_message" msgid="7557140873644765180">"ਐਪਸ ਲੋਡ ਕਰ ਰਿਹਾ ਹੈ..."</string>
+ <string name="all_apps_no_search_results" msgid="6332185285860416787">"\"<xliff:g id="QUERY">%1$s</xliff:g>\" ਨਾਲ ਮਿਲਦੀ ਕੋਈ ਵੀ ਐਪਸ ਨਹੀਂ ਲੱਭੀਆਂ"</string>
<string name="out_of_space" msgid="4691004494942118364">"ਇਸ ਹੋਮ ਸਕ੍ਰੀਨ ਲਈ ਹੋਰ ਖਾਲੀ ਸਥਾਨ ਨਹੀਂ ਹੈ।"</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"ਮਨਪਸੰਦ ਟ੍ਰੇ ਵਿੱਚ ਹੋਰ ਖਾਲੀ ਸਥਾਨ ਨਹੀਂ।"</string>
- <string name="invalid_hotseat_item" msgid="5779907847267573691">"ਇਹ ਵਿਜੇਟ ਮਨਪਸੰਦ ਟ੍ਰੇ ਲਈ ਬਹੁਤ ਜ਼ਿਆਦਾ ਵੱਡਾ ਹੈ"</string>
- <string name="shortcut_installed" msgid="1701742129426969556">"ਸ਼ੌਰਟਕਟ \"<xliff:g id="NAME">%s</xliff:g>\" ਬਣਾਇਆ ਗਿਆ।"</string>
- <string name="shortcut_uninstalled" msgid="8176767991305701821">"ਸ਼ੌਰਟਕਟ \"<xliff:g id="NAME">%s</xliff:g>\" ਹਟਾ ਦਿੱਤਾ ਗਿਆ ਸੀ।"</string>
- <string name="shortcut_duplicate" msgid="9167217446062498127">"ਸ਼ੌਰਟਕਟ \"<xliff:g id="NAME">%s</xliff:g>\" ਪਹਿਲਾਂ ਹੀ ਮੌਜੂਦ ਹੈ।"</string>
- <string name="title_select_shortcut" msgid="6680642571148153868">"ਸ਼ੌਰਟਕਟ ਚੁਣੋ"</string>
- <string name="title_select_application" msgid="3280812711670683644">"ਐਪ ਚੁਣੋ"</string>
<string name="all_apps_button_label" msgid="9110807029020582876">"ਐਪਸ"</string>
<string name="all_apps_home_button_label" msgid="252062713717058851">"ਹੋਮ"</string>
- <string name="delete_zone_label_workspace" msgid="4009607676751398685">"ਹਟਾਓ"</string>
- <string name="delete_zone_label_all_apps" msgid="8083826390278958980">"ਅਣਇੰਸਟੌਲ ਕਰੋ"</string>
<string name="delete_target_label" msgid="1822697352535677073">"ਹਟਾਓ"</string>
<string name="delete_target_uninstall_label" msgid="5100785476250872595">"ਅਣਇੰਸਟੌਲ ਕਰੋ"</string>
<string name="info_target_label" msgid="8053346143994679532">"ਐਪ ਜਾਣਕਾਰੀ"</string>
- <string name="accessibility_all_apps_button" msgid="2603132375383800483">"ਐਪਸ"</string>
- <string name="accessibility_delete_button" msgid="6466114477993744621">"ਹਟਾਓ"</string>
- <string name="delete_zone_label_all_apps_system_app" msgid="449755632749610895">"ਅਪਡੇਟ ਅਣਇੰਸਟੌਲ ਕਰੋ"</string>
- <string name="cab_menu_delete_app" msgid="7435191475867183689">"ਐਪ ਅਣਇੰਸਟੌਲ ਕਰੋ"</string>
- <string name="cab_menu_app_info" msgid="8593722221450362342">"ਐਪ ਵੇਰਵੇ"</string>
- <string name="cab_app_selection_text" msgid="374688303047985416">"1 ਐਪ ਚੁਣਿਆ"</string>
- <string name="cab_widget_selection_text" msgid="1833458597831541241">"1 ਵਿਜੇਟ ਚੁਣਿਆ"</string>
- <string name="cab_folder_selection_text" msgid="7999992513806132118">"1 ਫੋਲਡਰ ਚੁਣਿਆ"</string>
- <string name="cab_shortcut_selection_text" msgid="2103811025667946450">"1 ਸ਼ੌਰਟਕਟ ਚੁਣਿਆ"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"ਸ਼ੌਰਟਕਟ ਇੰਸਟੌਲ ਕਰੋ"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"ਇੱਕ ਐਪ ਨੂੰ ਉਪਭੋਗਤਾ ਦੇ ਦਖ਼ਲ ਤੋਂ ਬਿਨਾਂ ਸ਼ੌਰਟਕਟ ਜੋੜਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।"</string>
- <string name="permlab_uninstall_shortcut" msgid="864595034498083837">"ਸ਼ੌਰਟਕਟ ਅਣਇੰਸਟੌਲ ਕਰੋ"</string>
- <string name="permdesc_uninstall_shortcut" msgid="5134129545001836849">"ਐਪ ਨੂੰ ਉਪਭੋਗਤਾ ਦਖ਼ਲ ਤੋਂ ਬਿਨਾਂ ਸ਼ੌਰਟਕਟ ਹਟਾਉਣ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।"</string>
<string name="permlab_read_settings" msgid="1941457408239617576">"ਹੋਮ ਸੈਟਿੰਗਾਂ ਅਤੇ ਸ਼ੌਰਟਕਟ ਪੜ੍ਹੋ"</string>
<string name="permdesc_read_settings" msgid="5833423719057558387">"ਐਪ ਨੂੰ ਹੋਮ ਵਿੱਚ ਸੈਟਿੰਗਾਂ ਅਤੇ ਸ਼ੌਰਟਕਟ ਪੜ੍ਹਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।"</string>
<string name="permlab_write_settings" msgid="3574213698004620587">"ਹੋਮ ਸੈਟਿੰਗਾਂ ਅਤੇ ਸ਼ੌਰਟਕਟ ਲਿਖੋ"</string>
@@ -78,30 +48,17 @@
<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>
- <string name="dream_name" msgid="1530253749244328964">"ਰੌਕੇਟ ਲਾਂਚਰ"</string>
<string name="folder_hint_text" msgid="6617836969016293992">"ਬਿਨਾਂ ਨਾਮ ਦਿੱਤਾ ਫੋਲਡਰ"</string>
- <string name="workspace_description_format" msgid="2950174241104043327">"ਹੋਮ ਸਕ੍ਰੀਨ %1$d"</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="apps_customize_apps_scroll_format" msgid="370005296147130238">"ਐਪਸ ਸਫ਼ਾ %2$d ਦਾ %1$d"</string>
- <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"ਵਿਜੇਟ ਸਫਾ %2$d ਦਾ %1$d"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"ਸੁਆਗਤ ਹੈ"</string>
- <string name="first_run_cling_description" msgid="6447072552696253358">"ਆਪਣੇ ਹੋਮ ਵਰਗਾ ਸਮਝੋ।"</string>
- <string name="first_run_cling_custom_content_hint" msgid="6090628589029352439"></string>
- <string name="first_run_cling_search_bar_hint" msgid="5909062802402452582"></string>
- <string name="first_run_cling_create_screens_hint" msgid="6950729526680114157">"ਐਪਸ ਅਤੇ ਫੋਲਡਰ ਲਈ ਹੋਰ ਸਕ੍ਰੀਨਾਂ ਬਣਾਓ"</string>
<string name="migration_cling_title" msgid="9181776667882933767">"ਆਪਣੇ ਐਪ ਆਈਕਨਾਂ ਨੂੰ ਕਾਪੀ ਕਰੋ"</string>
<string name="migration_cling_description" msgid="2752413805582227644">"ਕੀ ਆਪਣੀਆਂ ਪੁਰਾਣੀਆਂ ਹੋਮ ਸਕ੍ਰੀਨਾਂ ਤੋਂ ਆਈਕਨਾਂ ਅਤੇ ਫੋਲਡਰ ਆਯਾਤ ਕਰਨੇ ਹਨ?"</string>
<string name="migration_cling_copy_apps" msgid="946331230090919440">"ਆਈਕਨਾਂ ਨੂੰ ਕਾਪੀ ਕਰੋ"</string>
<string name="migration_cling_use_default" msgid="2626475813981258626">"ਤਾਜ਼ਾ ਸ਼ੁਰੂ ਕਰੋ"</string>
- <string name="workspace_cling_title" msgid="5626202359865825661">"ਆਪਣਾ ਸਪੇਸ ਵਿਵਸਥਿਤ ਕਰੋ"</string>
- <string name="workspace_cling_move_item" msgid="528201129978005352">"ਵਾਲਪੇਪਰ, ਵਿਜੇਟ, ਸੈਟਿੰਗਾਂ ਵਿਵਸਥਿਤ ਕਰਨ ਲਈ ਪਿਛੋਕੜ ਛੋਹਵੋ &amp; ਹੋਲਡ ਕਰੋ।"</string>
<string name="workspace_cling_longpress_title" msgid="9173998993909018310">"ਵਾਲਪੇਪਰ, ਵਿਜੇਟ, &amp; ਸੈਟਿੰਗਾਂ"</string>
<string name="workspace_cling_longpress_description" msgid="4119994475505235248">"ਅਨੁਕੂਲ ਕਰਨ ਲਈ ਪਿਛੋਕੜ ਛੋਹਵੋ &amp; ਹੋਲਡ ਕਰੋ"</string>
<string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"ਸਮਝ ਗਿਆ"</string>
- <string name="folder_cling_title" msgid="3894908818693254164">"ਇੱਥੇ ਇੱਕ ਫੋਲਡਰ ਹੈ"</string>
- <string name="folder_cling_create_folder" msgid="6158215559475836131">"ਇਸ ਵਰਗਾ ਇੱਕ ਬਣਾਉਣ ਲਈ, ਇੱਕ ਐਪ ਨੂੰ ਛੋਹਵੋ &amp; ਹੋਲਡ ਕਰੋ, ਫਿਰ ਇਸਨੂੰ ਦੂਜੇ ਤੇ ਮੂਵ ਕਰੋ।"</string>
- <string name="cling_dismiss" msgid="8962359497601507581">"ਠੀਕ"</string>
<string name="folder_opened" msgid="94695026776264709">"ਫੋਲਡਰ ਖੋਲ੍ਹਿਆ, <xliff:g id="WIDTH">%1$d</xliff:g> ਬਾਇ <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
<string name="folder_tap_to_close" msgid="1884479294466410023">"ਫੋਲਡਰ ਬੰਦ ਕਰਨ ਲਈ ਛੋਹਵੋ"</string>
<string name="folder_tap_to_rename" msgid="9191075570492871147">"ਮੁੜ ਨਾਮ ਦਿਓ ਨੂੰ ਸੁਰੱਖਿਅਤ ਕਰਨ ਲਈ ਛੋਹਵੋ"</string>
@@ -111,14 +68,34 @@
<string name="widget_button_text" msgid="2880537293434387943">"ਵਿਜੇਟਸ"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"ਵਾਲਪੇਪਰ"</string>
<string name="settings_button_text" msgid="8119458837558863227">"ਸੈਟਿੰਗਾਂ"</string>
- <string name="package_state_enqueued" msgid="6227252464303085641">"ਉਡੀਕ ਕਰ ਰਿਹਾ ਹੈ"</string>
- <string name="package_state_downloading" msgid="4088770468458724721">"ਡਾਊਨਲੋਡ ਕਰ ਰਿਹਾ ਹੈ"</string>
- <string name="package_state_installing" msgid="7588193972189849870">"ਇੰਸਟੌਲ ਕਰ ਰਿਹਾ ਹੈ"</string>
+ <string name="allow_rotation_title" msgid="2118706734511831751">"ਰੋਟੇਸ਼ਨ ਦੀ ਆਗਿਆ ਦਿਓ"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"ਅਗਿਆਤ"</string>
- <string name="package_state_error" msgid="7672093962724223588">"ਰੀਸਟੋਰ ਨਹੀਂ ਕੀਤਾ"</string>
- <string name="abandoned_clean_all" msgid="5256770727689657618">"ਸਾਰੇ ਹਟਾਓ"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"ਹਟਾਓ"</string>
<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="action_add_to_workspace" msgid="8902165848117513641">"ਹੋਮ ਸਕ੍ਰੀਨ ਵਿੱਚ ਜੋੜੋ"</string>
+ <string name="action_move_here" msgid="2170188780612570250">"ਆਈਟਮ ਨੂੰ ਇੱਥੇ ਮੂਵ ਕਰੋ"</string>
+ <string name="item_added_to_workspace" msgid="4211073925752213539">"ਆਈਟਮ ਨੂੰ ਮੁੱਖ ਸਕ੍ਰੀਨ ਵਿੱਚ ਜੋੜਿਆ ਗਿਆ"</string>
+ <string name="item_removed" msgid="851119963877842327">"ਅਈਟਮ ਹਟਾਈ ਗਈ"</string>
+ <string name="action_move" msgid="4339390619886385032">"ਆਈਟਮ ਨੂੰ ਮੂਵ ਕਰੋ"</string>
+ <string name="move_to_empty_cell" msgid="2833711483015685619">"ਕਤਾਰ <xliff:g id="NUMBER_0">%1$s</xliff:g> ਕਾਲਮ <xliff:g id="NUMBER_1">%2$s</xliff:g> ਵਿੱਚ ਮੂਵ ਕਰੋ"</string>
+ <string name="move_to_position" msgid="6750008980455459790">"ਸਥਿਤੀ <xliff:g id="NUMBER">%1$s</xliff:g> ਵਿੱਚ ਮੂਵ ਕਰੋ"</string>
+ <string name="move_to_hotseat_position" msgid="6295412897075147808">"ਮਨਪਸੰਦ ਸਥਿਤੀ <xliff:g id="NUMBER">%1$s</xliff:g> ਵਿੱਚ ਮੂਵ ਕਰੋ"</string>
+ <string name="item_moved" msgid="4606538322571412879">"ਆਈਟਮ ਮੂਵ ਕੀਤੀ ਗਈ"</string>
+ <string name="add_to_folder" msgid="9040534766770853243">"ਇਸ ਫੋਲਡਰ ਵਿੱਚ ਜੋੜੋ: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="add_to_folder_with_app" msgid="4534929978967147231">"<xliff:g id="NAME">%1$s</xliff:g> ਦੇ ਨਾਲ ਫੋਲਡਰ ਵਿੱਚ ਜੋੜੋ"</string>
+ <string name="added_to_folder" msgid="4793259502305558003">"ਆਈਟਮ ਨੂੰ ਫੋਲਡਰ ਵਿੱਚ ਜੋੜਿਆ ਗਿਆ"</string>
+ <string name="create_folder_with" msgid="4050141361160214248">"ਇਸਦੇ ਨਾਲ ਫੋਲਡਰ ਬਣਾਓ: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="folder_created" msgid="6409794597405184510">"ਫੋਲਡਰ ਬਣਾਇਆ ਗਿਆ"</string>
+ <string name="action_move_to_workspace" msgid="1603837886334246317">"ਮੁੱਖ ਸਕ੍ਰੀਨ ਵਿੱਚ ਮੂਵ ਕਰੋ"</string>
+ <string name="action_move_screen_left" msgid="8854216831569401665">"ਸਕ੍ਰੀਨ ਨੂੰ ਖੱਬੇ ਮੂਵ ਕਰੋ"</string>
+ <string name="action_move_screen_right" msgid="329334910274311123">"ਸਕ੍ਰੀਨ ਨੂੰ ਸੱਜੇ ਮੂਵ ਕਰੋ"</string>
+ <string name="screen_moved" msgid="266230079505650577">"ਸਕ੍ਰੀਨ ਨੂੰ ਮੂਵ ਕੀਤਾ ਗਿਆ"</string>
+ <string name="action_resize" msgid="1802976324781771067">"ਮੁੜ ਆਕਾਰ ਦਿਓ"</string>
+ <string name="action_increase_width" msgid="8773715375078513326">"ਚੌੜਾਈ ਵਧਾਓ"</string>
+ <string name="action_increase_height" msgid="459390020612501122">"ਉਂਚਾਈ ਵਧਾਓ"</string>
+ <string name="action_decrease_width" msgid="1374549771083094654">"ਚੌੜਾਈ ਘਟਾਓ"</string>
+ <string name="action_decrease_height" msgid="282377193880900022">"ਉਂਚਾਈ ਘਟਾਓ"</string>
+ <string name="widget_resized" msgid="9130327887929620">"ਵਿਜੈਟ ਨੂੰ ਚੌੜਾਈ <xliff:g id="NUMBER_0">%1$s</xliff:g> ਉਂਚਾਈ <xliff:g id="NUMBER_1">%2$s</xliff:g> ਨੂੰ ਮੁੜ ਆਕਾਰ ਦਿੱਤਾ"</string>
</resources>
diff --git a/res/values-pl/strings.xml b/res/values-pl/strings.xml
index 4eabae96e..b3b761d9c 100644
--- a/res/values-pl/strings.xml
+++ b/res/values-pl/strings.xml
@@ -20,57 +20,27 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="application_name" msgid="5181331383435256801">"Launcher3"</string>
- <string name="home" msgid="7658288663002113681">"Ekran główny"</string>
- <string name="uid_name" msgid="7820867637514617527">"Główne aplikacje Androida"</string>
<string name="folder_name" msgid="7371454440695724752"></string>
+ <string name="work_folder_name" msgid="3753320833950115786">"Praca"</string>
<string name="activity_not_found" msgid="8071924732094499514">"Aplikacja nie jest zainstalowana."</string>
<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="widgets_tab_label" msgid="2921133187116603919">"Widżety"</string>
- <string name="widget_adder" msgid="3201040140710381657">"Widżety"</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="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
- <string name="external_drop_widget_error" msgid="3165821058322217155">"Nie można upuścić elementu na tym ekranie głównym."</string>
- <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Wybierz widżet, który chcesz dodać"</string>
- <string name="rename_folder_label" msgid="3727762225964550653">"Nazwa folderu"</string>
- <string name="rename_folder_title" msgid="3771389277707820891">"Zmień nazwę folderu"</string>
- <string name="rename_action" msgid="5559600076028658757">"OK"</string>
- <string name="cancel_action" msgid="7009134900002915310">"Anuluj"</string>
- <string name="menu_item_add_item" msgid="1264911265836810421">"Dodaj do ekranu głównego"</string>
- <string name="group_applications" msgid="3797214114206693605">"Aplikacje"</string>
- <string name="group_shortcuts" msgid="6012256992764410535">"Skróty"</string>
- <string name="group_widgets" msgid="1569030723286851002">"Widżety"</string>
- <string name="completely_out_of_space" msgid="6106288382070760318">"Brak miejsca na ekranach głównych."</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>
+ <string name="all_apps_no_search_results" msgid="6332185285860416787">"Nie znaleziono aplikacji pasujących do zapytania „<xliff:g id="QUERY">%1$s</xliff:g>”"</string>
<string name="out_of_space" msgid="4691004494942118364">"Brak miejsca na tym ekranie głównym."</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"Brak miejsca w Ulubionych"</string>
- <string name="invalid_hotseat_item" msgid="5779907847267573691">"Ten widżet jest za duży, by zmieścił się w Ulubionych"</string>
- <string name="shortcut_installed" msgid="1701742129426969556">"Skrót „<xliff:g id="NAME">%s</xliff:g>” został utworzony."</string>
- <string name="shortcut_uninstalled" msgid="8176767991305701821">"Skrót „<xliff:g id="NAME">%s</xliff:g>” został usunięty."</string>
- <string name="shortcut_duplicate" msgid="9167217446062498127">"Skrót „<xliff:g id="NAME">%s</xliff:g>” już istnieje."</string>
- <string name="title_select_shortcut" msgid="6680642571148153868">"Wybierz skrót"</string>
- <string name="title_select_application" msgid="3280812711670683644">"Wybierz aplikację"</string>
<string name="all_apps_button_label" msgid="9110807029020582876">"Aplikacje"</string>
<string name="all_apps_home_button_label" msgid="252062713717058851">"Ekran główny"</string>
- <string name="delete_zone_label_workspace" msgid="4009607676751398685">"Usuń"</string>
- <string name="delete_zone_label_all_apps" msgid="8083826390278958980">"Odinstaluj"</string>
<string name="delete_target_label" msgid="1822697352535677073">"Usuń"</string>
<string name="delete_target_uninstall_label" msgid="5100785476250872595">"Odinstaluj"</string>
<string name="info_target_label" msgid="8053346143994679532">"Informacje o aplikacji"</string>
- <string name="accessibility_all_apps_button" msgid="2603132375383800483">"Aplikacje"</string>
- <string name="accessibility_delete_button" msgid="6466114477993744621">"Usuń"</string>
- <string name="delete_zone_label_all_apps_system_app" msgid="449755632749610895">"Odinstaluj aktualizację"</string>
- <string name="cab_menu_delete_app" msgid="7435191475867183689">"Odinstaluj aplikację"</string>
- <string name="cab_menu_app_info" msgid="8593722221450362342">"Szczegóły aplikacji"</string>
- <string name="cab_app_selection_text" msgid="374688303047985416">"Wybrano 1 aplikację"</string>
- <string name="cab_widget_selection_text" msgid="1833458597831541241">"Wybrano 1 widżet"</string>
- <string name="cab_folder_selection_text" msgid="7999992513806132118">"Wybrano 1 folder"</string>
- <string name="cab_shortcut_selection_text" msgid="2103811025667946450">"Wybrano 1 skrót"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"instalowanie skrótów"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"Pozwala aplikacji dodawać skróty bez interwencji użytkownika."</string>
- <string name="permlab_uninstall_shortcut" msgid="864595034498083837">"odinstalowywanie skrótów"</string>
- <string name="permdesc_uninstall_shortcut" msgid="5134129545001836849">"Pozwala aplikacji usuwać skróty bez interwencji użytkownika."</string>
<string name="permlab_read_settings" msgid="1941457408239617576">"odczytywanie ustawień i skrótów na ekranie głównym"</string>
<string name="permdesc_read_settings" msgid="5833423719057558387">"Pozwala aplikacji na odczytywanie ustawień i skrótów na ekranie głównym."</string>
<string name="permlab_write_settings" msgid="3574213698004620587">"zapisywanie ustawień i skrótów na ekranie głównym"</string>
@@ -78,30 +48,17 @@
<string name="gadget_error_text" msgid="6081085226050792095">"Problem podczas ładowania widżetu"</string>
<string name="gadget_setup_text" msgid="8274003207686040488">"Konfiguracja"</string>
<string name="uninstall_system_app_text" msgid="4172046090762920660">"To aplikacja systemowa i nie można jej odinstalować."</string>
- <string name="dream_name" msgid="1530253749244328964">"Wyrzutnia rakiet"</string>
<string name="folder_hint_text" msgid="6617836969016293992">"Folder bez nazwy"</string>
- <string name="workspace_description_format" msgid="2950174241104043327">"Ekran główny %1$d"</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="apps_customize_apps_scroll_format" msgid="370005296147130238">"Strona aplikacji: %1$d z %2$d"</string>
- <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"Strona widżetów: %1$d z %2$d"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"Witamy"</string>
- <string name="first_run_cling_description" msgid="6447072552696253358">"Poczuj się jak u siebie."</string>
- <string name="first_run_cling_custom_content_hint" msgid="6090628589029352439"></string>
- <string name="first_run_cling_search_bar_hint" msgid="5909062802402452582"></string>
- <string name="first_run_cling_create_screens_hint" msgid="6950729526680114157">"Dodaj więcej ekranów na aplikacje i foldery"</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>
<string name="migration_cling_copy_apps" msgid="946331230090919440">"KOPIUJ IKONY"</string>
<string name="migration_cling_use_default" msgid="2626475813981258626">"ZACZNIJ OD NOWA"</string>
- <string name="workspace_cling_title" msgid="5626202359865825661">"Uporządkuj obszar roboczy"</string>
- <string name="workspace_cling_move_item" msgid="528201129978005352">"Kliknij i przytrzymaj tło, by zmienić tapetę, widżety lub ustawienia."</string>
<string name="workspace_cling_longpress_title" msgid="9173998993909018310">"Tapety, widżety i ustawienia"</string>
<string name="workspace_cling_longpress_description" msgid="4119994475505235248">"Kliknij i przytrzymaj tło, by dostosować"</string>
<string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"OK"</string>
- <string name="folder_cling_title" msgid="3894908818693254164">"Tu jest folder"</string>
- <string name="folder_cling_create_folder" msgid="6158215559475836131">"Aby utworzyć taki sam, kliknij i przytrzymaj aplikację, a następnie przenieś ją na następną."</string>
- <string name="cling_dismiss" msgid="8962359497601507581">"OK"</string>
<string name="folder_opened" msgid="94695026776264709">"Folder otwarty, <xliff:g id="WIDTH">%1$d</xliff:g> na <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
<string name="folder_tap_to_close" msgid="1884479294466410023">"Kliknij, by zamknąć folder"</string>
<string name="folder_tap_to_rename" msgid="9191075570492871147">"Kliknij, by zapisać zmianę nazwy"</string>
@@ -111,14 +68,34 @@
<string name="widget_button_text" msgid="2880537293434387943">"Widżety"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"Tapety"</string>
<string name="settings_button_text" msgid="8119458837558863227">"Ustawienia"</string>
- <string name="package_state_enqueued" msgid="6227252464303085641">"Oczekiwanie"</string>
- <string name="package_state_downloading" msgid="4088770468458724721">"Pobieranie"</string>
- <string name="package_state_installing" msgid="7588193972189849870">"Instalowanie"</string>
+ <string name="allow_rotation_title" msgid="2118706734511831751">"Zezwól na obrót"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Brak informacji"</string>
- <string name="package_state_error" msgid="7672093962724223588">"Nie przywrócono"</string>
- <string name="abandoned_clean_all" msgid="5256770727689657618">"Usuń wszystkie"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Usuń"</string>
<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="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>
+ <string name="item_removed" msgid="851119963877842327">"Element został usunięty"</string>
+ <string name="action_move" msgid="4339390619886385032">"Przenieś element"</string>
+ <string name="move_to_empty_cell" msgid="2833711483015685619">"Przenieś do wiersza <xliff:g id="NUMBER_0">%1$s</xliff:g> w kolumnie <xliff:g id="NUMBER_1">%2$s</xliff:g>"</string>
+ <string name="move_to_position" msgid="6750008980455459790">"Przenieś do pozycji <xliff:g id="NUMBER">%1$s</xliff:g>"</string>
+ <string name="move_to_hotseat_position" msgid="6295412897075147808">"Przenieś do pozycji ulubionych: <xliff:g id="NUMBER">%1$s</xliff:g>"</string>
+ <string name="item_moved" msgid="4606538322571412879">"Element został przeniesiony"</string>
+ <string name="add_to_folder" msgid="9040534766770853243">"Dodaj do folderu: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="add_to_folder_with_app" msgid="4534929978967147231">"Dodaj do folderu z: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="added_to_folder" msgid="4793259502305558003">"Element został dodany do folderu"</string>
+ <string name="create_folder_with" msgid="4050141361160214248">"Utwórz folder z: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="folder_created" msgid="6409794597405184510">"Folder został utworzony"</string>
+ <string name="action_move_to_workspace" msgid="1603837886334246317">"Przenieś na ekran główny"</string>
+ <string name="action_move_screen_left" msgid="8854216831569401665">"Przenieś ekran w lewo"</string>
+ <string name="action_move_screen_right" msgid="329334910274311123">"Przenieś ekran w prawo"</string>
+ <string name="screen_moved" msgid="266230079505650577">"Ekran został przeniesiony"</string>
+ <string name="action_resize" msgid="1802976324781771067">"Zmień rozmiar"</string>
+ <string name="action_increase_width" msgid="8773715375078513326">"Zwiększ szerokość"</string>
+ <string name="action_increase_height" msgid="459390020612501122">"Zwiększ wysokość"</string>
+ <string name="action_decrease_width" msgid="1374549771083094654">"Zmniejsz szerokość"</string>
+ <string name="action_decrease_height" msgid="282377193880900022">"Zmniejsz wysokość"</string>
+ <string name="widget_resized" msgid="9130327887929620">"Szerokość i wysokość widżetu zmieniła się na <xliff:g id="NUMBER_0">%1$s</xliff:g> x <xliff:g id="NUMBER_1">%2$s</xliff:g>"</string>
</resources>
diff --git a/res/values-port/dimens.xml b/res/values-port/dimens.xml
deleted file mode 100644
index c20f57b2b..000000000
--- a/res/values-port/dimens.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2009 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<resources>
-<!-- AppsCustomize -->
- <integer name="apps_customize_widget_cell_count_x">2</integer>
- <integer name="apps_customize_widget_cell_count_y">3</integer>
-</resources>
diff --git a/res/values-pt-rPT/strings.xml b/res/values-pt-rPT/strings.xml
index 4397ebf81..9140b62f2 100644
--- a/res/values-pt-rPT/strings.xml
+++ b/res/values-pt-rPT/strings.xml
@@ -20,57 +20,27 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="application_name" msgid="5181331383435256801">"Iniciador3"</string>
- <string name="home" msgid="7658288663002113681">"Ecrã principal"</string>
- <string name="uid_name" msgid="7820867637514617527">"Aplicações principais do Android"</string>
<string name="folder_name" msgid="7371454440695724752"></string>
+ <string name="work_folder_name" msgid="3753320833950115786">"Trabalho"</string>
<string name="activity_not_found" msgid="8071924732094499514">"A aplicação não está instalada."</string>
<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="widgets_tab_label" msgid="2921133187116603919">"Widgets"</string>
- <string name="widget_adder" msgid="3201040140710381657">"Widgets"</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="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
- <string name="external_drop_widget_error" msgid="3165821058322217155">"Não foi possível largar o item neste Ecrã Principal."</string>
- <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Escolher um widget para criar"</string>
- <string name="rename_folder_label" msgid="3727762225964550653">"Nome da pasta"</string>
- <string name="rename_folder_title" msgid="3771389277707820891">"Mudar o nome da pasta"</string>
- <string name="rename_action" msgid="5559600076028658757">"OK"</string>
- <string name="cancel_action" msgid="7009134900002915310">"Cancelar"</string>
- <string name="menu_item_add_item" msgid="1264911265836810421">"Adicionar ao Ecrã principal"</string>
- <string name="group_applications" msgid="3797214114206693605">"Aplicações"</string>
- <string name="group_shortcuts" msgid="6012256992764410535">"Atalhos"</string>
- <string name="group_widgets" msgid="1569030723286851002">"Widgets"</string>
- <string name="completely_out_of_space" msgid="6106288382070760318">"Sem espaço suficiente nos Ecrãs principais."</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>
+ <string name="all_apps_no_search_results" msgid="6332185285860416787">"Não foram encontradas aplic. que correspondam a \"<xliff:g id="QUERY">%1$s</xliff:g>\""</string>
<string name="out_of_space" msgid="4691004494942118364">"Sem espaço suficiente neste Ecrã principal."</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"Não existe mais espaço no tabuleiro de Favoritos"</string>
- <string name="invalid_hotseat_item" msgid="5779907847267573691">"Este widget é demasiado grande para o tabuleiro de Favoritos"</string>
- <string name="shortcut_installed" msgid="1701742129426969556">"Atalho “<xliff:g id="NAME">%s</xliff:g>” criado."</string>
- <string name="shortcut_uninstalled" msgid="8176767991305701821">"O atalho “<xliff:g id="NAME">%s</xliff:g>” foi removido."</string>
- <string name="shortcut_duplicate" msgid="9167217446062498127">"O atalho “<xliff:g id="NAME">%s</xliff:g>” já existe."</string>
- <string name="title_select_shortcut" msgid="6680642571148153868">"Escolher atalho"</string>
- <string name="title_select_application" msgid="3280812711670683644">"Escolher aplicação"</string>
<string name="all_apps_button_label" msgid="9110807029020582876">"Aplicações"</string>
<string name="all_apps_home_button_label" msgid="252062713717058851">"Ecrã principal"</string>
- <string name="delete_zone_label_workspace" msgid="4009607676751398685">"Remover"</string>
- <string name="delete_zone_label_all_apps" msgid="8083826390278958980">"Desinstalar"</string>
<string name="delete_target_label" msgid="1822697352535677073">"Remover"</string>
<string name="delete_target_uninstall_label" msgid="5100785476250872595">"Desinstalar"</string>
<string name="info_target_label" msgid="8053346143994679532">"Informações da aplicação"</string>
- <string name="accessibility_all_apps_button" msgid="2603132375383800483">"Aplicações"</string>
- <string name="accessibility_delete_button" msgid="6466114477993744621">"Remover"</string>
- <string name="delete_zone_label_all_apps_system_app" msgid="449755632749610895">"Desinstalar atualização"</string>
- <string name="cab_menu_delete_app" msgid="7435191475867183689">"Desinstalar a aplicação"</string>
- <string name="cab_menu_app_info" msgid="8593722221450362342">"Detalhes da aplicação"</string>
- <string name="cab_app_selection_text" msgid="374688303047985416">"1 aplicação selecionada"</string>
- <string name="cab_widget_selection_text" msgid="1833458597831541241">"1 widget selecionado"</string>
- <string name="cab_folder_selection_text" msgid="7999992513806132118">"1 pasta selecionada"</string>
- <string name="cab_shortcut_selection_text" msgid="2103811025667946450">"1 atalho selecionado"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"instalar atalhos"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"Permite a uma aplicação adicionar atalhos sem a intervenção do utilizador."</string>
- <string name="permlab_uninstall_shortcut" msgid="864595034498083837">"desinstalar atalhos"</string>
- <string name="permdesc_uninstall_shortcut" msgid="5134129545001836849">"Permite à aplicação remover atalhos sem intervenção do utilizador."</string>
<string name="permlab_read_settings" msgid="1941457408239617576">"ler definições e atalhos do Ecrã Principal"</string>
<string name="permdesc_read_settings" msgid="5833423719057558387">"Permite à aplicação ler as definições e os atalhos no Ecrã Principal."</string>
<string name="permlab_write_settings" msgid="3574213698004620587">"escrever definições e atalhos do Ecrã principal"</string>
@@ -78,30 +48,17 @@
<string name="gadget_error_text" msgid="6081085226050792095">"Problema ao carregar o widget"</string>
<string name="gadget_setup_text" msgid="8274003207686040488">"Configuração"</string>
<string name="uninstall_system_app_text" msgid="4172046090762920660">"É uma aplicação de sistema e não pode ser desinstalada."</string>
- <string name="dream_name" msgid="1530253749244328964">"Lança-mísseis"</string>
<string name="folder_hint_text" msgid="6617836969016293992">"Pasta sem nome"</string>
- <string name="workspace_description_format" msgid="2950174241104043327">"Ecrã principal %1$d"</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="apps_customize_apps_scroll_format" msgid="370005296147130238">"Página de aplicações %1$d de %2$d"</string>
- <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"Página de widgets %1$d de %2$d"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"Bem-vindo(a)"</string>
- <string name="first_run_cling_description" msgid="6447072552696253358">"Sinta-se em casa."</string>
- <string name="first_run_cling_custom_content_hint" msgid="6090628589029352439"></string>
- <string name="first_run_cling_search_bar_hint" msgid="5909062802402452582"></string>
- <string name="first_run_cling_create_screens_hint" msgid="6950729526680114157">"Crie mais ecrãs para aplicações e pastas"</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>
<string name="migration_cling_copy_apps" msgid="946331230090919440">"COPIAR ÍCONES"</string>
<string name="migration_cling_use_default" msgid="2626475813981258626">"COMEÇAR DO INÍCIO"</string>
- <string name="workspace_cling_title" msgid="5626202359865825661">"Organizar o seu espaço"</string>
- <string name="workspace_cling_move_item" msgid="528201129978005352">"Toque sem soltar no fundo para gerir a imagem de fundo, os widgets e as definições."</string>
<string name="workspace_cling_longpress_title" msgid="9173998993909018310">"Imagens de fundo, widgets e definições"</string>
<string name="workspace_cling_longpress_description" msgid="4119994475505235248">"Toque sem soltar no fundo para personalizar"</string>
<string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"COMPREENDI"</string>
- <string name="folder_cling_title" msgid="3894908818693254164">"Eis uma pasta"</string>
- <string name="folder_cling_create_folder" msgid="6158215559475836131">"Para criar uma pasta, toque sem soltar numa aplicação e arraste-a para cima de outra aplicação."</string>
- <string name="cling_dismiss" msgid="8962359497601507581">"OK"</string>
<string name="folder_opened" msgid="94695026776264709">"Pasta aberta, <xliff:g id="WIDTH">%1$d</xliff:g> por <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
<string name="folder_tap_to_close" msgid="1884479294466410023">"Toque para fechar a pasta"</string>
<string name="folder_tap_to_rename" msgid="9191075570492871147">"Toque para guardar o nome novo"</string>
@@ -111,14 +68,34 @@
<string name="widget_button_text" msgid="2880537293434387943">"Widgets"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"Imagens de fundo"</string>
<string name="settings_button_text" msgid="8119458837558863227">"Definições"</string>
- <string name="package_state_enqueued" msgid="6227252464303085641">"A aguardar"</string>
- <string name="package_state_downloading" msgid="4088770468458724721">"A transferir "</string>
- <string name="package_state_installing" msgid="7588193972189849870">"A instalar"</string>
+ <string name="allow_rotation_title" msgid="2118706734511831751">"Permitir rotação"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Desconhecido"</string>
- <string name="package_state_error" msgid="7672093962724223588">"Não restaurado"</string>
- <string name="abandoned_clean_all" msgid="5256770727689657618">"Remover todos"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Remover"</string>
<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="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>
+ <string name="item_removed" msgid="851119963877842327">"Item removido"</string>
+ <string name="action_move" msgid="4339390619886385032">"Mover item"</string>
+ <string name="move_to_empty_cell" msgid="2833711483015685619">"Mover para a linha <xliff:g id="NUMBER_0">%1$s</xliff:g>, coluna <xliff:g id="NUMBER_1">%2$s</xliff:g>"</string>
+ <string name="move_to_position" msgid="6750008980455459790">"Mover para a posição <xliff:g id="NUMBER">%1$s</xliff:g>"</string>
+ <string name="move_to_hotseat_position" msgid="6295412897075147808">"Mover para a posição <xliff:g id="NUMBER">%1$s</xliff:g> dos favoritos"</string>
+ <string name="item_moved" msgid="4606538322571412879">"Item movido"</string>
+ <string name="add_to_folder" msgid="9040534766770853243">"Adicionar à pasta: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="add_to_folder_with_app" msgid="4534929978967147231">"Adicionar à pasta com <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="added_to_folder" msgid="4793259502305558003">"Item adicionado à pasta"</string>
+ <string name="create_folder_with" msgid="4050141361160214248">"Criar pasta com: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="folder_created" msgid="6409794597405184510">"Pasta criada"</string>
+ <string name="action_move_to_workspace" msgid="1603837886334246317">"Mover para o Ecrã principal"</string>
+ <string name="action_move_screen_left" msgid="8854216831569401665">"Mover ecrã para a esquerda"</string>
+ <string name="action_move_screen_right" msgid="329334910274311123">"Mover ecrã para a direita"</string>
+ <string name="screen_moved" msgid="266230079505650577">"Ecrã movido"</string>
+ <string name="action_resize" msgid="1802976324781771067">"Redimensionar"</string>
+ <string name="action_increase_width" msgid="8773715375078513326">"Aumentar largura"</string>
+ <string name="action_increase_height" msgid="459390020612501122">"Aumentar altura"</string>
+ <string name="action_decrease_width" msgid="1374549771083094654">"Diminuir largura"</string>
+ <string name="action_decrease_height" msgid="282377193880900022">"Diminuir altura"</string>
+ <string name="widget_resized" msgid="9130327887929620">"Widget redimensionado para a largura <xliff:g id="NUMBER_0">%1$s</xliff:g>, altura <xliff:g id="NUMBER_1">%2$s</xliff:g>"</string>
</resources>
diff --git a/res/values-pt/strings.xml b/res/values-pt/strings.xml
index 07c82143e..c8e645849 100644
--- a/res/values-pt/strings.xml
+++ b/res/values-pt/strings.xml
@@ -20,57 +20,27 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="application_name" msgid="5181331383435256801">"Launcher3"</string>
- <string name="home" msgid="7658288663002113681">"Início"</string>
- <string name="uid_name" msgid="7820867637514617527">"Principais apps do Android"</string>
<string name="folder_name" msgid="7371454440695724752"></string>
+ <string name="work_folder_name" msgid="3753320833950115786">"Trabalho"</string>
<string name="activity_not_found" msgid="8071924732094499514">"O app não está instalado."</string>
<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="widgets_tab_label" msgid="2921133187116603919">"Widgets"</string>
- <string name="widget_adder" msgid="3201040140710381657">"Widgets"</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="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
- <string name="external_drop_widget_error" msgid="3165821058322217155">"Não foi possível soltar o item nesta tela inicial."</string>
- <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Selecione um widget para criar"</string>
- <string name="rename_folder_label" msgid="3727762225964550653">"Nome da pasta"</string>
- <string name="rename_folder_title" msgid="3771389277707820891">"Renomear pasta"</string>
- <string name="rename_action" msgid="5559600076028658757">"Ok"</string>
- <string name="cancel_action" msgid="7009134900002915310">"Cancelar"</string>
- <string name="menu_item_add_item" msgid="1264911265836810421">"Adicionar à tela inicial"</string>
- <string name="group_applications" msgid="3797214114206693605">"Apps"</string>
- <string name="group_shortcuts" msgid="6012256992764410535">"Atalhos"</string>
- <string name="group_widgets" msgid="1569030723286851002">"Widgets"</string>
- <string name="completely_out_of_space" msgid="6106288382070760318">"Não há mais espaço nas telas iniciais."</string>
+ <string name="all_apps_search_bar_hint" msgid="7084713969757597256">"Pesquisar apps"</string>
+ <string name="all_apps_loading_message" msgid="7557140873644765180">"Carregando apps…"</string>
+ <string name="all_apps_no_search_results" msgid="6332185285860416787">"Nenhum app encontrado que corresponda a \"<xliff:g id="QUERY">%1$s</xliff:g>\""</string>
<string name="out_of_space" msgid="4691004494942118364">"Não há mais espaço na tela inicial."</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"Sem espaço na bandeja de favoritos"</string>
- <string name="invalid_hotseat_item" msgid="5779907847267573691">"O widget é muito grande para a bandeja de favoritos"</string>
- <string name="shortcut_installed" msgid="1701742129426969556">"Atalho \"<xliff:g id="NAME">%s</xliff:g>\" criado."</string>
- <string name="shortcut_uninstalled" msgid="8176767991305701821">"O atalho \"<xliff:g id="NAME">%s</xliff:g>\" foi removido."</string>
- <string name="shortcut_duplicate" msgid="9167217446062498127">"O atalho \"<xliff:g id="NAME">%s</xliff:g>\" já existe."</string>
- <string name="title_select_shortcut" msgid="6680642571148153868">"Selecione um atalho"</string>
- <string name="title_select_application" msgid="3280812711670683644">"Selecione um app"</string>
<string name="all_apps_button_label" msgid="9110807029020582876">"Apps"</string>
<string name="all_apps_home_button_label" msgid="252062713717058851">"Início"</string>
- <string name="delete_zone_label_workspace" msgid="4009607676751398685">"Remover"</string>
- <string name="delete_zone_label_all_apps" msgid="8083826390278958980">"Desinstalar"</string>
<string name="delete_target_label" msgid="1822697352535677073">"Remover"</string>
<string name="delete_target_uninstall_label" msgid="5100785476250872595">"Desinstalar"</string>
<string name="info_target_label" msgid="8053346143994679532">"Informações do app"</string>
- <string name="accessibility_all_apps_button" msgid="2603132375383800483">"Apps"</string>
- <string name="accessibility_delete_button" msgid="6466114477993744621">"Remover"</string>
- <string name="delete_zone_label_all_apps_system_app" msgid="449755632749610895">"Desinstalar atualização"</string>
- <string name="cab_menu_delete_app" msgid="7435191475867183689">"Desinstalar app"</string>
- <string name="cab_menu_app_info" msgid="8593722221450362342">"Detalhes do app"</string>
- <string name="cab_app_selection_text" msgid="374688303047985416">"Um app selecionado"</string>
- <string name="cab_widget_selection_text" msgid="1833458597831541241">"Um widget selecionado"</string>
- <string name="cab_folder_selection_text" msgid="7999992513806132118">"Uma pasta selecionada"</string>
- <string name="cab_shortcut_selection_text" msgid="2103811025667946450">"Um atalho selecionado"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"instalar atalhos"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"Permite que um app adicione atalhos sem intervenção do usuário."</string>
- <string name="permlab_uninstall_shortcut" msgid="864595034498083837">"desinstalar atalhos"</string>
- <string name="permdesc_uninstall_shortcut" msgid="5134129545001836849">"Permite que o app remova atalhos sem a intervenção do usuário."</string>
<string name="permlab_read_settings" msgid="1941457408239617576">"ler configurações e atalhos da tela inicial"</string>
<string name="permdesc_read_settings" msgid="5833423719057558387">"Permite que o app leia as configurações e os atalhos na tela inicial."</string>
<string name="permlab_write_settings" msgid="3574213698004620587">"gravar configurações e atalhos da tela inicial"</string>
@@ -78,30 +48,17 @@
<string name="gadget_error_text" msgid="6081085226050792095">"Problema ao carregar o widget"</string>
<string name="gadget_setup_text" msgid="8274003207686040488">"Configuração"</string>
<string name="uninstall_system_app_text" msgid="4172046090762920660">"Este é um app do sistema e não pode ser desinstalado."</string>
- <string name="dream_name" msgid="1530253749244328964">"Rocket Launcher"</string>
<string name="folder_hint_text" msgid="6617836969016293992">"Pasta sem nome"</string>
- <string name="workspace_description_format" msgid="2950174241104043327">"Tela inicial %1$d"</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="apps_customize_apps_scroll_format" msgid="370005296147130238">"Página de apps, %1$d de %2$d"</string>
- <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"Página de widgets, %1$d de %2$d"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"Bem-vindo"</string>
- <string name="first_run_cling_description" msgid="6447072552696253358">"Fique à vontade."</string>
- <string name="first_run_cling_custom_content_hint" msgid="6090628589029352439"></string>
- <string name="first_run_cling_search_bar_hint" msgid="5909062802402452582"></string>
- <string name="first_run_cling_create_screens_hint" msgid="6950729526680114157">"Crie mais telas para apps e pastas"</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>
<string name="migration_cling_copy_apps" msgid="946331230090919440">"COPIAR ÍCONES"</string>
<string name="migration_cling_use_default" msgid="2626475813981258626">"COMEÇAR DO ZERO"</string>
- <string name="workspace_cling_title" msgid="5626202359865825661">"Organize seu espaço"</string>
- <string name="workspace_cling_move_item" msgid="528201129978005352">"Toque e mantenha pressionada a tela de fundo para gerenciar o plano de fundo, os widgets e as configurações."</string>
<string name="workspace_cling_longpress_title" msgid="9173998993909018310">"Plano de fundo, widgets e configurações"</string>
<string name="workspace_cling_longpress_description" msgid="4119994475505235248">"Toque e mantenha pressionado o segundo plano para personalizar"</string>
<string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"ENTENDI"</string>
- <string name="folder_cling_title" msgid="3894908818693254164">"Aqui está uma pasta"</string>
- <string name="folder_cling_create_folder" msgid="6158215559475836131">"Para criar uma pasta como esta, mantenha pressionado um app e mova-o para cima de outro."</string>
- <string name="cling_dismiss" msgid="8962359497601507581">"Ok"</string>
<string name="folder_opened" msgid="94695026776264709">"Pasta aberta, <xliff:g id="WIDTH">%1$d</xliff:g> por <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
<string name="folder_tap_to_close" msgid="1884479294466410023">"Toque para fechar a pasta"</string>
<string name="folder_tap_to_rename" msgid="9191075570492871147">"Toque para salvar o novo nome"</string>
@@ -111,14 +68,34 @@
<string name="widget_button_text" msgid="2880537293434387943">"Widgets"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"Planos de fundo"</string>
<string name="settings_button_text" msgid="8119458837558863227">"Configurações"</string>
- <string name="package_state_enqueued" msgid="6227252464303085641">"Aguardando"</string>
- <string name="package_state_downloading" msgid="4088770468458724721">"Transferindo"</string>
- <string name="package_state_installing" msgid="7588193972189849870">"Instalando"</string>
+ <string name="allow_rotation_title" msgid="2118706734511831751">"Permitir rotação"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Desconhecido"</string>
- <string name="package_state_error" msgid="7672093962724223588">"Não restaurado"</string>
- <string name="abandoned_clean_all" msgid="5256770727689657618">"Remover tudo"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Remover"</string>
<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="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>
+ <string name="item_removed" msgid="851119963877842327">"Item removido"</string>
+ <string name="action_move" msgid="4339390619886385032">"Mover item"</string>
+ <string name="move_to_empty_cell" msgid="2833711483015685619">"Mover para a linha <xliff:g id="NUMBER_0">%1$s</xliff:g>, coluna <xliff:g id="NUMBER_1">%2$s</xliff:g>"</string>
+ <string name="move_to_position" msgid="6750008980455459790">"Mover para a posição <xliff:g id="NUMBER">%1$s</xliff:g>"</string>
+ <string name="move_to_hotseat_position" msgid="6295412897075147808">"Mover para a posição <xliff:g id="NUMBER">%1$s</xliff:g> dos favoritos"</string>
+ <string name="item_moved" msgid="4606538322571412879">"Item movido"</string>
+ <string name="add_to_folder" msgid="9040534766770853243">"Adicionar à pasta: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="add_to_folder_with_app" msgid="4534929978967147231">"Adicionar à pasta com <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="added_to_folder" msgid="4793259502305558003">"Item adicionado à pasta"</string>
+ <string name="create_folder_with" msgid="4050141361160214248">"Criar pasta com: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="folder_created" msgid="6409794597405184510">"Pasta criada"</string>
+ <string name="action_move_to_workspace" msgid="1603837886334246317">"Mover para a tela inicial"</string>
+ <string name="action_move_screen_left" msgid="8854216831569401665">"Mover tela para a esquerda"</string>
+ <string name="action_move_screen_right" msgid="329334910274311123">"Mover tela para a direita"</string>
+ <string name="screen_moved" msgid="266230079505650577">"Tela movida"</string>
+ <string name="action_resize" msgid="1802976324781771067">"Redimensionar"</string>
+ <string name="action_increase_width" msgid="8773715375078513326">"Aumentar largura"</string>
+ <string name="action_increase_height" msgid="459390020612501122">"Aumentar altura"</string>
+ <string name="action_decrease_width" msgid="1374549771083094654">"Diminuir largura"</string>
+ <string name="action_decrease_height" msgid="282377193880900022">"Diminuir altura"</string>
+ <string name="widget_resized" msgid="9130327887929620">"Widget redimensionado para a largura <xliff:g id="NUMBER_0">%1$s</xliff:g>, altura <xliff:g id="NUMBER_1">%2$s</xliff:g>"</string>
</resources>
diff --git a/res/values-rm/strings.xml b/res/values-rm/strings.xml
index be35c6b09..0758148f5 100644
--- a/res/values-rm/strings.xml
+++ b/res/values-rm/strings.xml
@@ -152,8 +152,6 @@
<skip />
<!-- no translation found for first_run_cling_description (6447072552696253358) -->
<skip />
- <string name="first_run_cling_custom_content_hint" msgid="6090628589029352439"></string>
- <string name="first_run_cling_search_bar_hint" msgid="5909062802402452582"></string>
<!-- no translation found for first_run_cling_create_screens_hint (6950729526680114157) -->
<skip />
<!-- no translation found for migration_cling_title (9181776667882933767) -->
diff --git a/res/values-ro/strings.xml b/res/values-ro/strings.xml
index 54cb46c3f..88cbc79fc 100644
--- a/res/values-ro/strings.xml
+++ b/res/values-ro/strings.xml
@@ -20,57 +20,27 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="application_name" msgid="5181331383435256801">"Launcher3"</string>
- <string name="home" msgid="7658288663002113681">"Ecran de pornire"</string>
- <string name="uid_name" msgid="7820867637514617527">"Android Core Apps"</string>
<string name="folder_name" msgid="7371454440695724752"></string>
+ <string name="work_folder_name" msgid="3753320833950115786">"Work"</string>
<string name="activity_not_found" msgid="8071924732094499514">"Aplicația nu este instalată."</string>
<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="widgets_tab_label" msgid="2921133187116603919">"Widgeturi"</string>
- <string name="widget_adder" msgid="3201040140710381657">"Widgeturi"</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="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
- <string name="external_drop_widget_error" msgid="3165821058322217155">"Nu se poate plasa articolul pe ecranul de pornire."</string>
- <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Alegeți widgetul de creat"</string>
- <string name="rename_folder_label" msgid="3727762225964550653">"Numele dosarului"</string>
- <string name="rename_folder_title" msgid="3771389277707820891">"Redenumiți dosarul"</string>
- <string name="rename_action" msgid="5559600076028658757">"OK"</string>
- <string name="cancel_action" msgid="7009134900002915310">"Anulați"</string>
- <string name="menu_item_add_item" msgid="1264911265836810421">"Adăugați la Ecranul de pornire"</string>
- <string name="group_applications" msgid="3797214114206693605">"Aplicații"</string>
- <string name="group_shortcuts" msgid="6012256992764410535">"Comenzi rapide"</string>
- <string name="group_widgets" msgid="1569030723286851002">"Widgeturi"</string>
- <string name="completely_out_of_space" msgid="6106288382070760318">"Nu mai este loc pe ecranele de pornire."</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>
+ <string name="all_apps_no_search_results" msgid="6332185285860416787">"Nu s-a găsit nicio aplicație pentru „<xliff:g id="QUERY">%1$s</xliff:g>”"</string>
<string name="out_of_space" msgid="4691004494942118364">"Nu mai este loc pe acest Ecran de pornire."</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"Spațiu epuizat în bara Preferate"</string>
- <string name="invalid_hotseat_item" msgid="5779907847267573691">"Acest widget este prea mare pentru bara Preferate"</string>
- <string name="shortcut_installed" msgid="1701742129426969556">"Comanda rapidă „<xliff:g id="NAME">%s</xliff:g>\" a fost creată."</string>
- <string name="shortcut_uninstalled" msgid="8176767991305701821">"Comanda rapidă „<xliff:g id="NAME">%s</xliff:g>” a fost eliminată."</string>
- <string name="shortcut_duplicate" msgid="9167217446062498127">"Comanda rapidă „<xliff:g id="NAME">%s</xliff:g>” există deja."</string>
- <string name="title_select_shortcut" msgid="6680642571148153868">"Alegeți comanda rapidă"</string>
- <string name="title_select_application" msgid="3280812711670683644">"Alegeți aplicația"</string>
<string name="all_apps_button_label" msgid="9110807029020582876">"Aplicații"</string>
<string name="all_apps_home_button_label" msgid="252062713717058851">"Ecran de pornire"</string>
- <string name="delete_zone_label_workspace" msgid="4009607676751398685">"Eliminați"</string>
- <string name="delete_zone_label_all_apps" msgid="8083826390278958980">"Dezinstalați"</string>
<string name="delete_target_label" msgid="1822697352535677073">"Eliminați"</string>
<string name="delete_target_uninstall_label" msgid="5100785476250872595">"Dezinstalați"</string>
<string name="info_target_label" msgid="8053346143994679532">"Informații despre aplicație"</string>
- <string name="accessibility_all_apps_button" msgid="2603132375383800483">"Aplicații"</string>
- <string name="accessibility_delete_button" msgid="6466114477993744621">"Eliminați"</string>
- <string name="delete_zone_label_all_apps_system_app" msgid="449755632749610895">"Dezinstalați actualizarea"</string>
- <string name="cab_menu_delete_app" msgid="7435191475867183689">"Dezinstalați aplicația"</string>
- <string name="cab_menu_app_info" msgid="8593722221450362342">"Detalii despre aplicație"</string>
- <string name="cab_app_selection_text" msgid="374688303047985416">"1 aplicație selectată"</string>
- <string name="cab_widget_selection_text" msgid="1833458597831541241">"1 widget selectat"</string>
- <string name="cab_folder_selection_text" msgid="7999992513806132118">"1 dosar selectat"</string>
- <string name="cab_shortcut_selection_text" msgid="2103811025667946450">"1 comandă rapidă selectată"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"instalează comenzi rapide"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"Permite unei aplicații să adauge comenzi rapide fără intervenția utilizatorului."</string>
- <string name="permlab_uninstall_shortcut" msgid="864595034498083837">"dezinstalează comenzi rapide"</string>
- <string name="permdesc_uninstall_shortcut" msgid="5134129545001836849">"Permite aplicației să elimine comenzi rapide fără intervenția utilizatorului."</string>
<string name="permlab_read_settings" msgid="1941457408239617576">"citește setări și comenzi rapide pentru ecranul de pornire"</string>
<string name="permdesc_read_settings" msgid="5833423719057558387">"Permite aplicației să citească setările și comenzile rapide din ecranul de pornire."</string>
<string name="permlab_write_settings" msgid="3574213698004620587">"scrie setări și comenzi rapide pentru ecranul de pornire"</string>
@@ -78,30 +48,17 @@
<string name="gadget_error_text" msgid="6081085226050792095">"Problemă la încărcarea widgetului"</string>
<string name="gadget_setup_text" msgid="8274003207686040488">"Configurați"</string>
<string name="uninstall_system_app_text" msgid="4172046090762920660">"Aceasta este o aplicație de sistem și nu poate fi dezinstalată."</string>
- <string name="dream_name" msgid="1530253749244328964">"Rocket Launcher"</string>
<string name="folder_hint_text" msgid="6617836969016293992">"Dosar fără nume"</string>
- <string name="workspace_description_format" msgid="2950174241104043327">"Ecran de pornire %1$d"</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="apps_customize_apps_scroll_format" msgid="370005296147130238">"Pagina de aplicații %1$d din %2$d"</string>
- <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"Pagina de widgeturi %1$d din %2$d"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"Bun venit"</string>
- <string name="first_run_cling_description" msgid="6447072552696253358">"Simțiți-vă ca acasă."</string>
- <string name="first_run_cling_custom_content_hint" msgid="6090628589029352439"></string>
- <string name="first_run_cling_search_bar_hint" msgid="5909062802402452582"></string>
- <string name="first_run_cling_create_screens_hint" msgid="6950729526680114157">"Creați mai multe ecrane pentru aplicații și dosare"</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>
<string name="migration_cling_copy_apps" msgid="946331230090919440">"COPIAȚI PICTOGRAMELE"</string>
<string name="migration_cling_use_default" msgid="2626475813981258626">"REÎNCEPEȚI"</string>
- <string name="workspace_cling_title" msgid="5626202359865825661">"Organizați-vă spațiul"</string>
- <string name="workspace_cling_move_item" msgid="528201129978005352">"Atingeți lung fundalul pentru a gestiona imaginea de fundal, widgeturile și setările."</string>
<string name="workspace_cling_longpress_title" msgid="9173998993909018310">"Imagini de fundal, widgeturi și setări"</string>
<string name="workspace_cling_longpress_description" msgid="4119994475505235248">"Atingeți lung fundalul pentru a-l personaliza"</string>
<string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"AM ÎNȚELES"</string>
- <string name="folder_cling_title" msgid="3894908818693254164">"Iată un dosar"</string>
- <string name="folder_cling_create_folder" msgid="6158215559475836131">"Pentru a crea un dosar similar, atingeți și țineți degetul pe o aplicație, apoi mutați-o deasupra alteia."</string>
- <string name="cling_dismiss" msgid="8962359497601507581">"OK"</string>
<string name="folder_opened" msgid="94695026776264709">"Dosar deschis, <xliff:g id="WIDTH">%1$d</xliff:g> pe <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
<string name="folder_tap_to_close" msgid="1884479294466410023">"Atingeți pentru a închide dosarul"</string>
<string name="folder_tap_to_rename" msgid="9191075570492871147">"Atingeți pentru a salva redenumirea"</string>
@@ -111,14 +68,34 @@
<string name="widget_button_text" msgid="2880537293434387943">"Widgeturi"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"Imagini de fundal"</string>
<string name="settings_button_text" msgid="8119458837558863227">"Setări"</string>
- <string name="package_state_enqueued" msgid="6227252464303085641">"În așteptare"</string>
- <string name="package_state_downloading" msgid="4088770468458724721">"Se descarcă"</string>
- <string name="package_state_installing" msgid="7588193972189849870">"Se instalează"</string>
+ <string name="allow_rotation_title" msgid="2118706734511831751">"Permiteți rotirea"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Necunoscut"</string>
- <string name="package_state_error" msgid="7672093962724223588">"Nerestabilit"</string>
- <string name="abandoned_clean_all" msgid="5256770727689657618">"Eliminați-le pe toate"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Eliminați"</string>
<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="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>
+ <string name="item_removed" msgid="851119963877842327">"Element eliminat"</string>
+ <string name="action_move" msgid="4339390619886385032">"Mutați elementul"</string>
+ <string name="move_to_empty_cell" msgid="2833711483015685619">"Mutați pe rândul <xliff:g id="NUMBER_0">%1$s</xliff:g>, coloana <xliff:g id="NUMBER_1">%2$s</xliff:g>"</string>
+ <string name="move_to_position" msgid="6750008980455459790">"Mutați pe poziția <xliff:g id="NUMBER">%1$s</xliff:g>"</string>
+ <string name="move_to_hotseat_position" msgid="6295412897075147808">"Mutați în preferate, pe poziția <xliff:g id="NUMBER">%1$s</xliff:g>"</string>
+ <string name="item_moved" msgid="4606538322571412879">"Element mutat"</string>
+ <string name="add_to_folder" msgid="9040534766770853243">"Adăugați în dosar: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="add_to_folder_with_app" msgid="4534929978967147231">"Adăugați în dosarul cu <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="added_to_folder" msgid="4793259502305558003">"Element adăugat în dosar"</string>
+ <string name="create_folder_with" msgid="4050141361160214248">"Creați dosar cu: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="folder_created" msgid="6409794597405184510">"Dosar creat"</string>
+ <string name="action_move_to_workspace" msgid="1603837886334246317">"Mutați pe ecranul de pornire"</string>
+ <string name="action_move_screen_left" msgid="8854216831569401665">"Mutați ecranul la stânga"</string>
+ <string name="action_move_screen_right" msgid="329334910274311123">"Mutați ecranul la dreapta"</string>
+ <string name="screen_moved" msgid="266230079505650577">"Ecran mutat"</string>
+ <string name="action_resize" msgid="1802976324781771067">"Redimensionați"</string>
+ <string name="action_increase_width" msgid="8773715375078513326">"Creșteți lățimea"</string>
+ <string name="action_increase_height" msgid="459390020612501122">"Creșteți înălțimea"</string>
+ <string name="action_decrease_width" msgid="1374549771083094654">"Reduceți lățimea"</string>
+ <string name="action_decrease_height" msgid="282377193880900022">"Reduceți înălțimea"</string>
+ <string name="widget_resized" msgid="9130327887929620">"Widgetul a fost redimensionat la lățimea <xliff:g id="NUMBER_0">%1$s</xliff:g> și înălțimea <xliff:g id="NUMBER_1">%2$s</xliff:g>"</string>
</resources>
diff --git a/res/values-ru/strings.xml b/res/values-ru/strings.xml
index 70ef0f591..5b492fe12 100644
--- a/res/values-ru/strings.xml
+++ b/res/values-ru/strings.xml
@@ -20,57 +20,27 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="application_name" msgid="5181331383435256801">"Launcher3"</string>
- <string name="home" msgid="7658288663002113681">"Главный экран"</string>
- <string name="uid_name" msgid="7820867637514617527">"Основные приложения Android"</string>
<string name="folder_name" msgid="7371454440695724752"></string>
+ <string name="work_folder_name" msgid="3753320833950115786">"Работа"</string>
<string name="activity_not_found" msgid="8071924732094499514">"Приложение удалено"</string>
<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="widgets_tab_label" msgid="2921133187116603919">"Виджеты"</string>
- <string name="widget_adder" msgid="3201040140710381657">"Виджеты"</string>
<string name="toggle_weight_watcher" msgid="5645299835184636119">"Сведения о памяти"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"Чтобы выбрать виджет, нажмите на значок и удерживайте его."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d x %2$d"</string>
- <string name="external_drop_widget_error" msgid="3165821058322217155">"Не удалось добавить элемент на главный экран"</string>
- <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Выберите виджет"</string>
- <string name="rename_folder_label" msgid="3727762225964550653">"Название папки"</string>
- <string name="rename_folder_title" msgid="3771389277707820891">"Переименование папки"</string>
- <string name="rename_action" msgid="5559600076028658757">"ОК"</string>
- <string name="cancel_action" msgid="7009134900002915310">"Отмена"</string>
- <string name="menu_item_add_item" msgid="1264911265836810421">"Добавление на главный экран"</string>
- <string name="group_applications" msgid="3797214114206693605">"Приложения"</string>
- <string name="group_shortcuts" msgid="6012256992764410535">"Ярлыки"</string>
- <string name="group_widgets" msgid="1569030723286851002">"Виджеты"</string>
- <string name="completely_out_of_space" msgid="6106288382070760318">"На главных экранах все занято"</string>
+ <string name="all_apps_search_bar_hint" msgid="7084713969757597256">"Поиск приложений"</string>
+ <string name="all_apps_loading_message" msgid="7557140873644765180">"Загрузка…"</string>
+ <string name="all_apps_no_search_results" msgid="6332185285860416787">"По запросу \"<xliff:g id="QUERY">%1$s</xliff:g>\" ничего не найдено"</string>
<string name="out_of_space" msgid="4691004494942118364">"На этом экране все занято"</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"В разделе \"Избранное\" больше нет места"</string>
- <string name="invalid_hotseat_item" msgid="5779907847267573691">"Виджет слишком велик для раздела \"Избранное\""</string>
- <string name="shortcut_installed" msgid="1701742129426969556">"Ярлык \"<xliff:g id="NAME">%s</xliff:g>\" создан"</string>
- <string name="shortcut_uninstalled" msgid="8176767991305701821">"Ярлык \"<xliff:g id="NAME">%s</xliff:g>\" удален"</string>
- <string name="shortcut_duplicate" msgid="9167217446062498127">"Ярлык \"<xliff:g id="NAME">%s</xliff:g>\" уже существует"</string>
- <string name="title_select_shortcut" msgid="6680642571148153868">"Выбор ярлыка"</string>
- <string name="title_select_application" msgid="3280812711670683644">"Выбор приложения"</string>
<string name="all_apps_button_label" msgid="9110807029020582876">"Приложения"</string>
<string name="all_apps_home_button_label" msgid="252062713717058851">"Главный экран"</string>
- <string name="delete_zone_label_workspace" msgid="4009607676751398685">"Удалить"</string>
- <string name="delete_zone_label_all_apps" msgid="8083826390278958980">"Удалить"</string>
<string name="delete_target_label" msgid="1822697352535677073">"Удалить"</string>
<string name="delete_target_uninstall_label" msgid="5100785476250872595">"Удалить"</string>
<string name="info_target_label" msgid="8053346143994679532">"О приложении"</string>
- <string name="accessibility_all_apps_button" msgid="2603132375383800483">"Приложения"</string>
- <string name="accessibility_delete_button" msgid="6466114477993744621">"Удалить"</string>
- <string name="delete_zone_label_all_apps_system_app" msgid="449755632749610895">"Удалить обновление"</string>
- <string name="cab_menu_delete_app" msgid="7435191475867183689">"Удалить приложение"</string>
- <string name="cab_menu_app_info" msgid="8593722221450362342">"О приложении"</string>
- <string name="cab_app_selection_text" msgid="374688303047985416">"Выбрано 1 приложение"</string>
- <string name="cab_widget_selection_text" msgid="1833458597831541241">"Выбран 1 виджет"</string>
- <string name="cab_folder_selection_text" msgid="7999992513806132118">"Выбрана 1 папка"</string>
- <string name="cab_shortcut_selection_text" msgid="2103811025667946450">"Выбран 1 ярлык"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"Создание ярлыков"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"Приложение сможет самостоятельно добавлять ярлыки."</string>
- <string name="permlab_uninstall_shortcut" msgid="864595034498083837">"Удаление ярлыков"</string>
- <string name="permdesc_uninstall_shortcut" msgid="5134129545001836849">"Приложение сможет самостоятельно удалять ярлыки."</string>
<string name="permlab_read_settings" msgid="1941457408239617576">"Доступ к настройкам и ярлыкам главного экрана"</string>
<string name="permdesc_read_settings" msgid="5833423719057558387">"Приложение получит доступ к данным о настройках и ярлыках на главном экране."</string>
<string name="permlab_write_settings" msgid="3574213698004620587">"Изменение настроек и ярлыков главного экрана"</string>
@@ -78,30 +48,17 @@
<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>
- <string name="dream_name" msgid="1530253749244328964">"Rocket Launcher"</string>
<string name="folder_hint_text" msgid="6617836969016293992">"Папка без названия"</string>
- <string name="workspace_description_format" msgid="2950174241104043327">"Главный экран %1$d"</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="apps_customize_apps_scroll_format" msgid="370005296147130238">"Приложения: стр. %1$d из %2$d"</string>
- <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"Виджеты: стр. %1$d из %2$d"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"Добро пожаловать!"</string>
- <string name="first_run_cling_description" msgid="6447072552696253358">"Будьте как дома"</string>
- <string name="first_run_cling_custom_content_hint" msgid="6090628589029352439"></string>
- <string name="first_run_cling_search_bar_hint" msgid="5909062802402452582"></string>
- <string name="first_run_cling_create_screens_hint" msgid="6950729526680114157">"Создание дополнительных экранов для приложений и папок"</string>
<string name="migration_cling_title" msgid="9181776667882933767">"Копировать значки приложений"</string>
<string name="migration_cling_description" msgid="2752413805582227644">"Импортировать значки и папки со старого главного экрана?"</string>
<string name="migration_cling_copy_apps" msgid="946331230090919440">"КОПИРОВАТЬ ЗНАЧКИ"</string>
<string name="migration_cling_use_default" msgid="2626475813981258626">"ИСПОЛЬЗОВАТЬ СТАНДАРТНЫЙ МАКЕТ"</string>
- <string name="workspace_cling_title" msgid="5626202359865825661">"Организация рабочего пространства"</string>
- <string name="workspace_cling_move_item" msgid="528201129978005352">"Чтобы перейти к управлению обоями, виджетами и настройками, нажмите на фоновое изображение и удерживайте его."</string>
<string name="workspace_cling_longpress_title" msgid="9173998993909018310">"Обои, виджеты и настройки"</string>
<string name="workspace_cling_longpress_description" msgid="4119994475505235248">"Чтобы выполнить настройку, коснитесь фона и удерживайте его"</string>
<string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"ОК"</string>
- <string name="folder_cling_title" msgid="3894908818693254164">"Это папка"</string>
- <string name="folder_cling_create_folder" msgid="6158215559475836131">"Чтобы создать папку, нажмите и удерживайте значок приложения, а затем перетащите его на другой значок."</string>
- <string name="cling_dismiss" msgid="8962359497601507581">"ОК"</string>
<string name="folder_opened" msgid="94695026776264709">"Папка открыта, <xliff:g id="WIDTH">%1$d</xliff:g> x <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
<string name="folder_tap_to_close" msgid="1884479294466410023">"Нажмите, чтобы закрыть папку"</string>
<string name="folder_tap_to_rename" msgid="9191075570492871147">"Нажмите, чтобы подтвердить переименование"</string>
@@ -111,14 +68,34 @@
<string name="widget_button_text" msgid="2880537293434387943">"Виджеты"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"Обои"</string>
<string name="settings_button_text" msgid="8119458837558863227">"Настройки"</string>
- <string name="package_state_enqueued" msgid="6227252464303085641">"Ожидается"</string>
- <string name="package_state_downloading" msgid="4088770468458724721">"Скачивается"</string>
- <string name="package_state_installing" msgid="7588193972189849870">"Устанавливается"</string>
+ <string name="allow_rotation_title" msgid="2118706734511831751">"Разрешить автоповорот"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Неизвестно"</string>
- <string name="package_state_error" msgid="7672093962724223588">"Не восстановлен"</string>
- <string name="abandoned_clean_all" msgid="5256770727689657618">"Удалить все"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Удалить"</string>
<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="action_add_to_workspace" msgid="8902165848117513641">"Добавить на главный экран"</string>
+ <string name="action_move_here" msgid="2170188780612570250">"Переместить элемент сюда"</string>
+ <string name="item_added_to_workspace" msgid="4211073925752213539">"Элемент добавлен на главный экран"</string>
+ <string name="item_removed" msgid="851119963877842327">"Элемент удален"</string>
+ <string name="action_move" msgid="4339390619886385032">"Переместить элемент"</string>
+ <string name="move_to_empty_cell" msgid="2833711483015685619">"Переместить в ячейку <xliff:g id="NUMBER_0">%1$s</xliff:g> <xliff:g id="NUMBER_1">%2$s</xliff:g>"</string>
+ <string name="move_to_position" msgid="6750008980455459790">"Переместить в позицию <xliff:g id="NUMBER">%1$s</xliff:g>"</string>
+ <string name="move_to_hotseat_position" msgid="6295412897075147808">"Переместить в Избранное (<xliff:g id="NUMBER">%1$s</xliff:g>)"</string>
+ <string name="item_moved" msgid="4606538322571412879">"Элемент перемещен."</string>
+ <string name="add_to_folder" msgid="9040534766770853243">"Добавить в папку <xliff:g id="NAME">%1$s</xliff:g>."</string>
+ <string name="add_to_folder_with_app" msgid="4534929978967147231">"Добавить в папку с приложением \"<xliff:g id="NAME">%1$s</xliff:g>\""</string>
+ <string name="added_to_folder" msgid="4793259502305558003">"Элемент добавлен в папку."</string>
+ <string name="create_folder_with" msgid="4050141361160214248">"Создать папку с элементом <xliff:g id="NAME">%1$s</xliff:g>."</string>
+ <string name="folder_created" msgid="6409794597405184510">"Папка создана."</string>
+ <string name="action_move_to_workspace" msgid="1603837886334246317">"Переместить на главный экран"</string>
+ <string name="action_move_screen_left" msgid="8854216831569401665">"Переместить экран влево"</string>
+ <string name="action_move_screen_right" msgid="329334910274311123">"Переместить экран вправо"</string>
+ <string name="screen_moved" msgid="266230079505650577">"Экран перемещен"</string>
+ <string name="action_resize" msgid="1802976324781771067">"Изменить размер"</string>
+ <string name="action_increase_width" msgid="8773715375078513326">"Увеличить ширину"</string>
+ <string name="action_increase_height" msgid="459390020612501122">"Увеличить высоту"</string>
+ <string name="action_decrease_width" msgid="1374549771083094654">"Уменьшить ширину"</string>
+ <string name="action_decrease_height" msgid="282377193880900022">"Уменьшить высоту"</string>
+ <string name="widget_resized" msgid="9130327887929620">"Изменен размер виджета: до <xliff:g id="NUMBER_0">%1$s</xliff:g> в ширину и <xliff:g id="NUMBER_1">%2$s</xliff:g> в высоту"</string>
</resources>
diff --git a/res/values-si-rLK/strings.xml b/res/values-si-rLK/strings.xml
index ab3abb83b..68e3178ae 100644
--- a/res/values-si-rLK/strings.xml
+++ b/res/values-si-rLK/strings.xml
@@ -20,57 +20,27 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="application_name" msgid="5181331383435256801">"Launcher3"</string>
- <string name="home" msgid="7658288663002113681">"මුල් පිටුව"</string>
- <string name="uid_name" msgid="7820867637514617527">"Android මධ්‍ය යෙදුම්"</string>
<string name="folder_name" msgid="7371454440695724752"></string>
+ <string name="work_folder_name" msgid="3753320833950115786">"කාර්යාලය"</string>
<string name="activity_not_found" msgid="8071924732094499514">"යෙදුම ස්ථාපනය කර නැත."</string>
<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="widgets_tab_label" msgid="2921133187116603919">"විජට්"</string>
- <string name="widget_adder" msgid="3201040140710381657">"විජට්"</string>
<string name="toggle_weight_watcher" msgid="5645299835184636119">"Mem පෙන්වන්න"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"විජට් එක ස්පර්ශ කර අහුලා ගැනීමට අල්ලාගෙන සිටින්න."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
- <string name="external_drop_widget_error" msgid="3165821058322217155">"මෙම මුල් පිටු තිරය වෙත අයිතමය ඇද හෙළිය නොහැකි විය."</string>
- <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"සැදීමට විජට් එක තෝරන්න"</string>
- <string name="rename_folder_label" msgid="3727762225964550653">"ෆෝල්ඩරයේ නම"</string>
- <string name="rename_folder_title" msgid="3771389277707820891">"ෆෝල්ඩරය නැවත නම් කරන්න"</string>
- <string name="rename_action" msgid="5559600076028658757">"හරි"</string>
- <string name="cancel_action" msgid="7009134900002915310">"අවලංගු කරන්න"</string>
- <string name="menu_item_add_item" msgid="1264911265836810421">"මුල් පිටු තිරය වෙත එක් කරන්න"</string>
- <string name="group_applications" msgid="3797214114206693605">"යෙදුම්"</string>
- <string name="group_shortcuts" msgid="6012256992764410535">"කෙටිමං"</string>
- <string name="group_widgets" msgid="1569030723286851002">"විජට්"</string>
- <string name="completely_out_of_space" msgid="6106288382070760318">"මෙම මුල් පිටු තිර මත තවත් ඉඩ නැත."</string>
+ <string name="all_apps_search_bar_hint" msgid="7084713969757597256">"යෙදුම් සෙවීම"</string>
+ <string name="all_apps_loading_message" msgid="7557140873644765180">"යෙදුම් පූරණය වෙමින්…"</string>
+ <string name="all_apps_no_search_results" msgid="6332185285860416787">"\"<xliff:g id="QUERY">%1$s</xliff:g>\" සමග ගැළපෙන යෙදුම් හමු නොවිණි"</string>
<string name="out_of_space" msgid="4691004494942118364">"මෙම මුල් පිටු තිරය මත තවත් අවසර නැත."</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"ප්‍රියතම දෑ ඇති තැටියේ තවත් ඉඩ නොමැත"</string>
- <string name="invalid_hotseat_item" msgid="5779907847267573691">"ප්‍රියතම දෑ ඇති තැටිය සඳහා මෙම විජටය ඉතා විශාලය"</string>
- <string name="shortcut_installed" msgid="1701742129426969556">"\"<xliff:g id="NAME">%s</xliff:g>\" කෙටිමග සාදන ලදි."</string>
- <string name="shortcut_uninstalled" msgid="8176767991305701821">"\"<xliff:g id="NAME">%s</xliff:g>\" කෙටිමග ඉවත් කෙරිණි."</string>
- <string name="shortcut_duplicate" msgid="9167217446062498127">"\"<xliff:g id="NAME">%s</xliff:g>\" කෙටිමග දැනටමත් පවතී."</string>
- <string name="title_select_shortcut" msgid="6680642571148153868">"කෙටිමග තේරීම"</string>
- <string name="title_select_application" msgid="3280812711670683644">"යෙදුම තේරීම"</string>
<string name="all_apps_button_label" msgid="9110807029020582876">"යෙදුම්"</string>
<string name="all_apps_home_button_label" msgid="252062713717058851">"මුල් පිටුව"</string>
- <string name="delete_zone_label_workspace" msgid="4009607676751398685">"ඉවත් කරන්න"</string>
- <string name="delete_zone_label_all_apps" msgid="8083826390278958980">"අස්ථාපනය කරන්න"</string>
<string name="delete_target_label" msgid="1822697352535677073">"ඉවත් කරන්න"</string>
<string name="delete_target_uninstall_label" msgid="5100785476250872595">"අස්ථාපනය කරන්න"</string>
<string name="info_target_label" msgid="8053346143994679532">"යෙදුම් තොරතුරු"</string>
- <string name="accessibility_all_apps_button" msgid="2603132375383800483">"යෙදුම්"</string>
- <string name="accessibility_delete_button" msgid="6466114477993744621">"ඉවත් කරන්න"</string>
- <string name="delete_zone_label_all_apps_system_app" msgid="449755632749610895">"යාවත්කාලිනය අස්ථාපනය කරන්න"</string>
- <string name="cab_menu_delete_app" msgid="7435191475867183689">"යෙදුම අස්ථාපනය කරන්න"</string>
- <string name="cab_menu_app_info" msgid="8593722221450362342">"යෙදුම් විස්තර"</string>
- <string name="cab_app_selection_text" msgid="374688303047985416">"1 යෙදුමක් තෝරා ඇත"</string>
- <string name="cab_widget_selection_text" msgid="1833458597831541241">"1 විජටයක් තෝරා ඇත"</string>
- <string name="cab_folder_selection_text" msgid="7999992513806132118">"1 ෆෝල්ඩරයක් තෝරා ඇත"</string>
- <string name="cab_shortcut_selection_text" msgid="2103811025667946450">"1 කෙටිමඟක් තෝරා ඇත"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"කෙටිමං ස්ථාපනය කරන්න"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"පරිශීලක මැදිහත්වීමෙන් තොරව කෙටිමං එක් කිරීමට යෙදුමකට අවසර දෙයි."</string>
- <string name="permlab_uninstall_shortcut" msgid="864595034498083837">"කෙටිමං අස්ථාපනය කරන්න"</string>
- <string name="permdesc_uninstall_shortcut" msgid="5134129545001836849">"පරිශීලකයාගේ මැදිහත්වීමෙන් තොරව කෙටිමං ඉවත් කිරීමට යෙදුමකට අවසර දෙයි."</string>
<string name="permlab_read_settings" msgid="1941457408239617576">"මුල් පිටු සැකසීම් සහ කෙටිමං කියවන්න"</string>
<string name="permdesc_read_settings" msgid="5833423719057558387">"මුල් පිටුවේ ඇති සැකසීම් සහ කෙටිමං කියවීමට යෙදුමකට අවසර දෙයි."</string>
<string name="permlab_write_settings" msgid="3574213698004620587">"මුල් පිටු සැකසීම් සහ කෙටිමං ලියන්න"</string>
@@ -78,30 +48,17 @@
<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>
- <string name="dream_name" msgid="1530253749244328964">"රොකට් ආරම්භකය"</string>
<string name="folder_hint_text" msgid="6617836969016293992">"නම් නොකළ ෆෝල්ඩරය"</string>
- <string name="workspace_description_format" msgid="2950174241104043327">"මුල් පිටු තිරය %1$d"</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="apps_customize_apps_scroll_format" msgid="370005296147130238">"%2$d හි %1$d යෙදුම් පිටුව"</string>
- <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"විජට් පිටුව %2$d හි %1$d"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"සාදරයෙන් පිළිගනිමු"</string>
- <string name="first_run_cling_description" msgid="6447072552696253358">"ගෙදර ඉන්නවා වගේ ඉන්න."</string>
- <string name="first_run_cling_custom_content_hint" msgid="6090628589029352439"></string>
- <string name="first_run_cling_search_bar_hint" msgid="5909062802402452582"></string>
- <string name="first_run_cling_create_screens_hint" msgid="6950729526680114157">"යෙදුම් සහ ෆෝල්ඩර සඳහා තවත් තිර සාදන්න"</string>
<string name="migration_cling_title" msgid="9181776667882933767">"ඔබේ යෙදුම් නිරූපක පිටපත් කිරීම"</string>
<string name="migration_cling_description" msgid="2752413805582227644">"ඔබගේ පැරණි මුල් තිර වල නිරූපක සහ ෆෝල්ඩර ආයාත කරන්නද?"</string>
<string name="migration_cling_copy_apps" msgid="946331230090919440">"නිරූපක පිටපත් කරන්න"</string>
<string name="migration_cling_use_default" msgid="2626475813981258626">"අලුතින් පටන්ගන්න"</string>
- <string name="workspace_cling_title" msgid="5626202359865825661">"ඔබගේ ඉඩ සංවිධානය කරගන්න"</string>
- <string name="workspace_cling_move_item" msgid="528201129978005352">"බිතුපත, විජට් සහ සැකසීම් කළමනාකරණය කිරීමට පසුබිම ස්පර්ශ කර අල්ලාගෙන සිටින්න."</string>
<string name="workspace_cling_longpress_title" msgid="9173998993909018310">"වෝල්පේපර, විජට්, සහ සැකසීම්"</string>
<string name="workspace_cling_longpress_description" msgid="4119994475505235248">"පසුබිම අභිරුචිකරණය කිරීමට ස්පර්ශ කර අල්ලා සිටින්න"</string>
<string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"තේරුණා"</string>
- <string name="folder_cling_title" msgid="3894908818693254164">"මෙන්න ෆෝල්ඩරයක්"</string>
- <string name="folder_cling_create_folder" msgid="6158215559475836131">"මෙවැනි එකක් තැනීමට, යෙදුමක් තට්ටු කර අල්ලාගෙන සිටින්න, අනතුරුව එය තවත් එකක් උඩින් ගෙන යන්න."</string>
- <string name="cling_dismiss" msgid="8962359497601507581">"හරි"</string>
<string name="folder_opened" msgid="94695026776264709">"ෆෝල්ඩරය විවෘත විය, <xliff:g id="WIDTH">%1$d</xliff:g> හි <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
<string name="folder_tap_to_close" msgid="1884479294466410023">"ෆෝල්ඩරය වැසීමට ස්පර්ශ කරන්න"</string>
<string name="folder_tap_to_rename" msgid="9191075570492871147">"නැවත නම් කිරීම සුරැකීමට ස්පර්ශ කරන්න"</string>
@@ -111,14 +68,34 @@
<string name="widget_button_text" msgid="2880537293434387943">"විජට්"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"වෝල්පේපර"</string>
<string name="settings_button_text" msgid="8119458837558863227">"සැකසීම්"</string>
- <string name="package_state_enqueued" msgid="6227252464303085641">"රැඳී සිටිමින්"</string>
- <string name="package_state_downloading" msgid="4088770468458724721">"බාගනිමින්"</string>
- <string name="package_state_installing" msgid="7588193972189849870">"ස්ථාපනය කරමින්"</string>
+ <string name="allow_rotation_title" msgid="2118706734511831751">"කරකැවීමට ඉඩ දෙන්න"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"නොදනී"</string>
- <string name="package_state_error" msgid="7672093962724223588">"ප්‍රතිස්ථාපනය කළේ නැත"</string>
- <string name="abandoned_clean_all" msgid="5256770727689657618">"සියල්ල ඉවත් කරන්න"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"ඉවත් කරන්න"</string>
<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="action_add_to_workspace" msgid="8902165848117513641">"මුල් තිරය වෙත එක් කරන්න"</string>
+ <string name="action_move_here" msgid="2170188780612570250">"මෙතනට අයිතමය ගෙන එන්න"</string>
+ <string name="item_added_to_workspace" msgid="4211073925752213539">"අයිතමය මුල් තිරය වෙත එකතු කරන ලදි"</string>
+ <string name="item_removed" msgid="851119963877842327">"අයිතමය ඉවත් කරන ලදි"</string>
+ <string name="action_move" msgid="4339390619886385032">"අයිතමය ගෙනයන්න"</string>
+ <string name="move_to_empty_cell" msgid="2833711483015685619">"පේළිය <xliff:g id="NUMBER_0">%1$s</xliff:g> තීරුව <xliff:g id="NUMBER_1">%2$s</xliff:g> වෙත ගෙන යන්න"</string>
+ <string name="move_to_position" msgid="6750008980455459790">"<xliff:g id="NUMBER">%1$s</xliff:g> ස්ථානය වෙත ගෙන යන්න"</string>
+ <string name="move_to_hotseat_position" msgid="6295412897075147808">"ප්‍රියතම ස්ථානය <xliff:g id="NUMBER">%1$s</xliff:g> වෙත ගෙන යන්න"</string>
+ <string name="item_moved" msgid="4606538322571412879">"අයිතමය ගෙන යන ලදි"</string>
+ <string name="add_to_folder" msgid="9040534766770853243">"ෆෝල්ඩරය එක් කරන්න: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="add_to_folder_with_app" msgid="4534929978967147231">"<xliff:g id="NAME">%1$s</xliff:g> සමග ෆෝල්ඩරය වෙත එකතු කරන්න"</string>
+ <string name="added_to_folder" msgid="4793259502305558003">"අයිතමය ෆෝඩරය වෙතට එක් කරන ලදි"</string>
+ <string name="create_folder_with" msgid="4050141361160214248">"මේ සමග ෆෝල්ඩරය සාදන්න: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="folder_created" msgid="6409794597405184510">"ෆෝල්ඩරය සාදන ලදි"</string>
+ <string name="action_move_to_workspace" msgid="1603837886334246317">"මුල් තිරය වෙත ගෙන යන්න"</string>
+ <string name="action_move_screen_left" msgid="8854216831569401665">"තිරය වම් පැත්තට ගෙනයන්න"</string>
+ <string name="action_move_screen_right" msgid="329334910274311123">"තිරය දකුණු පැත්තට ගෙනයන්න"</string>
+ <string name="screen_moved" msgid="266230079505650577">"තිරය ගෙන යන ලදි"</string>
+ <string name="action_resize" msgid="1802976324781771067">"නැවත ප්‍රමාණගත කිරීම"</string>
+ <string name="action_increase_width" msgid="8773715375078513326">"පළල වැඩි කරන්න"</string>
+ <string name="action_increase_height" msgid="459390020612501122">"උස වැඩි කරන්න"</string>
+ <string name="action_decrease_width" msgid="1374549771083094654">"පළල අඩු කරන්න"</string>
+ <string name="action_decrease_height" msgid="282377193880900022">"උස අඩු කරන්න"</string>
+ <string name="widget_resized" msgid="9130327887929620">"විජට් පළල <xliff:g id="NUMBER_0">%1$s</xliff:g> උස <xliff:g id="NUMBER_1">%2$s</xliff:g> වෙත ප්‍රමාණකරණය කරන ලදි"</string>
</resources>
diff --git a/res/values-sk/strings.xml b/res/values-sk/strings.xml
index 05c5fc0c2..1cb76e3a8 100644
--- a/res/values-sk/strings.xml
+++ b/res/values-sk/strings.xml
@@ -20,57 +20,27 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="application_name" msgid="5181331383435256801">"Launcher3"</string>
- <string name="home" msgid="7658288663002113681">"Plocha"</string>
- <string name="uid_name" msgid="7820867637514617527">"Android Core Apps"</string>
<string name="folder_name" msgid="7371454440695724752"></string>
+ <string name="work_folder_name" msgid="3753320833950115786">"Pracovné"</string>
<string name="activity_not_found" msgid="8071924732094499514">"Aplikácia nie je nainštalovaná."</string>
<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="widgets_tab_label" msgid="2921133187116603919">"Miniaplikácie"</string>
- <string name="widget_adder" msgid="3201040140710381657">"Miniaplikácie"</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="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
- <string name="external_drop_widget_error" msgid="3165821058322217155">"Položku sa nepodarilo presunúť na túto plochu."</string>
- <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Zvoľte miniaplikáciu na vytvorenie"</string>
- <string name="rename_folder_label" msgid="3727762225964550653">"Názov priečinka"</string>
- <string name="rename_folder_title" msgid="3771389277707820891">"Premenovať priečinok"</string>
- <string name="rename_action" msgid="5559600076028658757">"OK"</string>
- <string name="cancel_action" msgid="7009134900002915310">"Zrušiť"</string>
- <string name="menu_item_add_item" msgid="1264911265836810421">"Pridať na plochu"</string>
- <string name="group_applications" msgid="3797214114206693605">"Aplikácie"</string>
- <string name="group_shortcuts" msgid="6012256992764410535">"Skratky"</string>
- <string name="group_widgets" msgid="1569030723286851002">"Miniaplikácie"</string>
- <string name="completely_out_of_space" msgid="6106288382070760318">"Na plochách už nie je miesto."</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>
+ <string name="all_apps_no_search_results" msgid="6332185285860416787">"Nenašli sa žiadne aplikácie zodpovedajúce dopytu <xliff:g id="QUERY">%1$s</xliff:g>"</string>
<string name="out_of_space" msgid="4691004494942118364">"Na tejto ploche už nie je miesto"</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"Na paneli Obľúbené položky už nie je miesto"</string>
- <string name="invalid_hotseat_item" msgid="5779907847267573691">"Táto miniaplikácia je príliš veľká pre panel Obľúbené položky"</string>
- <string name="shortcut_installed" msgid="1701742129426969556">"Odkaz <xliff:g id="NAME">%s</xliff:g> bol vytvorený."</string>
- <string name="shortcut_uninstalled" msgid="8176767991305701821">"Odkaz <xliff:g id="NAME">%s</xliff:g> bol odstránený."</string>
- <string name="shortcut_duplicate" msgid="9167217446062498127">"Odkaz <xliff:g id="NAME">%s</xliff:g> už existuje."</string>
- <string name="title_select_shortcut" msgid="6680642571148153868">"Vybrať odkaz"</string>
- <string name="title_select_application" msgid="3280812711670683644">"Vybrať aplikáciu"</string>
<string name="all_apps_button_label" msgid="9110807029020582876">"Aplikácie"</string>
<string name="all_apps_home_button_label" msgid="252062713717058851">"Domovská stránka"</string>
- <string name="delete_zone_label_workspace" msgid="4009607676751398685">"Odstrániť"</string>
- <string name="delete_zone_label_all_apps" msgid="8083826390278958980">"Odinštalovať"</string>
<string name="delete_target_label" msgid="1822697352535677073">"Odstrániť"</string>
<string name="delete_target_uninstall_label" msgid="5100785476250872595">"Odinštalovať"</string>
<string name="info_target_label" msgid="8053346143994679532">"O aplikácii"</string>
- <string name="accessibility_all_apps_button" msgid="2603132375383800483">"Aplikácie"</string>
- <string name="accessibility_delete_button" msgid="6466114477993744621">"Odstrániť"</string>
- <string name="delete_zone_label_all_apps_system_app" msgid="449755632749610895">"Odinštalovať aktualizáciu"</string>
- <string name="cab_menu_delete_app" msgid="7435191475867183689">"Odinštalovať aplikáciu"</string>
- <string name="cab_menu_app_info" msgid="8593722221450362342">"Podrobnosti o aplikácii"</string>
- <string name="cab_app_selection_text" msgid="374688303047985416">"Vybratá 1 aplikácia"</string>
- <string name="cab_widget_selection_text" msgid="1833458597831541241">"Vybratá 1 miniaplikácia"</string>
- <string name="cab_folder_selection_text" msgid="7999992513806132118">"Vybratý 1 priečinok"</string>
- <string name="cab_shortcut_selection_text" msgid="2103811025667946450">"Vybratý 1 odkaz"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"inštalovať odkazy"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"Povoľuje aplikácii pridať odkazy bez zásahu používateľa."</string>
- <string name="permlab_uninstall_shortcut" msgid="864595034498083837">"odinštalovať odkazy"</string>
- <string name="permdesc_uninstall_shortcut" msgid="5134129545001836849">"Povoľuje aplikácii odstrániť odkazy bez zásahu používateľa."</string>
<string name="permlab_read_settings" msgid="1941457408239617576">"čítanie nastavení a odkazov plochy"</string>
<string name="permdesc_read_settings" msgid="5833423719057558387">"Povoľuje aplikácii čítať nastavenia a odkazy na ploche."</string>
<string name="permlab_write_settings" msgid="3574213698004620587">"zápis nastavení a odkazov plochy"</string>
@@ -78,30 +48,17 @@
<string name="gadget_error_text" msgid="6081085226050792095">"Problém s načítaním miniaplikácií"</string>
<string name="gadget_setup_text" msgid="8274003207686040488">"Nastavenie"</string>
<string name="uninstall_system_app_text" msgid="4172046090762920660">"Toto je systémová aplikácia a nedá sa odinštalovať."</string>
- <string name="dream_name" msgid="1530253749244328964">"Raketomet"</string>
<string name="folder_hint_text" msgid="6617836969016293992">"Nepomenovaný priečinok"</string>
- <string name="workspace_description_format" msgid="2950174241104043327">"Plocha %1$d"</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="apps_customize_apps_scroll_format" msgid="370005296147130238">"Stránka aplikácií %1$d z %2$d"</string>
- <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"Stránka miniaplikácií %1$d z %2$d"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"Vitajte!"</string>
- <string name="first_run_cling_description" msgid="6447072552696253358">"Cíťte sa tu ako doma."</string>
- <string name="first_run_cling_custom_content_hint" msgid="6090628589029352439"></string>
- <string name="first_run_cling_search_bar_hint" msgid="5909062802402452582"></string>
- <string name="first_run_cling_create_screens_hint" msgid="6950729526680114157">"Vytvorte viac obrazoviek pre aplikácie a priečinky"</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>
<string name="migration_cling_copy_apps" msgid="946331230090919440">"SKOPÍROVAŤ IKONY"</string>
<string name="migration_cling_use_default" msgid="2626475813981258626">"ZAČAŤ ODZNOVA"</string>
- <string name="workspace_cling_title" msgid="5626202359865825661">"Usporiadajte svoj priestor"</string>
- <string name="workspace_cling_move_item" msgid="528201129978005352">"Ak chcete spravovať tapetu, miniaplikácie a nastavenia, dotknite sa pozadia a podržte."</string>
<string name="workspace_cling_longpress_title" msgid="9173998993909018310">"Pozadia, miniaplikácie a nastavenia"</string>
<string name="workspace_cling_longpress_description" msgid="4119994475505235248">"Ak si chcete pozadie prispôsobiť, klepnite naň a podržte ho"</string>
<string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"DOBRE"</string>
- <string name="folder_cling_title" msgid="3894908818693254164">"Tu je priečinok"</string>
- <string name="folder_cling_create_folder" msgid="6158215559475836131">"Ak chcete vytvoriť takýto priečinok, dotknite sa príslušnej aplikácie a podržte ju. Potom ju presuňte na druhú aplikáciu."</string>
- <string name="cling_dismiss" msgid="8962359497601507581">"OK"</string>
<string name="folder_opened" msgid="94695026776264709">"Otvorený priečinok, <xliff:g id="WIDTH">%1$d</xliff:g> x <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
<string name="folder_tap_to_close" msgid="1884479294466410023">"Dotykom zavriete priečinok"</string>
<string name="folder_tap_to_rename" msgid="9191075570492871147">"Dotykom premenovanie uložíte"</string>
@@ -111,14 +68,34 @@
<string name="widget_button_text" msgid="2880537293434387943">"Miniaplikácie"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"Tapety"</string>
<string name="settings_button_text" msgid="8119458837558863227">"Nastavenia"</string>
- <string name="package_state_enqueued" msgid="6227252464303085641">"Čaká sa"</string>
- <string name="package_state_downloading" msgid="4088770468458724721">"Sťahovanie"</string>
- <string name="package_state_installing" msgid="7588193972189849870">"Inštalácia"</string>
+ <string name="allow_rotation_title" msgid="2118706734511831751">"Povoliť otáčanie"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Neznáme"</string>
- <string name="package_state_error" msgid="7672093962724223588">"Nebolo obnovené"</string>
- <string name="abandoned_clean_all" msgid="5256770727689657618">"Odstrániť všetky"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Odstrániť"</string>
<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="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>
+ <string name="item_removed" msgid="851119963877842327">"Položka bola odstránená"</string>
+ <string name="action_move" msgid="4339390619886385032">"Presunúť položku"</string>
+ <string name="move_to_empty_cell" msgid="2833711483015685619">"Presunúť do stĺpca <xliff:g id="NUMBER_1">%2$s</xliff:g> v riadku <xliff:g id="NUMBER_0">%1$s</xliff:g>"</string>
+ <string name="move_to_position" msgid="6750008980455459790">"Presunúť na <xliff:g id="NUMBER">%1$s</xliff:g>. miesto"</string>
+ <string name="move_to_hotseat_position" msgid="6295412897075147808">"Presunúť na <xliff:g id="NUMBER">%1$s</xliff:g>. miesto v obľúbených položkách"</string>
+ <string name="item_moved" msgid="4606538322571412879">"Položka bola presunutá"</string>
+ <string name="add_to_folder" msgid="9040534766770853243">"Pridať do priečinka: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="add_to_folder_with_app" msgid="4534929978967147231">"Pridať do priečinka <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="added_to_folder" msgid="4793259502305558003">"Položka bola pridaná do priečinka"</string>
+ <string name="create_folder_with" msgid="4050141361160214248">"Vytvoriť priečinok pomocou: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="folder_created" msgid="6409794597405184510">"Priečinok bol vytvorený"</string>
+ <string name="action_move_to_workspace" msgid="1603837886334246317">"Presunúť na plochu"</string>
+ <string name="action_move_screen_left" msgid="8854216831569401665">"Presunúť obrazovku doľava"</string>
+ <string name="action_move_screen_right" msgid="329334910274311123">"Presunúť obrazovku doprava"</string>
+ <string name="screen_moved" msgid="266230079505650577">"Obrazovka bola posunutá"</string>
+ <string name="action_resize" msgid="1802976324781771067">"Zmeniť veľkosť"</string>
+ <string name="action_increase_width" msgid="8773715375078513326">"Zvýšiť šírku"</string>
+ <string name="action_increase_height" msgid="459390020612501122">"Zväčšiť výšku"</string>
+ <string name="action_decrease_width" msgid="1374549771083094654">"Znížiť šírku"</string>
+ <string name="action_decrease_height" msgid="282377193880900022">"Znížiť výšku"</string>
+ <string name="widget_resized" msgid="9130327887929620">"Veľkosť miniaplikácie bola zmenená na <xliff:g id="NUMBER_0">%1$s</xliff:g> x <xliff:g id="NUMBER_1">%2$s</xliff:g> (šírka x výška)"</string>
</resources>
diff --git a/res/values-sl/strings.xml b/res/values-sl/strings.xml
index d5a34d58f..92c69a562 100644
--- a/res/values-sl/strings.xml
+++ b/res/values-sl/strings.xml
@@ -20,57 +20,27 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="application_name" msgid="5181331383435256801">"Zaganjalnik3"</string>
- <string name="home" msgid="7658288663002113681">"Začetni zaslon"</string>
- <string name="uid_name" msgid="7820867637514617527">"Osnovne aplikacije sistema Android"</string>
<string name="folder_name" msgid="7371454440695724752"></string>
+ <string name="work_folder_name" msgid="3753320833950115786">"Služba"</string>
<string name="activity_not_found" msgid="8071924732094499514">"Aplikacija ni nameščena."</string>
<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="widgets_tab_label" msgid="2921133187116603919">"Pripomočki"</string>
- <string name="widget_adder" msgid="3201040140710381657">"Pripomočki"</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="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
- <string name="external_drop_widget_error" msgid="3165821058322217155">"Elementa ni mogoče spustiti na začetni zaslon."</string>
- <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Izberite pripomoček za ustvarjanje"</string>
- <string name="rename_folder_label" msgid="3727762225964550653">"Ime mape"</string>
- <string name="rename_folder_title" msgid="3771389277707820891">"Preimenovanje mape"</string>
- <string name="rename_action" msgid="5559600076028658757">"V redu"</string>
- <string name="cancel_action" msgid="7009134900002915310">"Prekliči"</string>
- <string name="menu_item_add_item" msgid="1264911265836810421">"Dodaj na začetni zaslon"</string>
- <string name="group_applications" msgid="3797214114206693605">"Aplikacije"</string>
- <string name="group_shortcuts" msgid="6012256992764410535">"Bližnjice"</string>
- <string name="group_widgets" msgid="1569030723286851002">"Pripomočki"</string>
- <string name="completely_out_of_space" msgid="6106288382070760318">"Na začetnih zaslonih ni več prostora."</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>
+ <string name="all_apps_no_search_results" msgid="6332185285860416787">"Ni aplikacij, ki bi ustrezale poizvedbi »<xliff:g id="QUERY">%1$s</xliff:g>«"</string>
<string name="out_of_space" msgid="4691004494942118364">"Na tem začetnem zaslonu ni več prostora."</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"V vrstici za priljubljene ni več prostora"</string>
- <string name="invalid_hotseat_item" msgid="5779907847267573691">"Ta pripomoček je prevelik za vrstico s priljubljenimi"</string>
- <string name="shortcut_installed" msgid="1701742129426969556">"Bližnjica »<xliff:g id="NAME">%s</xliff:g>« je ustvarjena."</string>
- <string name="shortcut_uninstalled" msgid="8176767991305701821">"Bližnjica »<xliff:g id="NAME">%s</xliff:g>« je bila odstranjena."</string>
- <string name="shortcut_duplicate" msgid="9167217446062498127">"Bližnjica »<xliff:g id="NAME">%s</xliff:g>« že obstaja."</string>
- <string name="title_select_shortcut" msgid="6680642571148153868">"Izberite bližnjico"</string>
- <string name="title_select_application" msgid="3280812711670683644">"Izberite aplikacijo"</string>
<string name="all_apps_button_label" msgid="9110807029020582876">"Aplikacije"</string>
<string name="all_apps_home_button_label" msgid="252062713717058851">"Začetni zaslon"</string>
- <string name="delete_zone_label_workspace" msgid="4009607676751398685">"Odstrani"</string>
- <string name="delete_zone_label_all_apps" msgid="8083826390278958980">"Odstrani"</string>
<string name="delete_target_label" msgid="1822697352535677073">"Odstrani"</string>
<string name="delete_target_uninstall_label" msgid="5100785476250872595">"Odstrani"</string>
<string name="info_target_label" msgid="8053346143994679532">"Podatki o aplikaciji"</string>
- <string name="accessibility_all_apps_button" msgid="2603132375383800483">"Aplikacije"</string>
- <string name="accessibility_delete_button" msgid="6466114477993744621">"Odstrani"</string>
- <string name="delete_zone_label_all_apps_system_app" msgid="449755632749610895">"Odstrani posodobitev"</string>
- <string name="cab_menu_delete_app" msgid="7435191475867183689">"Odstrani aplikacijo"</string>
- <string name="cab_menu_app_info" msgid="8593722221450362342">"Podrobnosti o aplikaciji"</string>
- <string name="cab_app_selection_text" msgid="374688303047985416">"Izbrana je 1 aplikacija"</string>
- <string name="cab_widget_selection_text" msgid="1833458597831541241">"Izbran je 1 pripomoček"</string>
- <string name="cab_folder_selection_text" msgid="7999992513806132118">"Izbrana je 1 mapa"</string>
- <string name="cab_shortcut_selection_text" msgid="2103811025667946450">"Izbrana je 1 bližnjica"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"namestitev bližnjic"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"Aplikaciji dovoli dodajanje bližnjic brez posredovanja uporabnika."</string>
- <string name="permlab_uninstall_shortcut" msgid="864595034498083837">"odstranitev bližnjic"</string>
- <string name="permdesc_uninstall_shortcut" msgid="5134129545001836849">"Aplikaciji dovoli odstranjevanje bližnjic brez posredovanja uporabnika."</string>
<string name="permlab_read_settings" msgid="1941457408239617576">"branje nastavitev in bližnjic na začetnem zaslonu"</string>
<string name="permdesc_read_settings" msgid="5833423719057558387">"Aplikaciji dovoli branje nastavitev in bližnjic na začetnem zaslonu."</string>
<string name="permlab_write_settings" msgid="3574213698004620587">"zapis nastavitev in bližnjic na začetnem zaslonu"</string>
@@ -78,30 +48,17 @@
<string name="gadget_error_text" msgid="6081085226050792095">"Težava pri nalaganju pripomočka"</string>
<string name="gadget_setup_text" msgid="8274003207686040488">"Nastavitev"</string>
<string name="uninstall_system_app_text" msgid="4172046090762920660">"To je sistemska aplikacija in je ni mogoče odstraniti."</string>
- <string name="dream_name" msgid="1530253749244328964">"Raketno izstrelišče"</string>
<string name="folder_hint_text" msgid="6617836969016293992">"Neimenovana mapa"</string>
- <string name="workspace_description_format" msgid="2950174241104043327">"Začetni zaslon %1$d"</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="apps_customize_apps_scroll_format" msgid="370005296147130238">"Stran aplikacij %1$d od %2$d"</string>
- <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"Stran pripomočkov %1$d od %2$d"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"Pozdravljeni"</string>
- <string name="first_run_cling_description" msgid="6447072552696253358">"Počutite se kot doma."</string>
- <string name="first_run_cling_custom_content_hint" msgid="6090628589029352439"></string>
- <string name="first_run_cling_search_bar_hint" msgid="5909062802402452582"></string>
- <string name="first_run_cling_create_screens_hint" msgid="6950729526680114157">"Ustvarite več zaslonov za aplikacije in mape"</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>
<string name="migration_cling_copy_apps" msgid="946331230090919440">"KOPIRAJ IKONE"</string>
<string name="migration_cling_use_default" msgid="2626475813981258626">"SVEŽ ZAČETEK"</string>
- <string name="workspace_cling_title" msgid="5626202359865825661">"Organizirajte svoj prostor"</string>
- <string name="workspace_cling_move_item" msgid="528201129978005352">"Če želite upravljati ozadje, pripomočke in nastavitve, se dotaknite ozadja in ga pridržite."</string>
<string name="workspace_cling_longpress_title" msgid="9173998993909018310">"Ozadja, pripomočki in nastavitve"</string>
<string name="workspace_cling_longpress_description" msgid="4119994475505235248">"Za prilagajanje se dotaknite ozadja in ga pridržite"</string>
<string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"V REDU"</string>
- <string name="folder_cling_title" msgid="3894908818693254164">"To je mapa"</string>
- <string name="folder_cling_create_folder" msgid="6158215559475836131">"Če želite ustvariti mapo, podobno tej, se dotaknite aplikacije in jo pridržite, nato pa jo premaknite nad drugo."</string>
- <string name="cling_dismiss" msgid="8962359497601507581">"V redu"</string>
<string name="folder_opened" msgid="94695026776264709">"Mapa je odprta, <xliff:g id="WIDTH">%1$d</xliff:g> krat <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
<string name="folder_tap_to_close" msgid="1884479294466410023">"Dotaknite se, da zaprete mapo"</string>
<string name="folder_tap_to_rename" msgid="9191075570492871147">"Dotaknite se, da shranite preimenovanje"</string>
@@ -111,14 +68,34 @@
<string name="widget_button_text" msgid="2880537293434387943">"Pripomočki"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"Ozadja"</string>
<string name="settings_button_text" msgid="8119458837558863227">"Nastavitve"</string>
- <string name="package_state_enqueued" msgid="6227252464303085641">"Čakanje"</string>
- <string name="package_state_downloading" msgid="4088770468458724721">"Prenašanje"</string>
- <string name="package_state_installing" msgid="7588193972189849870">"Nameščanje"</string>
+ <string name="allow_rotation_title" msgid="2118706734511831751">"Omogočanje zasuka"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Neznano"</string>
- <string name="package_state_error" msgid="7672093962724223588">"Ni obnovljen"</string>
- <string name="abandoned_clean_all" msgid="5256770727689657618">"Odstrani vse"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Odstrani"</string>
<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="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>
+ <string name="item_removed" msgid="851119963877842327">"Element je bil odstranjen"</string>
+ <string name="action_move" msgid="4339390619886385032">"Premik elementa"</string>
+ <string name="move_to_empty_cell" msgid="2833711483015685619">"Premik v <xliff:g id="NUMBER_0">%1$s</xliff:g>. vrstico <xliff:g id="NUMBER_1">%2$s</xliff:g>. stolpca"</string>
+ <string name="move_to_position" msgid="6750008980455459790">"Premk na mesto št. <xliff:g id="NUMBER">%1$s</xliff:g>"</string>
+ <string name="move_to_hotseat_position" msgid="6295412897075147808">"Premik na mesto priljubljenih št. <xliff:g id="NUMBER">%1$s</xliff:g>"</string>
+ <string name="item_moved" msgid="4606538322571412879">"Element je premaknjen"</string>
+ <string name="add_to_folder" msgid="9040534766770853243">"Dodajanje v mapo: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="add_to_folder_with_app" msgid="4534929978967147231">"Dodajanje v mapo z aplikacijo <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="added_to_folder" msgid="4793259502305558003">"Element je dodan v mapo"</string>
+ <string name="create_folder_with" msgid="4050141361160214248">"Ustvarjanje mape s tem: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="folder_created" msgid="6409794597405184510">"Mapa je ustvarjena"</string>
+ <string name="action_move_to_workspace" msgid="1603837886334246317">"Premik na začetni zaslon"</string>
+ <string name="action_move_screen_left" msgid="8854216831569401665">"Premik zaslona levo"</string>
+ <string name="action_move_screen_right" msgid="329334910274311123">"Premika zaslona desno"</string>
+ <string name="screen_moved" msgid="266230079505650577">"Zaslon je bil premaknjen"</string>
+ <string name="action_resize" msgid="1802976324781771067">"Spreminjanje velikosti"</string>
+ <string name="action_increase_width" msgid="8773715375078513326">"Povečanje širine"</string>
+ <string name="action_increase_height" msgid="459390020612501122">"Povečanje višine"</string>
+ <string name="action_decrease_width" msgid="1374549771083094654">"Zmanjšanje širine"</string>
+ <string name="action_decrease_height" msgid="282377193880900022">"Zmanjšanje višine"</string>
+ <string name="widget_resized" msgid="9130327887929620">"Velikost pripomočka je bila spremenjena na <xliff:g id="NUMBER_0">%1$s</xliff:g> širine in <xliff:g id="NUMBER_1">%2$s</xliff:g> višine"</string>
</resources>
diff --git a/res/values-sq-rAL/strings.xml b/res/values-sq-rAL/strings.xml
index 16afcf399..65aabf689 100644
--- a/res/values-sq-rAL/strings.xml
+++ b/res/values-sq-rAL/strings.xml
@@ -20,57 +20,27 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="application_name" msgid="5181331383435256801">"Nisësi3"</string>
- <string name="home" msgid="7658288663002113681">"Ekrani bazë"</string>
- <string name="uid_name" msgid="7820867637514617527">"Aplikacionet bazë të androidit"</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>
<string name="activity_not_available" msgid="7456344436509528827">"Aplikacioni nuk mundësohet"</string>
<string name="safemode_shortcut_error" msgid="9160126848219158407">"Aplikacioni i shkarkuar është i çaktivizuar në modalitetin e sigurt"</string>
<string name="safemode_widget_error" msgid="4863470563535682004">"Miniaplikacionet janë të çaktivizuara në modalitetin e sigurt"</string>
- <string name="widgets_tab_label" msgid="2921133187116603919">"Miniaplikacionet"</string>
- <string name="widget_adder" msgid="3201040140710381657">"Miniaplikacionet"</string>
<string name="toggle_weight_watcher" msgid="5645299835184636119">"Trego memorandumin"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"Prek dhe mbaj shtypur për të zgjedhur një miniaplikacion."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
- <string name="external_drop_widget_error" msgid="3165821058322217155">"Nuk mundi ta lëshonte artikullin në këtë ekran bazë."</string>
- <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Zgjidh miniaplikacionin për të krijuar"</string>
- <string name="rename_folder_label" msgid="3727762225964550653">"Emri i dosjes"</string>
- <string name="rename_folder_title" msgid="3771389277707820891">"Riemërto dosjen"</string>
- <string name="rename_action" msgid="5559600076028658757">"Në rregull"</string>
- <string name="cancel_action" msgid="7009134900002915310">"Anulo"</string>
- <string name="menu_item_add_item" msgid="1264911265836810421">"Shto në ekranin bazë"</string>
- <string name="group_applications" msgid="3797214114206693605">"Aplikacionet"</string>
- <string name="group_shortcuts" msgid="6012256992764410535">"Shkurtoret"</string>
- <string name="group_widgets" msgid="1569030723286851002">"Miniaplikacionet"</string>
- <string name="completely_out_of_space" msgid="6106288382070760318">"Nuk ka më hapësirë në ekranet e tua bazë."</string>
+ <string name="all_apps_search_bar_hint" msgid="7084713969757597256">"Kërko për aplikacione"</string>
+ <string name="all_apps_loading_message" msgid="7557140873644765180">"Po ngarkon aplikacionet..."</string>
+ <string name="all_apps_no_search_results" msgid="6332185285860416787">"Nuk u gjet asnjë aplikacion që përputhet me \"<xliff:g id="QUERY">%1$s</xliff:g>\""</string>
<string name="out_of_space" msgid="4691004494942118364">"Nuk ka më hapësirë në këtë ekran bazë."</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"Nuk ka më hapësirë në tabakanë \"Të preferuarat\""</string>
- <string name="invalid_hotseat_item" msgid="5779907847267573691">"Ky miniaplikacion është shumë i madh për tabakanë \"Të preferuarat\""</string>
- <string name="shortcut_installed" msgid="1701742129426969556">"Shkurtorja \"<xliff:g id="NAME">%s</xliff:g>\" u krijua."</string>
- <string name="shortcut_uninstalled" msgid="8176767991305701821">"Shkurtorja \"<xliff:g id="NAME">%s</xliff:g>\" u hoq."</string>
- <string name="shortcut_duplicate" msgid="9167217446062498127">"Shkurtorja \"<xliff:g id="NAME">%s</xliff:g>\" ekziston."</string>
- <string name="title_select_shortcut" msgid="6680642571148153868">"Zgjidh shkurtoren"</string>
- <string name="title_select_application" msgid="3280812711670683644">"Zgjidh aplikacionin"</string>
<string name="all_apps_button_label" msgid="9110807029020582876">"Aplikacionet"</string>
<string name="all_apps_home_button_label" msgid="252062713717058851">"Faqja kryesore"</string>
- <string name="delete_zone_label_workspace" msgid="4009607676751398685">"Hiq"</string>
- <string name="delete_zone_label_all_apps" msgid="8083826390278958980">"Çinstalo"</string>
<string name="delete_target_label" msgid="1822697352535677073">"Hiq"</string>
<string name="delete_target_uninstall_label" msgid="5100785476250872595">"Çinstalo"</string>
<string name="info_target_label" msgid="8053346143994679532">"Informacion mbi aplikacionin"</string>
- <string name="accessibility_all_apps_button" msgid="2603132375383800483">"Aplikacionet"</string>
- <string name="accessibility_delete_button" msgid="6466114477993744621">"Hiq"</string>
- <string name="delete_zone_label_all_apps_system_app" msgid="449755632749610895">"Çinstalo përditësimin"</string>
- <string name="cab_menu_delete_app" msgid="7435191475867183689">"Çinstalo aplikacionin"</string>
- <string name="cab_menu_app_info" msgid="8593722221450362342">"Detajet e aplikacionit"</string>
- <string name="cab_app_selection_text" msgid="374688303047985416">"U përzgjodh 1 aplikacion"</string>
- <string name="cab_widget_selection_text" msgid="1833458597831541241">"1 miniaplikacion i përzgjedhur"</string>
- <string name="cab_folder_selection_text" msgid="7999992513806132118">"U përzgjodh 1 dosje"</string>
- <string name="cab_shortcut_selection_text" msgid="2103811025667946450">"1 shkurtore e përzgjedhur"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"instalo shkurtore"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"Lejon një aplikacion të shtojë shkurtore pa ndërhyrjen e përdoruesit."</string>
- <string name="permlab_uninstall_shortcut" msgid="864595034498083837">"çinstalo shkurtoret"</string>
- <string name="permdesc_uninstall_shortcut" msgid="5134129545001836849">"Lejon aplikacionin të heqë shkurtore pa ndërhyrjen e përdoruesit."</string>
<string name="permlab_read_settings" msgid="1941457408239617576">"lexo cilësimet dhe shkurtoret e ekranit bazë"</string>
<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>
@@ -78,30 +48,17 @@
<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>
- <string name="dream_name" msgid="1530253749244328964">"Nisësi raketor"</string>
<string name="folder_hint_text" msgid="6617836969016293992">"Dosje e paemërtuar"</string>
- <string name="workspace_description_format" msgid="2950174241104043327">"Ekrani bazë: %1$d"</string>
<string name="default_scroll_format" msgid="7475544710230993317">"Faqja: %1$d nga gjithsej %2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"Ekrani bazë: %1$d nga gjithsej %2$d"</string>
- <string name="apps_customize_apps_scroll_format" msgid="370005296147130238">"Faqja e aplikacioneve: %1$d nga gjithsej %2$d"</string>
- <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"Faqja e miniaplikacioneve: %1$d nga gjithsej %2$d"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"Mirë se erdhe"</string>
- <string name="first_run_cling_description" msgid="6447072552696253358">"Ndihu si në shtëpinë tënde."</string>
- <string name="first_run_cling_custom_content_hint" msgid="6090628589029352439"></string>
- <string name="first_run_cling_search_bar_hint" msgid="5909062802402452582"></string>
- <string name="first_run_cling_create_screens_hint" msgid="6950729526680114157">"Krijo më shumë ekrane për aplikacione dhe dosje"</string>
<string name="migration_cling_title" msgid="9181776667882933767">"Kopjo ikonat e aplikacionit"</string>
<string name="migration_cling_description" msgid="2752413805582227644">"Të importohen ikona dhe dosje nga ekranet e vjetra bazë?"</string>
<string name="migration_cling_copy_apps" msgid="946331230090919440">"KOPJO IKONA"</string>
<string name="migration_cling_use_default" msgid="2626475813981258626">"FILLO NGA E PARA"</string>
- <string name="workspace_cling_title" msgid="5626202359865825661">"Organizo hapësirën tënde"</string>
- <string name="workspace_cling_move_item" msgid="528201129978005352">"Prek dhe mbaj shtypur sfondin për të menaxhuar imazhin në sfond, miniaplikacionet dhe cilësimet."</string>
<string name="workspace_cling_longpress_title" msgid="9173998993909018310">"Imazhe në sfond, miniaplikacione dhe cilësime"</string>
<string name="workspace_cling_longpress_description" msgid="4119994475505235248">"Prek dhe mbaj shtypur sfondin për ta personalizuar."</string>
<string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"E KUPTOVA!"</string>
- <string name="folder_cling_title" msgid="3894908818693254164">"Këtu ka një dosje"</string>
- <string name="folder_cling_create_folder" msgid="6158215559475836131">"Për të krijuar një të tillë, prek dhe mbaje aplikacionin, pastaj kaloje në një tjetër."</string>
- <string name="cling_dismiss" msgid="8962359497601507581">"Në rregull"</string>
<string name="folder_opened" msgid="94695026776264709">"Dosja u hap, <xliff:g id="WIDTH">%1$d</xliff:g> me <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
<string name="folder_tap_to_close" msgid="1884479294466410023">"Prek për të afruar dosjen"</string>
<string name="folder_tap_to_rename" msgid="9191075570492871147">"Prek për të ruajtur riemërtimin"</string>
@@ -111,14 +68,34 @@
<string name="widget_button_text" msgid="2880537293434387943">"Miniaplikacionet"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"Imazhet e sfondit"</string>
<string name="settings_button_text" msgid="8119458837558863227">"Cilësimet"</string>
- <string name="package_state_enqueued" msgid="6227252464303085641">"Po pret"</string>
- <string name="package_state_downloading" msgid="4088770468458724721">"Po shkarkohet"</string>
- <string name="package_state_installing" msgid="7588193972189849870">"Po instalohet"</string>
+ <string name="allow_rotation_title" msgid="2118706734511831751">"Lejo rotacionin"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"I panjohur"</string>
- <string name="package_state_error" msgid="7672093962724223588">"Nuk u restaurua"</string>
- <string name="abandoned_clean_all" msgid="5256770727689657618">"Hiqi të gjitha"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Hiq"</string>
<string name="abandoned_search" msgid="891119232568284442">"Kërko"</string>
<string name="abandoned_promises_title" msgid="7096178467971716750">"Aplikacioni nuk është i instaluar"</string>
<string name="abandoned_promise_explanation" msgid="3990027586878167529">"Aplikacioni për këtë ikonë nuk është i instaluar. Mund ta heqësh ose të kërkosh aplikacionin dhe ta instalosh atë në mënyrë manuale."</string>
+ <string name="action_add_to_workspace" msgid="8902165848117513641">"Shto në Ekranin bazë"</string>
+ <string name="action_move_here" msgid="2170188780612570250">"Zhvendose artikullin këtu"</string>
+ <string name="item_added_to_workspace" msgid="4211073925752213539">"Artikulli u shtua tek ekrani bazë"</string>
+ <string name="item_removed" msgid="851119963877842327">"Artikulli u hoq"</string>
+ <string name="action_move" msgid="4339390619886385032">"Zhvendose artikullin"</string>
+ <string name="move_to_empty_cell" msgid="2833711483015685619">"Zhvendos te rreshti <xliff:g id="NUMBER_0">%1$s</xliff:g>, kolona <xliff:g id="NUMBER_1">%2$s</xliff:g>"</string>
+ <string name="move_to_position" msgid="6750008980455459790">"Zhvendos te pozicioni <xliff:g id="NUMBER">%1$s</xliff:g>"</string>
+ <string name="move_to_hotseat_position" msgid="6295412897075147808">"Zhvendos te pozicioni <xliff:g id="NUMBER">%1$s</xliff:g> i preferencave"</string>
+ <string name="item_moved" msgid="4606538322571412879">"Artikulli u zhvendos"</string>
+ <string name="add_to_folder" msgid="9040534766770853243">"Shto te dosja: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="add_to_folder_with_app" msgid="4534929978967147231">"Shto te dosja me <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="added_to_folder" msgid="4793259502305558003">"Artikulli u shtua te dosja"</string>
+ <string name="create_folder_with" msgid="4050141361160214248">"Krijo një dosje me: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="folder_created" msgid="6409794597405184510">"Dosja u krijua"</string>
+ <string name="action_move_to_workspace" msgid="1603837886334246317">"Zhvendose në Ekranin bazë"</string>
+ <string name="action_move_screen_left" msgid="8854216831569401665">"Zhvendose ekranin në të majtë"</string>
+ <string name="action_move_screen_right" msgid="329334910274311123">"Zhvendose ekranin në të djathtë"</string>
+ <string name="screen_moved" msgid="266230079505650577">"Ekrani u zhvendos"</string>
+ <string name="action_resize" msgid="1802976324781771067">"Ndrysho madhësinë"</string>
+ <string name="action_increase_width" msgid="8773715375078513326">"Rrit gjerësinë"</string>
+ <string name="action_increase_height" msgid="459390020612501122">"Rrit lartësinë"</string>
+ <string name="action_decrease_width" msgid="1374549771083094654">"Zvogëlo gjerësinë"</string>
+ <string name="action_decrease_height" msgid="282377193880900022">"Zvogëlo lartësinë"</string>
+ <string name="widget_resized" msgid="9130327887929620">"Madhësia e miniaplikacionit u ndryshua me gjerësinë <xliff:g id="NUMBER_0">%1$s</xliff:g> dhe lartësinë <xliff:g id="NUMBER_1">%2$s</xliff:g>"</string>
</resources>
diff --git a/res/values-sr/strings.xml b/res/values-sr/strings.xml
index 9f40890c4..0f93bf3ea 100644
--- a/res/values-sr/strings.xml
+++ b/res/values-sr/strings.xml
@@ -20,57 +20,27 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="application_name" msgid="5181331383435256801">"Launcher3"</string>
- <string name="home" msgid="7658288663002113681">"Почетна"</string>
- <string name="uid_name" msgid="7820867637514617527">"Основне Android апликације"</string>
<string name="folder_name" msgid="7371454440695724752"></string>
+ <string name="work_folder_name" msgid="3753320833950115786">"Work"</string>
<string name="activity_not_found" msgid="8071924732094499514">"Апликација није инсталирана."</string>
<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="widgets_tab_label" msgid="2921133187116603919">"Виџети"</string>
- <string name="widget_adder" msgid="3201040140710381657">"Виџети"</string>
<string name="toggle_weight_watcher" msgid="5645299835184636119">"Прикажи меморију"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"Додирните и задржите да бисте изабрали виџет."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d×%2$d"</string>
- <string name="external_drop_widget_error" msgid="3165821058322217155">"Није могуће отпустити ставку на почетни екран."</string>
- <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Избор виџета за прављење"</string>
- <string name="rename_folder_label" msgid="3727762225964550653">"Назив директоријума"</string>
- <string name="rename_folder_title" msgid="3771389277707820891">"Преименовање директоријума"</string>
- <string name="rename_action" msgid="5559600076028658757">"Потврди"</string>
- <string name="cancel_action" msgid="7009134900002915310">"Откажи"</string>
- <string name="menu_item_add_item" msgid="1264911265836810421">"Додавање на почетни екран"</string>
- <string name="group_applications" msgid="3797214114206693605">"Апликације"</string>
- <string name="group_shortcuts" msgid="6012256992764410535">"Пречице"</string>
- <string name="group_widgets" msgid="1569030723286851002">"Виџети"</string>
- <string name="completely_out_of_space" msgid="6106288382070760318">"Нема више простора на почетним екранима."</string>
+ <string name="all_apps_search_bar_hint" msgid="7084713969757597256">"Претражите апликације"</string>
+ <string name="all_apps_loading_message" msgid="7557140873644765180">"Апликације се учитавају..."</string>
+ <string name="all_apps_no_search_results" msgid="6332185285860416787">"Није пронађена ниједна апликација за „<xliff:g id="QUERY">%1$s</xliff:g>“"</string>
<string name="out_of_space" msgid="4691004494942118364">"Нема више простора на овом почетном екрану."</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"Нема више простора на траци Омиљено"</string>
- <string name="invalid_hotseat_item" msgid="5779907847267573691">"Виџет је превелик за траку Омиљено"</string>
- <string name="shortcut_installed" msgid="1701742129426969556">"Пречица „<xliff:g id="NAME">%s</xliff:g>“ је направљена."</string>
- <string name="shortcut_uninstalled" msgid="8176767991305701821">"Пречица „<xliff:g id="NAME">%s</xliff:g>“ је уклоњена."</string>
- <string name="shortcut_duplicate" msgid="9167217446062498127">"Пречица „<xliff:g id="NAME">%s</xliff:g>“ већ постоји."</string>
- <string name="title_select_shortcut" msgid="6680642571148153868">"Избор пречице"</string>
- <string name="title_select_application" msgid="3280812711670683644">"Избор апликације"</string>
<string name="all_apps_button_label" msgid="9110807029020582876">"Апликације"</string>
<string name="all_apps_home_button_label" msgid="252062713717058851">"Почетна"</string>
- <string name="delete_zone_label_workspace" msgid="4009607676751398685">"Уклони"</string>
- <string name="delete_zone_label_all_apps" msgid="8083826390278958980">"Деинсталирај"</string>
<string name="delete_target_label" msgid="1822697352535677073">"Уклони"</string>
<string name="delete_target_uninstall_label" msgid="5100785476250872595">"Деинсталирај"</string>
<string name="info_target_label" msgid="8053346143994679532">"Информације о апликацији"</string>
- <string name="accessibility_all_apps_button" msgid="2603132375383800483">"Апликације"</string>
- <string name="accessibility_delete_button" msgid="6466114477993744621">"Уклони"</string>
- <string name="delete_zone_label_all_apps_system_app" msgid="449755632749610895">"Деинсталирај ажурирање"</string>
- <string name="cab_menu_delete_app" msgid="7435191475867183689">"Деинсталирање апликације"</string>
- <string name="cab_menu_app_info" msgid="8593722221450362342">"Детаљи о апликацији"</string>
- <string name="cab_app_selection_text" msgid="374688303047985416">"Изабрана је 1 апликација"</string>
- <string name="cab_widget_selection_text" msgid="1833458597831541241">"Изабран је 1 виџет"</string>
- <string name="cab_folder_selection_text" msgid="7999992513806132118">"Изабран је 1 директоријум"</string>
- <string name="cab_shortcut_selection_text" msgid="2103811025667946450">"Изабрана је 1 пречица"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"инсталирање пречица"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"Дозвољава апликацији да додаје пречице без интервенције корисника."</string>
- <string name="permlab_uninstall_shortcut" msgid="864595034498083837">"деинсталирање пречица"</string>
- <string name="permdesc_uninstall_shortcut" msgid="5134129545001836849">"Дозвољава апликацији да уклања пречице без интервенције корисника."</string>
<string name="permlab_read_settings" msgid="1941457408239617576">"читање подешавања и пречица на почетном екрану"</string>
<string name="permdesc_read_settings" msgid="5833423719057558387">"Дозвољава апликацији да чита подешавања и пречице на почетном екрану."</string>
<string name="permlab_write_settings" msgid="3574213698004620587">"уписивање подешавања и пречица на почетном екрану"</string>
@@ -78,30 +48,17 @@
<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>
- <string name="dream_name" msgid="1530253749244328964">"Лансер ракета"</string>
<string name="folder_hint_text" msgid="6617836969016293992">"Неименовани директоријум"</string>
- <string name="workspace_description_format" msgid="2950174241104043327">"Почетни екран %1$d"</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="apps_customize_apps_scroll_format" msgid="370005296147130238">"%1$d. страница апликација од %2$d"</string>
- <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"%1$d. страница виџета од %2$d"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"Добро дошли"</string>
- <string name="first_run_cling_description" msgid="6447072552696253358">"Осећајте се као код куће."</string>
- <string name="first_run_cling_custom_content_hint" msgid="6090628589029352439"></string>
- <string name="first_run_cling_search_bar_hint" msgid="5909062802402452582"></string>
- <string name="first_run_cling_create_screens_hint" msgid="6950729526680114157">"Направите још екрана за апликације и директоријуме"</string>
<string name="migration_cling_title" msgid="9181776667882933767">"Копирајте иконе апликација"</string>
<string name="migration_cling_description" msgid="2752413805582227644">"Увести иконе и директоријуме са старих почетних екрана?"</string>
<string name="migration_cling_copy_apps" msgid="946331230090919440">"КОПИРАЈТЕ ИКОНЕ"</string>
<string name="migration_cling_use_default" msgid="2626475813981258626">"ПОЧНИТЕ ИСПОЧЕТКА"</string>
- <string name="workspace_cling_title" msgid="5626202359865825661">"Организујте простор"</string>
- <string name="workspace_cling_move_item" msgid="528201129978005352">"Додирните позадину и задржите да бисте управљали позадином, виџетима и подешавањима."</string>
<string name="workspace_cling_longpress_title" msgid="9173998993909018310">"Позадине, виџети и подешавања"</string>
<string name="workspace_cling_longpress_description" msgid="4119994475505235248">"Додирните и задржите позадину да бисте прилагодили"</string>
<string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"ВАЖИ"</string>
- <string name="folder_cling_title" msgid="3894908818693254164">"Ево једног директоријума"</string>
- <string name="folder_cling_create_folder" msgid="6158215559475836131">"Да бисте направили директоријум попут овога, додирните и задржите апликацију, па је превуците преко друге."</string>
- <string name="cling_dismiss" msgid="8962359497601507581">"Потврди"</string>
<string name="folder_opened" msgid="94695026776264709">"Директоријум је отворен, <xliff:g id="WIDTH">%1$d</xliff:g> пута <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
<string name="folder_tap_to_close" msgid="1884479294466410023">"Додирните да бисте затворили директоријум"</string>
<string name="folder_tap_to_rename" msgid="9191075570492871147">"Додирните да бисте сачували промену имена"</string>
@@ -111,14 +68,34 @@
<string name="widget_button_text" msgid="2880537293434387943">"Виџети"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"Позадине"</string>
<string name="settings_button_text" msgid="8119458837558863227">"Подешавања"</string>
- <string name="package_state_enqueued" msgid="6227252464303085641">"Чека се"</string>
- <string name="package_state_downloading" msgid="4088770468458724721">"Преузима се"</string>
- <string name="package_state_installing" msgid="7588193972189849870">"Инсталира се"</string>
+ <string name="allow_rotation_title" msgid="2118706734511831751">"Дозволи ротацију"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Непознато"</string>
- <string name="package_state_error" msgid="7672093962724223588">"Није враћено"</string>
- <string name="abandoned_clean_all" msgid="5256770727689657618">"Уклони све"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Уклони"</string>
<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="action_add_to_workspace" msgid="8902165848117513641">"Додај на почетни екран"</string>
+ <string name="action_move_here" msgid="2170188780612570250">"Премести ставку овде"</string>
+ <string name="item_added_to_workspace" msgid="4211073925752213539">"Ставка је додата на почетни екран"</string>
+ <string name="item_removed" msgid="851119963877842327">"Ставка је уклоњена"</string>
+ <string name="action_move" msgid="4339390619886385032">"Премести ставку"</string>
+ <string name="move_to_empty_cell" msgid="2833711483015685619">"Премести у ред <xliff:g id="NUMBER_0">%1$s</xliff:g> и колону <xliff:g id="NUMBER_1">%2$s</xliff:g>"</string>
+ <string name="move_to_position" msgid="6750008980455459790">"Премести на <xliff:g id="NUMBER">%1$s</xliff:g>. позицију"</string>
+ <string name="move_to_hotseat_position" msgid="6295412897075147808">"Премести на <xliff:g id="NUMBER">%1$s</xliff:g>. позицију у омиљеним"</string>
+ <string name="item_moved" msgid="4606538322571412879">"Ставка је премештена"</string>
+ <string name="add_to_folder" msgid="9040534766770853243">"Додај у директоријум: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="add_to_folder_with_app" msgid="4534929978967147231">"Додај у директоријум у коме је <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="added_to_folder" msgid="4793259502305558003">"Ставка је додата у директоријум"</string>
+ <string name="create_folder_with" msgid="4050141361160214248">"Направите директоријум са: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="folder_created" msgid="6409794597405184510">"Директоријум је направљен"</string>
+ <string name="action_move_to_workspace" msgid="1603837886334246317">"Премести на почетни екран"</string>
+ <string name="action_move_screen_left" msgid="8854216831569401665">"Помери екран улево"</string>
+ <string name="action_move_screen_right" msgid="329334910274311123">"Помери екран удесно"</string>
+ <string name="screen_moved" msgid="266230079505650577">"Екран је померен"</string>
+ <string name="action_resize" msgid="1802976324781771067">"Промени величину"</string>
+ <string name="action_increase_width" msgid="8773715375078513326">"Повећај ширину"</string>
+ <string name="action_increase_height" msgid="459390020612501122">"Повећај висину"</string>
+ <string name="action_decrease_width" msgid="1374549771083094654">"Смањи ширину"</string>
+ <string name="action_decrease_height" msgid="282377193880900022">"Смањи висину"</string>
+ <string name="widget_resized" msgid="9130327887929620">"Величина виџета је промењена на ширину <xliff:g id="NUMBER_0">%1$s</xliff:g> и висину <xliff:g id="NUMBER_1">%2$s</xliff:g>"</string>
</resources>
diff --git a/res/values-sv/strings.xml b/res/values-sv/strings.xml
index 25f4d2623..93fce80ca 100644
--- a/res/values-sv/strings.xml
+++ b/res/values-sv/strings.xml
@@ -20,57 +20,27 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="application_name" msgid="5181331383435256801">"Launcher3"</string>
- <string name="home" msgid="7658288663002113681">"Startskärm"</string>
- <string name="uid_name" msgid="7820867637514617527">"Android Core Apps"</string>
<string name="folder_name" msgid="7371454440695724752"></string>
+ <string name="work_folder_name" msgid="3753320833950115786">"Arbete"</string>
<string name="activity_not_found" msgid="8071924732094499514">"Appen är inte installerad."</string>
<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="widgets_tab_label" msgid="2921133187116603919">"Widgetar"</string>
- <string name="widget_adder" msgid="3201040140710381657">"Widgetar"</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="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
- <string name="external_drop_widget_error" msgid="3165821058322217155">"Objektet kunde inte släppas på startskärmen."</string>
- <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Ange vilken widget du vill använda"</string>
- <string name="rename_folder_label" msgid="3727762225964550653">"Mappnamn"</string>
- <string name="rename_folder_title" msgid="3771389277707820891">"Byt namn på mapp"</string>
- <string name="rename_action" msgid="5559600076028658757">"OK"</string>
- <string name="cancel_action" msgid="7009134900002915310">"Avbryt"</string>
- <string name="menu_item_add_item" msgid="1264911265836810421">"Lägg till på startskärmen"</string>
- <string name="group_applications" msgid="3797214114206693605">"Appar"</string>
- <string name="group_shortcuts" msgid="6012256992764410535">"Genvägar"</string>
- <string name="group_widgets" msgid="1569030723286851002">"Widgetar"</string>
- <string name="completely_out_of_space" msgid="6106288382070760318">"Det finns inte plats för mer på dina startsidor."</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>
+ <string name="all_apps_no_search_results" msgid="6332185285860416787">"Det gick inte att hitta några appar som matchar <xliff:g id="QUERY">%1$s</xliff:g>"</string>
<string name="out_of_space" msgid="4691004494942118364">"Det finns inte plats för mer på den här startskärmen."</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"Favoritfältet är fullt"</string>
- <string name="invalid_hotseat_item" msgid="5779907847267573691">"Denna widget är för stor för favoritfältet"</string>
- <string name="shortcut_installed" msgid="1701742129426969556">"Genvägen <xliff:g id="NAME">%s</xliff:g> har skapats."</string>
- <string name="shortcut_uninstalled" msgid="8176767991305701821">"Genvägen <xliff:g id="NAME">%s</xliff:g> har tagits bort."</string>
- <string name="shortcut_duplicate" msgid="9167217446062498127">"Genvägen <xliff:g id="NAME">%s</xliff:g> finns redan."</string>
- <string name="title_select_shortcut" msgid="6680642571148153868">"Välj genväg"</string>
- <string name="title_select_application" msgid="3280812711670683644">"Välj app"</string>
<string name="all_apps_button_label" msgid="9110807029020582876">"Appar"</string>
<string name="all_apps_home_button_label" msgid="252062713717058851">"Startskärm"</string>
- <string name="delete_zone_label_workspace" msgid="4009607676751398685">"Ta bort"</string>
- <string name="delete_zone_label_all_apps" msgid="8083826390278958980">"Avinstallera"</string>
<string name="delete_target_label" msgid="1822697352535677073">"Ta bort"</string>
<string name="delete_target_uninstall_label" msgid="5100785476250872595">"Avinstallera"</string>
<string name="info_target_label" msgid="8053346143994679532">"Info om appen"</string>
- <string name="accessibility_all_apps_button" msgid="2603132375383800483">"Appar"</string>
- <string name="accessibility_delete_button" msgid="6466114477993744621">"Ta bort"</string>
- <string name="delete_zone_label_all_apps_system_app" msgid="449755632749610895">"Avinstallera uppdatering"</string>
- <string name="cab_menu_delete_app" msgid="7435191475867183689">"Avinstallera appen"</string>
- <string name="cab_menu_app_info" msgid="8593722221450362342">"Information om appen"</string>
- <string name="cab_app_selection_text" msgid="374688303047985416">"En app har valts"</string>
- <string name="cab_widget_selection_text" msgid="1833458597831541241">"En widget har valts"</string>
- <string name="cab_folder_selection_text" msgid="7999992513806132118">"En mapp har valts"</string>
- <string name="cab_shortcut_selection_text" msgid="2103811025667946450">"En genväg har valts"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"installera genvägar"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"Tillåter att en app lägger till genvägar utan åtgärd från användaren."</string>
- <string name="permlab_uninstall_shortcut" msgid="864595034498083837">"avinstallera genvägar"</string>
- <string name="permdesc_uninstall_shortcut" msgid="5134129545001836849">"Tillåter att appen tar bort genvägar utan åtgärd från användaren."</string>
<string name="permlab_read_settings" msgid="1941457408239617576">"läsa inställningar och genvägar för startsidan"</string>
<string name="permdesc_read_settings" msgid="5833423719057558387">"Tillåter att appen läser inställningar och genvägar på startsidan."</string>
<string name="permlab_write_settings" msgid="3574213698004620587">"skriva inställningar och genvägar för startsidan"</string>
@@ -78,30 +48,17 @@
<string name="gadget_error_text" msgid="6081085226050792095">"Det gick inte att läsa in widgeten"</string>
<string name="gadget_setup_text" msgid="8274003207686040488">"Konfiguration"</string>
<string name="uninstall_system_app_text" msgid="4172046090762920660">"Det här är en systemapp som inte kan avinstalleras."</string>
- <string name="dream_name" msgid="1530253749244328964">"Rocket Launcher"</string>
<string name="folder_hint_text" msgid="6617836969016293992">"Namnlös mapp"</string>
- <string name="workspace_description_format" msgid="2950174241104043327">"Startskärmen %1$d"</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="apps_customize_apps_scroll_format" msgid="370005296147130238">"Appsida %1$d av %2$d"</string>
- <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"Widget-sida %1$d av %2$d"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"Välkommen"</string>
- <string name="first_run_cling_description" msgid="6447072552696253358">"Känn dig som hemma."</string>
- <string name="first_run_cling_custom_content_hint" msgid="6090628589029352439"></string>
- <string name="first_run_cling_search_bar_hint" msgid="5909062802402452582"></string>
- <string name="first_run_cling_create_screens_hint" msgid="6950729526680114157">"Skapa fler skärmar för appar och mappar"</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>
<string name="migration_cling_copy_apps" msgid="946331230090919440">"KOPIERA IKONER"</string>
<string name="migration_cling_use_default" msgid="2626475813981258626">"BÖRJA OM"</string>
- <string name="workspace_cling_title" msgid="5626202359865825661">"Organisera ditt utrymme"</string>
- <string name="workspace_cling_move_item" msgid="528201129978005352">"Tryck länge på bakgrunden om du vill hantera bakgrundsbilder, widgetar och inställningar."</string>
<string name="workspace_cling_longpress_title" msgid="9173998993909018310">"Bakgrunder, widgetar och inställningar"</string>
<string name="workspace_cling_longpress_description" msgid="4119994475505235248">"Tryck länge på bakgrunden om du vill anpassa den"</string>
<string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"OK"</string>
- <string name="folder_cling_title" msgid="3894908818693254164">"Det här är en mapp"</string>
- <string name="folder_cling_create_folder" msgid="6158215559475836131">"Skapa en till mapp av det här slaget genom att trycka och hålla ned en app och sedan dra den ovanpå en annan."</string>
- <string name="cling_dismiss" msgid="8962359497601507581">"OK"</string>
<string name="folder_opened" msgid="94695026776264709">"Mappen är öppen, <xliff:g id="WIDTH">%1$d</xliff:g> gånger <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
<string name="folder_tap_to_close" msgid="1884479294466410023">"Tryck om du vill stänga mappen"</string>
<string name="folder_tap_to_rename" msgid="9191075570492871147">"Tryck om du vill spara det nya namnet"</string>
@@ -111,14 +68,34 @@
<string name="widget_button_text" msgid="2880537293434387943">"Widgetar"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"Bakgrunder"</string>
<string name="settings_button_text" msgid="8119458837558863227">"Inställningar"</string>
- <string name="package_state_enqueued" msgid="6227252464303085641">"Väntar"</string>
- <string name="package_state_downloading" msgid="4088770468458724721">"Hämtas"</string>
- <string name="package_state_installing" msgid="7588193972189849870">"Installerar"</string>
+ <string name="allow_rotation_title" msgid="2118706734511831751">"Tillåt rotering"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Okänt"</string>
- <string name="package_state_error" msgid="7672093962724223588">"Inte återställt"</string>
- <string name="abandoned_clean_all" msgid="5256770727689657618">"Ta bort alla"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Ta bort"</string>
<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="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>
+ <string name="item_removed" msgid="851119963877842327">"Objektet har tagits bort"</string>
+ <string name="action_move" msgid="4339390619886385032">"Flytta objekt"</string>
+ <string name="move_to_empty_cell" msgid="2833711483015685619">"Flytta till rad <xliff:g id="NUMBER_0">%1$s</xliff:g>, kolumn <xliff:g id="NUMBER_1">%2$s</xliff:g>"</string>
+ <string name="move_to_position" msgid="6750008980455459790">"Flytta till plats <xliff:g id="NUMBER">%1$s</xliff:g>"</string>
+ <string name="move_to_hotseat_position" msgid="6295412897075147808">"Flytta till favoritplats <xliff:g id="NUMBER">%1$s</xliff:g>"</string>
+ <string name="item_moved" msgid="4606538322571412879">"Objektet har flyttats"</string>
+ <string name="add_to_folder" msgid="9040534766770853243">"Lägg till i mapp: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="add_to_folder_with_app" msgid="4534929978967147231">"Lägg till i mappen med <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="added_to_folder" msgid="4793259502305558003">"Objektet har lagts till i mappen"</string>
+ <string name="create_folder_with" msgid="4050141361160214248">"Skapa mapp med: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="folder_created" msgid="6409794597405184510">"Mappen har skapats"</string>
+ <string name="action_move_to_workspace" msgid="1603837886334246317">"Flytta till startskärmen"</string>
+ <string name="action_move_screen_left" msgid="8854216831569401665">"Flytta skärmen till vänster"</string>
+ <string name="action_move_screen_right" msgid="329334910274311123">"Flytta skärmen till höger"</string>
+ <string name="screen_moved" msgid="266230079505650577">"Skärmen har flyttats"</string>
+ <string name="action_resize" msgid="1802976324781771067">"Ändra storlek"</string>
+ <string name="action_increase_width" msgid="8773715375078513326">"Öka bredden"</string>
+ <string name="action_increase_height" msgid="459390020612501122">"Öka höjden"</string>
+ <string name="action_decrease_width" msgid="1374549771083094654">"Minska bredden"</string>
+ <string name="action_decrease_height" msgid="282377193880900022">"Minska höjden"</string>
+ <string name="widget_resized" msgid="9130327887929620">"Widgetens storlek har ändrats till: bredd <xliff:g id="NUMBER_0">%1$s</xliff:g>, höjd <xliff:g id="NUMBER_1">%2$s</xliff:g>"</string>
</resources>
diff --git a/res/values-sw/strings.xml b/res/values-sw/strings.xml
index fa810618b..297b731bf 100644
--- a/res/values-sw/strings.xml
+++ b/res/values-sw/strings.xml
@@ -20,57 +20,27 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="application_name" msgid="5181331383435256801">"Kizindua3"</string>
- <string name="home" msgid="7658288663002113681">"Mwanzo"</string>
- <string name="uid_name" msgid="7820867637514617527">"Programu Msingi za Android"</string>
<string name="folder_name" msgid="7371454440695724752"></string>
+ <string name="work_folder_name" msgid="3753320833950115786">"Kazini"</string>
<string name="activity_not_found" msgid="8071924732094499514">"Programu haijasakinishwa."</string>
<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="widgets_tab_label" msgid="2921133187116603919">"Wijeti"</string>
- <string name="widget_adder" msgid="3201040140710381657">"Wijeti"</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="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
- <string name="external_drop_widget_error" msgid="3165821058322217155">"Haikuweza kudondosha kipengee kwenye skrini hii ya Kwanza."</string>
- <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Chagua wijeti ili uunde"</string>
- <string name="rename_folder_label" msgid="3727762225964550653">"Jina la folda"</string>
- <string name="rename_folder_title" msgid="3771389277707820891">"lipe folda jina jipya"</string>
- <string name="rename_action" msgid="5559600076028658757">"SAWA"</string>
- <string name="cancel_action" msgid="7009134900002915310">"Ghairi"</string>
- <string name="menu_item_add_item" msgid="1264911265836810421">"Ongeza kwenye skrini ya Mwanzo"</string>
- <string name="group_applications" msgid="3797214114206693605">"Programu"</string>
- <string name="group_shortcuts" msgid="6012256992764410535">"Njia za mkato"</string>
- <string name="group_widgets" msgid="1569030723286851002">"Wijeti"</string>
- <string name="completely_out_of_space" msgid="6106288382070760318">"Hakuna nafasi zaidi kwenye skrini zako za Nyumbani."</string>
+ <string name="all_apps_search_bar_hint" msgid="7084713969757597256">"Tafuta Programu"</string>
+ <string name="all_apps_loading_message" msgid="7557140873644765180">"Inapakia Programu..."</string>
+ <string name="all_apps_no_search_results" msgid="6332185285860416787">"Haikupata programu zinazolingana na \"<xliff:g id="QUERY">%1$s</xliff:g>\""</string>
<string name="out_of_space" msgid="4691004494942118364">"Hakuna nafasi katika skrini hii ya Mwanzo."</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"Hakuna nafasi zaidi katika treya ya Vipendeleo"</string>
- <string name="invalid_hotseat_item" msgid="5779907847267573691">"Wijeti hii ni kubwa mno kwa treya ya Vipendeleo"</string>
- <string name="shortcut_installed" msgid="1701742129426969556">"Njia ya mkato ya \"<xliff:g id="NAME">%s</xliff:g>\" imeundwa."</string>
- <string name="shortcut_uninstalled" msgid="8176767991305701821">"Njia ya mkato ya \"<xliff:g id="NAME">%s</xliff:g>\" iliondolewa."</string>
- <string name="shortcut_duplicate" msgid="9167217446062498127">"\"<xliff:g id="NAME">%s</xliff:g>\" la njia ya mkato tayari lipo."</string>
- <string name="title_select_shortcut" msgid="6680642571148153868">"Chagua njia ya mkato"</string>
- <string name="title_select_application" msgid="3280812711670683644">"Chagua programu"</string>
<string name="all_apps_button_label" msgid="9110807029020582876">"Programu"</string>
<string name="all_apps_home_button_label" msgid="252062713717058851">"Mwanzo"</string>
- <string name="delete_zone_label_workspace" msgid="4009607676751398685">"Ondoa"</string>
- <string name="delete_zone_label_all_apps" msgid="8083826390278958980">"Ondoa"</string>
<string name="delete_target_label" msgid="1822697352535677073">"Ondoa"</string>
<string name="delete_target_uninstall_label" msgid="5100785476250872595">"Ondoa"</string>
<string name="info_target_label" msgid="8053346143994679532">"Maelezo ya programu"</string>
- <string name="accessibility_all_apps_button" msgid="2603132375383800483">"Programu"</string>
- <string name="accessibility_delete_button" msgid="6466114477993744621">"Ondoa"</string>
- <string name="delete_zone_label_all_apps_system_app" msgid="449755632749610895">"Ondoa sasisho"</string>
- <string name="cab_menu_delete_app" msgid="7435191475867183689">"Ondoa programu"</string>
- <string name="cab_menu_app_info" msgid="8593722221450362342">"Maelezo ya programu"</string>
- <string name="cab_app_selection_text" msgid="374688303047985416">"Programu 1 imechaguliwa"</string>
- <string name="cab_widget_selection_text" msgid="1833458597831541241">"Wijeti 1 imechaguliwa"</string>
- <string name="cab_folder_selection_text" msgid="7999992513806132118">"Folda 1 limechaguliwa"</string>
- <string name="cab_shortcut_selection_text" msgid="2103811025667946450">"Njia 1 ya mkato imechaguliwa"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"kuweka njia za mkato"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"Huruhusu programu kuongeza njia za mkato bila mtumiaji kuingilia kati."</string>
- <string name="permlab_uninstall_shortcut" msgid="864595034498083837">"ondoa njia za mikato"</string>
- <string name="permdesc_uninstall_shortcut" msgid="5134129545001836849">"Huruhusu programu kuondoa njia za mikato bila mtumiaji kuingilia kati."</string>
<string name="permlab_read_settings" msgid="1941457408239617576">"soma mipangilio ya Mwanzo na njia za mkato"</string>
<string name="permdesc_read_settings" msgid="5833423719057558387">"Huruhusu programu kusoma mipangilio na njia za mikato zilizo katika skirini ya Mwanzo."</string>
<string name="permlab_write_settings" msgid="3574213698004620587">"andika mipangilio ya skrini ya Mwanzo na njia za mkato"</string>
@@ -78,32 +48,19 @@
<string name="gadget_error_text" msgid="6081085226050792095">"Tatizo la kupakia wijeti"</string>
<string name="gadget_setup_text" msgid="8274003207686040488">"Sanidi"</string>
<string name="uninstall_system_app_text" msgid="4172046090762920660">"Hii ni programu ya mfumo na haiwezi kuondolewa."</string>
- <string name="dream_name" msgid="1530253749244328964">"Kizinduzi cha Roketi"</string>
<string name="folder_hint_text" msgid="6617836969016293992">"Folda isiyo na jina"</string>
- <string name="workspace_description_format" msgid="2950174241104043327">"Skrini ya mwazo %1$d"</string>
<string name="default_scroll_format" msgid="7475544710230993317">"Ukurasa%1$d wa %2$d"</string>
<!-- String.format failed for translation -->
<!-- no translation found for workspace_scroll_format (8458889198184077399) -->
<skip />
- <string name="apps_customize_apps_scroll_format" msgid="370005296147130238">"Ukurasa wa programu %1$d ya %2$d"</string>
- <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"Ukurasa wa wijeti %1$d ya %2$d"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"Karibu"</string>
- <string name="first_run_cling_description" msgid="6447072552696253358">"Jisikie huru."</string>
- <string name="first_run_cling_custom_content_hint" msgid="6090628589029352439"></string>
- <string name="first_run_cling_search_bar_hint" msgid="5909062802402452582"></string>
- <string name="first_run_cling_create_screens_hint" msgid="6950729526680114157">"Unda skrini zaidi za programu na folda"</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>
<string name="migration_cling_copy_apps" msgid="946331230090919440">"NAKILI IKONI"</string>
<string name="migration_cling_use_default" msgid="2626475813981258626">"ANZA UPYA"</string>
- <string name="workspace_cling_title" msgid="5626202359865825661">"Panga nafasi yako"</string>
- <string name="workspace_cling_move_item" msgid="528201129978005352">"Gusa na ushikilie mandharinyuma ili udhibiti mandhari, wijeti, na mipangilio."</string>
<string name="workspace_cling_longpress_title" msgid="9173998993909018310">"Mandhari, wijeti, na mipangilio"</string>
<string name="workspace_cling_longpress_description" msgid="4119994475505235248">"Gusa na ushikilie mandhari ili uweke mapendeleo"</string>
<string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"NIMEELEWA"</string>
- <string name="folder_cling_title" msgid="3894908818693254164">"Hii ni folda"</string>
- <string name="folder_cling_create_folder" msgid="6158215559475836131">"Ili kuunda kama hii, gusa na ushikilie programu, kisha ipitishe juu ya nyingine."</string>
- <string name="cling_dismiss" msgid="8962359497601507581">"SAWA"</string>
<string name="folder_opened" msgid="94695026776264709">"Folda imefunguliwa, <xliff:g id="WIDTH">%1$d</xliff:g> kwa <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
<string name="folder_tap_to_close" msgid="1884479294466410023">"Gusa ili ufunge folda"</string>
<string name="folder_tap_to_rename" msgid="9191075570492871147">"Gusa ili uhifadhi jina jipya"</string>
@@ -113,14 +70,34 @@
<string name="widget_button_text" msgid="2880537293434387943">"Wijeti"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"Mandhari"</string>
<string name="settings_button_text" msgid="8119458837558863227">"Mipangilio"</string>
- <string name="package_state_enqueued" msgid="6227252464303085641">"Inasubiri"</string>
- <string name="package_state_downloading" msgid="4088770468458724721">"Inapakua"</string>
- <string name="package_state_installing" msgid="7588193972189849870">"Inasakinisha"</string>
+ <string name="allow_rotation_title" msgid="2118706734511831751">"Ruhusu kuzungusha"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Yasiyojulikana"</string>
- <string name="package_state_error" msgid="7672093962724223588">"Haijarejeshwa"</string>
- <string name="abandoned_clean_all" msgid="5256770727689657618">"Ondoa Zote"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Ondoa"</string>
<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="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>
+ <string name="item_removed" msgid="851119963877842327">"Kipengee kimeondolewa"</string>
+ <string name="action_move" msgid="4339390619886385032">"Hamisha kipengee"</string>
+ <string name="move_to_empty_cell" msgid="2833711483015685619">"Hamishia safu mlalo <xliff:g id="NUMBER_0">%1$s</xliff:g> safu wima <xliff:g id="NUMBER_1">%2$s</xliff:g>"</string>
+ <string name="move_to_position" msgid="6750008980455459790">"Hamishia nafasi ya <xliff:g id="NUMBER">%1$s</xliff:g>"</string>
+ <string name="move_to_hotseat_position" msgid="6295412897075147808">"Hamishia nafasi inayopendwa ya <xliff:g id="NUMBER">%1$s</xliff:g>"</string>
+ <string name="item_moved" msgid="4606538322571412879">"Kipengee kimesogezwa"</string>
+ <string name="add_to_folder" msgid="9040534766770853243">"Ongeza kwenye folda: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="add_to_folder_with_app" msgid="4534929978967147231">"Ongeza kwenye folda iliyo na <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="added_to_folder" msgid="4793259502305558003">"Kipengee kimeongezwa kwenye folda"</string>
+ <string name="create_folder_with" msgid="4050141361160214248">"Unda folda ukitumia: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="folder_created" msgid="6409794597405184510">"Folda imeundwa"</string>
+ <string name="action_move_to_workspace" msgid="1603837886334246317">"Hamishia Skrini ya kwanza"</string>
+ <string name="action_move_screen_left" msgid="8854216831569401665">"Sogeza skrini kushoto"</string>
+ <string name="action_move_screen_right" msgid="329334910274311123">"Sogeza skrini kulia"</string>
+ <string name="screen_moved" msgid="266230079505650577">"Skrini imesogezwa"</string>
+ <string name="action_resize" msgid="1802976324781771067">"Badilisha ukubwa"</string>
+ <string name="action_increase_width" msgid="8773715375078513326">"Ongeza upana"</string>
+ <string name="action_increase_height" msgid="459390020612501122">"Ongeza urefu"</string>
+ <string name="action_decrease_width" msgid="1374549771083094654">"Punguza upana"</string>
+ <string name="action_decrease_height" msgid="282377193880900022">"Punguza urefu"</string>
+ <string name="widget_resized" msgid="9130327887929620">"Wijeti imepunguzwa hadi upana <xliff:g id="NUMBER_0">%1$s</xliff:g> urefu <xliff:g id="NUMBER_1">%2$s</xliff:g>"</string>
</resources>
diff --git a/res/values-sw600dp/config.xml b/res/values-sw600dp/config.xml
index 15d5725d1..a7345a705 100644
--- a/res/values-sw600dp/config.xml
+++ b/res/values-sw600dp/config.xml
@@ -4,8 +4,4 @@
<!-- DragController -->
<integer name="config_flingToDeleteMinVelocity">-1000</integer>
-
- <!-- Camera distance for the overscroll effect. We use a higher value here because the
- workspace screens run nearly flush to the edge of the screen-->
- <integer name="config_cameraDistance">14000</integer>
</resources>
diff --git a/res/values-sw600dp/dimens.xml b/res/values-sw600dp/dimens.xml
index 28679be2e..2651fbb3f 100644
--- a/res/values-sw600dp/dimens.xml
+++ b/res/values-sw600dp/dimens.xml
@@ -15,14 +15,10 @@
-->
<resources>
- <dimen name="app_icon_size">64dp</dimen>
-
-<!-- AppsCustomize -->
- <dimen name="apps_customize_tab_bar_height">60dp</dimen>
- <dimen name="apps_customize_tab_bar_margin_top">8dp</dimen>
- <dimen name="app_widget_preview_label_margin_top">8dp</dimen>
- <dimen name="app_widget_preview_label_margin_left">@dimen/app_widget_preview_padding_left</dimen>
- <dimen name="app_widget_preview_label_margin_right">@dimen/app_widget_preview_padding_right</dimen>
+<!-- All Apps -->
+ <dimen name="all_apps_grid_view_start_margin">0dp</dimen>
+ <dimen name="all_apps_grid_section_text_size">26sp</dimen>
+ <dimen name="all_apps_icon_top_bottom_padding">12dp</dimen>
<!-- Cling -->
<dimen name="cling_migration_logo_height">400dp</dimen>
diff --git a/res/values-sw600dp/styles.xml b/res/values-sw600dp/styles.xml
deleted file mode 100644
index bcbbafdbb..000000000
--- a/res/values-sw600dp/styles.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-* Copyright (C) 2012 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>
-</resources>
diff --git a/res/values-sw720dp-land/dimens.xml b/res/values-sw720dp-land/dimens.xml
index ca13db05b..514980fe0 100644
--- a/res/values-sw720dp-land/dimens.xml
+++ b/res/values-sw720dp-land/dimens.xml
@@ -15,10 +15,6 @@
-->
<resources>
-<!-- AppsCustomize -->
- <integer name="apps_customize_widget_cell_count_x">4</integer>
- <integer name="apps_customize_widget_cell_count_y">2</integer>
-
<!-- the area at the edge of the screen that makes the workspace go left
or right while you're dragging. -->
<dimen name="scroll_zone">100dip</dimen>
diff --git a/res/values-sw720dp/config.xml b/res/values-sw720dp/config.xml
index c00b5943f..94cffcb55 100644
--- a/res/values-sw720dp/config.xml
+++ b/res/values-sw720dp/config.xml
@@ -2,17 +2,10 @@
<bool name="config_largeHeap">true</bool>
<bool name="is_large_tablet">true</bool>
-<!-- AllApps/Customize/AppsCustomize -->
+<!-- All Apps & Widgets -->
<!-- Out of 100, the percent to shrink the workspace during spring loaded mode. -->
<integer name="config_workspaceSpringLoadShrinkPercentage">90</integer>
-<!-- Workspace -->
- <!-- Whether or not the drop targets drop down as opposed to fade in -->
- <bool name="config_useDropTargetDownTransition">false</bool>
-
- <!-- Camera distance for the overscroll effect -->
- <integer name="config_cameraDistance">18000</integer>
-
<!-- Hotseat -->
<bool name="hotseat_transpose_layout_with_orientation">false</bool>
</resources>
diff --git a/res/values-sw720dp/dimens.xml b/res/values-sw720dp/dimens.xml
index 8be996474..d48f9eed0 100644
--- a/res/values-sw720dp/dimens.xml
+++ b/res/values-sw720dp/dimens.xml
@@ -15,17 +15,14 @@
-->
<resources>
- <dimen name="app_icon_size">72dp</dimen>
+<!-- All Apps -->
+ <dimen name="all_apps_search_bar_height">54dp</dimen>
+ <dimen name="all_apps_icon_top_bottom_padding">14dp</dimen>
<!-- QSB -->
<dimen name="toolbar_button_vertical_padding">8dip</dimen>
<dimen name="toolbar_button_horizontal_padding">8dip</dimen>
- <!-- When dragging items on the workspace, the number of dps by which the position of
- the drag view should be offset from the position of the original view. -->
- <dimen name="dragViewOffsetX">0dp</dimen>
- <dimen name="dragViewOffsetY">0dp</dimen>
-
<!-- Cling -->
<dimen name="cling_migration_content_margin">96dp</dimen>
<dimen name="cling_migration_content_width">320dp</dimen>
diff --git a/res/values-sw720dp/styles.xml b/res/values-sw720dp/styles.xml
index cbc1e29b3..e8b706e23 100644
--- a/res/values-sw720dp/styles.xml
+++ b/res/values-sw720dp/styles.xml
@@ -27,7 +27,7 @@
<item name="android:layout_height">match_parent</item>
</style>
- <style name="DropTargetButton" parent="DropTargetButton.Base">
+ <style name="DropTargetButton" parent="DropTargetButtonBase">
<item name="android:paddingLeft">60dp</item>
<item name="android:paddingRight">60dp</item>
<item name="android:shadowColor">#393939</item>
diff --git a/res/values-ta-rIN/strings.xml b/res/values-ta-rIN/strings.xml
index 9dba6f669..1f2a6f959 100644
--- a/res/values-ta-rIN/strings.xml
+++ b/res/values-ta-rIN/strings.xml
@@ -20,57 +20,27 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="application_name" msgid="5181331383435256801">"லாஞ்சர்3"</string>
- <string name="home" msgid="7658288663002113681">"முகப்பு"</string>
- <string name="uid_name" msgid="7820867637514617527">"Android முக்கியப் பயன்பாடுகள்"</string>
<string name="folder_name" msgid="7371454440695724752"></string>
+ <string name="work_folder_name" msgid="3753320833950115786">"பணியிடம்"</string>
<string name="activity_not_found" msgid="8071924732094499514">"பயன்பாடு நிறுவப்படவில்லை."</string>
<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="widgets_tab_label" msgid="2921133187116603919">"ஷார்ட்கட்ஸ்"</string>
- <string name="widget_adder" msgid="3201040140710381657">"ஷார்ட்கட்ஸ்"</string>
<string name="toggle_weight_watcher" msgid="5645299835184636119">"நினைவகத்தைக் காட்டு"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"விட்ஜெட்டைத் தேர்வுசெய்ய தொட்டுப் பிடிக்கவும்."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
- <string name="external_drop_widget_error" msgid="3165821058322217155">"உருப்படியை இந்த முகப்புத் திரையில் விட முடியவில்லை."</string>
- <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"உருவாக்குவதற்கு விட்ஜெட்டைத் தேர்வுசெய்யவும்"</string>
- <string name="rename_folder_label" msgid="3727762225964550653">"கோப்புறையின் பெயர்"</string>
- <string name="rename_folder_title" msgid="3771389277707820891">"கோப்புறைக்கு மறுபெயரிடு"</string>
- <string name="rename_action" msgid="5559600076028658757">"சரி"</string>
- <string name="cancel_action" msgid="7009134900002915310">"ரத்துசெய்"</string>
- <string name="menu_item_add_item" msgid="1264911265836810421">"முகப்புத் திரையில் சேர்"</string>
- <string name="group_applications" msgid="3797214114206693605">"பயன்பாடுகள்"</string>
- <string name="group_shortcuts" msgid="6012256992764410535">"குறுக்குவழிகள்"</string>
- <string name="group_widgets" msgid="1569030723286851002">"ஷார்ட்கட்ஸ்"</string>
- <string name="completely_out_of_space" msgid="6106288382070760318">"உங்கள் முகப்புத் திரைகளில் வேறு இடம் இல்லை."</string>
+ <string name="all_apps_search_bar_hint" msgid="7084713969757597256">"பயன்பாடுகளில் தேடுக"</string>
+ <string name="all_apps_loading_message" msgid="7557140873644765180">"பயன்பாடுகளை ஏற்றுகிறது..."</string>
+ <string name="all_apps_no_search_results" msgid="6332185285860416787">"\"<xliff:g id="QUERY">%1$s</xliff:g>\" உடன் பொருந்தும் பயன்பாடுகள் இல்லை"</string>
<string name="out_of_space" msgid="4691004494942118364">"முகப்புத் திரையில் இடமில்லை."</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"பிடித்தவை ட்ரேயில் இடமில்லை"</string>
- <string name="invalid_hotseat_item" msgid="5779907847267573691">"பிடித்தவை ட்ரேவிற்கு விட்ஜெட் மிகவும் பெரியது"</string>
- <string name="shortcut_installed" msgid="1701742129426969556">"\"<xliff:g id="NAME">%s</xliff:g>\" குறுக்குவழி உருவாக்கப்பட்டது."</string>
- <string name="shortcut_uninstalled" msgid="8176767991305701821">"\"<xliff:g id="NAME">%s</xliff:g>\" குறுக்குவழி அகற்றப்பட்டது."</string>
- <string name="shortcut_duplicate" msgid="9167217446062498127">"\"<xliff:g id="NAME">%s</xliff:g>\" குறுக்குவழி ஏற்கனவே உள்ளது."</string>
- <string name="title_select_shortcut" msgid="6680642571148153868">"குறுக்குவழியைத் தேர்வுசெய்யவும்"</string>
- <string name="title_select_application" msgid="3280812711670683644">"பயன்பாட்டைத் தேர்வுசெய்யவும்"</string>
<string name="all_apps_button_label" msgid="9110807029020582876">"பயன்பாடுகள்"</string>
<string name="all_apps_home_button_label" msgid="252062713717058851">"முகப்பு"</string>
- <string name="delete_zone_label_workspace" msgid="4009607676751398685">"அகற்று"</string>
- <string name="delete_zone_label_all_apps" msgid="8083826390278958980">"நிறுவல் நீக்கு"</string>
<string name="delete_target_label" msgid="1822697352535677073">"அகற்று"</string>
<string name="delete_target_uninstall_label" msgid="5100785476250872595">"நிறுவல் நீக்கு"</string>
<string name="info_target_label" msgid="8053346143994679532">"பயன்பாட்டுத் தகவல்"</string>
- <string name="accessibility_all_apps_button" msgid="2603132375383800483">"பயன்பாடுகள்"</string>
- <string name="accessibility_delete_button" msgid="6466114477993744621">"அகற்று"</string>
- <string name="delete_zone_label_all_apps_system_app" msgid="449755632749610895">"புதுப்பிப்பை நிறுவல் நீக்கு"</string>
- <string name="cab_menu_delete_app" msgid="7435191475867183689">"பயன்பாட்டை நிறுவல் நீக்கு"</string>
- <string name="cab_menu_app_info" msgid="8593722221450362342">"பயன்பாட்டின் விவரங்கள்"</string>
- <string name="cab_app_selection_text" msgid="374688303047985416">"1 பயன்பாடு தேர்ந்தெடுக்கப்பட்டது"</string>
- <string name="cab_widget_selection_text" msgid="1833458597831541241">"1 விட்ஜெட் தேர்ந்தெடுக்கப்பட்டது"</string>
- <string name="cab_folder_selection_text" msgid="7999992513806132118">"1 கோப்புறை தேர்ந்தெடுக்கப்பட்டது"</string>
- <string name="cab_shortcut_selection_text" msgid="2103811025667946450">"1 குறுக்குவழி தேர்ந்தெடுக்கப்பட்டது"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"குறுக்குவழிகளை நிறுவுதல்"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"பயனரின் அனுமதி இல்லாமல் குறுக்குவழிகளைச் சேர்க்கப் பயன்பாட்டை அனுமதிக்கிறது."</string>
- <string name="permlab_uninstall_shortcut" msgid="864595034498083837">"குறுக்குவழிகளை நிறுவல் நீக்குதல்"</string>
- <string name="permdesc_uninstall_shortcut" msgid="5134129545001836849">"பயனரின் அனுமதி இல்லாமல் குறுக்குவழிகளை அகற்ற பயன்பாட்டை அனுமதிக்கிறது."</string>
<string name="permlab_read_settings" msgid="1941457408239617576">"முகப்பின் அமைப்பு மற்றும் குறுக்குவழிகளைப் படித்தல்"</string>
<string name="permdesc_read_settings" msgid="5833423719057558387">"முகப்பில் உள்ள அமைப்பு மற்றும் குறுக்குவழிகளைப் படிக்க பயன்பாட்டை அனுமதிக்கிறது."</string>
<string name="permlab_write_settings" msgid="3574213698004620587">"முகப்பின் அமைப்பு மற்றும் குறுக்குவழிகளை எழுதுதல்"</string>
@@ -78,30 +48,17 @@
<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>
- <string name="dream_name" msgid="1530253749244328964">"ராக்கெட் லாஞ்சர்"</string>
<string name="folder_hint_text" msgid="6617836969016293992">"பெயரிடப்படாத கோப்புறை"</string>
- <string name="workspace_description_format" msgid="2950174241104043327">"முகப்புத் திரை %1$d"</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="apps_customize_apps_scroll_format" msgid="370005296147130238">"பயன்பாடுகளின் பக்கம் %1$d / %2$d"</string>
- <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"விட்ஜெட்களின் பக்கம் %1$d / %2$d"</string>
- <string name="first_run_cling_title" msgid="2459738000155917941">"வரவேற்கிறோம்"</string>
- <string name="first_run_cling_description" msgid="6447072552696253358">"உங்களுக்கேற்ற முறையில் உருவாக்கவும்."</string>
- <string name="first_run_cling_custom_content_hint" msgid="6090628589029352439"></string>
- <string name="first_run_cling_search_bar_hint" msgid="5909062802402452582"></string>
- <string name="first_run_cling_create_screens_hint" msgid="6950729526680114157">"பயன்பாடுகள் மற்றும் கோப்புறைகளுக்காகக் கூடுதல் திரைகளை உருவாக்கவும்"</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>
<string name="migration_cling_copy_apps" msgid="946331230090919440">"ஐகான்களை நகலெடு"</string>
<string name="migration_cling_use_default" msgid="2626475813981258626">"புதிதாகத் தொடங்கு"</string>
- <string name="workspace_cling_title" msgid="5626202359865825661">"இடத்தை ஒழுங்கமைக்கவும்"</string>
- <string name="workspace_cling_move_item" msgid="528201129978005352">"வால்பேப்பர், விட்ஜெட்கள், அமைப்பை நிர்வகிக்க பின்புலத்தைத் தொட்டுப் பிடிக்கவும்."</string>
<string name="workspace_cling_longpress_title" msgid="9173998993909018310">"வால்பேப்பர்கள், விட்ஜெட்கள் &amp; அமைப்புகள்"</string>
<string name="workspace_cling_longpress_description" msgid="4119994475505235248">"தனிப்பயனாக்க, பின்னணியைத் தொட்டுப் பிடிக்கவும்"</string>
<string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"புரிந்தது"</string>
- <string name="folder_cling_title" msgid="3894908818693254164">"இதோ கோப்புறை"</string>
- <string name="folder_cling_create_folder" msgid="6158215559475836131">"இதுபோன்ற ஒன்றை உருவாக்க பயன்பாட்டைத் தொட்டுப் பிடிக்கவும், பிறகு அதை வேறொன்றிற்கு நகர்த்தவும்."</string>
- <string name="cling_dismiss" msgid="8962359497601507581">"சரி"</string>
<string name="folder_opened" msgid="94695026776264709">"திறக்கப்பட்டக் கோப்புறை, <xliff:g id="WIDTH">%1$d</xliff:g> x <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
<string name="folder_tap_to_close" msgid="1884479294466410023">"கோப்புறையை மூட, தொடவும்"</string>
<string name="folder_tap_to_rename" msgid="9191075570492871147">"மறுபெயரிட்டதைச் சேமிக்க, தொடவும்"</string>
@@ -111,14 +68,34 @@
<string name="widget_button_text" msgid="2880537293434387943">"ஷார்ட்கட்ஸ்"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"வால்பேப்பர்கள்"</string>
<string name="settings_button_text" msgid="8119458837558863227">"அமைப்பு"</string>
- <string name="package_state_enqueued" msgid="6227252464303085641">"காத்திருக்கிறது"</string>
- <string name="package_state_downloading" msgid="4088770468458724721">"பதிவிறக்குகிறது"</string>
- <string name="package_state_installing" msgid="7588193972189849870">"நிறுவுகிறது"</string>
+ <string name="allow_rotation_title" msgid="2118706734511831751">"சுழற்ற அனுமதி"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"தெரியாதது"</string>
- <string name="package_state_error" msgid="7672093962724223588">"மீட்டெடுக்க முடியாது"</string>
- <string name="abandoned_clean_all" msgid="5256770727689657618">"அனைத்தையும் அகற்று"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"அகற்று"</string>
<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="action_add_to_workspace" msgid="8902165848117513641">"முகப்புத் திரையில் சேர்"</string>
+ <string name="action_move_here" msgid="2170188780612570250">"இங்கு நகர்த்து"</string>
+ <string name="item_added_to_workspace" msgid="4211073925752213539">"முகப்புத் திரையில் சேர்க்கப்பட்டது"</string>
+ <string name="item_removed" msgid="851119963877842327">"அகற்றப்பட்டது"</string>
+ <string name="action_move" msgid="4339390619886385032">"நகர்த்து"</string>
+ <string name="move_to_empty_cell" msgid="2833711483015685619">"<xliff:g id="NUMBER_0">%1$s</xliff:g> வரிசை, <xliff:g id="NUMBER_1">%2$s</xliff:g> நெடுவரிசைக்கு நகர்த்து"</string>
+ <string name="move_to_position" msgid="6750008980455459790">"நிலை <xliff:g id="NUMBER">%1$s</xliff:g>க்கு நகர்த்து"</string>
+ <string name="move_to_hotseat_position" msgid="6295412897075147808">"விரும்பும் நிலை <xliff:g id="NUMBER">%1$s</xliff:g>க்கு நகர்த்து"</string>
+ <string name="item_moved" msgid="4606538322571412879">"உருப்படி நகர்த்தப்பட்டது"</string>
+ <string name="add_to_folder" msgid="9040534766770853243">"இந்தக் கோப்புறையில் சேர்க்கும்: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="add_to_folder_with_app" msgid="4534929978967147231">"<xliff:g id="NAME">%1$s</xliff:g> உள்ள கோப்புறையில் சேர்க்கும்"</string>
+ <string name="added_to_folder" msgid="4793259502305558003">"கோப்புறையில் உருப்படி சேர்க்கப்பட்டது"</string>
+ <string name="create_folder_with" msgid="4050141361160214248">"இதனுடன் கோப்புறையை உருவாக்கும்: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="folder_created" msgid="6409794597405184510">"கோப்புறை உருவாக்கப்பட்டது"</string>
+ <string name="action_move_to_workspace" msgid="1603837886334246317">"முகப்புத் திரைக்கு நகர்த்து"</string>
+ <string name="action_move_screen_left" msgid="8854216831569401665">"திரையை இடப்புறம் நகர்த்து"</string>
+ <string name="action_move_screen_right" msgid="329334910274311123">"திரையை வலப்புறம் நகர்த்து"</string>
+ <string name="screen_moved" msgid="266230079505650577">"திரை நகர்த்தப்பட்டது"</string>
+ <string name="action_resize" msgid="1802976324781771067">"அளவு மாற்று"</string>
+ <string name="action_increase_width" msgid="8773715375078513326">"அகலத்தை அதிகரி"</string>
+ <string name="action_increase_height" msgid="459390020612501122">"உயரத்தை அதிகரி"</string>
+ <string name="action_decrease_width" msgid="1374549771083094654">"அகலத்தைக் குறை"</string>
+ <string name="action_decrease_height" msgid="282377193880900022">"உயரத்தைக் குறை"</string>
+ <string name="widget_resized" msgid="9130327887929620">"அகலம் <xliff:g id="NUMBER_0">%1$s</xliff:g> மற்றும் உயரம் <xliff:g id="NUMBER_1">%2$s</xliff:g>க்கு விட்ஜெட் அளவு மாற்றப்பட்டது"</string>
</resources>
diff --git a/res/values-te-rIN/strings.xml b/res/values-te-rIN/strings.xml
index bfbc7920f..bd5fd70db 100644
--- a/res/values-te-rIN/strings.xml
+++ b/res/values-te-rIN/strings.xml
@@ -20,57 +20,27 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="application_name" msgid="5181331383435256801">"లాంచర్3"</string>
- <string name="home" msgid="7658288663002113681">"హోమ్"</string>
- <string name="uid_name" msgid="7820867637514617527">"Android ప్రధాన అనువర్తనాలు"</string>
<string name="folder_name" msgid="7371454440695724752"></string>
+ <string name="work_folder_name" msgid="3753320833950115786">"కార్యాలయం"</string>
<string name="activity_not_found" msgid="8071924732094499514">"అనువర్తనం ఇన్‌స్టాల్ చేయబడలేదు."</string>
<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="widgets_tab_label" msgid="2921133187116603919">"విడ్జెట్‌లు"</string>
- <string name="widget_adder" msgid="3201040140710381657">"విడ్జెట్‌లు"</string>
<string name="toggle_weight_watcher" msgid="5645299835184636119">"మెమరీ చూపు"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"విడ్జెట్‌ను ఎంచుకోవడానికి తాకి &amp; నొక్కి పెట్టండి."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
- <string name="external_drop_widget_error" msgid="3165821058322217155">"ఈ హోమ్ స్క్రీన్‌లో అంశాన్ని వదలడం సాధ్యపడలేదు."</string>
- <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"సృష్టించాల్సిన విడ్జెట్ ఎంచుకోండి"</string>
- <string name="rename_folder_label" msgid="3727762225964550653">"ఫోల్డర్ పేరు"</string>
- <string name="rename_folder_title" msgid="3771389277707820891">"ఫోల్డర్‌ పేరు మార్చండి"</string>
- <string name="rename_action" msgid="5559600076028658757">"సరే"</string>
- <string name="cancel_action" msgid="7009134900002915310">"రద్దు చేయి"</string>
- <string name="menu_item_add_item" msgid="1264911265836810421">"హోమ్ స్క్రీన్‌కు జోడించు"</string>
- <string name="group_applications" msgid="3797214114206693605">"అనువర్తనాలు"</string>
- <string name="group_shortcuts" msgid="6012256992764410535">"సత్వరమార్గాలు"</string>
- <string name="group_widgets" msgid="1569030723286851002">"విడ్జెట్‌లు"</string>
- <string name="completely_out_of_space" msgid="6106288382070760318">"మీ హోమ్ స్క్రీన్‌ల్లో ఖాళీ లేదు."</string>
+ <string name="all_apps_search_bar_hint" msgid="7084713969757597256">"అనువర్తనాలను శోధించండి"</string>
+ <string name="all_apps_loading_message" msgid="7557140873644765180">"అనువర్తనాలను లోడ్ చేస్తోంది…"</string>
+ <string name="all_apps_no_search_results" msgid="6332185285860416787">"\"<xliff:g id="QUERY">%1$s</xliff:g>\"కి సరిపోలే అనువర్తనాలేవీ కనుగొనబడలేదు"</string>
<string name="out_of_space" msgid="4691004494942118364">"ఈ హోమ్ స్క్రీన్‌లో ఖాళీ లేదు."</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"ఇష్టమైనవి ట్రేలో ఖాళీ లేదు"</string>
- <string name="invalid_hotseat_item" msgid="5779907847267573691">"ఇష్టమైనవి ట్రే కోసం ఈ విడ్జెట్ చాలా పెద్దదిగా ఉంది"</string>
- <string name="shortcut_installed" msgid="1701742129426969556">"సత్వరమార్గం \"<xliff:g id="NAME">%s</xliff:g>\" సృష్టించబడింది."</string>
- <string name="shortcut_uninstalled" msgid="8176767991305701821">"సత్వరమార్గం \"<xliff:g id="NAME">%s</xliff:g>\" తీసివేయబడింది."</string>
- <string name="shortcut_duplicate" msgid="9167217446062498127">"సత్వరమార్గం \"<xliff:g id="NAME">%s</xliff:g>\" ఇప్పటికే ఉంది."</string>
- <string name="title_select_shortcut" msgid="6680642571148153868">"సత్వరమార్గాన్ని ఎంచుకోండి"</string>
- <string name="title_select_application" msgid="3280812711670683644">"అనువర్తనాన్ని ఎంచుకోండి"</string>
<string name="all_apps_button_label" msgid="9110807029020582876">"అనువర్తనాలు"</string>
<string name="all_apps_home_button_label" msgid="252062713717058851">"హోమ్"</string>
- <string name="delete_zone_label_workspace" msgid="4009607676751398685">"తీసివేయి"</string>
- <string name="delete_zone_label_all_apps" msgid="8083826390278958980">"అన్ఇన్‌స్టాల్ చేయి"</string>
<string name="delete_target_label" msgid="1822697352535677073">"తీసివేయి"</string>
<string name="delete_target_uninstall_label" msgid="5100785476250872595">"అన్ఇన్‌స్టాల్ చేయి"</string>
<string name="info_target_label" msgid="8053346143994679532">"అనువర్తన సమాచారం"</string>
- <string name="accessibility_all_apps_button" msgid="2603132375383800483">"అనువర్తనాలు"</string>
- <string name="accessibility_delete_button" msgid="6466114477993744621">"తీసివేయి"</string>
- <string name="delete_zone_label_all_apps_system_app" msgid="449755632749610895">"నవీకరణను అన్‌ఇన్‌స్టాల్ చేయి"</string>
- <string name="cab_menu_delete_app" msgid="7435191475867183689">"అనువర్తనాన్ని అన్‌ఇన్‌స్టాల్ చేయి"</string>
- <string name="cab_menu_app_info" msgid="8593722221450362342">"అనువర్తన వివరాలు"</string>
- <string name="cab_app_selection_text" msgid="374688303047985416">"1 అనువర్తనం ఎంచుకోబడింది"</string>
- <string name="cab_widget_selection_text" msgid="1833458597831541241">"1 విడ్జెట్ ఎంచుకోబడింది"</string>
- <string name="cab_folder_selection_text" msgid="7999992513806132118">"1 ఫోల్డర్ ఎంచుకోబడింది"</string>
- <string name="cab_shortcut_selection_text" msgid="2103811025667946450">"1 సత్వరమార్గం ఎంచుకోబడింది"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"సత్వరమార్గాలను ఇన్‌స్టాల్ చేయడం"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"వినియోగదారు ప్రమేయం లేకుండా సత్వరమార్గాలను జోడించడానికి అనువర్తనాన్ని అనుమతిస్తుంది."</string>
- <string name="permlab_uninstall_shortcut" msgid="864595034498083837">"సత్వరమార్గాలను అన్ఇన్‌స్టాల్ చేయడం"</string>
- <string name="permdesc_uninstall_shortcut" msgid="5134129545001836849">"వినియోగదారు ప్రమేయం లేకుండా సత్వరమార్గాలను తీసివేయడానికి అనువర్తనాన్ని అనుమతిస్తుంది."</string>
<string name="permlab_read_settings" msgid="1941457408239617576">"హోమ్ సెట్టింగ్‌లు మరియు సత్వరమార్గాలను చదవడం"</string>
<string name="permdesc_read_settings" msgid="5833423719057558387">"హోమ్‌లో సెట్టింగ్‌లు మరియు సత్వరమార్గాలను చదవడానికి అనువర్తనాన్ని అనుమతిస్తుంది."</string>
<string name="permlab_write_settings" msgid="3574213698004620587">"హోమ్ సెట్టింగ్‌లు మరియు సత్వరమార్గాలను వ్రాయడం"</string>
@@ -78,30 +48,17 @@
<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>
- <string name="dream_name" msgid="1530253749244328964">"రాకెట్ లాంచర్"</string>
<string name="folder_hint_text" msgid="6617836969016293992">"పేరు లేని ఫోల్డర్"</string>
- <string name="workspace_description_format" msgid="2950174241104043327">"హోమ్ స్క్రీన్ %1$d"</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="apps_customize_apps_scroll_format" msgid="370005296147130238">"%2$dలో %1$dవ అనువర్తనాల పేజీ"</string>
- <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"%2$dలో %1$dవ విడ్జెట్‌‌ల పేజీ"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"స్వాగతం"</string>
- <string name="first_run_cling_description" msgid="6447072552696253358">"మీ స్వంత స్థలంగా భావించండి."</string>
- <string name="first_run_cling_custom_content_hint" msgid="6090628589029352439"></string>
- <string name="first_run_cling_search_bar_hint" msgid="5909062802402452582"></string>
- <string name="first_run_cling_create_screens_hint" msgid="6950729526680114157">"అనువర్తనాలు మరియు ఫోల్డర్‌ల కోసం మరిన్ని స్క్రీన్‌లు సృష్టి."</string>
<string name="migration_cling_title" msgid="9181776667882933767">"మీ అనువర్తన చిహ్నాలను కాపీ చేయండి"</string>
<string name="migration_cling_description" msgid="2752413805582227644">"మీ పాత హోమ్ స్క్రీన్‌ల నుండి చిహ్నాలు మరియు ఫోల్డర్‌లను దిగుమతి చేయాలా?"</string>
<string name="migration_cling_copy_apps" msgid="946331230090919440">"చిహ్నాలను కాపీ చేయి"</string>
<string name="migration_cling_use_default" msgid="2626475813981258626">"తాజాగా ప్రారంభించు"</string>
- <string name="workspace_cling_title" msgid="5626202359865825661">"మీ స్థలాన్ని నిర్వహించండి"</string>
- <string name="workspace_cling_move_item" msgid="528201129978005352">"వాల్‌., విడ్జె., సెట్టి. నిర్వ. నేపథ్యం తాకి &amp; నొక్కి పెట్టండి."</string>
<string name="workspace_cling_longpress_title" msgid="9173998993909018310">"వాల్‌పేపర్‌లు, విడ్జెట్‌లు &amp; సెట్టింగ్‌లు"</string>
<string name="workspace_cling_longpress_description" msgid="4119994475505235248">"అనుకూలీకరించడానికి నేపథ్యాన్ని నొక్కి &amp; ఉంచండి"</string>
<string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"అర్థమైంది"</string>
- <string name="folder_cling_title" msgid="3894908818693254164">"ఇక్కడ ఫోల్డర్ ఉంది"</string>
- <string name="folder_cling_create_folder" msgid="6158215559475836131">"ఇలాంటిది సృష్టించడానికి అనువర్తనాన్ని తాకి &amp; నొక్కి పెట్టండి, ఆపై మరోదాని పైన ఉంచండి."</string>
- <string name="cling_dismiss" msgid="8962359497601507581">"సరే"</string>
<string name="folder_opened" msgid="94695026776264709">"ఫోల్డర్ తెరవబడింది, <xliff:g id="WIDTH">%1$d</xliff:g> X <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
<string name="folder_tap_to_close" msgid="1884479294466410023">"ఫోల్డర్‌ను మూసివేయడానికి తాకండి"</string>
<string name="folder_tap_to_rename" msgid="9191075570492871147">"పేరు మార్పును సేవ్ చేయడానికి తాకండి"</string>
@@ -111,14 +68,34 @@
<string name="widget_button_text" msgid="2880537293434387943">"విడ్జెట్‌లు"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"వాల్‌పేపర్‌లు"</string>
<string name="settings_button_text" msgid="8119458837558863227">"సెట్టింగ్‌లు"</string>
- <string name="package_state_enqueued" msgid="6227252464303085641">"వేచి ఉంది"</string>
- <string name="package_state_downloading" msgid="4088770468458724721">"డౌన్‌లోడ్ చేస్తోంది"</string>
- <string name="package_state_installing" msgid="7588193972189849870">"ఇన్‌స్టాల్ చేస్తోంది"</string>
+ <string name="allow_rotation_title" msgid="2118706734511831751">"భ్రమణాన్ని అనుమతించండి"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"తెలియదు"</string>
- <string name="package_state_error" msgid="7672093962724223588">"పునరుద్ధరించబడలేదు"</string>
- <string name="abandoned_clean_all" msgid="5256770727689657618">"అన్నీ తీసివేయి"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"తీసివేయి"</string>
<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="action_add_to_workspace" msgid="8902165848117513641">"హోమ్ స్క్రీన్‌కు జోడించు"</string>
+ <string name="action_move_here" msgid="2170188780612570250">"అంశాన్ని ఇక్కడికి తరలించు"</string>
+ <string name="item_added_to_workspace" msgid="4211073925752213539">"అంశం హోమ్‌స్క్రీన్‌కి జోడించబడింది"</string>
+ <string name="item_removed" msgid="851119963877842327">"అంశం తీసివేయబడింది"</string>
+ <string name="action_move" msgid="4339390619886385032">"అంశాన్ని తరలించు"</string>
+ <string name="move_to_empty_cell" msgid="2833711483015685619">"అడ్డు వరుస <xliff:g id="NUMBER_0">%1$s</xliff:g> నిలువు వరుస <xliff:g id="NUMBER_1">%2$s</xliff:g>కి తరలించు"</string>
+ <string name="move_to_position" msgid="6750008980455459790">"<xliff:g id="NUMBER">%1$s</xliff:g>వ స్థానానికి తరలించు"</string>
+ <string name="move_to_hotseat_position" msgid="6295412897075147808">"ఇష్టమైనవిలో <xliff:g id="NUMBER">%1$s</xliff:g>వ స్థానానికి తరలించు"</string>
+ <string name="item_moved" msgid="4606538322571412879">"అంశం తరలించబడింది"</string>
+ <string name="add_to_folder" msgid="9040534766770853243">"ఈ ఫోల్డర్‌కి జోడించండి: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="add_to_folder_with_app" msgid="4534929978967147231">"<xliff:g id="NAME">%1$s</xliff:g> గల ఫోల్డర్‌కు జోడించు"</string>
+ <string name="added_to_folder" msgid="4793259502305558003">"అంశం ఫోల్డర్‌కు జోడించబడింది"</string>
+ <string name="create_folder_with" msgid="4050141361160214248">"ఈ పేరుతో ఫోల్డర్‌ను సృష్టించండి: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="folder_created" msgid="6409794597405184510">"ఫోల్డర్ సృష్టించబడింది"</string>
+ <string name="action_move_to_workspace" msgid="1603837886334246317">"హోమ్‌స్క్రీన్‌కు తరలించు"</string>
+ <string name="action_move_screen_left" msgid="8854216831569401665">"స్క్రీన్‌ను ఎడమవైపుకి జరుపు"</string>
+ <string name="action_move_screen_right" msgid="329334910274311123">"స్క్రీన్‌ను కుడివైపుకి జరుపు"</string>
+ <string name="screen_moved" msgid="266230079505650577">"స్క్రీన్ జరపబడింది"</string>
+ <string name="action_resize" msgid="1802976324781771067">"పరిమాణం మార్చు"</string>
+ <string name="action_increase_width" msgid="8773715375078513326">"వెడల్పును పెంచు"</string>
+ <string name="action_increase_height" msgid="459390020612501122">"ఎత్తును పెంచు"</string>
+ <string name="action_decrease_width" msgid="1374549771083094654">"వెడల్పును తగ్గించు"</string>
+ <string name="action_decrease_height" msgid="282377193880900022">"ఎత్తును తగ్గించు"</string>
+ <string name="widget_resized" msgid="9130327887929620">"విడ్జెట్ పరిమాణం వెడల్పు <xliff:g id="NUMBER_0">%1$s</xliff:g>కి, ఎత్తు <xliff:g id="NUMBER_1">%2$s</xliff:g>కి మార్చబడింది"</string>
</resources>
diff --git a/res/values-th/strings.xml b/res/values-th/strings.xml
index 0fc20d26f..85919af9a 100644
--- a/res/values-th/strings.xml
+++ b/res/values-th/strings.xml
@@ -20,57 +20,27 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="application_name" msgid="5181331383435256801">"Launcher3"</string>
- <string name="home" msgid="7658288663002113681">"หน้าแรก"</string>
- <string name="uid_name" msgid="7820867637514617527">"แอปหลักของ Android"</string>
<string name="folder_name" msgid="7371454440695724752"></string>
+ <string name="work_folder_name" msgid="3753320833950115786">"งาน"</string>
<string name="activity_not_found" msgid="8071924732094499514">"ไม่ได้ติดตั้งแอป"</string>
<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="widgets_tab_label" msgid="2921133187116603919">"วิดเจ็ต"</string>
- <string name="widget_adder" msgid="3201040140710381657">"วิดเจ็ต"</string>
<string name="toggle_weight_watcher" msgid="5645299835184636119">"แสดง Mem"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"แตะค้างเพื่อรับวิดเจ็ต"</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
- <string name="external_drop_widget_error" msgid="3165821058322217155">"ไม่สามารถวางรายการลงในหน้าจอหลักนี้"</string>
- <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"เลือกวิดเจ็ตที่จะสร้าง"</string>
- <string name="rename_folder_label" msgid="3727762225964550653">"ชื่อโฟลเดอร์"</string>
- <string name="rename_folder_title" msgid="3771389277707820891">"เปลี่ยนชื่อโฟลเดอร์"</string>
- <string name="rename_action" msgid="5559600076028658757">"ตกลง"</string>
- <string name="cancel_action" msgid="7009134900002915310">"ยกเลิก"</string>
- <string name="menu_item_add_item" msgid="1264911265836810421">"เพิ่มลงในหน้าแรก"</string>
- <string name="group_applications" msgid="3797214114206693605">"แอป"</string>
- <string name="group_shortcuts" msgid="6012256992764410535">"ทางลัด"</string>
- <string name="group_widgets" msgid="1569030723286851002">"วิดเจ็ต"</string>
- <string name="completely_out_of_space" msgid="6106288382070760318">"ไม่มีที่ว่างในหน้าจอหลักของคุณ"</string>
+ <string name="all_apps_search_bar_hint" msgid="7084713969757597256">"ค้นหาแอป"</string>
+ <string name="all_apps_loading_message" msgid="7557140873644765180">"กำลังโหลดแอป…"</string>
+ <string name="all_apps_no_search_results" msgid="6332185285860416787">"ไม่พบแอปที่ตรงกับ \"<xliff:g id="QUERY">%1$s</xliff:g>\""</string>
<string name="out_of_space" msgid="4691004494942118364">"ไม่มีที่ว่างในหน้าจอหลักนี้"</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"ไม่มีพื้นที่เหลือในถาดรายการโปรด"</string>
- <string name="invalid_hotseat_item" msgid="5779907847267573691">"วิดเจ็ตนี้มีขนาดใหญ่เกินไปสำหรับถาดรายการโปรด"</string>
- <string name="shortcut_installed" msgid="1701742129426969556">"สร้างทางลัด \"<xliff:g id="NAME">%s</xliff:g>\" แล้ว"</string>
- <string name="shortcut_uninstalled" msgid="8176767991305701821">"นำทางลัด \"<xliff:g id="NAME">%s</xliff:g>\" ออกแล้ว"</string>
- <string name="shortcut_duplicate" msgid="9167217446062498127">"มีทางลัด \"<xliff:g id="NAME">%s</xliff:g>\" อยู่แล้ว"</string>
- <string name="title_select_shortcut" msgid="6680642571148153868">"เลือกทางลัด"</string>
- <string name="title_select_application" msgid="3280812711670683644">"เลือกแอป"</string>
<string name="all_apps_button_label" msgid="9110807029020582876">"แอป"</string>
<string name="all_apps_home_button_label" msgid="252062713717058851">"หน้าแรก"</string>
- <string name="delete_zone_label_workspace" msgid="4009607676751398685">"ลบ"</string>
- <string name="delete_zone_label_all_apps" msgid="8083826390278958980">"ถอนการติดตั้ง"</string>
<string name="delete_target_label" msgid="1822697352535677073">"ลบ"</string>
<string name="delete_target_uninstall_label" msgid="5100785476250872595">"ถอนการติดตั้ง"</string>
<string name="info_target_label" msgid="8053346143994679532">"ข้อมูลแอป"</string>
- <string name="accessibility_all_apps_button" msgid="2603132375383800483">"แอป"</string>
- <string name="accessibility_delete_button" msgid="6466114477993744621">"ลบ"</string>
- <string name="delete_zone_label_all_apps_system_app" msgid="449755632749610895">"ถอนการติดตั้งการอัปเดต"</string>
- <string name="cab_menu_delete_app" msgid="7435191475867183689">"ถอนการติดตั้งแอป"</string>
- <string name="cab_menu_app_info" msgid="8593722221450362342">"รายละเอียดแอป"</string>
- <string name="cab_app_selection_text" msgid="374688303047985416">"เลือกไว้ 1 แอป"</string>
- <string name="cab_widget_selection_text" msgid="1833458597831541241">"เลือกไว้ 1 วิดเจ็ต"</string>
- <string name="cab_folder_selection_text" msgid="7999992513806132118">"เลือกไว้ 1 โฟลเดอร์"</string>
- <string name="cab_shortcut_selection_text" msgid="2103811025667946450">"เลือกไว้ 1 ทางลัด"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"ติดตั้งทางลัด"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"อนุญาตให้แอปเพิ่มทางลัดโดยไม่ต้องให้ผู้ใช้จัดการ"</string>
- <string name="permlab_uninstall_shortcut" msgid="864595034498083837">"ถอนการติดตั้งทางลัด"</string>
- <string name="permdesc_uninstall_shortcut" msgid="5134129545001836849">"อนุญาตให้แอปนำทางลัดออกโดยไม่ต้องให้ผู้ใช้จัดการ"</string>
<string name="permlab_read_settings" msgid="1941457408239617576">"อ่านการตั้งค่าและทางลัดหน้าแรกแล้ว"</string>
<string name="permdesc_read_settings" msgid="5833423719057558387">"อนุญาตให้แอปอ่านการตั้งค่าและทางลัดในหน้าแรก"</string>
<string name="permlab_write_settings" msgid="3574213698004620587">"เขียนการตั้งค่าและทางลัดหน้าแรกแล้ว"</string>
@@ -78,30 +48,17 @@
<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>
- <string name="dream_name" msgid="1530253749244328964">"Rocket Launcher"</string>
<string name="folder_hint_text" msgid="6617836969016293992">"โฟลเดอร์ที่ไม่มีชื่อ"</string>
- <string name="workspace_description_format" msgid="2950174241104043327">"หน้าจอหลัก %1$d"</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="apps_customize_apps_scroll_format" msgid="370005296147130238">"แอปหน้า %1$d จาก %2$d"</string>
- <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"วิดเจ็ตหน้า %1$d จาก %2$d"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"ยินดีต้อนรับ"</string>
- <string name="first_run_cling_description" msgid="6447072552696253358">"ทำตัวตามสบาย"</string>
- <string name="first_run_cling_custom_content_hint" msgid="6090628589029352439"></string>
- <string name="first_run_cling_search_bar_hint" msgid="5909062802402452582"></string>
- <string name="first_run_cling_create_screens_hint" msgid="6950729526680114157">"สร้างหน้าจอเพิ่มสำหรับแอปและโฟลเดอร์"</string>
<string name="migration_cling_title" msgid="9181776667882933767">"คัดลอกไอคอนแอปของคุณ"</string>
<string name="migration_cling_description" msgid="2752413805582227644">"นำเข้าไอคอนและโฟลเดอร์จากหน้าจอหลักเก่าของคุณ"</string>
<string name="migration_cling_copy_apps" msgid="946331230090919440">"คัดลอกไอคอน"</string>
<string name="migration_cling_use_default" msgid="2626475813981258626">"เริ่มต้นใหม่"</string>
- <string name="workspace_cling_title" msgid="5626202359865825661">"จัดระเบียบพื้นที่ของคุณ"</string>
- <string name="workspace_cling_move_item" msgid="528201129978005352">"แตะพื้นหลังค้างไว้เพื่อจัดการวอลเปเปอร์ วิดเจ็ต และการตั้งค่า"</string>
<string name="workspace_cling_longpress_title" msgid="9173998993909018310">"วอลเปเปอร์ วิดเจ็ต และการตั้งค่า"</string>
<string name="workspace_cling_longpress_description" msgid="4119994475505235248">"แตะพื้นหลังค้างไว้เพื่อกำหนดค่า"</string>
<string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"รับทราบ"</string>
- <string name="folder_cling_title" msgid="3894908818693254164">"นี่คือโฟลเดอร์"</string>
- <string name="folder_cling_create_folder" msgid="6158215559475836131">"หากต้องการสร้างโฟลเดอร์ลักษณะนี้ แตะแอปค้างไว้ แล้วย้ายไปทับอีกแอปหนึ่ง"</string>
- <string name="cling_dismiss" msgid="8962359497601507581">"ตกลง"</string>
<string name="folder_opened" msgid="94695026776264709">"เปิดโฟลเดอร์ <xliff:g id="WIDTH">%1$d</xliff:g> x <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
<string name="folder_tap_to_close" msgid="1884479294466410023">"แตะเพื่อปิดโฟลเดอร์"</string>
<string name="folder_tap_to_rename" msgid="9191075570492871147">"แตะเพื่อบันทึกการเปลี่ยนชื่อ"</string>
@@ -111,14 +68,34 @@
<string name="widget_button_text" msgid="2880537293434387943">"วิดเจ็ต"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"วอลเปเปอร์"</string>
<string name="settings_button_text" msgid="8119458837558863227">"การตั้งค่า"</string>
- <string name="package_state_enqueued" msgid="6227252464303085641">"กำลังรอ"</string>
- <string name="package_state_downloading" msgid="4088770468458724721">"กำลังดาวน์โหลด"</string>
- <string name="package_state_installing" msgid="7588193972189849870">"กำลังติดตั้ง"</string>
+ <string name="allow_rotation_title" msgid="2118706734511831751">"อนุญาตให้ใช้การหมุน"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"ไม่รู้จัก"</string>
- <string name="package_state_error" msgid="7672093962724223588">"ไม่ได้คืนค่า"</string>
- <string name="abandoned_clean_all" msgid="5256770727689657618">"ลบทั้งหมด"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"ลบ"</string>
<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="action_add_to_workspace" msgid="8902165848117513641">"เพิ่มลงในหน้าแรก"</string>
+ <string name="action_move_here" msgid="2170188780612570250">"ย้ายรายการมาที่นี่"</string>
+ <string name="item_added_to_workspace" msgid="4211073925752213539">"เพิ่มรายการไปยังหน้าจอหลักแล้ว"</string>
+ <string name="item_removed" msgid="851119963877842327">"นำออกรายการออกแล้ว"</string>
+ <string name="action_move" msgid="4339390619886385032">"ย้ายรายการ"</string>
+ <string name="move_to_empty_cell" msgid="2833711483015685619">"ย้ายไปที่แถว <xliff:g id="NUMBER_0">%1$s</xliff:g> คอลัมน์ <xliff:g id="NUMBER_1">%2$s</xliff:g>"</string>
+ <string name="move_to_position" msgid="6750008980455459790">"ย้ายไปยังตำแหน่ง <xliff:g id="NUMBER">%1$s</xliff:g>"</string>
+ <string name="move_to_hotseat_position" msgid="6295412897075147808">"ย้ายไปยังตำแหน่งที่ <xliff:g id="NUMBER">%1$s</xliff:g> ของรายการโปรด"</string>
+ <string name="item_moved" msgid="4606538322571412879">"ย้ายรายการแล้ว"</string>
+ <string name="add_to_folder" msgid="9040534766770853243">"เพิ่มไปยังโฟลเดอร์: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="add_to_folder_with_app" msgid="4534929978967147231">"เพิ่มไปยังโฟลเดอร์ที่มี <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="added_to_folder" msgid="4793259502305558003">"เพิ่มรายการไปยังโฟลเดอร์แล้ว"</string>
+ <string name="create_folder_with" msgid="4050141361160214248">"สร้างโฟลเดอร์ด้วย: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="folder_created" msgid="6409794597405184510">"สร้างโฟลเดอร์แล้ว"</string>
+ <string name="action_move_to_workspace" msgid="1603837886334246317">"ย้ายไปที่หน้าจอหลัก"</string>
+ <string name="action_move_screen_left" msgid="8854216831569401665">"เลื่อนหน้าจอไปทางซ้าย"</string>
+ <string name="action_move_screen_right" msgid="329334910274311123">"เลื่อนหน้าจอไปทางขวา"</string>
+ <string name="screen_moved" msgid="266230079505650577">"ย้ายหน้าจอแล้ว"</string>
+ <string name="action_resize" msgid="1802976324781771067">"ปรับขนาด"</string>
+ <string name="action_increase_width" msgid="8773715375078513326">"เพิ่มความกว้าง"</string>
+ <string name="action_increase_height" msgid="459390020612501122">"เพิ่มความสูง"</string>
+ <string name="action_decrease_width" msgid="1374549771083094654">"ลดความกว้าง"</string>
+ <string name="action_decrease_height" msgid="282377193880900022">"ลดความสูง"</string>
+ <string name="widget_resized" msgid="9130327887929620">"ปรับขนาดของวิดเจ็ตเป็นกว้าง <xliff:g id="NUMBER_0">%1$s</xliff:g> สูง <xliff:g id="NUMBER_1">%2$s</xliff:g> แล้ว"</string>
</resources>
diff --git a/res/values-tl/strings.xml b/res/values-tl/strings.xml
index 4d2f1d478..69a5bb7d9 100644
--- a/res/values-tl/strings.xml
+++ b/res/values-tl/strings.xml
@@ -20,57 +20,27 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="application_name" msgid="5181331383435256801">"Launcher3"</string>
- <string name="home" msgid="7658288663002113681">"Home"</string>
- <string name="uid_name" msgid="7820867637514617527">"Android Core Apps"</string>
<string name="folder_name" msgid="7371454440695724752"></string>
+ <string name="work_folder_name" msgid="3753320833950115786">"Trabaho"</string>
<string name="activity_not_found" msgid="8071924732094499514">"Hindi naka-install ang app."</string>
<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="widgets_tab_label" msgid="2921133187116603919">"Mga Widget"</string>
- <string name="widget_adder" msgid="3201040140710381657">"Mga Widget"</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="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
- <string name="external_drop_widget_error" msgid="3165821058322217155">"Hindi ma-drop ang item sa Home screen na ito."</string>
- <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Pumili ng widget na gagawin"</string>
- <string name="rename_folder_label" msgid="3727762225964550653">"Pangalan ng folder"</string>
- <string name="rename_folder_title" msgid="3771389277707820891">"Palitan ang pangalan ng folder"</string>
- <string name="rename_action" msgid="5559600076028658757">"OK"</string>
- <string name="cancel_action" msgid="7009134900002915310">"Kanselahin"</string>
- <string name="menu_item_add_item" msgid="1264911265836810421">"Idagdag sa Home screen"</string>
- <string name="group_applications" msgid="3797214114206693605">"Apps"</string>
- <string name="group_shortcuts" msgid="6012256992764410535">"Mga Shortcut"</string>
- <string name="group_widgets" msgid="1569030723286851002">"Mga Widget"</string>
- <string name="completely_out_of_space" msgid="6106288382070760318">"Wala nang lugar sa iyong mga Home screen."</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>
+ <string name="all_apps_no_search_results" msgid="6332185285860416787">"Walang nakitang Mga App na tumutugma sa \"<xliff:g id="QUERY">%1$s</xliff:g>\""</string>
<string name="out_of_space" msgid="4691004494942118364">"Wala nang lugar sa Home screen na ito."</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"Wala nang lugar sa tray ng Mga Paborito"</string>
- <string name="invalid_hotseat_item" msgid="5779907847267573691">"Masyadong malaki ang widget na ito para sa tray ng Mga Paborito"</string>
- <string name="shortcut_installed" msgid="1701742129426969556">"Nagawa ang shortcut na \"<xliff:g id="NAME">%s</xliff:g>.\""</string>
- <string name="shortcut_uninstalled" msgid="8176767991305701821">"Inalis ang shortcut na \"<xliff:g id="NAME">%s</xliff:g>.\""</string>
- <string name="shortcut_duplicate" msgid="9167217446062498127">"Umiiral na ang shortcut na \"<xliff:g id="NAME">%s</xliff:g>.\""</string>
- <string name="title_select_shortcut" msgid="6680642571148153868">"Pumili ng shortcut"</string>
- <string name="title_select_application" msgid="3280812711670683644">"Pumili ng app"</string>
<string name="all_apps_button_label" msgid="9110807029020582876">"Apps"</string>
<string name="all_apps_home_button_label" msgid="252062713717058851">"Home"</string>
- <string name="delete_zone_label_workspace" msgid="4009607676751398685">"Alisin"</string>
- <string name="delete_zone_label_all_apps" msgid="8083826390278958980">"I-uninstall"</string>
<string name="delete_target_label" msgid="1822697352535677073">"Alisin"</string>
<string name="delete_target_uninstall_label" msgid="5100785476250872595">"I-uninstall"</string>
<string name="info_target_label" msgid="8053346143994679532">"Impormasyon ng app"</string>
- <string name="accessibility_all_apps_button" msgid="2603132375383800483">"Apps"</string>
- <string name="accessibility_delete_button" msgid="6466114477993744621">"Alisin"</string>
- <string name="delete_zone_label_all_apps_system_app" msgid="449755632749610895">"I-uninstall ang update"</string>
- <string name="cab_menu_delete_app" msgid="7435191475867183689">"I-uninstall ang app"</string>
- <string name="cab_menu_app_info" msgid="8593722221450362342">"Mga detalye ng app"</string>
- <string name="cab_app_selection_text" msgid="374688303047985416">"1 app ang napili"</string>
- <string name="cab_widget_selection_text" msgid="1833458597831541241">"1 widget ang napili"</string>
- <string name="cab_folder_selection_text" msgid="7999992513806132118">"1 folder ang napili"</string>
- <string name="cab_shortcut_selection_text" msgid="2103811025667946450">"1 shortcut ang napili"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"i-install ang mga shortcut"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"Pinapayagan ang isang app na magdagdag ng mga shortcut nang walang panghihimasok ng user."</string>
- <string name="permlab_uninstall_shortcut" msgid="864595034498083837">"i-uninstall ang mga shortcut"</string>
- <string name="permdesc_uninstall_shortcut" msgid="5134129545001836849">"Pinapayagan ang app na mag-alis ng mga shortcut nang walang panghihimasok ng user."</string>
<string name="permlab_read_settings" msgid="1941457408239617576">"basahin ang mga setting at shortcut ng Home"</string>
<string name="permdesc_read_settings" msgid="5833423719057558387">"Pinapayagan ang app na basahin ang mga setting at shortcut sa Home."</string>
<string name="permlab_write_settings" msgid="3574213698004620587">"magsulat ng mga setting at shortcut ng Home"</string>
@@ -78,30 +48,17 @@
<string name="gadget_error_text" msgid="6081085226050792095">"Problema sa pag-load ng widget"</string>
<string name="gadget_setup_text" msgid="8274003207686040488">"I-setup"</string>
<string name="uninstall_system_app_text" msgid="4172046090762920660">"Isa itong app ng system at hindi maaaring i-uninstall."</string>
- <string name="dream_name" msgid="1530253749244328964">"Rocket Launcher"</string>
<string name="folder_hint_text" msgid="6617836969016293992">"Walang Pangalang Folder"</string>
- <string name="workspace_description_format" msgid="2950174241104043327">"Home screen %1$d"</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="apps_customize_apps_scroll_format" msgid="370005296147130238">"Pahina ng apps %1$d ng %2$d"</string>
- <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"Pahina ng widget %1$d ng %2$d"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"Maligayang Pagdating"</string>
- <string name="first_run_cling_description" msgid="6447072552696253358">"Gawing kumportable ang iyong sarili."</string>
- <string name="first_run_cling_custom_content_hint" msgid="6090628589029352439"></string>
- <string name="first_run_cling_search_bar_hint" msgid="5909062802402452582"></string>
- <string name="first_run_cling_create_screens_hint" msgid="6950729526680114157">"Gumawa ng higit pang mga screen para sa apps at mga folder"</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>
<string name="migration_cling_copy_apps" msgid="946331230090919440">"KOPYAHIN ANG MGA ICON"</string>
<string name="migration_cling_use_default" msgid="2626475813981258626">"MAGSIMULA NANG BAGO"</string>
- <string name="workspace_cling_title" msgid="5626202359865825661">"Ayusin ang iyong espasyo"</string>
- <string name="workspace_cling_move_item" msgid="528201129978005352">"Pindutin nang matagal ang background upang pamahalaan ang wallpaper, mga widget at setting"</string>
<string name="workspace_cling_longpress_title" msgid="9173998993909018310">"Mga wallpaper, widget at setting"</string>
<string name="workspace_cling_longpress_description" msgid="4119994475505235248">"Pindutin nang matagal ang background upang i-customize"</string>
<string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"NAKUHA KO"</string>
- <string name="folder_cling_title" msgid="3894908818693254164">"Narito ang isang folder"</string>
- <string name="folder_cling_create_folder" msgid="6158215559475836131">"Upang gumawa ng katulad nito, pindutin nang matagal ang isang app, pagkatapos ay ilipat ito sa isa pang folder."</string>
- <string name="cling_dismiss" msgid="8962359497601507581">"OK"</string>
<string name="folder_opened" msgid="94695026776264709">"Binuksan ang folder, <xliff:g id="WIDTH">%1$d</xliff:g> by <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
<string name="folder_tap_to_close" msgid="1884479294466410023">"Pindutin upang isara ang folder"</string>
<string name="folder_tap_to_rename" msgid="9191075570492871147">"Pindutin upang i-save ang pagpapalit ng pangalan"</string>
@@ -111,14 +68,34 @@
<string name="widget_button_text" msgid="2880537293434387943">"Mga Widget"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"Mga Wallpaper"</string>
<string name="settings_button_text" msgid="8119458837558863227">"Mga Setting"</string>
- <string name="package_state_enqueued" msgid="6227252464303085641">"Naghihintay"</string>
- <string name="package_state_downloading" msgid="4088770468458724721">"Nagda-download"</string>
- <string name="package_state_installing" msgid="7588193972189849870">"Nag-i-install"</string>
+ <string name="allow_rotation_title" msgid="2118706734511831751">"Payagan ang pag-rotate"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Hindi kilala"</string>
- <string name="package_state_error" msgid="7672093962724223588">"Hindi naibalik"</string>
- <string name="abandoned_clean_all" msgid="5256770727689657618">"Alisin Lahat"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Alisin"</string>
<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="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>
+ <string name="item_removed" msgid="851119963877842327">"Naalis na ang item"</string>
+ <string name="action_move" msgid="4339390619886385032">"Ilipat ang item"</string>
+ <string name="move_to_empty_cell" msgid="2833711483015685619">"Ilipat sa row <xliff:g id="NUMBER_0">%1$s</xliff:g> column <xliff:g id="NUMBER_1">%2$s</xliff:g>"</string>
+ <string name="move_to_position" msgid="6750008980455459790">"Ilipat sa posisyon <xliff:g id="NUMBER">%1$s</xliff:g>"</string>
+ <string name="move_to_hotseat_position" msgid="6295412897075147808">"Ilipat sa posisyon <xliff:g id="NUMBER">%1$s</xliff:g> sa mga paborito"</string>
+ <string name="item_moved" msgid="4606538322571412879">"Nalipat ang item"</string>
+ <string name="add_to_folder" msgid="9040534766770853243">"Idagdag sa folder: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="add_to_folder_with_app" msgid="4534929978967147231">"Idagdag sa folder kasama ng <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="added_to_folder" msgid="4793259502305558003">"Idinagdag ang item sa folder"</string>
+ <string name="create_folder_with" msgid="4050141361160214248">"Gumawa ng folder na may: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="folder_created" msgid="6409794597405184510">"Nagawa ang folder"</string>
+ <string name="action_move_to_workspace" msgid="1603837886334246317">"Ilipat sa Home screen"</string>
+ <string name="action_move_screen_left" msgid="8854216831569401665">"Ilipat sa kaliwa ang screen"</string>
+ <string name="action_move_screen_right" msgid="329334910274311123">"Ilipat sa kanan ang screen"</string>
+ <string name="screen_moved" msgid="266230079505650577">"Nailipat ang screen"</string>
+ <string name="action_resize" msgid="1802976324781771067">"I-resize"</string>
+ <string name="action_increase_width" msgid="8773715375078513326">"Dagdagan ang lapad"</string>
+ <string name="action_increase_height" msgid="459390020612501122">"Dagdagan ang taas"</string>
+ <string name="action_decrease_width" msgid="1374549771083094654">"Bawasan ang lapad"</string>
+ <string name="action_decrease_height" msgid="282377193880900022">"Bawasan ang taas"</string>
+ <string name="widget_resized" msgid="9130327887929620">"Na-resize ang widget sa lapad <xliff:g id="NUMBER_0">%1$s</xliff:g> taas <xliff:g id="NUMBER_1">%2$s</xliff:g>"</string>
</resources>
diff --git a/res/values-tr/strings.xml b/res/values-tr/strings.xml
index 6c78f6f63..d933c8770 100644
--- a/res/values-tr/strings.xml
+++ b/res/values-tr/strings.xml
@@ -20,57 +20,27 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="application_name" msgid="5181331383435256801">"Launcher3"</string>
- <string name="home" msgid="7658288663002113681">"Ana ekran"</string>
- <string name="uid_name" msgid="7820867637514617527">"Android Çekirdek Uygulamaları"</string>
<string name="folder_name" msgid="7371454440695724752"></string>
+ <string name="work_folder_name" msgid="3753320833950115786">"İş"</string>
<string name="activity_not_found" msgid="8071924732094499514">"Uygulama yüklü değil."</string>
<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="widgets_tab_label" msgid="2921133187116603919">"Widget\'lar"</string>
- <string name="widget_adder" msgid="3201040140710381657">"Widget\'lar"</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="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
- <string name="external_drop_widget_error" msgid="3165821058322217155">"Öğe bu Ana ekrana bırakılamadı."</string>
- <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Oluşturmak için widget seçin"</string>
- <string name="rename_folder_label" msgid="3727762225964550653">"Klasör adı"</string>
- <string name="rename_folder_title" msgid="3771389277707820891">"Klasörü yeniden adlandırın"</string>
- <string name="rename_action" msgid="5559600076028658757">"Tamam"</string>
- <string name="cancel_action" msgid="7009134900002915310">"İptal"</string>
- <string name="menu_item_add_item" msgid="1264911265836810421">"Ana ekrana ekleyin"</string>
- <string name="group_applications" msgid="3797214114206693605">"Uygulamalar"</string>
- <string name="group_shortcuts" msgid="6012256992764410535">"Kısayollar"</string>
- <string name="group_widgets" msgid="1569030723286851002">"Widget\'lar"</string>
- <string name="completely_out_of_space" msgid="6106288382070760318">"Ana ekranlarınızda yer kalmadı."</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>
+ <string name="all_apps_no_search_results" msgid="6332185285860416787">"\"<xliff:g id="QUERY">%1$s</xliff:g>\" ile eşleşen uygulama bulunamadı"</string>
<string name="out_of_space" msgid="4691004494942118364">"Bu Ana ekranda yer kalmadı."</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"Favoriler tepsisinde başka yer kalmadı"</string>
- <string name="invalid_hotseat_item" msgid="5779907847267573691">"Bu widget, Favoriler tepsisi için çok geniş"</string>
- <string name="shortcut_installed" msgid="1701742129426969556">"\"<xliff:g id="NAME">%s</xliff:g>\" kısayolu oluşturuldu."</string>
- <string name="shortcut_uninstalled" msgid="8176767991305701821">"\"<xliff:g id="NAME">%s</xliff:g>\" kısayolu kaldırıldı."</string>
- <string name="shortcut_duplicate" msgid="9167217446062498127">"\"<xliff:g id="NAME">%s</xliff:g>\" kısayolu zaten var."</string>
- <string name="title_select_shortcut" msgid="6680642571148153868">"Kısayolu seçin"</string>
- <string name="title_select_application" msgid="3280812711670683644">"Uygulama seçin"</string>
<string name="all_apps_button_label" msgid="9110807029020582876">"Uygulamalar"</string>
<string name="all_apps_home_button_label" msgid="252062713717058851">"Ana ekran"</string>
- <string name="delete_zone_label_workspace" msgid="4009607676751398685">"Kaldır"</string>
- <string name="delete_zone_label_all_apps" msgid="8083826390278958980">"Yüklemeyi kaldır"</string>
<string name="delete_target_label" msgid="1822697352535677073">"Kaldır"</string>
<string name="delete_target_uninstall_label" msgid="5100785476250872595">"Yüklemeyi kaldır"</string>
<string name="info_target_label" msgid="8053346143994679532">"Uygulama bilgileri"</string>
- <string name="accessibility_all_apps_button" msgid="2603132375383800483">"Uygulamalar"</string>
- <string name="accessibility_delete_button" msgid="6466114477993744621">"Kaldır"</string>
- <string name="delete_zone_label_all_apps_system_app" msgid="449755632749610895">"Güncellemeyi kaldır"</string>
- <string name="cab_menu_delete_app" msgid="7435191475867183689">"Uygulamanın yüklemesini kaldır"</string>
- <string name="cab_menu_app_info" msgid="8593722221450362342">"Uygulama ayrıntıları"</string>
- <string name="cab_app_selection_text" msgid="374688303047985416">"1 uygulama seçildi"</string>
- <string name="cab_widget_selection_text" msgid="1833458597831541241">"1 widget seçildi"</string>
- <string name="cab_folder_selection_text" msgid="7999992513806132118">"1 klasör seçildi"</string>
- <string name="cab_shortcut_selection_text" msgid="2103811025667946450">"1 kısayol seçildi"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"kısayolları yükle"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"Uygulamaya, kullanıcı müdahalesi olmadan kısayol ekleme izni verir."</string>
- <string name="permlab_uninstall_shortcut" msgid="864595034498083837">"kısayolların yüklemesini kaldır"</string>
- <string name="permdesc_uninstall_shortcut" msgid="5134129545001836849">"Uygulamaya, kullanıcı müdahalesi olmadan kısayolları kaldırma izni verir."</string>
<string name="permlab_read_settings" msgid="1941457408239617576">"Ana ekran ayarlarını ve kısayollarını oku"</string>
<string name="permdesc_read_settings" msgid="5833423719057558387">"Uygulamaya, Ana ekrandaki ayarları ve kısayolları okuma izni verir."</string>
<string name="permlab_write_settings" msgid="3574213698004620587">"Ana ekran ayarlarını ve kısayollarını yaz"</string>
@@ -78,30 +48,17 @@
<string name="gadget_error_text" msgid="6081085226050792095">"Widget yüklenirken sorun oluştu"</string>
<string name="gadget_setup_text" msgid="8274003207686040488">"Kurulum"</string>
<string name="uninstall_system_app_text" msgid="4172046090762920660">"Bu bir sistem uygulamasıdır ve yüklemesi kaldırılamaz."</string>
- <string name="dream_name" msgid="1530253749244328964">"Roket Fırlatıcı"</string>
<string name="folder_hint_text" msgid="6617836969016293992">"Adsız Klasör"</string>
- <string name="workspace_description_format" msgid="2950174241104043327">"Ana ekran %1$d"</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="apps_customize_apps_scroll_format" msgid="370005296147130238">"Uygulama sayfası %1$d / %2$d"</string>
- <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"Widget sayfası %1$d / %2$d"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"Hoş geldiniz"</string>
- <string name="first_run_cling_description" msgid="6447072552696253358">"Rahatınıza bakın."</string>
- <string name="first_run_cling_custom_content_hint" msgid="6090628589029352439"></string>
- <string name="first_run_cling_search_bar_hint" msgid="5909062802402452582"></string>
- <string name="first_run_cling_create_screens_hint" msgid="6950729526680114157">"Uygulamalar ve klasörler için daha fazla ekran oluşturun"</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>
<string name="migration_cling_copy_apps" msgid="946331230090919440">"SİMGELERİ KOPYALA"</string>
<string name="migration_cling_use_default" msgid="2626475813981258626">"VARSAYILANI KULLAN"</string>
- <string name="workspace_cling_title" msgid="5626202359865825661">"Alanınızı düzenleyin"</string>
- <string name="workspace_cling_move_item" msgid="528201129978005352">"Duvar kağıdını, widget\'ları ve ayarları yönetmek için arka plana uzun basın."</string>
<string name="workspace_cling_longpress_title" msgid="9173998993909018310">"Duvar kağıtları, widget\'lar ve ayarlar"</string>
<string name="workspace_cling_longpress_description" msgid="4119994475505235248">"Özelleştirmek için arka plana dokunun ve basılı tutun"</string>
<string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"TAMAM"</string>
- <string name="folder_cling_title" msgid="3894908818693254164">"İşte bir klasör"</string>
- <string name="folder_cling_create_folder" msgid="6158215559475836131">"Buna benzer bir klasör oluşturmak için uygulamaya uzun basın ve sonra uygulamayı başka bir uygulamanın üzerine taşıyın."</string>
- <string name="cling_dismiss" msgid="8962359497601507581">"Tamam"</string>
<string name="folder_opened" msgid="94695026776264709">"Klasör açıldı, <xliff:g id="WIDTH">%1$d</xliff:g> x <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
<string name="folder_tap_to_close" msgid="1884479294466410023">"Klasörü kapatmak için dokunun"</string>
<string name="folder_tap_to_rename" msgid="9191075570492871147">"Yeni adı kaydetmek için dokunun"</string>
@@ -111,14 +68,34 @@
<string name="widget_button_text" msgid="2880537293434387943">"Widget\'lar"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"Duvar Kağıtları"</string>
<string name="settings_button_text" msgid="8119458837558863227">"Ayarlar"</string>
- <string name="package_state_enqueued" msgid="6227252464303085641">"Bekliyor"</string>
- <string name="package_state_downloading" msgid="4088770468458724721">"İndiriliyor"</string>
- <string name="package_state_installing" msgid="7588193972189849870">"Yükleniyor"</string>
+ <string name="allow_rotation_title" msgid="2118706734511831751">"Döndürmeye izin ver"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Bilinmiyor"</string>
- <string name="package_state_error" msgid="7672093962724223588">"Geri yüklenmedi"</string>
- <string name="abandoned_clean_all" msgid="5256770727689657618">"Tümünü Kaldır"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Kaldır"</string>
<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="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>
+ <string name="item_removed" msgid="851119963877842327">"Öğe kaldırıldı"</string>
+ <string name="action_move" msgid="4339390619886385032">"Öğeyi taşı"</string>
+ <string name="move_to_empty_cell" msgid="2833711483015685619">"<xliff:g id="NUMBER_0">%1$s</xliff:g>. satır <xliff:g id="NUMBER_1">%2$s</xliff:g>. sütuna taşı"</string>
+ <string name="move_to_position" msgid="6750008980455459790">"<xliff:g id="NUMBER">%1$s</xliff:g>. sıraya taşı"</string>
+ <string name="move_to_hotseat_position" msgid="6295412897075147808">"Favorilerde <xliff:g id="NUMBER">%1$s</xliff:g>. sıraya taşı"</string>
+ <string name="item_moved" msgid="4606538322571412879">"Öğe taşındı"</string>
+ <string name="add_to_folder" msgid="9040534766770853243">"Klasöre ekle: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="add_to_folder_with_app" msgid="4534929978967147231">"<xliff:g id="NAME">%1$s</xliff:g> öğesini içeren klasöre ekle"</string>
+ <string name="added_to_folder" msgid="4793259502305558003">"Öğe, klasöre eklendi"</string>
+ <string name="create_folder_with" msgid="4050141361160214248">"Şu öğeyle klasör oluştur: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="folder_created" msgid="6409794597405184510">"Klasör oluşturuldu"</string>
+ <string name="action_move_to_workspace" msgid="1603837886334246317">"Ana ekrana taşı"</string>
+ <string name="action_move_screen_left" msgid="8854216831569401665">"Ekranı sola taşı"</string>
+ <string name="action_move_screen_right" msgid="329334910274311123">"Ekranı sağa taşı"</string>
+ <string name="screen_moved" msgid="266230079505650577">"Ekran taşındı"</string>
+ <string name="action_resize" msgid="1802976324781771067">"Yeniden boyutlandır"</string>
+ <string name="action_increase_width" msgid="8773715375078513326">"Genişliği artır"</string>
+ <string name="action_increase_height" msgid="459390020612501122">"Yüksekliği artır"</string>
+ <string name="action_decrease_width" msgid="1374549771083094654">"Genişliği azalt"</string>
+ <string name="action_decrease_height" msgid="282377193880900022">"Yüksekliği azalt"</string>
+ <string name="widget_resized" msgid="9130327887929620">"Widget, <xliff:g id="NUMBER_0">%1$s</xliff:g> genişlik ve <xliff:g id="NUMBER_1">%2$s</xliff:g> yükseklik değerine yeniden boyutlandırıldı"</string>
</resources>
diff --git a/res/values-uk/strings.xml b/res/values-uk/strings.xml
index 129b4388c..b06177e71 100644
--- a/res/values-uk/strings.xml
+++ b/res/values-uk/strings.xml
@@ -20,57 +20,27 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="application_name" msgid="5181331383435256801">"Launcher3"</string>
- <string name="home" msgid="7658288663002113681">"Головний екран"</string>
- <string name="uid_name" msgid="7820867637514617527">"Базові програми Android"</string>
<string name="folder_name" msgid="7371454440695724752"></string>
+ <string name="work_folder_name" msgid="3753320833950115786">"Робоча папка"</string>
<string name="activity_not_found" msgid="8071924732094499514">"Додаток видалено."</string>
<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="widgets_tab_label" msgid="2921133187116603919">"Віджети"</string>
- <string name="widget_adder" msgid="3201040140710381657">"Віджети"</string>
<string name="toggle_weight_watcher" msgid="5645299835184636119">"Показати пам’ять"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"Натисніть і утримуйте, щоб вибрати віджет."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
- <string name="external_drop_widget_error" msgid="3165821058322217155">"Не вдалося додати елемент на цей головний екран."</string>
- <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Вибрати віджет для створення"</string>
- <string name="rename_folder_label" msgid="3727762225964550653">"Назва папки"</string>
- <string name="rename_folder_title" msgid="3771389277707820891">"Перейменувати папку"</string>
- <string name="rename_action" msgid="5559600076028658757">"OК"</string>
- <string name="cancel_action" msgid="7009134900002915310">"Скасувати"</string>
- <string name="menu_item_add_item" msgid="1264911265836810421">"Додати на головний екран"</string>
- <string name="group_applications" msgid="3797214114206693605">"Додатки"</string>
- <string name="group_shortcuts" msgid="6012256992764410535">"Ярлики"</string>
- <string name="group_widgets" msgid="1569030723286851002">"Віджети"</string>
- <string name="completely_out_of_space" msgid="6106288382070760318">"На головних екранах більше немає місця."</string>
+ <string name="all_apps_search_bar_hint" msgid="7084713969757597256">"Пошук додатків"</string>
+ <string name="all_apps_loading_message" msgid="7557140873644765180">"Завантаження додатків…"</string>
+ <string name="all_apps_no_search_results" msgid="6332185285860416787">"Немає додатків для запиту \"<xliff:g id="QUERY">%1$s</xliff:g>\""</string>
<string name="out_of_space" msgid="4691004494942118364">"На цьому головному екрані більше немає місця."</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"В області \"Вибране\" немає місця"</string>
- <string name="invalid_hotseat_item" msgid="5779907847267573691">"Цей віджет завеликий для області \"Вибране\""</string>
- <string name="shortcut_installed" msgid="1701742129426969556">"Ярлик \"<xliff:g id="NAME">%s</xliff:g>\" створено."</string>
- <string name="shortcut_uninstalled" msgid="8176767991305701821">"Ярлик \"<xliff:g id="NAME">%s</xliff:g>\" вилучено."</string>
- <string name="shortcut_duplicate" msgid="9167217446062498127">"Ярлик \"<xliff:g id="NAME">%s</xliff:g>\" уже існує."</string>
- <string name="title_select_shortcut" msgid="6680642571148153868">"Вибрати ярлик"</string>
- <string name="title_select_application" msgid="3280812711670683644">"Виберіть додаток"</string>
<string name="all_apps_button_label" msgid="9110807029020582876">"Додатки"</string>
<string name="all_apps_home_button_label" msgid="252062713717058851">"Головний екран"</string>
- <string name="delete_zone_label_workspace" msgid="4009607676751398685">"Вилучити"</string>
- <string name="delete_zone_label_all_apps" msgid="8083826390278958980">"Видалити"</string>
<string name="delete_target_label" msgid="1822697352535677073">"Вилучити"</string>
<string name="delete_target_uninstall_label" msgid="5100785476250872595">"Видалити"</string>
<string name="info_target_label" msgid="8053346143994679532">"Про програму"</string>
- <string name="accessibility_all_apps_button" msgid="2603132375383800483">"Додатки"</string>
- <string name="accessibility_delete_button" msgid="6466114477993744621">"Вилучити"</string>
- <string name="delete_zone_label_all_apps_system_app" msgid="449755632749610895">"Видалити оновлення"</string>
- <string name="cab_menu_delete_app" msgid="7435191475867183689">"Видалити програму"</string>
- <string name="cab_menu_app_info" msgid="8593722221450362342">"Відомості про програму"</string>
- <string name="cab_app_selection_text" msgid="374688303047985416">"Вибрано 1 програму"</string>
- <string name="cab_widget_selection_text" msgid="1833458597831541241">"Вибрано 1 віджет"</string>
- <string name="cab_folder_selection_text" msgid="7999992513806132118">"Вибрано 1 папку"</string>
- <string name="cab_shortcut_selection_text" msgid="2103811025667946450">"Вибрано 1 ярлик"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"створення ярликів"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"Дозволяє програмі самостійно додавати ярлики."</string>
- <string name="permlab_uninstall_shortcut" msgid="864595034498083837">"видаляти ярлики"</string>
- <string name="permdesc_uninstall_shortcut" msgid="5134129545001836849">"Дозволяє програмі самостійно вилучати ярлики."</string>
<string name="permlab_read_settings" msgid="1941457408239617576">"читати налаштування та ярлики головного екрана"</string>
<string name="permdesc_read_settings" msgid="5833423719057558387">"Дозволяє програмі читати налаштування та ярлики на головному екрані."</string>
<string name="permlab_write_settings" msgid="3574213698004620587">"записувати налаштування та ярлики головного екрана"</string>
@@ -78,30 +48,17 @@
<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>
- <string name="dream_name" msgid="1530253749244328964">"Rocket Launcher"</string>
<string name="folder_hint_text" msgid="6617836969016293992">"Папка без назви"</string>
- <string name="workspace_description_format" msgid="2950174241104043327">"Головний екран %1$d"</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="apps_customize_apps_scroll_format" msgid="370005296147130238">"Сторінка програм %1$d з %2$d"</string>
- <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"Сторінка віджетів %1$d з %2$d"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"Вітаємо"</string>
- <string name="first_run_cling_description" msgid="6447072552696253358">"Будьте як удома."</string>
- <string name="first_run_cling_custom_content_hint" msgid="6090628589029352439"></string>
- <string name="first_run_cling_search_bar_hint" msgid="5909062802402452582"></string>
- <string name="first_run_cling_create_screens_hint" msgid="6950729526680114157">"Створюйте нові екрани для програм і папок"</string>
<string name="migration_cling_title" msgid="9181776667882933767">"Копіювати значки програм"</string>
<string name="migration_cling_description" msgid="2752413805582227644">"Імпортувати значки та папки зі старих головних екранів?"</string>
<string name="migration_cling_copy_apps" msgid="946331230090919440">"КОПІЮВАТИ ЗНАЧКИ"</string>
<string name="migration_cling_use_default" msgid="2626475813981258626">"ПАНЕЛЬ ЗАПУСКУ ЗА УМОВЧАННЯМ"</string>
- <string name="workspace_cling_title" msgid="5626202359865825661">"Організуйте робочий простір"</string>
- <string name="workspace_cling_move_item" msgid="528201129978005352">"Натисніть і утримуйте фон, щоб керувати фоновим малюнком, віджетами та налаштуваннями."</string>
<string name="workspace_cling_longpress_title" msgid="9173998993909018310">"Фонові малюнки, віджети й налаштування"</string>
<string name="workspace_cling_longpress_description" msgid="4119994475505235248">"Натисніть і втримуйте фон, щоб налаштувати робочу область"</string>
<string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"ЗРОЗУМІЛО"</string>
- <string name="folder_cling_title" msgid="3894908818693254164">"Це папка"</string>
- <string name="folder_cling_create_folder" msgid="6158215559475836131">"Щоб створити папку, натисніть і утримуйте програму, а потім перетягніть її на іншу."</string>
- <string name="cling_dismiss" msgid="8962359497601507581">"OК"</string>
<string name="folder_opened" msgid="94695026776264709">"Папку відкрито (<xliff:g id="WIDTH">%1$d</xliff:g> х <xliff:g id="HEIGHT">%2$d</xliff:g>)"</string>
<string name="folder_tap_to_close" msgid="1884479294466410023">"Торкніться, щоб закрити папку"</string>
<string name="folder_tap_to_rename" msgid="9191075570492871147">"Торкніться, щоб зберегти нову назву"</string>
@@ -111,14 +68,34 @@
<string name="widget_button_text" msgid="2880537293434387943">"Віджети"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"Фонові малюнки"</string>
<string name="settings_button_text" msgid="8119458837558863227">"Налаштування"</string>
- <string name="package_state_enqueued" msgid="6227252464303085641">"Очікування"</string>
- <string name="package_state_downloading" msgid="4088770468458724721">"Завантаження"</string>
- <string name="package_state_installing" msgid="7588193972189849870">"Встановлення"</string>
+ <string name="allow_rotation_title" msgid="2118706734511831751">"Дозволити обертання"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Невідомо"</string>
- <string name="package_state_error" msgid="7672093962724223588">"Не відновлено"</string>
- <string name="abandoned_clean_all" msgid="5256770727689657618">"Видалити всі"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Видалити"</string>
<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="action_add_to_workspace" msgid="8902165848117513641">"Додати на головний екран"</string>
+ <string name="action_move_here" msgid="2170188780612570250">"Перемістити елемент сюди"</string>
+ <string name="item_added_to_workspace" msgid="4211073925752213539">"Елемент додано на головний екран"</string>
+ <string name="item_removed" msgid="851119963877842327">"Елемент вилучено"</string>
+ <string name="action_move" msgid="4339390619886385032">"Перемістити елемент"</string>
+ <string name="move_to_empty_cell" msgid="2833711483015685619">"Перемістити в рядок <xliff:g id="NUMBER_0">%1$s</xliff:g>, стовпець <xliff:g id="NUMBER_1">%2$s</xliff:g>"</string>
+ <string name="move_to_position" msgid="6750008980455459790">"Перемістити на <xliff:g id="NUMBER">%1$s</xliff:g> місце"</string>
+ <string name="move_to_hotseat_position" msgid="6295412897075147808">"Перемістити у вибране на <xliff:g id="NUMBER">%1$s</xliff:g> місце"</string>
+ <string name="item_moved" msgid="4606538322571412879">"Елемент переміщено"</string>
+ <string name="add_to_folder" msgid="9040534766770853243">"Додати в папку \"<xliff:g id="NAME">%1$s</xliff:g>\""</string>
+ <string name="add_to_folder_with_app" msgid="4534929978967147231">"Додати в папку з додатком <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="added_to_folder" msgid="4793259502305558003">"Елемент додано в папку"</string>
+ <string name="create_folder_with" msgid="4050141361160214248">"Створити папку з: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="folder_created" msgid="6409794597405184510">"Папку створено"</string>
+ <string name="action_move_to_workspace" msgid="1603837886334246317">"Перемістити на головний екран"</string>
+ <string name="action_move_screen_left" msgid="8854216831569401665">"Перемістити екран ліворуч"</string>
+ <string name="action_move_screen_right" msgid="329334910274311123">"Перемістити екран праворуч"</string>
+ <string name="screen_moved" msgid="266230079505650577">"Екран переміщено"</string>
+ <string name="action_resize" msgid="1802976324781771067">"Змінити розміри"</string>
+ <string name="action_increase_width" msgid="8773715375078513326">"Збільшити ширину"</string>
+ <string name="action_increase_height" msgid="459390020612501122">"Збільшити висоту"</string>
+ <string name="action_decrease_width" msgid="1374549771083094654">"Зменшити ширину"</string>
+ <string name="action_decrease_height" msgid="282377193880900022">"Зменшити висоту"</string>
+ <string name="widget_resized" msgid="9130327887929620">"Розміри віджета змінено на <xliff:g id="NUMBER_0">%1$s</xliff:g> завширшки та <xliff:g id="NUMBER_1">%2$s</xliff:g> заввишки"</string>
</resources>
diff --git a/res/values-ur-rPK/strings.xml b/res/values-ur-rPK/strings.xml
index ba1d3fa9a..ba189c87d 100644
--- a/res/values-ur-rPK/strings.xml
+++ b/res/values-ur-rPK/strings.xml
@@ -20,57 +20,27 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="application_name" msgid="5181331383435256801">"Launcher3"</string>
- <string name="home" msgid="7658288663002113681">"ہوم"</string>
- <string name="uid_name" msgid="7820867637514617527">"‏Android کور ایپس"</string>
<string name="folder_name" msgid="7371454440695724752"></string>
+ <string name="work_folder_name" msgid="3753320833950115786">"دفتری"</string>
<string name="activity_not_found" msgid="8071924732094499514">"ایپ انسٹال نہیں ہے۔"</string>
<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="widgets_tab_label" msgid="2921133187116603919">"ویجیٹس"</string>
- <string name="widget_adder" msgid="3201040140710381657">"ویجیٹس"</string>
<string name="toggle_weight_watcher" msgid="5645299835184636119">"‏Mem دکھائیں"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"کوئی ویجیٹ منتخب کرنے کیلئے ٹچ کریں اور پکڑے رہیں۔"</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
- <string name="external_drop_widget_error" msgid="3165821058322217155">"آئٹم کو اس ہوم اسکرین پر ڈراپ نہیں کیا جا سکا۔"</string>
- <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"بنانے کیلئے ویجیٹ منتخب کریں"</string>
- <string name="rename_folder_label" msgid="3727762225964550653">"فولڈر کا نام"</string>
- <string name="rename_folder_title" msgid="3771389277707820891">"فولڈر کا نام تبدیل کریں"</string>
- <string name="rename_action" msgid="5559600076028658757">"ٹھیک ہے"</string>
- <string name="cancel_action" msgid="7009134900002915310">"منسوخ کریں"</string>
- <string name="menu_item_add_item" msgid="1264911265836810421">"ہوم اسکرین میں شامل کریں"</string>
- <string name="group_applications" msgid="3797214114206693605">"ایپس"</string>
- <string name="group_shortcuts" msgid="6012256992764410535">"شارٹ کٹس"</string>
- <string name="group_widgets" msgid="1569030723286851002">"ویجیٹس"</string>
- <string name="completely_out_of_space" msgid="6106288382070760318">"آپ کی ہوم اسکرینوں پر مزید کوئی گنجائش نہیں ہے۔"</string>
+ <string name="all_apps_search_bar_hint" msgid="7084713969757597256">"ایپس تلاش کریں"</string>
+ <string name="all_apps_loading_message" msgid="7557140873644765180">"ایپس لوڈ ہو رہی ہیں…"</string>
+ <string name="all_apps_no_search_results" msgid="6332185285860416787">"\"<xliff:g id="QUERY">%1$s</xliff:g>\" سے مماثل کوئی ایپس نہیں ملیں"</string>
<string name="out_of_space" msgid="4691004494942118364">"اس ہوم اسکرین پر مزید کوئی گنجائش نہیں ہے۔"</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"پسندیدہ ٹرے میں مزید کوئی گنجائش نہیں ہے"</string>
- <string name="invalid_hotseat_item" msgid="5779907847267573691">"یہ ویجیٹ پسندیدہ ٹرے کیلئے کافی بڑا ہے"</string>
- <string name="shortcut_installed" msgid="1701742129426969556">"شارٹ کٹ \"<xliff:g id="NAME">%s</xliff:g>\" بنایا گیا۔"</string>
- <string name="shortcut_uninstalled" msgid="8176767991305701821">"شارٹ کٹ \"<xliff:g id="NAME">%s</xliff:g>\" ہٹا دیا گیا۔"</string>
- <string name="shortcut_duplicate" msgid="9167217446062498127">"شارٹ کٹ \"<xliff:g id="NAME">%s</xliff:g>\" پہلے سے موجود ہے۔"</string>
- <string name="title_select_shortcut" msgid="6680642571148153868">"شارٹ کٹ منتخب کریں"</string>
- <string name="title_select_application" msgid="3280812711670683644">"ایپ منتخب کریں"</string>
<string name="all_apps_button_label" msgid="9110807029020582876">"ایپس"</string>
<string name="all_apps_home_button_label" msgid="252062713717058851">"ہوم"</string>
- <string name="delete_zone_label_workspace" msgid="4009607676751398685">"ہٹائیں"</string>
- <string name="delete_zone_label_all_apps" msgid="8083826390278958980">"اَن انسٹال کریں"</string>
<string name="delete_target_label" msgid="1822697352535677073">"ہٹائیں"</string>
<string name="delete_target_uninstall_label" msgid="5100785476250872595">"اَن انسٹال کریں"</string>
<string name="info_target_label" msgid="8053346143994679532">"ایپ کی معلومات"</string>
- <string name="accessibility_all_apps_button" msgid="2603132375383800483">"ایپس"</string>
- <string name="accessibility_delete_button" msgid="6466114477993744621">"ہٹائیں"</string>
- <string name="delete_zone_label_all_apps_system_app" msgid="449755632749610895">"اپ ڈیٹ اَن انسٹال کریں"</string>
- <string name="cab_menu_delete_app" msgid="7435191475867183689">"ایپ کو اَن انسٹال کریں"</string>
- <string name="cab_menu_app_info" msgid="8593722221450362342">"ایپ کی تفصیلات"</string>
- <string name="cab_app_selection_text" msgid="374688303047985416">"1 ایپ منتخب کی گئی"</string>
- <string name="cab_widget_selection_text" msgid="1833458597831541241">"1 ویجیٹ منتخب کیا گیا"</string>
- <string name="cab_folder_selection_text" msgid="7999992513806132118">"1 فولڈر منتخب کیا گیا"</string>
- <string name="cab_shortcut_selection_text" msgid="2103811025667946450">"1 شارٹ کٹ منتخب کیا گیا"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"شارٹ کٹس انسٹال کریں"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"کسی ایپ کو صارف کی مداخلت کے بغیر شارٹ کٹس شامل کرنے کی اجازت دیتا ہے۔"</string>
- <string name="permlab_uninstall_shortcut" msgid="864595034498083837">"شارٹ کٹس کو اَن انسٹال کریں"</string>
- <string name="permdesc_uninstall_shortcut" msgid="5134129545001836849">"ایپ کو صارف کی مداخلت کے بغیر شارٹ کٹس ہٹانے کی اجازت دیتا ہے۔"</string>
<string name="permlab_read_settings" msgid="1941457408239617576">"ہوم ترتیبات اور شارٹ کٹس کو پڑھیں"</string>
<string name="permdesc_read_settings" msgid="5833423719057558387">"ایپ کو ہوم میں ترتیبات اور شارٹ کٹس کو پڑھنے کی اجازت دیتا ہے۔"</string>
<string name="permlab_write_settings" msgid="3574213698004620587">"ہوم ترتیبات اور شارٹ کٹس کو لکھیں"</string>
@@ -78,30 +48,17 @@
<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>
- <string name="dream_name" msgid="1530253749244328964">"راکٹ لانچر"</string>
<string name="folder_hint_text" msgid="6617836969016293992">"بلا نام فولڈر"</string>
- <string name="workspace_description_format" msgid="2950174241104043327">"‏ہوم اسکرین ‎%1$d"</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="apps_customize_apps_scroll_format" msgid="370005296147130238">"‏ایپس کا صفحہ ‎%1$d از ‎%2$d"</string>
- <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"‏ویجیٹس کا صفحہ ‎%1$d از ‎%2$d"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"خوش آمدید"</string>
- <string name="first_run_cling_description" msgid="6447072552696253358">"ہوم سکرین مرضی کے مطابق بنائیں۔"</string>
- <string name="first_run_cling_custom_content_hint" msgid="6090628589029352439"></string>
- <string name="first_run_cling_search_bar_hint" msgid="5909062802402452582"></string>
- <string name="first_run_cling_create_screens_hint" msgid="6950729526680114157">"ایپس اور فولڈرز کیلئے مزید اسکرینیں بنائیں"</string>
<string name="migration_cling_title" msgid="9181776667882933767">"اپنے ایپ آئیکنز کو کاپی کریں"</string>
<string name="migration_cling_description" msgid="2752413805582227644">"اپنی پرانی ہوم اسکرینوں سے آئیکنز اور فولڈرز درآمد کریں؟"</string>
<string name="migration_cling_copy_apps" msgid="946331230090919440">"آئیکنز کاپی کریں"</string>
<string name="migration_cling_use_default" msgid="2626475813981258626">"نئے سرے سے شروع کریں"</string>
- <string name="workspace_cling_title" msgid="5626202359865825661">"اپنی جگہ کو منظم کریں"</string>
- <string name="workspace_cling_move_item" msgid="528201129978005352">"وال پیپر، ویجیٹس اور ترتیبات کا نظم کرنے کیلئے پس منظر کو ٹچ کریں اور پکڑ کر رکھیں۔"</string>
<string name="workspace_cling_longpress_title" msgid="9173998993909018310">"وال پیپرز، ویجیٹس اور ترتیبات"</string>
<string name="workspace_cling_longpress_description" msgid="4119994475505235248">"حسب ضرورت بنانے کیلئے پس منظر کو ٹچ کریں اور دبائے رکھیں"</string>
<string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"سمجھ آ گئی"</string>
- <string name="folder_cling_title" msgid="3894908818693254164">"یہ ہے ایک فولڈر"</string>
- <string name="folder_cling_create_folder" msgid="6158215559475836131">"اس طرح کا ایک بنانے کیلئے، کسی ایپ کو ٹچ کریں اور پکڑ کر رکھیں، پھر اسے کسی دوسرے میں منتقل کریں۔"</string>
- <string name="cling_dismiss" msgid="8962359497601507581">"ٹھیک ہے"</string>
<string name="folder_opened" msgid="94695026776264709">"فولڈر کھولا گیا، <xliff:g id="WIDTH">%1$d</xliff:g> × <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
<string name="folder_tap_to_close" msgid="1884479294466410023">"فولڈر بند کرنے کیلئے ٹچ کریں"</string>
<string name="folder_tap_to_rename" msgid="9191075570492871147">"نام کی تبدیلی محفوظ کرنے کیلئے ٹچ کریں"</string>
@@ -111,14 +68,34 @@
<string name="widget_button_text" msgid="2880537293434387943">"ویجیٹس"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"وال پیپرز"</string>
<string name="settings_button_text" msgid="8119458837558863227">"ترتیبات"</string>
- <string name="package_state_enqueued" msgid="6227252464303085641">"منتظر"</string>
- <string name="package_state_downloading" msgid="4088770468458724721">"ڈاؤن لوڈ کیا جا رہا ہے"</string>
- <string name="package_state_installing" msgid="7588193972189849870">"انسٹال کیا جا رہا ہے"</string>
+ <string name="allow_rotation_title" msgid="2118706734511831751">"گردش کی اجازت دیں"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"نامعلوم"</string>
- <string name="package_state_error" msgid="7672093962724223588">"بحال نہیں ہوا"</string>
- <string name="abandoned_clean_all" msgid="5256770727689657618">"سبھی کو ہٹا دیں"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"ہٹائیں"</string>
<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="action_add_to_workspace" msgid="8902165848117513641">"ہوم اسکرین میں شامل کریں"</string>
+ <string name="action_move_here" msgid="2170188780612570250">"آئٹم یہاں منتقل کریں"</string>
+ <string name="item_added_to_workspace" msgid="4211073925752213539">"آئٹم کو ہوم اسکرین میں شامل کر دیا گیا"</string>
+ <string name="item_removed" msgid="851119963877842327">"آئٹم ہٹا دیا گیا"</string>
+ <string name="action_move" msgid="4339390619886385032">"آئٹم منتقل کریں"</string>
+ <string name="move_to_empty_cell" msgid="2833711483015685619">"قطار <xliff:g id="NUMBER_0">%1$s</xliff:g> کالم <xliff:g id="NUMBER_1">%2$s</xliff:g> میں منتقل کریں"</string>
+ <string name="move_to_position" msgid="6750008980455459790">"پوزیشن <xliff:g id="NUMBER">%1$s</xliff:g> میں منتقل کریں"</string>
+ <string name="move_to_hotseat_position" msgid="6295412897075147808">"پسندیدہ پوزیشن <xliff:g id="NUMBER">%1$s</xliff:g> میں منتقل کریں"</string>
+ <string name="item_moved" msgid="4606538322571412879">"آئٹم منتقل کر دیا گیا"</string>
+ <string name="add_to_folder" msgid="9040534766770853243">"فولڈر میں شامل کریں: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="add_to_folder_with_app" msgid="4534929978967147231">"<xliff:g id="NAME">%1$s</xliff:g> کے فولڈر میں شامل کریں"</string>
+ <string name="added_to_folder" msgid="4793259502305558003">"آئٹم فولڈر میں شامل کر دیا گیا"</string>
+ <string name="create_folder_with" msgid="4050141361160214248">"اس کے ساتھ فولڈر بنائیں: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="folder_created" msgid="6409794597405184510">"فولڈر بنا دیا گیا"</string>
+ <string name="action_move_to_workspace" msgid="1603837886334246317">"ہوم اسکرین میں منتقل کریں"</string>
+ <string name="action_move_screen_left" msgid="8854216831569401665">"اسکرین کو بائیں منتقل کریں"</string>
+ <string name="action_move_screen_right" msgid="329334910274311123">"اسکرین کو دائیں منتقل کریں"</string>
+ <string name="screen_moved" msgid="266230079505650577">"اسکرین منتقل کر دی گئی"</string>
+ <string name="action_resize" msgid="1802976324781771067">"سائز تبدیل کریں"</string>
+ <string name="action_increase_width" msgid="8773715375078513326">"چوڑائی بڑھائیں"</string>
+ <string name="action_increase_height" msgid="459390020612501122">"اونچائی بڑھائیں"</string>
+ <string name="action_decrease_width" msgid="1374549771083094654">"چوڑائی کم کریں"</string>
+ <string name="action_decrease_height" msgid="282377193880900022">"اونچائی کم کریں"</string>
+ <string name="widget_resized" msgid="9130327887929620">"ویجیٹ کے سائز کو چوڑائی <xliff:g id="NUMBER_0">%1$s</xliff:g> اونچائی <xliff:g id="NUMBER_1">%2$s</xliff:g> میں تبدیل کر دیا گیا"</string>
</resources>
diff --git a/res/values-uz-rUZ/strings.xml b/res/values-uz-rUZ/strings.xml
index 60d3ac065..c3bffeb3c 100644
--- a/res/values-uz-rUZ/strings.xml
+++ b/res/values-uz-rUZ/strings.xml
@@ -20,57 +20,27 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="application_name" msgid="5181331383435256801">"Ishga tushirgich3"</string>
- <string name="home" msgid="7658288663002113681">"Uy"</string>
- <string name="uid_name" msgid="7820867637514617527">"Androidga asoslangan dasturlar"</string>
<string name="folder_name" msgid="7371454440695724752"></string>
+ <string name="work_folder_name" msgid="3753320833950115786">"Ishga oid"</string>
<string name="activity_not_found" msgid="8071924732094499514">"Ilova o‘rnatilmadi."</string>
<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="widgets_tab_label" msgid="2921133187116603919">"Vidjetlar"</string>
- <string name="widget_adder" msgid="3201040140710381657">"Vidjetlar"</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="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
- <string name="external_drop_widget_error" msgid="3165821058322217155">"Elementni ushbu \"Uy\" ekraniga tashlab bo‘lmadi."</string>
- <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Yaratish uchun vidjet tanlang"</string>
- <string name="rename_folder_label" msgid="3727762225964550653">"Jild nomi"</string>
- <string name="rename_folder_title" msgid="3771389277707820891">"Jild nomini o‘zgartirish"</string>
- <string name="rename_action" msgid="5559600076028658757">"OK"</string>
- <string name="cancel_action" msgid="7009134900002915310">"Bekor qilish"</string>
- <string name="menu_item_add_item" msgid="1264911265836810421">"Uy ekraniga qo‘shish"</string>
- <string name="group_applications" msgid="3797214114206693605">"Ilovalar"</string>
- <string name="group_shortcuts" msgid="6012256992764410535">"Yorliqlar"</string>
- <string name="group_widgets" msgid="1569030723286851002">"Vidjetlar"</string>
- <string name="completely_out_of_space" msgid="6106288382070760318">"Uy ekraningizda birorta ham xona yo‘q."</string>
+ <string name="all_apps_search_bar_hint" msgid="7084713969757597256">"Ilovalarni qidirish"</string>
+ <string name="all_apps_loading_message" msgid="7557140873644765180">"Ilovalar yuklanmoqda…"</string>
+ <string name="all_apps_no_search_results" msgid="6332185285860416787">"“<xliff:g id="QUERY">%1$s</xliff:g>” bilan mos hech qanday ilova topilmadi"</string>
<string name="out_of_space" msgid="4691004494942118364">"Uy ekranida bitta ham xona yo‘q."</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"Ajratilganlarda birorta ham xona yo‘q"</string>
- <string name="invalid_hotseat_item" msgid="5779907847267573691">"Ajratilganlar uchun ushbu vidjet juda katta"</string>
- <string name="shortcut_installed" msgid="1701742129426969556">"\"<xliff:g id="NAME">%s</xliff:g>\" yorlig‘i yaratildi."</string>
- <string name="shortcut_uninstalled" msgid="8176767991305701821">"\"<xliff:g id="NAME">%s</xliff:g>\" yorlig‘i o‘chirildi."</string>
- <string name="shortcut_duplicate" msgid="9167217446062498127">"\"<xliff:g id="NAME">%s</xliff:g>\" yorlig‘i allaqachon mavjud."</string>
- <string name="title_select_shortcut" msgid="6680642571148153868">"Yorliqni tanlash"</string>
- <string name="title_select_application" msgid="3280812711670683644">"Ilovani tanlash"</string>
<string name="all_apps_button_label" msgid="9110807029020582876">"Ilovalar"</string>
<string name="all_apps_home_button_label" msgid="252062713717058851">"Uy"</string>
- <string name="delete_zone_label_workspace" msgid="4009607676751398685">"O‘chirish"</string>
- <string name="delete_zone_label_all_apps" msgid="8083826390278958980">"O‘chirish"</string>
<string name="delete_target_label" msgid="1822697352535677073">"O‘chirish"</string>
<string name="delete_target_uninstall_label" msgid="5100785476250872595">"O‘chirish"</string>
<string name="info_target_label" msgid="8053346143994679532">"Ilova haqida"</string>
- <string name="accessibility_all_apps_button" msgid="2603132375383800483">"Ilovalar"</string>
- <string name="accessibility_delete_button" msgid="6466114477993744621">"O‘chirish"</string>
- <string name="delete_zone_label_all_apps_system_app" msgid="449755632749610895">"Yangilashni o‘chirish"</string>
- <string name="cab_menu_delete_app" msgid="7435191475867183689">"Ilovani o‘chirish"</string>
- <string name="cab_menu_app_info" msgid="8593722221450362342">"Ilova ma’lumotlari"</string>
- <string name="cab_app_selection_text" msgid="374688303047985416">"1 ta ilova tanlandi"</string>
- <string name="cab_widget_selection_text" msgid="1833458597831541241">"1 ta vidjet tanlandi"</string>
- <string name="cab_folder_selection_text" msgid="7999992513806132118">"1 ta jild tanlandi"</string>
- <string name="cab_shortcut_selection_text" msgid="2103811025667946450">"1 ta yorliq tanlandi"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"yorliqlar yaratish"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"Ilovalarga foydalanuvchidan so‘ramasdan yorliqlar qo‘shishga ruxsat beradi."</string>
- <string name="permlab_uninstall_shortcut" msgid="864595034498083837">"yorliqlarni o‘chirish"</string>
- <string name="permdesc_uninstall_shortcut" msgid="5134129545001836849">"Ilovaga foydalanuvchiga bildirmasdan yorliqlarni o‘chirish uchun ruxsat beradi."</string>
<string name="permlab_read_settings" msgid="1941457408239617576">"Uy sozlamalari va yorliqlarini o‘qish"</string>
<string name="permdesc_read_settings" msgid="5833423719057558387">"Ilovaga \"Uy\" ekranidagi yorliqlar va sozlamalarni o‘qish uchun ruxsat beradi."</string>
<string name="permlab_write_settings" msgid="3574213698004620587">"Uy sozlamalari va yorliqlarini yozish"</string>
@@ -78,30 +48,17 @@
<string name="gadget_error_text" msgid="6081085226050792095">"Vidjetni yuklashda muammo"</string>
<string name="gadget_setup_text" msgid="8274003207686040488">"Sozlash"</string>
<string name="uninstall_system_app_text" msgid="4172046090762920660">"Bu tizim ilovasi, shuning uchun o‘chirib bo‘lmaydi."</string>
- <string name="dream_name" msgid="1530253749244328964">"Rocket Launcher"</string>
<string name="folder_hint_text" msgid="6617836969016293992">"Nomsiz jild"</string>
- <string name="workspace_description_format" msgid="2950174241104043327">"Uy ekrani %1$d"</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="apps_customize_apps_scroll_format" msgid="370005296147130238">"Ilovalar sahifasi %2$ddan %1$d"</string>
- <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"Vidjetlar sahifasi %2$ddan %1$d"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"Xush kelibsiz"</string>
- <string name="first_run_cling_description" msgid="6447072552696253358">"O‘zingizni uyingizdagidek his qiling."</string>
- <string name="first_run_cling_custom_content_hint" msgid="6090628589029352439"></string>
- <string name="first_run_cling_search_bar_hint" msgid="5909062802402452582"></string>
- <string name="first_run_cling_create_screens_hint" msgid="6950729526680114157">"Ilovalar va jildlar uchun ko‘proq ekranlar yaratish"</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>
<string name="migration_cling_copy_apps" msgid="946331230090919440">"NISHONCHALARNI NUSXALASH"</string>
<string name="migration_cling_use_default" msgid="2626475813981258626">"YANGIDAN BOSHLASH"</string>
- <string name="workspace_cling_title" msgid="5626202359865825661">"Joylaringizni boshqaring"</string>
- <string name="workspace_cling_move_item" msgid="528201129978005352">"Fon rasmi, vidjet va sozlamalarni boshqarish uchun orqa fonga bosib turing"</string>
<string name="workspace_cling_longpress_title" msgid="9173998993909018310">"Orqa fon rasmlari, vidjet va sozlamalar"</string>
<string name="workspace_cling_longpress_description" msgid="4119994475505235248">"Orqa fonni moslashtirish uchun uni bosing va ushlab turing"</string>
<string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"OK"</string>
- <string name="folder_cling_title" msgid="3894908818693254164">"Mana sizga jild"</string>
- <string name="folder_cling_create_folder" msgid="6158215559475836131">"Bunga o‘xshaganini yaratish uchun bosib turing, keyin boshqasiga o‘ting."</string>
- <string name="cling_dismiss" msgid="8962359497601507581">"OK"</string>
<string name="folder_opened" msgid="94695026776264709">"Jild ochildi, <xliff:g id="WIDTH">%1$d</xliff:g> ga <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
<string name="folder_tap_to_close" msgid="1884479294466410023">"Jildni yopish uchun bosing"</string>
<string name="folder_tap_to_rename" msgid="9191075570492871147">"O‘zgartirilgan nomni saqlash uchun bosing"</string>
@@ -111,14 +68,34 @@
<string name="widget_button_text" msgid="2880537293434387943">"Vidjetlar"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"Fon rasmlari"</string>
<string name="settings_button_text" msgid="8119458837558863227">"Sozlamalar"</string>
- <string name="package_state_enqueued" msgid="6227252464303085641">"Kutilmoqda"</string>
- <string name="package_state_downloading" msgid="4088770468458724721">"Yuklab olinmoqda"</string>
- <string name="package_state_installing" msgid="7588193972189849870">"O‘rnatilmoqda"</string>
+ <string name="allow_rotation_title" msgid="2118706734511831751">"Aylanishga ruxsat berish"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Noma’lum"</string>
- <string name="package_state_error" msgid="7672093962724223588">"Qayta tiklanmadi"</string>
- <string name="abandoned_clean_all" msgid="5256770727689657618">"Barchasini o‘chirish"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"O‘chirish"</string>
<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="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>
+ <string name="item_removed" msgid="851119963877842327">"Obyekt o‘chirib tashlandi"</string>
+ <string name="action_move" msgid="4339390619886385032">"Obyektni ko‘chirib o‘tkazish"</string>
+ <string name="move_to_empty_cell" msgid="2833711483015685619">"<xliff:g id="NUMBER_0">%1$s</xliff:g> <xliff:g id="NUMBER_1">%2$s</xliff:g> katakka ko‘chirib o‘tkazish"</string>
+ <string name="move_to_position" msgid="6750008980455459790">"<xliff:g id="NUMBER">%1$s</xliff:g>-joyga ko‘chirib o‘tkazish"</string>
+ <string name="move_to_hotseat_position" msgid="6295412897075147808">"Sevimlilarga (<xliff:g id="NUMBER">%1$s</xliff:g>) ko‘chirib o‘tkazish"</string>
+ <string name="item_moved" msgid="4606538322571412879">"Element ko‘chirib o‘tkazildi"</string>
+ <string name="add_to_folder" msgid="9040534766770853243">"<xliff:g id="NAME">%1$s</xliff:g> jildiga qo‘shish"</string>
+ <string name="add_to_folder_with_app" msgid="4534929978967147231">"<xliff:g id="NAME">%1$s</xliff:g> ilovasi bor jildga qo‘shish"</string>
+ <string name="added_to_folder" msgid="4793259502305558003">"Element jildga qo‘shildi"</string>
+ <string name="create_folder_with" msgid="4050141361160214248">"<xliff:g id="NAME">%1$s</xliff:g> bilan jild yaratish"</string>
+ <string name="folder_created" msgid="6409794597405184510">"Jild yaratildi"</string>
+ <string name="action_move_to_workspace" msgid="1603837886334246317">"Bosh ekranga ko‘chirish"</string>
+ <string name="action_move_screen_left" msgid="8854216831569401665">"Ekranni chapga siljitish"</string>
+ <string name="action_move_screen_right" msgid="329334910274311123">"Ekranni o‘ngga siljitish"</string>
+ <string name="screen_moved" msgid="266230079505650577">"Ekran siljitildi"</string>
+ <string name="action_resize" msgid="1802976324781771067">"O‘lchamini o‘zgartirish"</string>
+ <string name="action_increase_width" msgid="8773715375078513326">"Enini uzaytirish"</string>
+ <string name="action_increase_height" msgid="459390020612501122">"Bo‘yini uzaytirish"</string>
+ <string name="action_decrease_width" msgid="1374549771083094654">"Enini kichraytirish"</string>
+ <string name="action_decrease_height" msgid="282377193880900022">"Bo‘yini kichraytirish"</string>
+ <string name="widget_resized" msgid="9130327887929620">"Vidjetning eni <xliff:g id="NUMBER_0">%1$s</xliff:g>, bo‘yi <xliff:g id="NUMBER_1">%2$s</xliff:g> qilib o‘zgartirildi"</string>
</resources>
diff --git a/res/values-v17/styles.xml b/res/values-v17/styles.xml
deleted file mode 100644
index 11d2a1f82..000000000
--- a/res/values-v17/styles.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
- <style name="PagedViewWidgetImageView">
- <item name="android:paddingStart">@dimen/app_widget_preview_padding_left</item>
- </style>
-</resources>
diff --git a/res/values-vi/strings.xml b/res/values-vi/strings.xml
index 5bc16275e..f57f491ae 100644
--- a/res/values-vi/strings.xml
+++ b/res/values-vi/strings.xml
@@ -20,57 +20,27 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="application_name" msgid="5181331383435256801">"Launcher3"</string>
- <string name="home" msgid="7658288663002113681">"Màn hình chính"</string>
- <string name="uid_name" msgid="7820867637514617527">"Ứng dụng lõi Android"</string>
<string name="folder_name" msgid="7371454440695724752"></string>
+ <string name="work_folder_name" msgid="3753320833950115786">"Work"</string>
<string name="activity_not_found" msgid="8071924732094499514">"Ứng dụng chưa được cài đặt."</string>
<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="widgets_tab_label" msgid="2921133187116603919">"Tiện ích con"</string>
- <string name="widget_adder" msgid="3201040140710381657">"Tiện ích con"</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="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
- <string name="external_drop_widget_error" msgid="3165821058322217155">"Không thể thả mục vào Màn hình chính này."</string>
- <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Chọn tiện ích con để tạo"</string>
- <string name="rename_folder_label" msgid="3727762225964550653">"Tên thư mục"</string>
- <string name="rename_folder_title" msgid="3771389277707820891">"Đổi tên thư mục"</string>
- <string name="rename_action" msgid="5559600076028658757">"OK"</string>
- <string name="cancel_action" msgid="7009134900002915310">"Hủy"</string>
- <string name="menu_item_add_item" msgid="1264911265836810421">"Thêm vào Màn hình chính"</string>
- <string name="group_applications" msgid="3797214114206693605">"Ứng dụng"</string>
- <string name="group_shortcuts" msgid="6012256992764410535">"Lối tắt"</string>
- <string name="group_widgets" msgid="1569030723286851002">"Tiện ích con"</string>
- <string name="completely_out_of_space" msgid="6106288382070760318">"Không còn chỗ trên Màn hình chính của bạn."</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>
+ <string name="all_apps_no_search_results" msgid="6332185285860416787">"Không tìm thấy ứng dụng nào phù hợp với \"<xliff:g id="QUERY">%1$s</xliff:g>\""</string>
<string name="out_of_space" msgid="4691004494942118364">"Không còn chỗ trên Màn hình chính này."</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"Không còn chỗ trong khay Mục yêu thích"</string>
- <string name="invalid_hotseat_item" msgid="5779907847267573691">"Tiện ích con này có kích thước quá lớn để đặt vào khay Mục yêu thích"</string>
- <string name="shortcut_installed" msgid="1701742129426969556">"Lối tắt \"<xliff:g id="NAME">%s</xliff:g>\" đã được tạo."</string>
- <string name="shortcut_uninstalled" msgid="8176767991305701821">"Lối tắt \"<xliff:g id="NAME">%s</xliff:g>\" đã bị xóa."</string>
- <string name="shortcut_duplicate" msgid="9167217446062498127">"Lối tắt \"<xliff:g id="NAME">%s</xliff:g>\" đã tồn tại."</string>
- <string name="title_select_shortcut" msgid="6680642571148153868">"Chọn lối tắt"</string>
- <string name="title_select_application" msgid="3280812711670683644">"Chọn ứng dụng"</string>
<string name="all_apps_button_label" msgid="9110807029020582876">"Ứng dụng"</string>
<string name="all_apps_home_button_label" msgid="252062713717058851">"Màn hình chính"</string>
- <string name="delete_zone_label_workspace" msgid="4009607676751398685">"Xóa"</string>
- <string name="delete_zone_label_all_apps" msgid="8083826390278958980">"Gỡ cài đặt"</string>
<string name="delete_target_label" msgid="1822697352535677073">"Xóa"</string>
<string name="delete_target_uninstall_label" msgid="5100785476250872595">"Gỡ cài đặt"</string>
<string name="info_target_label" msgid="8053346143994679532">"Thông tin ứng dụng"</string>
- <string name="accessibility_all_apps_button" msgid="2603132375383800483">"Ứng dụng"</string>
- <string name="accessibility_delete_button" msgid="6466114477993744621">"Xóa"</string>
- <string name="delete_zone_label_all_apps_system_app" msgid="449755632749610895">"Gỡ cài đặt cập nhật"</string>
- <string name="cab_menu_delete_app" msgid="7435191475867183689">"Gỡ cài đặt ứng dụng"</string>
- <string name="cab_menu_app_info" msgid="8593722221450362342">"Thông tin chi tiết về ứng dụng"</string>
- <string name="cab_app_selection_text" msgid="374688303047985416">"Đã chọn 1 ứng dụng"</string>
- <string name="cab_widget_selection_text" msgid="1833458597831541241">"Đã chọn 1 tiện ích con"</string>
- <string name="cab_folder_selection_text" msgid="7999992513806132118">"Đã chọn 1 thư mục"</string>
- <string name="cab_shortcut_selection_text" msgid="2103811025667946450">"Đã chọn 1 lối tắt"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"cài đặt lối tắt"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"Cho phép ứng dụng thêm lối tắt mà không cần sự can thiệp của người dùng."</string>
- <string name="permlab_uninstall_shortcut" msgid="864595034498083837">"gỡ cài đặt lối tắt"</string>
- <string name="permdesc_uninstall_shortcut" msgid="5134129545001836849">"Cho phép ứng dụng xóa lối tắt mà không cần sự can thiệp của người dùng."</string>
<string name="permlab_read_settings" msgid="1941457408239617576">"đọc cài đặt và lối tắt trên Màn hình chính"</string>
<string name="permdesc_read_settings" msgid="5833423719057558387">"Cho phép ứng dụng đọc cài đặt và lối tắt trên Màn hình chính."</string>
<string name="permlab_write_settings" msgid="3574213698004620587">"ghi cài đặt và lối tắt trên Màn hình chính"</string>
@@ -78,30 +48,17 @@
<string name="gadget_error_text" msgid="6081085226050792095">"Sự cố khi tải tiện ích con"</string>
<string name="gadget_setup_text" msgid="8274003207686040488">"Thiết lập"</string>
<string name="uninstall_system_app_text" msgid="4172046090762920660">"Đây là ứng dụng hệ thống và không thể gỡ cài đặt."</string>
- <string name="dream_name" msgid="1530253749244328964">"Rocket Launcher"</string>
<string name="folder_hint_text" msgid="6617836969016293992">"Thư mục chưa đặt tên"</string>
- <string name="workspace_description_format" msgid="2950174241104043327">"Màn hình chính %1$d"</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="apps_customize_apps_scroll_format" msgid="370005296147130238">"Trang ứng dụng %1$d / %2$d"</string>
- <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"Trang tiện ích con %1$d / %2$d"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"Chào mừng"</string>
- <string name="first_run_cling_description" msgid="6447072552696253358">"Tự nhiên như ở nhà."</string>
- <string name="first_run_cling_custom_content_hint" msgid="6090628589029352439"></string>
- <string name="first_run_cling_search_bar_hint" msgid="5909062802402452582"></string>
- <string name="first_run_cling_create_screens_hint" msgid="6950729526680114157">"Tạo thêm màn hình cho ứng dụng và thư mục"</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>
<string name="migration_cling_copy_apps" msgid="946331230090919440">"BIỂU TƯỢNG SAO CHÉP"</string>
<string name="migration_cling_use_default" msgid="2626475813981258626">"BẮT ĐẦU LÀM MỚI"</string>
- <string name="workspace_cling_title" msgid="5626202359865825661">"Sắp xếp không gian của bạn"</string>
- <string name="workspace_cling_move_item" msgid="528201129978005352">"Chạm và giữ nền để quản lý hình nền, tiện ích con và cài đặt."</string>
<string name="workspace_cling_longpress_title" msgid="9173998993909018310">"Hình nền, tiện ích và cài đặt"</string>
<string name="workspace_cling_longpress_description" msgid="4119994475505235248">"Chạm và giữ nền để tùy chỉnh"</string>
<string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"OK"</string>
- <string name="folder_cling_title" msgid="3894908818693254164">"Đây là một thư mục"</string>
- <string name="folder_cling_create_folder" msgid="6158215559475836131">"Để tạo thư mục như thế này, hãy chạm và giữ một ứng dụng, sau đó di chuyển ứng dụng đó lên trên một ứng dụng khác."</string>
- <string name="cling_dismiss" msgid="8962359497601507581">"OK"</string>
<string name="folder_opened" msgid="94695026776264709">"Đã mở thư mục, <xliff:g id="WIDTH">%1$d</xliff:g> x <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
<string name="folder_tap_to_close" msgid="1884479294466410023">"Chạm để đóng thư mục"</string>
<string name="folder_tap_to_rename" msgid="9191075570492871147">"Chạm để lưu tên mới"</string>
@@ -111,14 +68,34 @@
<string name="widget_button_text" msgid="2880537293434387943">"Tiện ích con"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"Hình nền"</string>
<string name="settings_button_text" msgid="8119458837558863227">"Cài đặt"</string>
- <string name="package_state_enqueued" msgid="6227252464303085641">"Đang đợi"</string>
- <string name="package_state_downloading" msgid="4088770468458724721">"Đang tải xuống"</string>
- <string name="package_state_installing" msgid="7588193972189849870">"Đang cài đặt"</string>
+ <string name="allow_rotation_title" msgid="2118706734511831751">"Cho phép xoay"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Không xác định"</string>
- <string name="package_state_error" msgid="7672093962724223588">"Không được khôi phục"</string>
- <string name="abandoned_clean_all" msgid="5256770727689657618">"Xóa tất cả"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Xóa"</string>
<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="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>
+ <string name="item_removed" msgid="851119963877842327">"Đã xóa mục"</string>
+ <string name="action_move" msgid="4339390619886385032">"Di chuyển mục"</string>
+ <string name="move_to_empty_cell" msgid="2833711483015685619">"Di chuyển đến hàng <xliff:g id="NUMBER_0">%1$s</xliff:g> cột <xliff:g id="NUMBER_1">%2$s</xliff:g>"</string>
+ <string name="move_to_position" msgid="6750008980455459790">"Di chuyển tới vị trí <xliff:g id="NUMBER">%1$s</xliff:g>"</string>
+ <string name="move_to_hotseat_position" msgid="6295412897075147808">"Di chuyển tới vị trí mục yêu thích <xliff:g id="NUMBER">%1$s</xliff:g>"</string>
+ <string name="item_moved" msgid="4606538322571412879">"Đã di chuyển mục"</string>
+ <string name="add_to_folder" msgid="9040534766770853243">"Thêm vào thư mục: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="add_to_folder_with_app" msgid="4534929978967147231">"Thêm vào thư mục có <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="added_to_folder" msgid="4793259502305558003">"Đã thêm mục vào thư mục"</string>
+ <string name="create_folder_with" msgid="4050141361160214248">"Tạo thư mục bằng: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="folder_created" msgid="6409794597405184510">"Đã tạo thư mục"</string>
+ <string name="action_move_to_workspace" msgid="1603837886334246317">"Di chuyển đến màn hình chính"</string>
+ <string name="action_move_screen_left" msgid="8854216831569401665">"Di chuyển màn hình sang trái"</string>
+ <string name="action_move_screen_right" msgid="329334910274311123">"Di chuyển màn hình sang phải"</string>
+ <string name="screen_moved" msgid="266230079505650577">"Đã di chuyển màn hình"</string>
+ <string name="action_resize" msgid="1802976324781771067">"Đổi kích thước"</string>
+ <string name="action_increase_width" msgid="8773715375078513326">"Tăng chiều rộng"</string>
+ <string name="action_increase_height" msgid="459390020612501122">"Tăng chiều cao"</string>
+ <string name="action_decrease_width" msgid="1374549771083094654">"Giảm chiều rộng"</string>
+ <string name="action_decrease_height" msgid="282377193880900022">"Giảm chiều cao"</string>
+ <string name="widget_resized" msgid="9130327887929620">"Đã đổi kích thước tiện ích thành chiều rộng <xliff:g id="NUMBER_0">%1$s</xliff:g> chiều cao <xliff:g id="NUMBER_1">%2$s</xliff:g>"</string>
</resources>
diff --git a/res/values-zh-rCN/strings.xml b/res/values-zh-rCN/strings.xml
index b7c42fe5c..82274ba2c 100644
--- a/res/values-zh-rCN/strings.xml
+++ b/res/values-zh-rCN/strings.xml
@@ -20,57 +20,27 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="application_name" msgid="5181331383435256801">"Launcher3"</string>
- <string name="home" msgid="7658288663002113681">"主屏"</string>
- <string name="uid_name" msgid="7820867637514617527">"Android 核心应用"</string>
<string name="folder_name" msgid="7371454440695724752"></string>
+ <string name="work_folder_name" msgid="3753320833950115786">"Work"</string>
<string name="activity_not_found" msgid="8071924732094499514">"未安装该应用。"</string>
<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="widgets_tab_label" msgid="2921133187116603919">"小部件"</string>
- <string name="widget_adder" msgid="3201040140710381657">"小部件"</string>
<string name="toggle_weight_watcher" msgid="5645299835184636119">"显示内存空间"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"触摸并按住小部件即可选择。"</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
- <string name="external_drop_widget_error" msgid="3165821058322217155">"无法将相关内容拖放到此主屏幕上。"</string>
- <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"选择要创建的小部件"</string>
- <string name="rename_folder_label" msgid="3727762225964550653">"文件夹名称"</string>
- <string name="rename_folder_title" msgid="3771389277707820891">"重命名文件夹"</string>
- <string name="rename_action" msgid="5559600076028658757">"确定"</string>
- <string name="cancel_action" msgid="7009134900002915310">"取消"</string>
- <string name="menu_item_add_item" msgid="1264911265836810421">"添加到主屏幕"</string>
- <string name="group_applications" msgid="3797214114206693605">"应用"</string>
- <string name="group_shortcuts" msgid="6012256992764410535">"快捷方式"</string>
- <string name="group_widgets" msgid="1569030723286851002">"小部件"</string>
- <string name="completely_out_of_space" msgid="6106288382070760318">"您的主屏幕上没有空间了。"</string>
+ <string name="all_apps_search_bar_hint" msgid="7084713969757597256">"搜索应用"</string>
+ <string name="all_apps_loading_message" msgid="7557140873644765180">"正在加载应用…"</string>
+ <string name="all_apps_no_search_results" msgid="6332185285860416787">"未找到与“<xliff:g id="QUERY">%1$s</xliff:g>”相符的应用"</string>
<string name="out_of_space" msgid="4691004494942118364">"此主屏幕上已没有空间。"</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"收藏栏已满"</string>
- <string name="invalid_hotseat_item" msgid="5779907847267573691">"该小部件太大,收藏栏中放不下"</string>
- <string name="shortcut_installed" msgid="1701742129426969556">"已创建“<xliff:g id="NAME">%s</xliff:g>”快捷方式。"</string>
- <string name="shortcut_uninstalled" msgid="8176767991305701821">"已删除“<xliff:g id="NAME">%s</xliff:g>”快捷方式。"</string>
- <string name="shortcut_duplicate" msgid="9167217446062498127">"“<xliff:g id="NAME">%s</xliff:g>”快捷方式已存在。"</string>
- <string name="title_select_shortcut" msgid="6680642571148153868">"选择快捷方式"</string>
- <string name="title_select_application" msgid="3280812711670683644">"选择应用"</string>
<string name="all_apps_button_label" msgid="9110807029020582876">"应用"</string>
<string name="all_apps_home_button_label" msgid="252062713717058851">"主屏幕"</string>
- <string name="delete_zone_label_workspace" msgid="4009607676751398685">"删除"</string>
- <string name="delete_zone_label_all_apps" msgid="8083826390278958980">"卸载"</string>
<string name="delete_target_label" msgid="1822697352535677073">"删除"</string>
<string name="delete_target_uninstall_label" msgid="5100785476250872595">"卸载"</string>
<string name="info_target_label" msgid="8053346143994679532">"应用信息"</string>
- <string name="accessibility_all_apps_button" msgid="2603132375383800483">"应用"</string>
- <string name="accessibility_delete_button" msgid="6466114477993744621">"删除"</string>
- <string name="delete_zone_label_all_apps_system_app" msgid="449755632749610895">"卸载更新内容"</string>
- <string name="cab_menu_delete_app" msgid="7435191475867183689">"卸载应用"</string>
- <string name="cab_menu_app_info" msgid="8593722221450362342">"应用详情"</string>
- <string name="cab_app_selection_text" msgid="374688303047985416">"已选择1个应用"</string>
- <string name="cab_widget_selection_text" msgid="1833458597831541241">"已选择1个小部件"</string>
- <string name="cab_folder_selection_text" msgid="7999992513806132118">"已选择1个文件夹"</string>
- <string name="cab_shortcut_selection_text" msgid="2103811025667946450">"已选择1个快捷方式"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"安装快捷方式"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"允许应用自行添加快捷方式。"</string>
- <string name="permlab_uninstall_shortcut" msgid="864595034498083837">"卸载快捷方式"</string>
- <string name="permdesc_uninstall_shortcut" msgid="5134129545001836849">"允许应用自行删除快捷方式。"</string>
<string name="permlab_read_settings" msgid="1941457408239617576">"读取主屏幕设置和快捷方式"</string>
<string name="permdesc_read_settings" msgid="5833423719057558387">"允许应用读取主屏幕中的设置和快捷方式。"</string>
<string name="permlab_write_settings" msgid="3574213698004620587">"写入主屏幕设置和快捷方式"</string>
@@ -78,30 +48,17 @@
<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>
- <string name="dream_name" msgid="1530253749244328964">"火箭发射器"</string>
<string name="folder_hint_text" msgid="6617836969016293992">"未命名文件夹"</string>
- <string name="workspace_description_format" msgid="2950174241104043327">"主屏幕%1$d"</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="apps_customize_apps_scroll_format" msgid="370005296147130238">"应用:第%1$d页,共%2$d页"</string>
- <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"小部件:第%1$d页,共%2$d页"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"欢迎使用"</string>
- <string name="first_run_cling_description" msgid="6447072552696253358">"您的主屏幕您做主。"</string>
- <string name="first_run_cling_custom_content_hint" msgid="6090628589029352439"></string>
- <string name="first_run_cling_search_bar_hint" msgid="5909062802402452582"></string>
- <string name="first_run_cling_create_screens_hint" msgid="6950729526680114157">"添加更多屏幕来容纳应用和文件夹"</string>
<string name="migration_cling_title" msgid="9181776667882933767">"复制应用图标"</string>
<string name="migration_cling_description" msgid="2752413805582227644">"要导入旧的主屏幕中的图标和文件夹吗?"</string>
<string name="migration_cling_copy_apps" msgid="946331230090919440">"复制图标"</string>
<string name="migration_cling_use_default" msgid="2626475813981258626">"使用全新配置"</string>
- <string name="workspace_cling_title" msgid="5626202359865825661">"整理您的空间"</string>
- <string name="workspace_cling_move_item" msgid="528201129978005352">"触摸并按住背景,即可管理壁纸、小部件和设置。"</string>
<string name="workspace_cling_longpress_title" msgid="9173998993909018310">"壁纸、小部件和设置"</string>
<string name="workspace_cling_longpress_description" msgid="4119994475505235248">"触摸并按住背景,即可进行个性化设置"</string>
<string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"知道了"</string>
- <string name="folder_cling_title" msgid="3894908818693254164">"这是一个文件夹"</string>
- <string name="folder_cling_create_folder" msgid="6158215559475836131">"要创建一个类似的文件夹,请触摸并按住某个应用,然后将其移至另一个应用上。"</string>
- <string name="cling_dismiss" msgid="8962359497601507581">"确定"</string>
<string name="folder_opened" msgid="94695026776264709">"文件夹已打开,大小为<xliff:g id="WIDTH">%1$d</xliff:g>×<xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
<string name="folder_tap_to_close" msgid="1884479294466410023">"触摸可关闭文件夹"</string>
<string name="folder_tap_to_rename" msgid="9191075570492871147">"触摸可保存新名称"</string>
@@ -111,14 +68,34 @@
<string name="widget_button_text" msgid="2880537293434387943">"小部件"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"壁纸"</string>
<string name="settings_button_text" msgid="8119458837558863227">"设置"</string>
- <string name="package_state_enqueued" msgid="6227252464303085641">"正在等待"</string>
- <string name="package_state_downloading" msgid="4088770468458724721">"正在下载"</string>
- <string name="package_state_installing" msgid="7588193972189849870">"正在安装"</string>
+ <string name="allow_rotation_title" msgid="2118706734511831751">"允许旋转"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"未知"</string>
- <string name="package_state_error" msgid="7672093962724223588">"无法还原"</string>
- <string name="abandoned_clean_all" msgid="5256770727689657618">"全部移除"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"移除"</string>
<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="action_add_to_workspace" msgid="8902165848117513641">"添加到主屏幕"</string>
+ <string name="action_move_here" msgid="2170188780612570250">"将项目移至此处"</string>
+ <string name="item_added_to_workspace" msgid="4211073925752213539">"已将项目添加到主屏幕"</string>
+ <string name="item_removed" msgid="851119963877842327">"项目已移除"</string>
+ <string name="action_move" msgid="4339390619886385032">"移动项目"</string>
+ <string name="move_to_empty_cell" msgid="2833711483015685619">"移至第 <xliff:g id="NUMBER_0">%1$s</xliff:g> 行第 <xliff:g id="NUMBER_1">%2$s</xliff:g> 列"</string>
+ <string name="move_to_position" msgid="6750008980455459790">"移至第 <xliff:g id="NUMBER">%1$s</xliff:g> 个位置"</string>
+ <string name="move_to_hotseat_position" msgid="6295412897075147808">"移至收藏夹第 <xliff:g id="NUMBER">%1$s</xliff:g> 个位置"</string>
+ <string name="item_moved" msgid="4606538322571412879">"已移动项目"</string>
+ <string name="add_to_folder" msgid="9040534766770853243">"添加到“<xliff:g id="NAME">%1$s</xliff:g>”文件夹"</string>
+ <string name="add_to_folder_with_app" msgid="4534929978967147231">"添加到“<xliff:g id="NAME">%1$s</xliff:g>”所在文件夹"</string>
+ <string name="added_to_folder" msgid="4793259502305558003">"项目已添加到文件夹"</string>
+ <string name="create_folder_with" msgid="4050141361160214248">"创建“<xliff:g id="NAME">%1$s</xliff:g>”文件夹"</string>
+ <string name="folder_created" msgid="6409794597405184510">"文件夹已创建"</string>
+ <string name="action_move_to_workspace" msgid="1603837886334246317">"移至主屏幕"</string>
+ <string name="action_move_screen_left" msgid="8854216831569401665">"将屏幕向左移动"</string>
+ <string name="action_move_screen_right" msgid="329334910274311123">"将屏幕向右移动"</string>
+ <string name="screen_moved" msgid="266230079505650577">"屏幕已移动"</string>
+ <string name="action_resize" msgid="1802976324781771067">"调整大小"</string>
+ <string name="action_increase_width" msgid="8773715375078513326">"增加宽度"</string>
+ <string name="action_increase_height" msgid="459390020612501122">"增加高度"</string>
+ <string name="action_decrease_width" msgid="1374549771083094654">"减小宽度"</string>
+ <string name="action_decrease_height" msgid="282377193880900022">"减小高度"</string>
+ <string name="widget_resized" msgid="9130327887929620">"小部件尺寸已调整为:宽度 <xliff:g id="NUMBER_0">%1$s</xliff:g>,高度 <xliff:g id="NUMBER_1">%2$s</xliff:g>"</string>
</resources>
diff --git a/res/values-zh-rHK/strings.xml b/res/values-zh-rHK/strings.xml
index 2eb700890..f7d240e05 100644
--- a/res/values-zh-rHK/strings.xml
+++ b/res/values-zh-rHK/strings.xml
@@ -20,57 +20,27 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="application_name" msgid="5181331383435256801">"Launcher3"</string>
- <string name="home" msgid="7658288663002113681">"主畫面"</string>
- <string name="uid_name" msgid="7820867637514617527">"Android 核心應用程式"</string>
<string name="folder_name" msgid="7371454440695724752"></string>
+ <string name="work_folder_name" msgid="3753320833950115786">"工作"</string>
<string name="activity_not_found" msgid="8071924732094499514">"尚未安裝應用程式。"</string>
<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="widgets_tab_label" msgid="2921133187116603919">"小工具"</string>
- <string name="widget_adder" msgid="3201040140710381657">"小工具"</string>
<string name="toggle_weight_watcher" msgid="5645299835184636119">"顯示記憶體"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"輕觸並按住小工具即可選取。"</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
- <string name="external_drop_widget_error" msgid="3165821058322217155">"無法將項目拖放至主畫面。"</string>
- <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"選擇要建立的小工具"</string>
- <string name="rename_folder_label" msgid="3727762225964550653">"資料夾名稱"</string>
- <string name="rename_folder_title" msgid="3771389277707820891">"重新命名資料夾"</string>
- <string name="rename_action" msgid="5559600076028658757">"確定"</string>
- <string name="cancel_action" msgid="7009134900002915310">"取消"</string>
- <string name="menu_item_add_item" msgid="1264911265836810421">"新增至主畫面"</string>
- <string name="group_applications" msgid="3797214114206693605">"應用程式"</string>
- <string name="group_shortcuts" msgid="6012256992764410535">"捷徑"</string>
- <string name="group_widgets" msgid="1569030723286851002">"小工具"</string>
- <string name="completely_out_of_space" msgid="6106288382070760318">"主畫面已無空間。"</string>
+ <string name="all_apps_search_bar_hint" msgid="7084713969757597256">"搜尋應用程式"</string>
+ <string name="all_apps_loading_message" msgid="7557140873644765180">"正在載入應用程式…"</string>
+ <string name="all_apps_no_search_results" msgid="6332185285860416787">"無法找到與「<xliff:g id="QUERY">%1$s</xliff:g>」相符的應用程式"</string>
<string name="out_of_space" msgid="4691004494942118364">"主畫面已無空間。"</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"我的收藏寄存區沒有足夠空間"</string>
- <string name="invalid_hotseat_item" msgid="5779907847267573691">"這個小工具過大,我的收藏寄存區沒有足夠空間"</string>
- <string name="shortcut_installed" msgid="1701742129426969556">"已建立「<xliff:g id="NAME">%s</xliff:g>」捷徑。"</string>
- <string name="shortcut_uninstalled" msgid="8176767991305701821">"已移除「<xliff:g id="NAME">%s</xliff:g>」捷徑。"</string>
- <string name="shortcut_duplicate" msgid="9167217446062498127">"「<xliff:g id="NAME">%s</xliff:g>」捷徑已存在。"</string>
- <string name="title_select_shortcut" msgid="6680642571148153868">"選擇捷徑"</string>
- <string name="title_select_application" msgid="3280812711670683644">"選擇應用程式"</string>
<string name="all_apps_button_label" msgid="9110807029020582876">"應用程式"</string>
<string name="all_apps_home_button_label" msgid="252062713717058851">"主畫面"</string>
- <string name="delete_zone_label_workspace" msgid="4009607676751398685">"移除"</string>
- <string name="delete_zone_label_all_apps" msgid="8083826390278958980">"解除安裝"</string>
<string name="delete_target_label" msgid="1822697352535677073">"移除"</string>
<string name="delete_target_uninstall_label" msgid="5100785476250872595">"解除安裝"</string>
<string name="info_target_label" msgid="8053346143994679532">"應用程式資料"</string>
- <string name="accessibility_all_apps_button" msgid="2603132375383800483">"應用程式"</string>
- <string name="accessibility_delete_button" msgid="6466114477993744621">"移除"</string>
- <string name="delete_zone_label_all_apps_system_app" msgid="449755632749610895">"解除安裝更新"</string>
- <string name="cab_menu_delete_app" msgid="7435191475867183689">"解除安裝應用程式"</string>
- <string name="cab_menu_app_info" msgid="8593722221450362342">"應用程式詳細資料"</string>
- <string name="cab_app_selection_text" msgid="374688303047985416">"已選取 1 個應用程式"</string>
- <string name="cab_widget_selection_text" msgid="1833458597831541241">"已選取 1 個小工具"</string>
- <string name="cab_folder_selection_text" msgid="7999992513806132118">"已選取 1 個資料夾"</string>
- <string name="cab_shortcut_selection_text" msgid="2103811025667946450">"已選取 1 個捷徑"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"安裝捷徑"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"允許應用程式無需使用者許可也可新增捷徑。"</string>
- <string name="permlab_uninstall_shortcut" msgid="864595034498083837">"解除安裝捷徑"</string>
- <string name="permdesc_uninstall_shortcut" msgid="5134129545001836849">"允許應用程式無需使用者許可也可移除捷徑。"</string>
<string name="permlab_read_settings" msgid="1941457408239617576">"讀取主畫面的設定和捷徑"</string>
<string name="permdesc_read_settings" msgid="5833423719057558387">"允許應用程式讀取主畫面中的設定和捷徑。"</string>
<string name="permlab_write_settings" msgid="3574213698004620587">"寫入主畫面的設定和捷徑"</string>
@@ -78,30 +48,17 @@
<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>
- <string name="dream_name" msgid="1530253749244328964">"Rocket Launcher"</string>
<string name="folder_hint_text" msgid="6617836969016293992">"未命名的資料夾"</string>
- <string name="workspace_description_format" msgid="2950174241104043327">"主畫面 %1$d"</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="apps_customize_apps_scroll_format" msgid="370005296147130238">"第 %1$d 個應用程式頁面,共 %2$d 頁"</string>
- <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"第 %1$d 個小工具頁面,共 %2$d 頁"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"歡迎"</string>
- <string name="first_run_cling_description" msgid="6447072552696253358">"自訂主畫面。"</string>
- <string name="first_run_cling_custom_content_hint" msgid="6090628589029352439"></string>
- <string name="first_run_cling_search_bar_hint" msgid="5909062802402452582"></string>
- <string name="first_run_cling_create_screens_hint" msgid="6950729526680114157">"建立更多應用程式和資料夾的畫面"</string>
<string name="migration_cling_title" msgid="9181776667882933767">"複製您的應用程式圖示"</string>
<string name="migration_cling_description" msgid="2752413805582227644">"要從舊主畫面匯入圖示和資料夾嗎?"</string>
<string name="migration_cling_copy_apps" msgid="946331230090919440">"複製圖示"</string>
<string name="migration_cling_use_default" msgid="2626475813981258626">"重新開始"</string>
- <string name="workspace_cling_title" msgid="5626202359865825661">"管理您的空間"</string>
- <string name="workspace_cling_move_item" msgid="528201129978005352">"輕觸並按住背景,即可管理桌布、小工具和設定。"</string>
<string name="workspace_cling_longpress_title" msgid="9173998993909018310">"桌布、小工具和設定"</string>
<string name="workspace_cling_longpress_description" msgid="4119994475505235248">"輕觸並按住背景即可自訂"</string>
<string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"知道了"</string>
- <string name="folder_cling_title" msgid="3894908818693254164">"資料夾顯示如下"</string>
- <string name="folder_cling_create_folder" msgid="6158215559475836131">"如要建立類似的資料夾,請輕觸並按住某個應用程式,然後疊到另一個應用程式之上。"</string>
- <string name="cling_dismiss" msgid="8962359497601507581">"確定"</string>
<string name="folder_opened" msgid="94695026776264709">"資料夾已開啟 (<xliff:g id="WIDTH">%1$d</xliff:g> x <xliff:g id="HEIGHT">%2$d</xliff:g>)"</string>
<string name="folder_tap_to_close" msgid="1884479294466410023">"輕觸即可關閉資料夾"</string>
<string name="folder_tap_to_rename" msgid="9191075570492871147">"輕觸即可儲存新改的名稱"</string>
@@ -111,14 +68,34 @@
<string name="widget_button_text" msgid="2880537293434387943">"小工具"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"桌布"</string>
<string name="settings_button_text" msgid="8119458837558863227">"設定"</string>
- <string name="package_state_enqueued" msgid="6227252464303085641">"等候中"</string>
- <string name="package_state_downloading" msgid="4088770468458724721">"下載中"</string>
- <string name="package_state_installing" msgid="7588193972189849870">"安裝中"</string>
+ <string name="allow_rotation_title" msgid="2118706734511831751">"允許旋轉"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"不明"</string>
- <string name="package_state_error" msgid="7672093962724223588">"無法還原"</string>
- <string name="abandoned_clean_all" msgid="5256770727689657618">"全部移除"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"移除"</string>
<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="action_add_to_workspace" msgid="8902165848117513641">"新增至主畫面"</string>
+ <string name="action_move_here" msgid="2170188780612570250">"移動項目至這裡"</string>
+ <string name="item_added_to_workspace" msgid="4211073925752213539">"已將項目加入至主畫面"</string>
+ <string name="item_removed" msgid="851119963877842327">"項目已移除"</string>
+ <string name="action_move" msgid="4339390619886385032">"移動項目"</string>
+ <string name="move_to_empty_cell" msgid="2833711483015685619">"移動至第 <xliff:g id="NUMBER_0">%1$s</xliff:g> 行第 <xliff:g id="NUMBER_1">%2$s</xliff:g> 列"</string>
+ <string name="move_to_position" msgid="6750008980455459790">"移動至位置 <xliff:g id="NUMBER">%1$s</xliff:g>"</string>
+ <string name="move_to_hotseat_position" msgid="6295412897075147808">"移動至喜愛的位置 <xliff:g id="NUMBER">%1$s</xliff:g>"</string>
+ <string name="item_moved" msgid="4606538322571412879">"已移動項目"</string>
+ <string name="add_to_folder" msgid="9040534766770853243">"加入資料夾:<xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="add_to_folder_with_app" msgid="4534929978967147231">"加入至資料夾:<xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="added_to_folder" msgid="4793259502305558003">"項目已加入資料夾"</string>
+ <string name="create_folder_with" msgid="4050141361160214248">"使用以下項目建立資料夾:<xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="folder_created" msgid="6409794597405184510">"已建立資料夾"</string>
+ <string name="action_move_to_workspace" msgid="1603837886334246317">"移動至主畫面"</string>
+ <string name="action_move_screen_left" msgid="8854216831569401665">"向左移動螢幕"</string>
+ <string name="action_move_screen_right" msgid="329334910274311123">"向右移動螢幕"</string>
+ <string name="screen_moved" msgid="266230079505650577">"已移動螢幕"</string>
+ <string name="action_resize" msgid="1802976324781771067">"重新調整大小"</string>
+ <string name="action_increase_width" msgid="8773715375078513326">"增加闊度"</string>
+ <string name="action_increase_height" msgid="459390020612501122">"增加高度"</string>
+ <string name="action_decrease_width" msgid="1374549771083094654">"減少闊度"</string>
+ <string name="action_decrease_height" msgid="282377193880900022">"減少高度"</string>
+ <string name="widget_resized" msgid="9130327887929620">"已調整小工具的大小至闊 <xliff:g id="NUMBER_0">%1$s</xliff:g> 高 <xliff:g id="NUMBER_1">%2$s</xliff:g>"</string>
</resources>
diff --git a/res/values-zh-rTW/strings.xml b/res/values-zh-rTW/strings.xml
index 52e758396..39a0ec77a 100644
--- a/res/values-zh-rTW/strings.xml
+++ b/res/values-zh-rTW/strings.xml
@@ -20,57 +20,27 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="application_name" msgid="5181331383435256801">"Launcher3"</string>
- <string name="home" msgid="7658288663002113681">"主螢幕"</string>
- <string name="uid_name" msgid="7820867637514617527">"Android 核心應用程式"</string>
<string name="folder_name" msgid="7371454440695724752"></string>
+ <string name="work_folder_name" msgid="3753320833950115786">"公司"</string>
<string name="activity_not_found" msgid="8071924732094499514">"應用程式未安裝。"</string>
<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="widgets_tab_label" msgid="2921133187116603919">"小工具"</string>
- <string name="widget_adder" msgid="3201040140710381657">"小工具"</string>
<string name="toggle_weight_watcher" msgid="5645299835184636119">"顯示記憶體"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"輕觸並按住小工具即可選取。"</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
- <string name="external_drop_widget_error" msgid="3165821058322217155">"無法將項目拖放至這個主螢幕上。"</string>
- <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"選擇要建立的小工具"</string>
- <string name="rename_folder_label" msgid="3727762225964550653">"資料夾名稱"</string>
- <string name="rename_folder_title" msgid="3771389277707820891">"重新命名資料夾"</string>
- <string name="rename_action" msgid="5559600076028658757">"確定"</string>
- <string name="cancel_action" msgid="7009134900002915310">"取消"</string>
- <string name="menu_item_add_item" msgid="1264911265836810421">"新增至主螢幕"</string>
- <string name="group_applications" msgid="3797214114206693605">"應用程式"</string>
- <string name="group_shortcuts" msgid="6012256992764410535">"捷徑"</string>
- <string name="group_widgets" msgid="1569030723286851002">"小工具"</string>
- <string name="completely_out_of_space" msgid="6106288382070760318">"主螢幕已無空間。"</string>
+ <string name="all_apps_search_bar_hint" msgid="7084713969757597256">"搜尋應用程式"</string>
+ <string name="all_apps_loading_message" msgid="7557140873644765180">"正在載入應用程式…"</string>
+ <string name="all_apps_no_search_results" msgid="6332185285860416787">"找不到符合「<xliff:g id="QUERY">%1$s</xliff:g>」的應用程式"</string>
<string name="out_of_space" msgid="4691004494942118364">"這個主螢幕已無空間。"</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"「我的最愛」匣已無可用空間"</string>
- <string name="invalid_hotseat_item" msgid="5779907847267573691">"這個小工具過大,「我的最愛」匣無法容納"</string>
- <string name="shortcut_installed" msgid="1701742129426969556">"已建立「<xliff:g id="NAME">%s</xliff:g>」捷徑。"</string>
- <string name="shortcut_uninstalled" msgid="8176767991305701821">"已移除「<xliff:g id="NAME">%s</xliff:g>」捷徑。"</string>
- <string name="shortcut_duplicate" msgid="9167217446062498127">"「<xliff:g id="NAME">%s</xliff:g>」捷徑已存在。"</string>
- <string name="title_select_shortcut" msgid="6680642571148153868">"選擇捷徑"</string>
- <string name="title_select_application" msgid="3280812711670683644">"選擇應用程式"</string>
<string name="all_apps_button_label" msgid="9110807029020582876">"應用程式"</string>
<string name="all_apps_home_button_label" msgid="252062713717058851">"主螢幕"</string>
- <string name="delete_zone_label_workspace" msgid="4009607676751398685">"移除"</string>
- <string name="delete_zone_label_all_apps" msgid="8083826390278958980">"解除安裝"</string>
<string name="delete_target_label" msgid="1822697352535677073">"移除"</string>
<string name="delete_target_uninstall_label" msgid="5100785476250872595">"解除安裝"</string>
<string name="info_target_label" msgid="8053346143994679532">"應用程式資訊"</string>
- <string name="accessibility_all_apps_button" msgid="2603132375383800483">"應用程式"</string>
- <string name="accessibility_delete_button" msgid="6466114477993744621">"移除"</string>
- <string name="delete_zone_label_all_apps_system_app" msgid="449755632749610895">"解除安裝更新"</string>
- <string name="cab_menu_delete_app" msgid="7435191475867183689">"解除安裝應用程式"</string>
- <string name="cab_menu_app_info" msgid="8593722221450362342">"應用程式詳細資料"</string>
- <string name="cab_app_selection_text" msgid="374688303047985416">"已選取 1 個應用程式"</string>
- <string name="cab_widget_selection_text" msgid="1833458597831541241">"已選取 1 個小工具"</string>
- <string name="cab_folder_selection_text" msgid="7999992513806132118">"已選取 1 個資料夾"</string>
- <string name="cab_shortcut_selection_text" msgid="2103811025667946450">"已選取 1 個捷徑"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"安裝捷徑"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"允許應用程式自動新增捷徑。"</string>
- <string name="permlab_uninstall_shortcut" msgid="864595034498083837">"解除安裝捷徑"</string>
- <string name="permdesc_uninstall_shortcut" msgid="5134129545001836849">"允許應用程式自動移除捷徑。"</string>
<string name="permlab_read_settings" msgid="1941457408239617576">"讀取主螢幕的設定和捷徑"</string>
<string name="permdesc_read_settings" msgid="5833423719057558387">"允許應用程式讀取主螢幕中的設定和捷徑。"</string>
<string name="permlab_write_settings" msgid="3574213698004620587">"寫入主螢幕設定和捷徑"</string>
@@ -78,30 +48,17 @@
<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>
- <string name="dream_name" msgid="1530253749244328964">"Rocket Launcher"</string>
<string name="folder_hint_text" msgid="6617836969016293992">"未命名的資料夾"</string>
- <string name="workspace_description_format" msgid="2950174241104043327">"主螢幕 %1$d"</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="apps_customize_apps_scroll_format" msgid="370005296147130238">"應用程式:第 %1$d 頁,共 %2$d 頁"</string>
- <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"小工具:第 %1$d 頁,共 %2$d 頁"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"歡迎使用"</string>
- <string name="first_run_cling_description" msgid="6447072552696253358">"主螢幕由您作主。"</string>
- <string name="first_run_cling_custom_content_hint" msgid="6090628589029352439"></string>
- <string name="first_run_cling_search_bar_hint" msgid="5909062802402452582"></string>
- <string name="first_run_cling_create_screens_hint" msgid="6950729526680114157">"建立更多畫面容納應用程式和資料夾"</string>
<string name="migration_cling_title" msgid="9181776667882933767">"複製您的應用程式圖示"</string>
<string name="migration_cling_description" msgid="2752413805582227644">"要從舊的主螢幕匯入圖示和資料夾嗎?"</string>
<string name="migration_cling_copy_apps" msgid="946331230090919440">"複製圖示"</string>
<string name="migration_cling_use_default" msgid="2626475813981258626">"重新開始"</string>
- <string name="workspace_cling_title" msgid="5626202359865825661">"管理您的空間"</string>
- <string name="workspace_cling_move_item" msgid="528201129978005352">"輕觸並按住背景,即可管理桌布、小工具和設定。"</string>
<string name="workspace_cling_longpress_title" msgid="9173998993909018310">"桌布、小工具和設定"</string>
<string name="workspace_cling_longpress_description" msgid="4119994475505235248">"輕觸並按住背景即可自訂"</string>
<string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"知道了"</string>
- <string name="folder_cling_title" msgid="3894908818693254164">"資料夾顯示如下"</string>
- <string name="folder_cling_create_folder" msgid="6158215559475836131">"如要建立類似的資料夾,請輕觸並按住應用程式,然後將應用程式疊放在另一個應用程式上。"</string>
- <string name="cling_dismiss" msgid="8962359497601507581">"確定"</string>
<string name="folder_opened" msgid="94695026776264709">"資料夾已開啟 (<xliff:g id="WIDTH">%1$d</xliff:g> x <xliff:g id="HEIGHT">%2$d</xliff:g>)"</string>
<string name="folder_tap_to_close" msgid="1884479294466410023">"輕觸即可關閉資料夾"</string>
<string name="folder_tap_to_rename" msgid="9191075570492871147">"輕觸即可儲存新名稱"</string>
@@ -111,14 +68,34 @@
<string name="widget_button_text" msgid="2880537293434387943">"小工具"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"桌布"</string>
<string name="settings_button_text" msgid="8119458837558863227">"設定"</string>
- <string name="package_state_enqueued" msgid="6227252464303085641">"等待中"</string>
- <string name="package_state_downloading" msgid="4088770468458724721">"下載中…"</string>
- <string name="package_state_installing" msgid="7588193972189849870">"安裝中"</string>
+ <string name="allow_rotation_title" msgid="2118706734511831751">"允許輪播"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"不明"</string>
- <string name="package_state_error" msgid="7672093962724223588">"無法還原"</string>
- <string name="abandoned_clean_all" msgid="5256770727689657618">"全部移除"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"移除"</string>
<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="action_add_to_workspace" msgid="8902165848117513641">"新增至主畫面"</string>
+ <string name="action_move_here" msgid="2170188780612570250">"將項目移至這裡"</string>
+ <string name="item_added_to_workspace" msgid="4211073925752213539">"已將項目新增到主畫面"</string>
+ <string name="item_removed" msgid="851119963877842327">"已移除項目"</string>
+ <string name="action_move" msgid="4339390619886385032">"移動項目"</string>
+ <string name="move_to_empty_cell" msgid="2833711483015685619">"移至第 <xliff:g id="NUMBER_0">%1$s</xliff:g> 列第 <xliff:g id="NUMBER_1">%2$s</xliff:g> 欄"</string>
+ <string name="move_to_position" msgid="6750008980455459790">"移至位置 <xliff:g id="NUMBER">%1$s</xliff:g>"</string>
+ <string name="move_to_hotseat_position" msgid="6295412897075147808">"移至收藏位置 <xliff:g id="NUMBER">%1$s</xliff:g>"</string>
+ <string name="item_moved" msgid="4606538322571412879">"已移動項目"</string>
+ <string name="add_to_folder" msgid="9040534766770853243">"新增到「<xliff:g id="NAME">%1$s</xliff:g>」資料夾"</string>
+ <string name="add_to_folder_with_app" msgid="4534929978967147231">"新增到「<xliff:g id="NAME">%1$s</xliff:g>」所在資料夾"</string>
+ <string name="added_to_folder" msgid="4793259502305558003">"已將項目新增到資料夾"</string>
+ <string name="create_folder_with" msgid="4050141361160214248">"建立「<xliff:g id="NAME">%1$s</xliff:g>」資料夾"</string>
+ <string name="folder_created" msgid="6409794597405184510">"已建立資料夾"</string>
+ <string name="action_move_to_workspace" msgid="1603837886334246317">"移至主畫面"</string>
+ <string name="action_move_screen_left" msgid="8854216831569401665">"將畫面往左移"</string>
+ <string name="action_move_screen_right" msgid="329334910274311123">"將畫面往右移"</string>
+ <string name="screen_moved" msgid="266230079505650577">"已移動畫面"</string>
+ <string name="action_resize" msgid="1802976324781771067">"調整大小"</string>
+ <string name="action_increase_width" msgid="8773715375078513326">"增加寬度"</string>
+ <string name="action_increase_height" msgid="459390020612501122">"增加高度"</string>
+ <string name="action_decrease_width" msgid="1374549771083094654">"減少寬度"</string>
+ <string name="action_decrease_height" msgid="282377193880900022">"減少高度"</string>
+ <string name="widget_resized" msgid="9130327887929620">"已將小工具的寬度和高度分別調整為 <xliff:g id="NUMBER_0">%1$s</xliff:g> 和 <xliff:g id="NUMBER_1">%2$s</xliff:g>"</string>
</resources>
diff --git a/res/values-zu/strings.xml b/res/values-zu/strings.xml
index aea09e845..83ba089df 100644
--- a/res/values-zu/strings.xml
+++ b/res/values-zu/strings.xml
@@ -20,57 +20,27 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="application_name" msgid="5181331383435256801">"Isiqalisi3"</string>
- <string name="home" msgid="7658288663002113681">"Ikhaya"</string>
- <string name="uid_name" msgid="7820867637514617527">"Izinhlelo zokusebenza ze-Android Core"</string>
<string name="folder_name" msgid="7371454440695724752"></string>
+ <string name="work_folder_name" msgid="3753320833950115786">"Umsebenzi"</string>
<string name="activity_not_found" msgid="8071924732094499514">"Uhlelo lokusebenza alufakiwe."</string>
<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="widgets_tab_label" msgid="2921133187116603919">"Amawijethi"</string>
- <string name="widget_adder" msgid="3201040140710381657">"Amawijethi"</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="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
- <string name="external_drop_widget_error" msgid="3165821058322217155">"Ayikwazanga ukwehlisela into kulesi sikrini se-Ikhaya."</string>
- <string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Khetha iwijethi ongayidala"</string>
- <string name="rename_folder_label" msgid="3727762225964550653">"Igama lefolda"</string>
- <string name="rename_folder_title" msgid="3771389277707820891">"Qamba kabusha ifolda"</string>
- <string name="rename_action" msgid="5559600076028658757">"KULUNGILE"</string>
- <string name="cancel_action" msgid="7009134900002915310">"Khansela"</string>
- <string name="menu_item_add_item" msgid="1264911265836810421">"Faka kwisikrini saseKhaya"</string>
- <string name="group_applications" msgid="3797214114206693605">"Izinhlelo zokusebenza"</string>
- <string name="group_shortcuts" msgid="6012256992764410535">"Izinqamuleli"</string>
- <string name="group_widgets" msgid="1569030723286851002">"Amawijethi"</string>
- <string name="completely_out_of_space" msgid="6106288382070760318">"Akusenagumbi ezikrinini zakho Zekhaya."</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>
+ <string name="all_apps_no_search_results" msgid="6332185285860416787">"Azikho izinhlelo zokusebenza ezitholakele ezifana ne-\"<xliff:g id="QUERY">%1$s</xliff:g>\""</string>
<string name="out_of_space" msgid="4691004494942118364">"Asisekho isikhala kulesi sikrini Sasekhaya."</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"Asisekho isikhala kwitreyi lezintandokazi"</string>
- <string name="invalid_hotseat_item" msgid="5779907847267573691">"Le wijethi inkulu kakhulu ukuba kwitreyi lezintandokazi."</string>
- <string name="shortcut_installed" msgid="1701742129426969556">"Isinqamuleli esithi \"<xliff:g id="NAME">%s</xliff:g>\" sidaliwe."</string>
- <string name="shortcut_uninstalled" msgid="8176767991305701821">"Isinqamuleli esithi \"<xliff:g id="NAME">%s</xliff:g>\" sisusiwe."</string>
- <string name="shortcut_duplicate" msgid="9167217446062498127">"Isinqamuleli esithi \"<xliff:g id="NAME">%s</xliff:g>\" sesivele sikhona."</string>
- <string name="title_select_shortcut" msgid="6680642571148153868">"Khetha isinqamulelo"</string>
- <string name="title_select_application" msgid="3280812711670683644">"Khetha uhlelo lokusebenza"</string>
<string name="all_apps_button_label" msgid="9110807029020582876">"Izinhlelo zokusebenza"</string>
<string name="all_apps_home_button_label" msgid="252062713717058851">"Ikhaya"</string>
- <string name="delete_zone_label_workspace" msgid="4009607676751398685">"Susa"</string>
- <string name="delete_zone_label_all_apps" msgid="8083826390278958980">"Khipha"</string>
<string name="delete_target_label" msgid="1822697352535677073">"Susa"</string>
<string name="delete_target_uninstall_label" msgid="5100785476250872595">"Khipha"</string>
<string name="info_target_label" msgid="8053346143994679532">"Ulwazi lohlelo lokusebenza"</string>
- <string name="accessibility_all_apps_button" msgid="2603132375383800483">"Izinhlelo zokusebenza"</string>
- <string name="accessibility_delete_button" msgid="6466114477993744621">"Susa"</string>
- <string name="delete_zone_label_all_apps_system_app" msgid="449755632749610895">"Khipha isibuyekezo"</string>
- <string name="cab_menu_delete_app" msgid="7435191475867183689">"Khipha uhlelo lokusebenza"</string>
- <string name="cab_menu_app_info" msgid="8593722221450362342">"Imininingwane yohlelo lokusebenza"</string>
- <string name="cab_app_selection_text" msgid="374688303047985416">"1 uhlelo lokusebenza olukhethiwe"</string>
- <string name="cab_widget_selection_text" msgid="1833458597831541241">"1 iwijethi ekhethiwe"</string>
- <string name="cab_folder_selection_text" msgid="7999992513806132118">"1 ifolda ekhethiwe"</string>
- <string name="cab_shortcut_selection_text" msgid="2103811025667946450">"1 isinqamuleli esikhethiwe"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"faka izinqamuleli"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"Ivumela uhlelo lokusebenza ukufaka izinqamuleli ngaphandle kokungenelela komsebenzisi."</string>
- <string name="permlab_uninstall_shortcut" msgid="864595034498083837">"khipha izinqamuleli"</string>
- <string name="permdesc_uninstall_shortcut" msgid="5134129545001836849">"Ivumela uhlelo lokusebenza ukuthi lisuse izinqamuleli ngaphandle kokungenelela komsebenzisi."</string>
<string name="permlab_read_settings" msgid="1941457408239617576">"funda izilungiselelo zokuthi Ikhaya nezinqamuleli"</string>
<string name="permdesc_read_settings" msgid="5833423719057558387">"Ivumela uhlelo lokusebenza ukuthi lifunde izilungiselelo nezinqamuleli ekhaya."</string>
<string name="permlab_write_settings" msgid="3574213698004620587">"bhala izilungiselelo zokuthi Ikhaya nezinqamuleli"</string>
@@ -78,30 +48,17 @@
<string name="gadget_error_text" msgid="6081085226050792095">"Inkinga yokulayisha iwijethi"</string>
<string name="gadget_setup_text" msgid="8274003207686040488">"Ukumisa"</string>
<string name="uninstall_system_app_text" msgid="4172046090762920660">"Lolu uhlelo lokusebenza lwesistimu futhi alikwazi ukukhishwa."</string>
- <string name="dream_name" msgid="1530253749244328964">"Isiqalisi se-Rocket"</string>
<string name="folder_hint_text" msgid="6617836969016293992">"Ifolda engenagama"</string>
- <string name="workspace_description_format" msgid="2950174241104043327">"Isikrini sasekhaya esingu-%1$d"</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="apps_customize_apps_scroll_format" msgid="370005296147130238">"Ikhasi lezinhlelo zokusebenza elingu-%1$d le-%2$d"</string>
- <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"Ikhasi lamawijethi elingu-%1$d le-%2$d"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"Siyakwamukela"</string>
- <string name="first_run_cling_description" msgid="6447072552696253358">"Zizwe usekhaya."</string>
- <string name="first_run_cling_custom_content_hint" msgid="6090628589029352439"></string>
- <string name="first_run_cling_search_bar_hint" msgid="5909062802402452582"></string>
- <string name="first_run_cling_create_screens_hint" msgid="6950729526680114157">"Dala izikrini eziningi zezinhlelo zokusebenza namafolda"</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>
<string name="migration_cling_copy_apps" msgid="946331230090919440">"KOPISHA IZITHONJANA"</string>
<string name="migration_cling_use_default" msgid="2626475813981258626">"QALISA KABUSHA"</string>
- <string name="workspace_cling_title" msgid="5626202359865825661">"Hlela isikhala sakho"</string>
- <string name="workspace_cling_move_item" msgid="528201129978005352">"Thinta uphinde ubambe okungemuva ukuze uphathe isithombe sangemuva, amawijethi nezilungiselelo."</string>
<string name="workspace_cling_longpress_title" msgid="9173998993909018310">"Izithombe zangemuva, amawijethi, nezilungiselelo"</string>
<string name="workspace_cling_longpress_description" msgid="4119994475505235248">"Thinta uphinde ubambe ingemuva ukuze wenze ngokwezifiso"</string>
<string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"NGIYITHOLILE"</string>
- <string name="folder_cling_title" msgid="3894908818693254164">"Nayi ifolda"</string>
- <string name="folder_cling_create_folder" msgid="6158215559475836131">"Ukuze udale eyodwa efana nale, thinta uphinde ubambe uhlelo lokusebenza, bese ulidlulisa ngaphezulu kwelinye."</string>
- <string name="cling_dismiss" msgid="8962359497601507581">"KULUNGILE"</string>
<string name="folder_opened" msgid="94695026776264709">"Ifolda ivuliwe, <xliff:g id="WIDTH">%1$d</xliff:g> nge-<xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
<string name="folder_tap_to_close" msgid="1884479294466410023">"Thinta ukuze uvale ifolda"</string>
<string name="folder_tap_to_rename" msgid="9191075570492871147">"Thinta ukuze ulondoloze ukuqamba kabusha"</string>
@@ -111,14 +68,34 @@
<string name="widget_button_text" msgid="2880537293434387943">"Amawijethi"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"Izithombe zangemuva"</string>
<string name="settings_button_text" msgid="8119458837558863227">"Izilungiselelo"</string>
- <string name="package_state_enqueued" msgid="6227252464303085641">"Ilindile"</string>
- <string name="package_state_downloading" msgid="4088770468458724721">"Iyalanda"</string>
- <string name="package_state_installing" msgid="7588193972189849870">"Iyafaka"</string>
+ <string name="allow_rotation_title" msgid="2118706734511831751">"Vumela ukuphenduka"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Akwaziwa"</string>
- <string name="package_state_error" msgid="7672093962724223588">"Ayibuyiselwe"</string>
- <string name="abandoned_clean_all" msgid="5256770727689657618">"Susa konke"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Susa"</string>
<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="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>
+ <string name="item_removed" msgid="851119963877842327">"Into isusiwe"</string>
+ <string name="action_move" msgid="4339390619886385032">"Hambisa into"</string>
+ <string name="move_to_empty_cell" msgid="2833711483015685619">"Hambisa kurowu engu-<xliff:g id="NUMBER_0">%1$s</xliff:g> ikholomu engu-<xliff:g id="NUMBER_1">%2$s</xliff:g>"</string>
+ <string name="move_to_position" msgid="6750008980455459790">"Hambisa kusimo esingu-<xliff:g id="NUMBER">%1$s</xliff:g>"</string>
+ <string name="move_to_hotseat_position" msgid="6295412897075147808">"Hambisa kusimo sezintandokazi esingu-<xliff:g id="NUMBER">%1$s</xliff:g>"</string>
+ <string name="item_moved" msgid="4606538322571412879">"Into ihanjisiwe"</string>
+ <string name="add_to_folder" msgid="9040534766770853243">"Engeza kufolda: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="add_to_folder_with_app" msgid="4534929978967147231">"Engeza kufolda nge-<xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="added_to_folder" msgid="4793259502305558003">"Into ingeziwe kufolda"</string>
+ <string name="create_folder_with" msgid="4050141361160214248">"Dala ifolda nge-: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="folder_created" msgid="6409794597405184510">"Ifolda idaliwe"</string>
+ <string name="action_move_to_workspace" msgid="1603837886334246317">"Hambisa kusikrini sasekhaya"</string>
+ <string name="action_move_screen_left" msgid="8854216831569401665">"Hambisa isikrini kwesokunxele"</string>
+ <string name="action_move_screen_right" msgid="329334910274311123">"Hambisa isikrini kwesokudla"</string>
+ <string name="screen_moved" msgid="266230079505650577">"Isikrini sihanjisiwe"</string>
+ <string name="action_resize" msgid="1802976324781771067">"Shintsha usayizi"</string>
+ <string name="action_increase_width" msgid="8773715375078513326">"Khuphula ububanzi"</string>
+ <string name="action_increase_height" msgid="459390020612501122">"Khuphula ubude"</string>
+ <string name="action_decrease_width" msgid="1374549771083094654">"Nciphisa ububanzi"</string>
+ <string name="action_decrease_height" msgid="282377193880900022">"Nciphisa ubude"</string>
+ <string name="widget_resized" msgid="9130327887929620">"Iwijethi inikezwe usayizi omusha ngobubanzi obungu-<xliff:g id="NUMBER_0">%1$s</xliff:g> ubude obungu-<xliff:g id="NUMBER_1">%2$s</xliff:g>"</string>
</resources>
diff --git a/res/values/attrs.xml b/res/values/attrs.xml
index 3331cdec4..827332ad7 100644
--- a/res/values/attrs.xml
+++ b/res/values/attrs.xml
@@ -18,6 +18,19 @@
<resources>
+ <!-- BubbleTextView specific attributes. -->
+ <declare-styleable name="BubbleTextView">
+ <attr name="layoutHorizontal" format="boolean" />
+ <attr name="iconSizeOverride" format="dimension" />
+ <attr name="iconDisplay" format="integer">
+ <enum name="workspace" value="0" />
+ <enum name="all_apps" value="1" />
+ <enum name="widget_section" value="2" />
+ </attr>
+ <attr name="deferShadowGeneration" format="boolean" />
+ <attr name="customShadows" format="boolean" />
+ </declare-styleable>
+
<!-- Page Indicator specific attributes. -->
<declare-styleable name="PageIndicator">
<attr name="windowSize" format="integer" />
@@ -59,16 +72,6 @@
<attr name="maxGap" format="dimension" />
</declare-styleable>
- <!-- StrokedTextView specific attributes. -->
- <declare-styleable name="StrokedTextView">
- <!-- The color of the stroke outline -->
- <attr name="strokeColor" format="color" />
- <!-- The color of the text -->
- <attr name="strokeTextColor" format="color" />
- <!-- The width of the stroke -->
- <attr name="strokeWidth" format="float" />
- </declare-styleable>
-
<!-- PagedView specific attributes. These attributes are used to customize
a PagedView view in XML files. -->
<declare-styleable name="PagedView">
@@ -80,28 +83,6 @@
<attr name="pageIndicator" format="reference" />
</declare-styleable>
- <declare-styleable name="BubbleTextView">
- <!-- A spacing override for the icons within a page -->
- <attr name="customShadows" format="boolean" />
- </declare-styleable>
-
- <!-- AppsCustomizePagedView specific attributes. These attributes are used to
- customize an AppsCustomizePagedView in xml files. -->
- <declare-styleable name="AppsCustomizePagedView">
- <!-- Max number of cells of applications horizontally -->
- <attr name="maxAppCellCountX" format="integer" />
- <!-- Max number of cells of applications vertically -->
- <attr name="maxAppCellCountY" format="integer" />
- <!-- Horizontal spacing between widgets and wallpapers -->
- <attr name="widgetCellWidthGap" format="dimension" />
- <!-- Vertical spacing between widgets -->
- <attr name="widgetCellHeightGap" format="dimension" />
- <!-- Number of widgets horizontally -->
- <attr name="widgetCountX" format="integer" />
- <!-- Number of widgets vertically -->
- <attr name="widgetCountY" format="integer" />
- </declare-styleable>
-
<!-- XML attributes used by default_workspace.xml -->
<declare-styleable name="Favorite">
<attr name="className" format="string" />
diff --git a/res/values/colors.xml b/res/values/colors.xml
index 2daf9fe12..51e4d40a5 100644
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -20,20 +20,34 @@
<resources>
<!-- The color tints to apply to the text and drag view when hovering
over the delete target or the info target -->
- <color name="delete_target_hover_tint">#DAFF0000</color>
- <color name="info_target_hover_tint">#DA0099CC</color>
+ <color name="delete_target_hover_tint">#FFC1C1C1</color>
+ <color name="uninstall_target_hover_tint">#FFF0592B</color>
+ <color name="info_target_hover_tint">#FF009688</color>
<color name="cling_scrim_background">#80000000</color>
- <color name="bubble_dark_background">#20000000</color>
<color name="focused_background">#80c6c5c5</color>
- <color name="appwidget_error_color">#FCCC</color>
-
<color name="workspace_icon_text_color">#FFF</color>
+ <color name="workspace_edge_effect_color">#FFFFFFFF</color>
+ <color name="folder_edge_effect_color">#FF757575</color>
+
<color name="quantum_panel_text_color">#FF666666</color>
- <color name="quantum_panel_text_shadow_color">#FFC4C4C4</color>
+ <color name="quantum_panel_bg_color">#FFF5F5F5</color>
+ <color name="quantum_panel_bg_color_dark">#FF374248</color>
+
<color name="outline_color">#FFFFFFFF</color>
- <color name="widget_text_panel">#FF374248</color>
+ <!-- Containers -->
+ <color name="container_fastscroll_thumb_inactive_color">#42000000</color>
+ <color name="container_fastscroll_thumb_active_color">#009688</color>
+
+ <!-- All Apps -->
+ <color name="all_apps_grid_section_text_color">#009688</color>
+
+ <!-- Widgets view -->
+ <color name="widgets_view_fastscroll_thumb_inactive_color">#42FFFFFF</color>
+ <color name="widgets_view_section_text_color">#FFFFFF</color>
+ <color name="widgets_view_item_text_color">#C4C4C4</color>
+ <color name="widgets_cell_color">#263238</color>
</resources>
diff --git a/res/values/config.xml b/res/values/config.xml
index 96bd13bbb..73de79417 100644
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -1,8 +1,5 @@
<resources>
<!-- Dynamic Grid -->
- <integer name="config_dynamic_grid_max_long_edge_cell_count">6</integer>
- <integer name="config_dynamic_grid_max_short_edge_cell_count">5</integer>
- <integer name="config_dynamic_grid_min_edge_cell_count">3</integer>
<!-- Out of 100, the percent of space the overview bar should try and take vertically. -->
<integer name="config_dynamic_grid_overview_icon_zone_percentage">20</integer>
<!-- Out of 100, the percent to shrink the workspace during overview mode. -->
@@ -23,28 +20,22 @@
<!-- DragController -->
<integer name="config_flingToDeleteMinVelocity">-1500</integer>
+ <item type="id" name="drag_event_parity" />
-<!-- AllApps/Customize/AppsCustomize -->
+<!-- AllApps & Launcher transitions -->
<!-- The alpha of the AppsCustomize bg in spring loaded mode -->
<integer name="config_workspaceScrimAlpha">55</integer>
- <integer name="config_workspaceUnshrinkTime">300</integer>
+ <integer name="config_allAppsTransitionTime">100</integer>
<integer name="config_overviewTransitionTime">250</integer>
<!-- Out of 100, the percent to shrink the workspace during spring loaded mode. -->
<integer name="config_workspaceSpringLoadShrinkPercentage">80</integer>
- <!-- Fade/zoom in/out duration & scale in the AllApps transition.
- Note: This should be less than the workspaceShrinkTime as they happen together. -->
- <integer name="config_appsCustomizeRevealTime">220</integer>
- <integer name="config_appsCustomizeZoomInTime">350</integer>
- <integer name="config_appsCustomizeZoomOutTime">600</integer>
- <integer name="config_appsCustomizeZoomScaleFactor">7</integer>
- <integer name="config_appsCustomizeFadeInTime">250</integer>
- <integer name="config_appsCustomizeFadeOutTime">200</integer>
- <integer name="config_appsCustomizeWorkspaceShrinkTime">300</integer>
-
- <integer name="config_appsCustomizeConcealTime">250</integer>
- <integer name="config_appsCustomizeItemsAlphaStagger">60</integer>
+ <!-- Fade/zoom in/out duration & scale in a Launcher overlay transition.
+ Note: This should be less than the config_overlayTransitionTime as they happen together. -->
+ <integer name="config_overlayRevealTime">220</integer>
+ <integer name="config_overlayTransitionTime">300</integer>
+ <integer name="config_overlayItemsAlphaStagger">60</integer>
<!-- This constant stores the ratio of the all apps button drawable which
is used for internal (baked-in) padding -->
@@ -52,20 +43,7 @@
<integer name="config_workspaceDefaultScreen">0</integer>
- <!-- Tab transition animation duration -->
- <integer name="config_tabTransitionDuration">250</integer>
-
- <!-- The slope, in percent, of the drag movement needed to drag an item out of
- AppsCustomize (y / x * 100%) -->
- <integer name="config_appsCustomizeDragSlopeThreshold">150</integer>
-
<!-- Workspace -->
- <!-- Whether or not the drop targets drop down as opposed to fade in -->
- <bool name="config_useDropTargetDownTransition">false</bool>
-
- <!-- The transition duration for the background of the drop targets -->
- <integer name="config_dropTargetBgTransitionDuration">0</integer>
-
<!-- The duration (in ms) of the fade animation on the object outlines, used when
we are dragging objects around on the home screen. -->
<integer name="config_dragOutlineFadeTime">900</integer>
@@ -86,13 +64,6 @@
<!-- The distance at which the animation should take the max duration -->
<integer name="config_dropAnimMaxDist">800</integer>
- <!-- Properties controlling the workspace fade-out during dragging -->
- <integer name="config_dragFadeOutAlpha">80</integer>
- <integer name="config_dragFadeOutDuration">250</integer>
-
- <!-- Camera distance for the overscroll effect -->
- <integer name="config_cameraDistance">8000</integer>
-
<!-- Hotseat -->
<bool name="hotseat_transpose_layout_with_orientation">true</bool>
@@ -106,4 +77,15 @@
<!-- Name of a subclass of com.android.launcher3.BuildInfo used to
get build information. Can be empty. -->
<string name="build_info_class" translatable="false"></string>
+
+<!-- Accessibility actions -->
+ <item type="id" name="action_remove" />
+ <item type="id" name="action_uninstall" />
+ <item type="id" name="action_info" />
+ <item type="id" name="action_add_to_workspace" />
+ <item type="id" name="action_move" />
+ <item type="id" name="action_move_to_workspace" />
+ <item type="id" name="action_move_screen_backwards" />
+ <item type="id" name="action_move_screen_forwards" />
+ <item type="id" name="action_resize" />
</resources>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index f12cb57ba..589d69666 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -15,19 +15,25 @@
-->
<resources>
+ <dimen name="app_icon_size">64dp</dimen>
+
<!-- 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>
<dimen name="dynamic_grid_page_indicator_height">20dp</dimen>
<dimen name="dynamic_grid_icon_drawable_padding">4dp</dimen>
- <dimen name="dynamic_grid_all_apps_cell_padding">18dp</dimen>
<dimen name="dynamic_grid_workspace_page_spacing">8dp</dimen>
<dimen name="dynamic_grid_overview_min_icon_zone_height">80dp</dimen>
<dimen name="dynamic_grid_overview_max_icon_zone_height">120dp</dimen>
<dimen name="dynamic_grid_overview_bar_item_width">80dp</dimen>
<dimen name="dynamic_grid_overview_bar_spacer_width">20dp</dimen>
+<!-- App Widget resize frame -->
+ <dimen name="default_widget_padding">8dp</dimen>
+ <dimen name="widget_handle_margin">13dp</dimen>
+ <dimen name="resize_frame_background_padding">24dp</dimen>
+
<!-- Cling -->
<dimen name="cling_migration_logo_height">240dp</dimen>
<dimen name="cling_migration_logo_width">165dp</dimen>
@@ -38,60 +44,89 @@
<!-- Workspace -->
<dimen name="workspace_max_gap">16dp</dimen>
- <dimen name="workspace_overscroll_drawable_padding">0dp</dimen>
<!-- QSB -->
<dimen name="toolbar_button_vertical_padding">4dip</dimen>
<dimen name="toolbar_button_horizontal_padding">12dip</dimen>
-<!-- AllApps/Customize/AppsCustomize -->
- <!-- The height of the tab bar - if this changes, we should update the
- external icon width/height above to compensate -->
- <dimen name="apps_customize_tab_bar_height">52dp</dimen>
- <dimen name="apps_customize_tab_bar_margin_top">0dp</dimen>
- <dimen name="app_icon_size">48dp</dimen>
- <dimen name="apps_customize_horizontal_padding">0dp</dimen>
+<!-- Container -->
+ <!-- Note: This needs to match the fixed insets for the search box. -->
+ <dimen name="container_bounds_inset">8dp</dimen>
+ <!-- Notes: container_bounds_inset - quantum_panel_outer_padding -->
+ <dimen name="container_bounds_minus_quantum_panel_padding_inset">4dp</dimen>
+
+ <dimen name="container_fastscroll_thumb_min_width">4dp</dimen>
+ <dimen name="container_fastscroll_thumb_max_width">8dp</dimen>
+ <dimen name="container_fastscroll_thumb_height">64dp</dimen>
+ <dimen name="container_fastscroll_thumb_touch_inset">-24dp</dimen>
+ <dimen name="container_fastscroll_popup_size">72dp</dimen>
+ <dimen name="container_fastscroll_popup_text_size">48dp</dimen>
+
+<!-- All Apps -->
+ <dimen name="all_apps_grid_view_start_margin">0dp</dimen>
+ <dimen name="all_apps_grid_section_y_offset">8dp</dimen>
+ <dimen name="all_apps_grid_section_text_size">24sp</dimen>
+ <dimen name="all_apps_search_bar_height">48dp</dimen>
+ <dimen name="all_apps_search_bar_prediction_bar_padding">8dp</dimen>
+ <dimen name="all_apps_icon_top_bottom_padding">8dp</dimen>
+ <dimen name="all_apps_icon_width_gap">24dp</dimen>
+ <!-- The top padding should account for the existing all_apps_list_top_bottom_padding -->
+ <dimen name="all_apps_prediction_icon_top_padding">8dp</dimen>
+ <dimen name="all_apps_prediction_icon_bottom_padding">18dp</dimen>
+ <dimen name="all_apps_list_top_bottom_padding">8dp</dimen>
+
+<!-- Widget tray -->
+ <dimen name="widget_container_inset">8dp</dimen>
+ <dimen name="widget_preview_label_vertical_padding">8dp</dimen>
+ <dimen name="widget_preview_label_horizontal_padding">8dp</dimen>
+ <dimen name="widget_preview_horizontal_padding">8dp</dimen>
- <!-- The AppsCustomize page indicator -->
- <dimen name="apps_customize_page_indicator_height">12dp</dimen>
- <dimen name="apps_customize_page_indicator_margin">4dp</dimen>
- <dimen name="apps_customize_page_indicator_offset">16dp</dimen>
+ <dimen name="widget_section_height">56dp</dimen>
+ <dimen name="widget_section_icon_size">40dp</dimen>
+ <dimen name="widget_section_vertical_padding">8dp</dimen>
+ <dimen name="widget_section_horizontal_padding">16dp</dimen>
+ <dimen name="widget_row_padding">8dp</dimen>
+ <dimen name="widget_row_divider">2dp</dimen>
+
+ <!-- Padding applied to shortcut previews -->
+ <dimen name="shortcut_preview_padding_left">0dp</dimen>
+ <dimen name="shortcut_preview_padding_right">0dp</dimen>
+ <dimen name="shortcut_preview_padding_top">0dp</dimen>
+
+<!-- Dragging -->
<!-- Drag padding to add to the bottom of drop targets -->
<dimen name="drop_target_drag_padding">14dp</dimen>
<dimen name="drop_target_text_size">14sp</dimen>
-<!-- Dragging -->
<!-- the area at the edge of the screen that makes the workspace go left
or right while you're dragging. -->
<dimen name="scroll_zone">20dp</dimen>
- <!-- When dragging items on the workspace, the number of dps by which the position of
- the drag view should be offset from the position of the original view. -->
- <dimen name="dragViewOffsetX">0dp</dimen>
- <dimen name="dragViewOffsetY">0dp</dimen>
- <!-- When dragging an item, how much bigger (fixed dps) the dragged view
- should be. If 0, it will not be scaled at all. -->
+ <!-- When dragging an item, how much bigger (fixed dps) the dragged view
+ should be. If 0, it will not be scaled at all. -->
<dimen name="dragViewScale">12dp</dimen>
- <!-- Padding applied to AppWidget previews -->
- <dimen name="app_widget_preview_padding_left">16dp</dimen>
- <dimen name="app_widget_preview_padding_right">16dp</dimen>
- <dimen name="app_widget_preview_padding_top">32dp</dimen>
- <dimen name="app_widget_preview_label_vertical_padding">8dp</dimen>
- <dimen name="app_widget_preview_label_horizontal_padding">8dp</dimen>
+ <!-- Elevation for the drag view. It should be larger than elevation of all other drag sources
+ and drop targets like all-apps and folders -->
+ <dimen name="drag_elevation">30dp</dimen>
- <!-- Padding applied to shortcut previews -->
- <dimen name="shortcut_preview_padding_left">0dp</dimen>
- <dimen name="shortcut_preview_padding_right">0dp</dimen>
- <dimen name="shortcut_preview_padding_top">0dp</dimen>
+<!-- Theme -->
+ <dimen name="quantum_panel_outer_padding">4dp</dimen>
<!-- Folders -->
<!-- The amount that the preview contents are inset from the preview background -->
<dimen name="folder_preview_padding">4dp</dimen>
- <dimen name="folder_name_padding">10dp</dimen>
<!-- Sizes for managed profile badges -->
<dimen name="profile_badge_size">24dp</dimen>
- <dimen name="profile_badge_margin">4dp</dimen>
+ <dimen name="profile_badge_margin">5dp</dimen>
+ <dimen name="profile_badge_minimum_top">2dp</dimen>
+
+<!-- Shadows and outlines -->
+ <dimen name="blur_size_thin_outline">1dp</dimen>
+ <dimen name="blur_size_medium_outline">2dp</dimen>
+ <dimen name="blur_size_click_shadow">4dp</dimen>
+ <dimen name="click_shadow_high_shift">2dp</dimen>
+
</resources>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index b6f42379d..88f149bd0 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -32,12 +32,10 @@
<!-- Application name -->
<string name="application_name">Launcher3</string>
- <!-- Accessibility-facing application name -->
- <string name="home">Home</string>
- <!-- Name for all applications running as this uid. -->
- <string name="uid_name">Android Core Apps</string>
<!-- Default folder name -->
<string name="folder_name"></string>
+ <!-- Work folder name -->
+ <string name="work_folder_name">Work</string>
<!-- Displayed when user selects a shortcut for an app that was uninstalled [CHAR_LIMIT=none]-->
<string name="activity_not_found">App isn\'t installed.</string>
<!-- Displayed when user selects a shortcut for an app that is current not available [CHAR_LIMIT=none]-->
@@ -46,84 +44,36 @@
<string name="safemode_shortcut_error">Downloaded app disabled in Safe mode</string>
<!-- SafeMode widget error string -->
<string name="safemode_widget_error">Widgets disabled in Safe mode</string>
- <!-- Labels for the tabs in the customize drawer -->
- <string name="widgets_tab_label">Widgets</string>
-
- <string name="widget_adder">Widgets</string>
<string name="toggle_weight_watcher">Show Mem</string>
- <!-- AppsCustomize pane -->
+ <!-- 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 &amp; hold to pick up a widget.</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>
- <!-- External-drop widget pick label format string [CHAR_LIMIT=25] -->
- <string name="external_drop_widget_pick_format" translatable="false">%1$s (%2$d \u00d7 %3$d)</string>
- <!-- External-drop widget error string. This is the error that is shown
- when you drag and item into the homescreen and it is unable to fit,
- or an error is encountered. [CHAR_LIMIT=50] -->
- <string name="external_drop_widget_error">Couldn\'t drop item on this Home screen.</string>
- <!-- External-drop widget pick title. This is shown as the title of the
- dialog which allows you to pick which widgets to handle a particular
- drop if there are multiple choices. [CHAR_LIMIT=35] -->
- <string name="external_drop_widget_pick_title">Choose widget to create</string>
-
- <!-- Folders -->
- <skip />
- <!-- Label of Folder name field in Rename folder dialog box -->
- <string name="rename_folder_label">Folder name</string>
- <!-- Title of dialog box -->
- <string name="rename_folder_title">Rename folder</string>
- <!-- Buttons in Rename folder dialog box -->
- <string name="rename_action">OK</string>
- <!-- Buttons in Rename folder dialog box -->
- <string name="cancel_action">Cancel</string>
-
- <!-- Shortcuts -->
+ <!-- All Apps -->
+ <!-- Search bar text in the apps view. [CHAR_LIMIT=50] -->
+ <string name="all_apps_search_bar_hint">Search Apps</string>
+ <!-- Loading apps text. [CHAR_LIMIT=50] -->
+ <string name="all_apps_loading_message">Loading Apps&#8230;</string>
+ <!-- No-search-results text. [CHAR_LIMIT=50] -->
+ <string name="all_apps_no_search_results">No Apps found matching \"<xliff:g id="query" example="Android">%1$s</xliff:g>\"</string>
+
+ <!-- Drag and drop -->
<skip />
- <!-- Title of dialog box -->
- <string name="menu_item_add_item">Add to Home screen</string>
- <!-- Options in "Add to Home" dialog box; Title of the group containing the list of all apps -->
- <string name="group_applications">Apps</string>
- <!-- Options in "Add to Home" dialog box; Title of the group containing the list of all shortcut
-s -->
- <string name="group_shortcuts">Shortcuts</string>
- <!-- Options in "Add to Home" dialog box; Title of the group containing the list of all widgets/gadgets -->
- <string name="group_widgets">Widgets</string>
- <!-- Error message when user has filled all their home screens -->
- <string name="completely_out_of_space">No more room on your Home screens.</string>
<!-- Error message when user has filled a home screen -->
<string name="out_of_space">No more room on this Home screen.</string>
<!-- Error message when user has filled the hotseat -->
<string name="hotseat_out_of_space">No more room in the Favorites tray</string>
- <!-- Error message when user tries to drop an invalid item on the hotseat -->
- <string name="invalid_hotseat_item">This widget is too large for the Favorites tray</string>
- <!-- Message displayed when a shortcut is created by an external application -->
- <string name="shortcut_installed">Shortcut \"<xliff:g id="name" example="Browser">%s</xliff:g>\" created.</string>
- <!-- Message displayed when a shortcut is uninstalled by an external application -->
- <string name="shortcut_uninstalled">Shortcut \"<xliff:g id="name" example="Browser">%s</xliff:g>\" was removed.</string>
- <!-- Message displayed when an external application attemps to create a shortcut that already exists -->
- <string name="shortcut_duplicate">Shortcut \"<xliff:g id="name" example="Browser">%s</xliff:g>\" already exists.</string>
-
- <!-- Title of dialog when user is selecting shortcut to add to homescreen -->
- <string name="title_select_shortcut">Choose shortcut</string>
- <!-- Title of dialog when user is selecting an application to add to homescreen -->
- <string name="title_select_application">Choose app</string>
<!-- All applications label -->
<string name="all_apps_button_label">Apps</string>
<!-- Label for button in all applications label to go back home (to the workspace / desktop)
for accessibilty (spoken when the button gets focus). -->
<string name="all_apps_home_button_label">Home</string>
- <!-- Label for trash icon on workspace. Meant to communicate the idea of removing the
- icon/widget from the home screen, but not permanently. [CHAR_LIMIT=30] -->
- <string name="delete_zone_label_workspace">Remove</string>
- <!-- Label for trash icon in All Apps. The icon/widget will become completely unavailable on the
- device. [CHAR_LIMIT=30]-->
- <string name="delete_zone_label_all_apps">Uninstall</string>
<!-- Label for delete drop target. [CHAR_LIMIT=20] -->
<string name="delete_target_label">Remove</string>
@@ -132,35 +82,6 @@ s -->
<!-- Label for the info icon. [CHAR_LIMIT=20] -->
<string name="info_target_label">App info</string>
- <!-- Accessibility: AllApps button -->
- <string name="accessibility_all_apps_button">Apps</string>
- <!-- Accessibility: Delete button -->
- <string name="accessibility_delete_button">Remove</string>
-
- <!-- Label for trash icon in All Apps, when an updated system app is selected. The update will
- be uninstalled. [CHAR_LIMIT=30] -->
- <string name="delete_zone_label_all_apps_system_app">Uninstall update</string>
-
- <!-- URL pointing to help text. If empty, no link to help will be created [DO NOT TRANSLATE] -->
- <string name="help_url" translatable="false"></string>
-
- <!-- Strings for the contextual action bar (CAB) in All Apps -->
- <skip />
- <!-- Describes the button for uninstalling the currently selected application.
- Text is not displayed, but provided for accessibility. [CHAR_LIMIT=none] -->
- <string name="cab_menu_delete_app">Uninstall app</string>
- <!-- Describes the button for getting details/info about currently selected application.
- Text is not displayed, but provided for accessibility. [CHAR_LIMIT=none] -->
- <string name="cab_menu_app_info">App details</string>
- <!-- Appears in the CAB when an app is selected in All Apps or Customize mode. [CHAR_LIMIT=50] -->
- <string name="cab_app_selection_text">1 app selected</string>
- <!-- Appears in the CAB when a widget is selected in Customize mode. [CHAR_LIMIT=50] -->
- <string name="cab_widget_selection_text">1 widget selected</string>
- <!-- Appears in the CAB when a folder is selected in Customize mode. [CHAR_LIMIT=50] -->
- <string name="cab_folder_selection_text">1 folder selected</string>
- <!-- Appears in the CAB when a shortcut is selected in Customize mode. [CHAR_LIMIT=50] -->
- <string name="cab_shortcut_selection_text">1 shortcut selected</string>
-
<!-- Permissions: -->
<skip />
<!-- Permission short label -->
@@ -169,11 +90,6 @@ s -->
<string name="permdesc_install_shortcut">Allows an app to add
shortcuts without user intervention.</string>
<!-- Permission short label -->
- <string name="permlab_uninstall_shortcut">uninstall shortcuts</string>
- <!-- Permission description -->
- <string name="permdesc_uninstall_shortcut">Allows the app to remove
- shortcuts without user intervention.</string>
- <!-- Permission short label -->
<string name="permlab_read_settings">read Home settings and shortcuts</string>
<!-- Permission description -->
<string name="permdesc_read_settings">Allows the app to read the settings and
@@ -196,38 +112,20 @@ s -->
<!-- Text to inform the user that they can't uninstall a system application -->
<string name="uninstall_system_app_text">This is a system app and can\'t be uninstalled.</string>
- <!-- Title of the Android Dreams (screensaver) module -->
- <string name="dream_name">Rocket Launcher</string>
-
<!-- Default folder title -->
<string name="folder_hint_text">Unnamed Folder</string>
<!-- Accessibility -->
<skip />
- <!-- The format string for Workspace descriptions [CHAR_LIMIT=none] -->
- <string name="workspace_description_format">Home screen %1$d</string>
-
<!-- The format string for default page scroll text [CHAR_LIMIT=none] -->
<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>
- <!-- The format string for AppsCustomize Apps page scroll text [CHAR_LIMIT=none] -->
- <string name="apps_customize_apps_scroll_format">Apps page %1$d of %2$d</string>
- <!-- The format string for AppsCustomize Apps page scroll text [CHAR_LIMIT=none] -->
- <string name="apps_customize_widgets_scroll_format">Widgets page %1$d of %2$d</string>
<!-- Clings -->
<!-- The title text for the workspace cling [CHAR_LIMIT=30] -->
<string name="first_run_cling_title">Welcome</string>
- <!-- The description of how to use the workspace [CHAR_LIMIT=60] -->
- <string name="first_run_cling_description">Make yourself at home.</string>
- <!-- The description of how to use the workspace [CHAR_LIMIT=60] -->
- <string name="first_run_cling_custom_content_hint"></string>
- <!-- The description of how to use the workspace [CHAR_LIMIT=60] -->
- <string name="first_run_cling_search_bar_hint"></string>
- <!-- The description of how to use the workspace [CHAR_LIMIT=60] -->
- <string name="first_run_cling_create_screens_hint">Create more screens for apps and folders</string>
<!-- The title text for the migration cling [CHAR_LIMIT=30] -->
<string name="migration_cling_title">Copy your app icons</string>
<!-- The description of what migration does [CHAR_LIMIT=70] -->
@@ -236,25 +134,12 @@ s -->
<string name="migration_cling_copy_apps">COPY ICONS</string>
<!-- The description of the button to use the default launcher layout [CHAR_LIMIT=30] -->
<string name="migration_cling_use_default">START FRESH</string>
- <!-- The title text for the workspace cling [CHAR_LIMIT=30] -->
- <string name="workspace_cling_title">Organize your space</string>
- <!-- The description of how to use the workspace [CHAR_LIMIT=70] -->
- <string name="workspace_cling_move_item">Touch &amp; hold background to manage wallpaper, widgets and settings.</string>
<!-- The title text for workspace longpress action [CHAR_LIMIT=40] -->
<string name="workspace_cling_longpress_title">Wallpapers, widgets, &amp; settings</string>
<!-- The description of how to use the workspace [CHAR_LIMIT=70] -->
<string name="workspace_cling_longpress_description">Touch &amp; hold background to customize</string>
<!-- The description of the button to dismiss the cling [CHAR_LIMIT=30] -->
<string name="workspace_cling_longpress_dismiss">GOT IT</string>
- <!-- The title text for the Folder cling [CHAR_LIMIT=30] -->
- <string name="folder_cling_title">Here\'s a folder</string>
- <!-- The description of how to create a folder [CHAR_LIMIT=70] -->
- <string name="folder_cling_create_folder">To create one like this, touch &amp; hold an app, then move it over another.</string>
- <!-- The text on the button to dismiss a cling [CHAR_LIMIT=30] -->
- <string name="cling_dismiss">OK</string>
- <!-- Error message on dummy custom cling layout [DO NOT TRANSLATE] -->
- <string name="dummy_custom_cling_error_message">Error: custom workspace layout passed in but custom cling was not overwritten</string>
- <add-resource type="string" name="default_folder_name" />
<!-- Folder accessibility -->
<!-- The format string for when a folder is opened, speaks the dimensions -->
@@ -281,19 +166,13 @@ s -->
<!-- Text for settings button -->
<string name="settings_button_text">Settings</string>
- <!-- Label on an icon that references an uninstalled package, that is going to be installed at some point. [CHAR_LIMIT=15] -->
- <string name="package_state_enqueued">Waiting</string>
- <!-- Label on an icon that references an uninstalled package, that is currently being downloaded. [CHAR_LIMIT=15] -->
- <string name="package_state_downloading">Downloading</string>
- <!-- Label on an icon that references an uninstalled package, that is currently being installed. [CHAR_LIMIT=15] -->
- <string name="package_state_installing">Installing</string>
+ <!-- Strings for settings -->
+ <!-- Title for Allow Rotation setting. [CHAR LIMIT=50] -->
+ <string name="allow_rotation_title">Allow rotation</string>
+
<!-- Label on an icon that references an uninstalled package, for which we have no information about when it might be installed. [CHAR_LIMIT=15] -->
<string name="package_state_unknown">Unknown</string>
- <!-- Label on an icon that references an uninstalled package, for which restore from market has failed. [CHAR_LIMIT=15] -->
- <string name="package_state_error">Not restored</string>
- <!-- Button for abandoned promises dialog, that removes all abandoned promise icons. -->
- <string name="abandoned_clean_all">Remove All</string>
<!-- Button for abandoned promises dialog, to removes this abandoned promise icon. -->
<string name="abandoned_clean_this">Remove</string>
<!-- Button for abandoned promise dialog, to search in the market for the missing package. -->
@@ -305,4 +184,78 @@ s -->
<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>
+
+<!-- Strings for accessibility actions -->
+ <!-- Accessibility action to add an app to workspace. [CHAR_LIMIT=30] -->
+ <string name="action_add_to_workspace">Add to Home screen</string>
+
+ <!-- Accessibility action to move item to the current location. [CHAR_LIMIT=30] -->
+ <string name="action_move_here">Move item here</string>
+
+ <!-- Accessibility confirmation for item added to workspace. -->
+ <string name="item_added_to_workspace">Item added to home screen</string>
+
+ <!-- Accessibility confirmation for item removed. -->
+ <string name="item_removed">Item removed</string>
+
+ <!-- Accessibility action to move an item on the workspace. [CHAR_LIMIT=30] -->
+ <string name="action_move">Move item</string>
+
+ <!-- Accessibility description to move item to empty cell. -->
+ <string name="move_to_empty_cell">Move to row <xliff:g id="number" example="1">%1$s</xliff:g> column <xliff:g id="number" example="1">%2$s</xliff:g></string>
+
+ <!-- Accessibility description to move item inside a folder. -->
+ <string name="move_to_position">Move to position <xliff:g id="number" example="1">%1$s</xliff:g></string>
+
+ <!-- Accessibility description to move item to the hotseat. -->
+ <string name="move_to_hotseat_position">Move to favorites position <xliff:g id="number" example="1">%1$s</xliff:g></string>
+
+ <!-- Accessibility confirmation for item move. -->
+ <string name="item_moved">Item moved</string>
+
+ <!-- Accessibility description to move item into an existing folder. -->
+ <string name="add_to_folder">Add to folder: <xliff:g id="name" example="Games">%1$s</xliff:g></string>
+
+ <!-- Accessibility description to move item into an existing folder containing an app. -->
+ <string name="add_to_folder_with_app">Add to folder with <xliff:g id="name" example="Messenger">%1$s</xliff:g></string>
+
+ <!-- Accessibility confirmation for item added to folder. -->
+ <string name="added_to_folder">Item added to folder</string>
+
+ <!-- Accessibility description to create folder with another item. -->
+ <string name="create_folder_with">Create folder with: <xliff:g id="name" example="Game">%1$s</xliff:g></string>
+
+ <!-- Accessibility confirmation for folder created. -->
+ <string name="folder_created">Folder created</string>
+
+ <!-- Accessibility action to move an item from folder to workspace. [CHAR_LIMIT=30] -->
+ <string name="action_move_to_workspace">Move to Home screen</string>
+
+ <!-- Accessibility action to move an homescreen to the left. [CHAR_LIMIT=30] -->
+ <string name="action_move_screen_left">Move screen to left</string>
+
+ <!-- Accessibility action to move an homescreen to the right. [CHAR_LIMIT=30] -->
+ <string name="action_move_screen_right">Move screen to right</string>
+
+ <!-- Accessibility confirmation when a screen was moved. -->
+ <string name="screen_moved">Screen moved</string>
+
+ <!-- Accessibility action to resize a widget. [CHAR_LIMIT=30] -->
+ <string name="action_resize">Resize</string>
+
+ <!-- Accessibility action to increase width of a widget. [CHAR_LIMIT=30] -->
+ <string name="action_increase_width">Increase width</string>
+
+ <!-- Accessibility action to increase height of a widget. [CHAR_LIMIT=30] -->
+ <string name="action_increase_height">Increase height</string>
+
+ <!-- Accessibility action to decrease width of a widget. [CHAR_LIMIT=30] -->
+ <string name="action_decrease_width">Decrease width</string>
+
+ <!-- Accessibility action to decrease height of a widget. [CHAR_LIMIT=30] -->
+ <string name="action_decrease_height">Decrease height</string>
+
+ <!-- Accessibility confirmation for widget resize. -->
+ <string name="widget_resized">Widget resized to width <xliff:g id="number" example="2">%1$s</xliff:g> height <xliff:g id="number" example="1">%2$s</xliff:g></string>
+
</resources>
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 77798f174..7d60cbe0a 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -18,8 +18,15 @@
-->
<resources>
+ <style name="Theme.Light.CustomOverscroll" parent="@android:style/Theme.DeviceDefault">
+ <item name="android:colorEdgeEffect">@color/folder_edge_effect_color</item>
+ </style>
+
+ <style name="Theme.Dark.CustomOverscroll" parent="@android:style/Theme.DeviceDefault">
+ <item name="android:colorEdgeEffect">@color/workspace_edge_effect_color</item>
+ </style>
- <style name="WorkspaceIcon">
+ <style name="Icon">
<item name="android:layout_width">match_parent</item>
<item name="android:layout_height">match_parent</item>
<item name="android:layout_gravity">center</item>
@@ -32,11 +39,7 @@
<item name="android:fontFamily">sans-serif-condensed</item>
</style>
- <style name="WorkspaceIcon.Portrait"></style>
-
- <style name="WorkspaceIcon.Landscape"></style>
-
- <style name="WorkspaceIcon.AppsCustomize">
+ <style name="Icon.AllApps">
<item name="android:background">@null</item>
<item name="android:textColor">@color/quantum_panel_text_color</item>
<item name="android:drawablePadding">@dimen/dynamic_grid_icon_drawable_padding</item>
@@ -44,7 +47,7 @@
<item name="customShadows">false</item>
</style>
- <style name="WorkspaceIcon.Folder">
+ <style name="Icon.Folder">
<item name="android:background">@null</item>
<item name="android:textColor">@color/quantum_panel_text_color</item>
<item name="android:shadowRadius">0</item>
@@ -58,7 +61,7 @@
<item name="android:layout_height">match_parent</item>
</style>
- <style name="DropTargetButton.Base">
+ <style name="DropTargetButtonBase">
<item name="android:layout_width">wrap_content</item>
<item name="android:layout_height">match_parent</item>
<item name="android:layout_gravity">center</item>
@@ -76,7 +79,7 @@
<item name="android:shadowRadius">4.0</item>
</style>
- <style name="DropTargetButton" parent="DropTargetButton.Base"></style>
+ <style name="DropTargetButton" parent="DropTargetButtonBase" />
<style name="PreloadIcon">
<item name="background">@drawable/virtual_preload</item>
@@ -90,9 +93,4 @@
<item name="ringOutset">4dp</item>
</style>
- <!-- Overridden in device overlays -->
- <style name="PagedViewWidgetImageView">
- <item name="android:paddingLeft">@dimen/app_widget_preview_padding_left</item>
- </style>
-
</resources>
diff --git a/res/xml/app_target_browser.xml b/res/xml/app_target_browser.xml
new file mode 100644
index 000000000..d7c3ed5fd
--- /dev/null
+++ b/res/xml/app_target_browser.xml
@@ -0,0 +1,23 @@
+<?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.
+-->
+
+<resolve xmlns:launcher="http://schemas.android.com/apk/res-auto/com.android.launcher3" >
+
+ <favorite launcher:uri="#Intent;action=android.intent.action.MAIN;category=android.intent.category.APP_BROWSER;end" />
+ <favorite launcher:uri="http://www.example.com/" />
+
+</resolve> \ No newline at end of file
diff --git a/res/anim/fade_out_fast.xml b/res/xml/app_target_camera.xml
index a061a6ca9..f65a2b168 100644
--- a/res/anim/fade_out_fast.xml
+++ b/res/xml/app_target_camera.xml
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2009 The Android Open Source Project
+<!--
+ 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.
@@ -14,10 +15,9 @@
limitations under the License.
-->
-<alpha xmlns:android="http://schemas.android.com/apk/res/android"
- android:interpolator="@android:anim/accelerate_interpolator"
+<resolve xmlns:launcher="http://schemas.android.com/apk/res-auto/com.android.launcher3" >
- android:fromAlpha="1.0"
- android:toAlpha="0.0"
+ <favorite launcher:uri="#Intent;action=android.media.action.STILL_IMAGE_CAMERA;end" />
+ <favorite launcher:uri="#Intent;action=android.intent.action.CAMERA_BUTTON;end" />
- android:duration="@android:integer/config_mediumAnimTime" />
+</resolve> \ No newline at end of file
diff --git a/res/anim/fade_in_fast.xml b/res/xml/app_target_email.xml
index 4fa9847aa..44f0a407d 100644
--- a/res/anim/fade_in_fast.xml
+++ b/res/xml/app_target_email.xml
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2009 The Android Open Source Project
+<!--
+ 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.
@@ -14,10 +15,9 @@
limitations under the License.
-->
-<alpha xmlns:android="http://schemas.android.com/apk/res/android"
- android:interpolator="@android:anim/accelerate_interpolator"
+<resolve xmlns:launcher="http://schemas.android.com/apk/res-auto/com.android.launcher3" >
- android:fromAlpha="0.0"
- android:toAlpha="1.0"
+ <favorite launcher:uri="#Intent;action=android.intent.action.MAIN;category=android.intent.category.APP_EMAIL;end" />
+ <favorite launcher:uri="mailto:" />
- android:duration="@android:integer/config_mediumAnimTime" />
+</resolve> \ No newline at end of file
diff --git a/res/xml/app_target_gallery.xml b/res/xml/app_target_gallery.xml
new file mode 100644
index 000000000..c9d34924a
--- /dev/null
+++ b/res/xml/app_target_gallery.xml
@@ -0,0 +1,23 @@
+<?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.
+-->
+
+<resolve xmlns:launcher="http://schemas.android.com/apk/res-auto/com.android.launcher3" >
+
+ <favorite launcher:uri="#Intent;action=android.intent.action.MAIN;category=android.intent.category.APP_GALLERY;end" />
+ <favorite launcher:uri="#Intent;type=images/*;end" />
+
+</resolve> \ No newline at end of file
diff --git a/res/xml/app_target_messenger.xml b/res/xml/app_target_messenger.xml
new file mode 100644
index 000000000..278eb5ca8
--- /dev/null
+++ b/res/xml/app_target_messenger.xml
@@ -0,0 +1,26 @@
+<?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.
+-->
+
+<resolve xmlns:launcher="http://schemas.android.com/apk/res-auto/com.android.launcher3" >
+
+ <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> \ No newline at end of file
diff --git a/res/xml/app_target_phone.xml b/res/xml/app_target_phone.xml
new file mode 100644
index 000000000..5d6ca316e
--- /dev/null
+++ b/res/xml/app_target_phone.xml
@@ -0,0 +1,24 @@
+<?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.
+-->
+
+<resolve xmlns:launcher="http://schemas.android.com/apk/res-auto/com.android.launcher3" >
+
+ <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> \ No newline at end of file
diff --git a/res/xml/launcher_preferences.xml b/res/xml/launcher_preferences.xml
new file mode 100644
index 000000000..624d9eb2c
--- /dev/null
+++ b/res/xml/launcher_preferences.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2015 Google Inc.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <SwitchPreference
+ android:key="pref_allowRotation"
+ android:title="@string/allow_rotation_title"
+ android:defaultValue="@bool/allow_rotation"
+ android:persistent="true"
+ />
+
+</PreferenceScreen>
diff --git a/res/xml/update_workspace.xml b/res/xml/update_workspace.xml
deleted file mode 100644
index 38442b91c..000000000
--- a/res/xml/update_workspace.xml
+++ /dev/null
@@ -1,49 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2011 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<favorites xmlns:launcher="http://schemas.android.com/apk/res-auto/com.android.launcher3">
- <!-- Update the db with new hotseat items. Note that we reference the browser's original
- package name. -->
- <!-- Hotseat (We use the screen as the position of the item in the hotseat) -->
- <favorite
- launcher:packageName="com.android.dialer"
- launcher:className="com.android.dialer.DialtactsActivity"
- launcher:container="-101"
- launcher:screen="0"
- launcher:x="0"
- launcher:y="0" />
- <favorite
- launcher:packageName="com.android.contacts"
- launcher:className="com.android.contacts.activities.PeopleActivity"
- launcher:container="-101"
- launcher:screen="1"
- launcher:x="1"
- launcher:y="0" />
- <favorite
- launcher:packageName="com.android.mms"
- launcher:className="com.android.mms.ui.ConversationList"
- launcher:container="-101"
- launcher:screen="3"
- launcher:x="3"
- launcher:y="0" />
- <favorite
- launcher:packageName="com.android.browser"
- launcher:className="com.android.browser.BrowserActivity"
- launcher:container="-101"
- launcher:screen="4"
- launcher:x="4"
- launcher:y="0" />
-</favorites>
diff --git a/src/com/android/launcher3/AllAppsList.java b/src/com/android/launcher3/AllAppsList.java
index 72c6693b3..3b25dca34 100644
--- a/src/com/android/launcher3/AllAppsList.java
+++ b/src/com/android/launcher3/AllAppsList.java
@@ -24,6 +24,7 @@ import com.android.launcher3.compat.LauncherAppsCompat;
import com.android.launcher3.compat.UserHandleCompat;
import java.util.ArrayList;
+import java.util.HashSet;
import java.util.List;
@@ -98,14 +99,14 @@ class AllAppsList {
user);
for (LauncherActivityInfoCompat info : matches) {
- add(new AppInfo(context, info, user, mIconCache, null));
+ add(new AppInfo(context, info, user, mIconCache));
}
}
/**
* Remove the apps for the given apk identified by packageName.
*/
- public void removePackage(String packageName, UserHandleCompat user, boolean clearCache) {
+ public void removePackage(String packageName, UserHandleCompat user) {
final List<AppInfo> data = this.data;
for (int i = data.size() - 1; i >= 0; i--) {
AppInfo info = data.get(i);
@@ -115,8 +116,15 @@ class AllAppsList {
data.remove(i);
}
}
- if (clearCache) {
- mIconCache.remove(packageName, user);
+ }
+
+ public void updateIconsAndLabels(HashSet<String> packages, UserHandleCompat user,
+ ArrayList<AppInfo> outUpdates) {
+ for (AppInfo info : data) {
+ if (info.user.equals(user) && packages.contains(info.componentName.getPackageName())) {
+ mIconCache.updateTitleAndIcon(info);
+ outUpdates.add(info);
+ }
}
}
@@ -137,7 +145,6 @@ class AllAppsList {
&& packageName.equals(component.getPackageName())) {
if (!findActivity(matches, component)) {
removed.add(applicationInfo);
- mIconCache.remove(component, user);
data.remove(i);
}
}
@@ -150,10 +157,9 @@ class AllAppsList {
info.getComponentName().getPackageName(), user,
info.getComponentName().getClassName());
if (applicationInfo == null) {
- add(new AppInfo(context, info, user, mIconCache, null));
+ add(new AppInfo(context, info, user, mIconCache));
} else {
- mIconCache.remove(applicationInfo.componentName, user);
- mIconCache.getTitleAndIcon(applicationInfo, info, null);
+ mIconCache.getTitleAndIcon(applicationInfo, info, true /* useLowResIcon */);
modified.add(applicationInfo);
}
}
diff --git a/src/com/android/launcher3/AppInfo.java b/src/com/android/launcher3/AppInfo.java
index a66bac08a..c95d5585a 100644
--- a/src/com/android/launcher3/AppInfo.java
+++ b/src/com/android/launcher3/AppInfo.java
@@ -19,19 +19,16 @@ package com.android.launcher3;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
-import android.content.pm.PackageInfo;
-import android.content.pm.PackageManager.NameNotFoundException;
-import android.content.pm.ResolveInfo;
import android.graphics.Bitmap;
import android.util.Log;
import com.android.launcher3.compat.LauncherActivityInfoCompat;
-import com.android.launcher3.compat.UserManagerCompat;
import com.android.launcher3.compat.UserHandleCompat;
+import com.android.launcher3.compat.UserManagerCompat;
+import com.android.launcher3.util.ComponentKey;
import java.util.ArrayList;
import java.util.Arrays;
-import java.util.HashMap;
/**
* Represents an app in AllAppsView.
@@ -42,19 +39,24 @@ public class AppInfo extends ItemInfo {
/**
* The intent used to start the application.
*/
- Intent intent;
+ public Intent intent;
/**
* A bitmap version of the application icon.
*/
- Bitmap iconBitmap;
+ public Bitmap iconBitmap;
+
+ /**
+ * Indicates whether we're using a low res icon
+ */
+ boolean usingLowResIcon;
/**
* The time at which the app was first installed.
*/
long firstInstallTime;
- ComponentName componentName;
+ public ComponentName componentName;
static final int DOWNLOADED_FLAG = 1;
static final int UPDATED_SYSTEM_APP_FLAG = 2;
@@ -77,13 +79,13 @@ public class AppInfo extends ItemInfo {
* Must not hold the Context.
*/
public AppInfo(Context context, LauncherActivityInfoCompat info, UserHandleCompat user,
- IconCache iconCache, HashMap<Object, CharSequence> labelCache) {
+ IconCache iconCache) {
this.componentName = info.getComponentName();
this.container = ItemInfo.NO_ID;
flags = initFlags(info);
firstInstallTime = info.getFirstInstallTime();
- iconCache.getTitleAndIcon(this, info, labelCache);
+ iconCache.getTitleAndIcon(this, info, true /* useLowResIcon */);
intent = makeLaunchIntent(context, info, user);
this.user = user;
}
@@ -104,7 +106,7 @@ public class AppInfo extends ItemInfo {
public AppInfo(AppInfo info) {
super(info);
componentName = info.componentName;
- title = info.title.toString();
+ title = Utilities.trim(info.title);
intent = new Intent(info.intent);
flags = info.flags;
firstInstallTime = info.firstInstallTime;
@@ -113,19 +115,22 @@ public class AppInfo extends ItemInfo {
@Override
public String toString() {
- return "ApplicationInfo(title=" + title.toString() + " id=" + this.id
+ return "ApplicationInfo(title=" + title + " id=" + this.id
+ " type=" + this.itemType + " container=" + this.container
+ " screen=" + screenId + " cellX=" + cellX + " cellY=" + cellY
+ " spanX=" + spanX + " spanY=" + spanY + " dropPos=" + Arrays.toString(dropPos)
+ " user=" + user + ")";
}
+ /**
+ * Helper method used for debugging.
+ */
public static void dumpApplicationInfoList(String tag, String label, ArrayList<AppInfo> list) {
Log.d(tag, label + " size=" + list.size());
for (AppInfo info: list) {
- Log.d(tag, " title=\"" + info.title + "\" iconBitmap="
- + info.iconBitmap + " firstInstallTime="
- + info.firstInstallTime);
+ Log.d(tag, " title=\"" + info.title + "\" iconBitmap=" + info.iconBitmap
+ + " firstInstallTime=" + info.firstInstallTime
+ + " componentName=" + info.componentName.getPackageName());
}
}
@@ -133,6 +138,10 @@ public class AppInfo extends ItemInfo {
return new ShortcutInfo(this);
}
+ public ComponentKey toComponentKey() {
+ return new ComponentKey(componentName, user);
+ }
+
public static Intent makeLaunchIntent(Context context, LauncherActivityInfoCompat info,
UserHandleCompat user) {
long serialNumber = UserManagerCompat.getInstance(context).getSerialNumberForUser(user);
diff --git a/src/com/android/launcher3/AppWidgetResizeFrame.java b/src/com/android/launcher3/AppWidgetResizeFrame.java
index f57f4d036..ea7c22189 100644
--- a/src/com/android/launcher3/AppWidgetResizeFrame.java
+++ b/src/com/android/launcher3/AppWidgetResizeFrame.java
@@ -8,30 +8,43 @@ import android.animation.ValueAnimator.AnimatorUpdateListener;
import android.appwidget.AppWidgetHostView;
import android.appwidget.AppWidgetProviderInfo;
import android.content.Context;
+import android.content.res.Resources;
import android.graphics.Rect;
import android.view.Gravity;
import android.widget.FrameLayout;
import android.widget.ImageView;
public class AppWidgetResizeFrame extends FrameLayout {
- private LauncherAppWidgetHostView mWidgetView;
- private CellLayout mCellLayout;
- private DragLayer mDragLayer;
- private ImageView mLeftHandle;
- private ImageView mRightHandle;
- private ImageView mTopHandle;
- private ImageView mBottomHandle;
+ private static final int SNAP_DURATION = 150;
+ private static final float DIMMED_HANDLE_ALPHA = 0f;
+ private static final float RESIZE_THRESHOLD = 0.66f;
+
+ private static Rect sTmpRect = new Rect();
+
+ private final Launcher mLauncher;
+ private final LauncherAppWidgetHostView mWidgetView;
+ private final CellLayout mCellLayout;
+ private final DragLayer mDragLayer;
+
+ private final ImageView mLeftHandle;
+ private final ImageView mRightHandle;
+ private final ImageView mTopHandle;
+ private final ImageView mBottomHandle;
+
+ private final Rect mWidgetPadding;
+
+ private final int mBackgroundPadding;
+ private final int mTouchTargetWidth;
+
+ private final int[] mDirectionVector = new int[2];
+ private final int[] mLastDirectionVector = new int[2];
+ private final int[] mTmpPt = new int[2];
private boolean mLeftBorderActive;
private boolean mRightBorderActive;
private boolean mTopBorderActive;
private boolean mBottomBorderActive;
- private int mWidgetPaddingLeft;
- private int mWidgetPaddingRight;
- private int mWidgetPaddingTop;
- private int mWidgetPaddingBottom;
-
private int mBaselineWidth;
private int mBaselineHeight;
private int mBaselineX;
@@ -47,30 +60,9 @@ public class AppWidgetResizeFrame extends FrameLayout {
private int mDeltaXAddOn;
private int mDeltaYAddOn;
- private int mBackgroundPadding;
- private int mTouchTargetWidth;
-
private int mTopTouchRegionAdjustment = 0;
private int mBottomTouchRegionAdjustment = 0;
- int[] mDirectionVector = new int[2];
- int[] mLastDirectionVector = new int[2];
- int[] mTmpPt = new int[2];
-
- final int SNAP_DURATION = 150;
- final int BACKGROUND_PADDING = 24;
- final float DIMMED_HANDLE_ALPHA = 0f;
- final float RESIZE_THRESHOLD = 0.66f;
-
- private static Rect mTmpRect = new Rect();
-
- public static final int LEFT = 0;
- public static final int TOP = 1;
- public static final int RIGHT = 2;
- public static final int BOTTOM = 3;
-
- private Launcher mLauncher;
-
public AppWidgetResizeFrame(Context context,
LauncherAppWidgetHostView widgetView, CellLayout cellLayout, DragLayer dragLayer) {
@@ -78,48 +70,56 @@ public class AppWidgetResizeFrame extends FrameLayout {
mLauncher = (Launcher) context;
mCellLayout = cellLayout;
mWidgetView = widgetView;
- mResizeMode = widgetView.getAppWidgetInfo().resizeMode;
+ LauncherAppWidgetProviderInfo info = (LauncherAppWidgetProviderInfo)
+ widgetView.getAppWidgetInfo();
+ mResizeMode = info.resizeMode;
mDragLayer = dragLayer;
- final AppWidgetProviderInfo info = widgetView.getAppWidgetInfo();
- int[] result = Launcher.getMinSpanForWidget(mLauncher, info);
- mMinHSpan = result[0];
- mMinVSpan = result[1];
+ mMinHSpan = info.getMinSpanX(mLauncher);
+ mMinVSpan = info.getMinSpanY(mLauncher);
- setBackgroundResource(R.drawable.widget_resize_frame_holo);
+ setBackgroundResource(R.drawable.widget_resize_shadow);
+ setForeground(getResources().getDrawable(R.drawable.widget_resize_frame));
setPadding(0, 0, 0, 0);
+ final int handleMargin = getResources().getDimensionPixelSize(R.dimen.widget_handle_margin);
LayoutParams lp;
mLeftHandle = new ImageView(context);
- mLeftHandle.setImageResource(R.drawable.widget_resize_handle_left);
- lp = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT,
+ mLeftHandle.setImageResource(R.drawable.ic_widget_resize_handle);
+ lp = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT,
Gravity.LEFT | Gravity.CENTER_VERTICAL);
+ lp.leftMargin = handleMargin;
addView(mLeftHandle, lp);
mRightHandle = new ImageView(context);
- mRightHandle.setImageResource(R.drawable.widget_resize_handle_right);
- lp = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT,
+ mRightHandle.setImageResource(R.drawable.ic_widget_resize_handle);
+ lp = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT,
Gravity.RIGHT | Gravity.CENTER_VERTICAL);
+ lp.rightMargin = handleMargin;
addView(mRightHandle, lp);
mTopHandle = new ImageView(context);
- mTopHandle.setImageResource(R.drawable.widget_resize_handle_top);
- lp = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT,
+ mTopHandle.setImageResource(R.drawable.ic_widget_resize_handle);
+ lp = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT,
Gravity.CENTER_HORIZONTAL | Gravity.TOP);
+ lp.topMargin = handleMargin;
addView(mTopHandle, lp);
mBottomHandle = new ImageView(context);
- mBottomHandle.setImageResource(R.drawable.widget_resize_handle_bottom);
- lp = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT,
+ mBottomHandle.setImageResource(R.drawable.ic_widget_resize_handle);
+ lp = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT,
Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM);
+ lp.bottomMargin = handleMargin;
addView(mBottomHandle, lp);
- Rect p = AppWidgetHostView.getDefaultPaddingForWidget(context,
- widgetView.getAppWidgetInfo().provider, null);
- mWidgetPaddingLeft = p.left;
- mWidgetPaddingTop = p.top;
- mWidgetPaddingRight = p.right;
- mWidgetPaddingBottom = p.bottom;
+ if (!info.isCustomWidget) {
+ mWidgetPadding = AppWidgetHostView.getDefaultPaddingForWidget(context,
+ widgetView.getAppWidgetInfo().provider, null);
+ } else {
+ Resources r = context.getResources();
+ int padding = r.getDimensionPixelSize(R.dimen.default_widget_padding);
+ mWidgetPadding = new Rect(padding, padding, padding, padding);
+ }
if (mResizeMode == AppWidgetProviderInfo.RESIZE_HORIZONTAL) {
mTopHandle.setVisibility(GONE);
@@ -129,8 +129,8 @@ public class AppWidgetResizeFrame extends FrameLayout {
mRightHandle.setVisibility(GONE);
}
- final float density = mLauncher.getResources().getDisplayMetrics().density;
- mBackgroundPadding = (int) Math.ceil(density * BACKGROUND_PADDING);
+ mBackgroundPadding = getResources()
+ .getDimensionPixelSize(R.dimen.resize_frame_background_padding);
mTouchTargetWidth = 2 * mBackgroundPadding;
// When we create the resize frame, we first mark all cells as unoccupied. The appropriate
@@ -335,13 +335,12 @@ public class AppWidgetResizeFrame extends FrameLayout {
static void updateWidgetSizeRanges(AppWidgetHostView widgetView, Launcher launcher,
int spanX, int spanY) {
-
- getWidgetSizeRanges(launcher, spanX, spanY, mTmpRect);
- widgetView.updateAppWidgetSize(null, mTmpRect.left, mTmpRect.top,
- mTmpRect.right, mTmpRect.bottom);
+ getWidgetSizeRanges(launcher, spanX, spanY, sTmpRect);
+ widgetView.updateAppWidgetSize(null, sTmpRect.left, sTmpRect.top,
+ sTmpRect.right, sTmpRect.bottom);
}
- static Rect getWidgetSizeRanges(Launcher launcher, int spanX, int spanY, Rect rect) {
+ public static Rect getWidgetSizeRanges(Launcher launcher, int spanX, int spanY, Rect rect) {
if (rect == null) {
rect = new Rect();
}
@@ -396,19 +395,19 @@ public class AppWidgetResizeFrame extends FrameLayout {
public void snapToWidget(boolean animate) {
final DragLayer.LayoutParams lp = (DragLayer.LayoutParams) getLayoutParams();
- int newWidth = mWidgetView.getWidth() + 2 * mBackgroundPadding - mWidgetPaddingLeft -
- mWidgetPaddingRight;
- int newHeight = mWidgetView.getHeight() + 2 * mBackgroundPadding - mWidgetPaddingTop -
- mWidgetPaddingBottom;
+ int newWidth = mWidgetView.getWidth() + 2 * mBackgroundPadding
+ - mWidgetPadding.left - mWidgetPadding.right;
+ int newHeight = mWidgetView.getHeight() + 2 * mBackgroundPadding
+ - mWidgetPadding.top - mWidgetPadding.bottom;
mTmpPt[0] = mWidgetView.getLeft();
mTmpPt[1] = mWidgetView.getTop();
mDragLayer.getDescendantCoordRelativeToSelf(mCellLayout.getShortcutsAndWidgets(), mTmpPt);
- int newX = mTmpPt[0] - mBackgroundPadding + mWidgetPaddingLeft;
- int newY = mTmpPt[1] - mBackgroundPadding + mWidgetPaddingTop;
+ int newX = mTmpPt[0] - mBackgroundPadding + mWidgetPadding.left;
+ int newY = mTmpPt[1] - mBackgroundPadding + mWidgetPadding.top;
- // We need to make sure the frame's touchable regions lie fully within the bounds of the
+ // We need to make sure the frame's touchable regions lie fully within the bounds of the
// DragLayer. We allow the actual handles to be clipped, but we shift the touch regions
// down accordingly to provide a proper touch target.
if (newY < 0) {
diff --git a/src/com/android/launcher3/AppWidgetsRestoredReceiver.java b/src/com/android/launcher3/AppWidgetsRestoredReceiver.java
index 880aaf1ec..5e7a012d2 100644
--- a/src/com/android/launcher3/AppWidgetsRestoredReceiver.java
+++ b/src/com/android/launcher3/AppWidgetsRestoredReceiver.java
@@ -90,5 +90,10 @@ public class AppWidgetsRestoredReceiver extends BroadcastReceiver {
}
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void) null);
}
+
+ LauncherAppState app = LauncherAppState.getInstanceNoCreate();
+ if (app != null) {
+ app.reloadWorkspace();
+ }
}
}
diff --git a/src/com/android/launcher3/AppsCustomizeCellLayout.java b/src/com/android/launcher3/AppsCustomizeCellLayout.java
deleted file mode 100644
index a50fb6821..000000000
--- a/src/com/android/launcher3/AppsCustomizeCellLayout.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.launcher3;
-
-import android.content.Context;
-import android.view.View;
-
-public class AppsCustomizeCellLayout extends CellLayout implements Page {
-
- final FocusIndicatorView mFocusHandlerView;
-
- public AppsCustomizeCellLayout(Context context) {
- super(context);
-
- mFocusHandlerView = new FocusIndicatorView(context);
- addView(mFocusHandlerView, 0);
- mFocusHandlerView.getLayoutParams().width = FocusIndicatorView.DEFAULT_LAYOUT_SIZE;
- mFocusHandlerView.getLayoutParams().height = FocusIndicatorView.DEFAULT_LAYOUT_SIZE;
- }
-
- @Override
- public void removeAllViewsOnPage() {
- removeAllViews();
- setLayerType(LAYER_TYPE_NONE, null);
- }
-
- @Override
- public void removeViewOnPageAt(int index) {
- removeViewAt(index);
- }
-
- @Override
- public int getPageChildCount() {
- return getChildCount();
- }
-
- @Override
- public View getChildOnPageAt(int i) {
- return getChildAt(i);
- }
-
- @Override
- public int indexOfChildOnPage(View v) {
- return indexOfChild(v);
- }
-
- /**
- * Clears all the key listeners for the individual icons.
- */
- public void resetChildrenOnKeyListeners() {
- ShortcutAndWidgetContainer children = getShortcutsAndWidgets();
- int childCount = children.getChildCount();
- for (int j = 0; j < childCount; ++j) {
- children.getChildAt(j).setOnKeyListener(null);
- }
- }
-}
diff --git a/src/com/android/launcher3/AppsCustomizePagedView.java b/src/com/android/launcher3/AppsCustomizePagedView.java
deleted file mode 100644
index c8187f068..000000000
--- a/src/com/android/launcher3/AppsCustomizePagedView.java
+++ /dev/null
@@ -1,1567 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.launcher3;
-
-import android.animation.AnimatorSet;
-import android.animation.ValueAnimator;
-import android.appwidget.AppWidgetHostView;
-import android.appwidget.AppWidgetManager;
-import android.appwidget.AppWidgetProviderInfo;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
-import android.content.res.Resources;
-import android.content.res.TypedArray;
-import android.graphics.Bitmap;
-import android.graphics.Point;
-import android.graphics.Rect;
-import android.graphics.drawable.Drawable;
-import android.os.AsyncTask;
-import android.os.Build;
-import android.os.Bundle;
-import android.os.Process;
-import android.util.AttributeSet;
-import android.util.Log;
-import android.view.Gravity;
-import android.view.KeyEvent;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.animation.AccelerateInterpolator;
-import android.widget.GridLayout;
-import android.widget.ImageView;
-import android.widget.Toast;
-
-import com.android.launcher3.DropTarget.DragObject;
-import com.android.launcher3.compat.AppWidgetManagerCompat;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Iterator;
-import java.util.List;
-
-/**
- * A simple callback interface which also provides the results of the task.
- */
-interface AsyncTaskCallback {
- void run(AppsCustomizeAsyncTask task, AsyncTaskPageData data);
-}
-
-/**
- * The data needed to perform either of the custom AsyncTasks.
- */
-class AsyncTaskPageData {
- enum Type {
- LoadWidgetPreviewData
- }
-
- AsyncTaskPageData(int p, ArrayList<Object> l, int cw, int ch, AsyncTaskCallback bgR,
- AsyncTaskCallback postR, WidgetPreviewLoader w) {
- page = p;
- items = l;
- generatedImages = new ArrayList<Bitmap>();
- maxImageWidth = cw;
- maxImageHeight = ch;
- doInBackgroundCallback = bgR;
- postExecuteCallback = postR;
- widgetPreviewLoader = w;
- }
- void cleanup(boolean cancelled) {
- // Clean up any references to source/generated bitmaps
- if (generatedImages != null) {
- if (cancelled) {
- for (int i = 0; i < generatedImages.size(); i++) {
- widgetPreviewLoader.recycleBitmap(items.get(i), generatedImages.get(i));
- }
- }
- generatedImages.clear();
- }
- }
- int page;
- ArrayList<Object> items;
- ArrayList<Bitmap> sourceImages;
- ArrayList<Bitmap> generatedImages;
- int maxImageWidth;
- int maxImageHeight;
- AsyncTaskCallback doInBackgroundCallback;
- AsyncTaskCallback postExecuteCallback;
- WidgetPreviewLoader widgetPreviewLoader;
-}
-
-/**
- * A generic template for an async task used in AppsCustomize.
- */
-class AppsCustomizeAsyncTask extends AsyncTask<AsyncTaskPageData, Void, AsyncTaskPageData> {
- AppsCustomizeAsyncTask(int p, AsyncTaskPageData.Type ty) {
- page = p;
- threadPriority = Process.THREAD_PRIORITY_DEFAULT;
- dataType = ty;
- }
- @Override
- protected AsyncTaskPageData doInBackground(AsyncTaskPageData... params) {
- if (params.length != 1) return null;
- // Load each of the widget previews in the background
- params[0].doInBackgroundCallback.run(this, params[0]);
- return params[0];
- }
- @Override
- protected void onPostExecute(AsyncTaskPageData result) {
- // All the widget previews are loaded, so we can just callback to inflate the page
- result.postExecuteCallback.run(this, result);
- }
-
- void setThreadPriority(int p) {
- threadPriority = p;
- }
- void syncThreadPriority() {
- Process.setThreadPriority(threadPriority);
- }
-
- // The page that this async task is associated with
- AsyncTaskPageData.Type dataType;
- int page;
- int threadPriority;
-}
-
-/**
- * The Apps/Customize page that displays all the applications, widgets, and shortcuts.
- */
-public class AppsCustomizePagedView extends PagedViewWithDraggableItems implements
- View.OnClickListener, View.OnKeyListener, DragSource,
- PagedViewWidget.ShortPressListener, LauncherTransitionable {
- static final String TAG = "AppsCustomizePagedView";
-
- private static Rect sTmpRect = new Rect();
-
- /**
- * The different content types that this paged view can show.
- */
- public enum ContentType {
- Applications,
- Widgets
- }
- private ContentType mContentType = ContentType.Applications;
-
- // Refs
- private Launcher mLauncher;
- private DragController mDragController;
- private final LayoutInflater mLayoutInflater;
- private final PackageManager mPackageManager;
-
- // Save and Restore
- private int mSaveInstanceStateItemIndex = -1;
-
- // Content
- private ArrayList<AppInfo> mApps;
- private ArrayList<Object> mWidgets;
-
- // Caching
- private IconCache mIconCache;
-
- // Dimens
- private int mContentWidth, mContentHeight;
- private int mWidgetCountX, mWidgetCountY;
- private PagedViewCellLayout mWidgetSpacingLayout;
- private int mNumAppsPages;
- private int mNumWidgetPages;
- private Rect mAllAppsPadding = new Rect();
-
- // Previews & outlines
- ArrayList<AppsCustomizeAsyncTask> mRunningTasks;
- private static final int sPageSleepDelay = 200;
-
- private Runnable mInflateWidgetRunnable = null;
- private Runnable mBindWidgetRunnable = null;
- static final int WIDGET_NO_CLEANUP_REQUIRED = -1;
- static final int WIDGET_PRELOAD_PENDING = 0;
- static final int WIDGET_BOUND = 1;
- static final int WIDGET_INFLATED = 2;
- int mWidgetCleanupState = WIDGET_NO_CLEANUP_REQUIRED;
- int mWidgetLoadingId = -1;
- PendingAddWidgetInfo mCreateWidgetInfo = null;
- private boolean mDraggingWidget = false;
- boolean mPageBackgroundsVisible = true;
-
- private Toast mWidgetInstructionToast;
-
- // Deferral of loading widget previews during launcher transitions
- private boolean mInTransition;
- private ArrayList<AsyncTaskPageData> mDeferredSyncWidgetPageItems =
- new ArrayList<AsyncTaskPageData>();
- private ArrayList<Runnable> mDeferredPrepareLoadWidgetPreviewsTasks =
- new ArrayList<Runnable>();
-
- WidgetPreviewLoader mWidgetPreviewLoader;
-
- private boolean mInBulkBind;
- private boolean mNeedToUpdatePageCountsAndInvalidateData;
-
- public AppsCustomizePagedView(Context context, AttributeSet attrs) {
- super(context, attrs);
- mLayoutInflater = LayoutInflater.from(context);
- mPackageManager = context.getPackageManager();
- mApps = new ArrayList<AppInfo>();
- mWidgets = new ArrayList<Object>();
- mIconCache = (LauncherAppState.getInstance()).getIconCache();
- mRunningTasks = new ArrayList<AppsCustomizeAsyncTask>();
-
- // Save the default widget preview background
- TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.AppsCustomizePagedView, 0, 0);
- mWidgetCountX = a.getInt(R.styleable.AppsCustomizePagedView_widgetCountX, 2);
- mWidgetCountY = a.getInt(R.styleable.AppsCustomizePagedView_widgetCountY, 2);
- a.recycle();
- mWidgetSpacingLayout = new PagedViewCellLayout(getContext());
-
- // The padding on the non-matched dimension for the default widget preview icons
- // (top + bottom)
- mFadeInAdjacentScreens = false;
-
- // Unless otherwise specified this view is important for accessibility.
- if (getImportantForAccessibility() == View.IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
- setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES);
- }
- setSinglePageInViewport();
- }
-
- @Override
- protected void init() {
- super.init();
- mCenterPagesVertically = false;
-
- Context context = getContext();
- Resources r = context.getResources();
- setDragSlopeThreshold(r.getInteger(R.integer.config_appsCustomizeDragSlopeThreshold)/100f);
- }
-
- public void onFinishInflate() {
- super.onFinishInflate();
-
- LauncherAppState app = LauncherAppState.getInstance();
- DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
- setPadding(grid.edgeMarginPx, 2 * grid.edgeMarginPx,
- grid.edgeMarginPx, 2 * grid.edgeMarginPx);
- }
-
- void setAllAppsPadding(Rect r) {
- mAllAppsPadding.set(r);
- }
-
- void setWidgetsPageIndicatorPadding(int pageIndicatorHeight) {
- setPadding(getPaddingLeft(), getPaddingTop(), getPaddingRight(), pageIndicatorHeight);
- }
-
- WidgetPreviewLoader getWidgetPreviewLoader() {
- if (mWidgetPreviewLoader == null) {
- mWidgetPreviewLoader = new WidgetPreviewLoader(mLauncher);
- }
- return mWidgetPreviewLoader;
- }
-
- /** Returns the item index of the center item on this page so that we can restore to this
- * item index when we rotate. */
- private int getMiddleComponentIndexOnCurrentPage() {
- int i = -1;
- if (getPageCount() > 0) {
- int currentPage = getCurrentPage();
- if (mContentType == ContentType.Applications) {
- AppsCustomizeCellLayout layout = (AppsCustomizeCellLayout) getPageAt(currentPage);
- ShortcutAndWidgetContainer childrenLayout = layout.getShortcutsAndWidgets();
- int numItemsPerPage = mCellCountX * mCellCountY;
- int childCount = childrenLayout.getChildCount();
- if (childCount > 0) {
- i = (currentPage * numItemsPerPage) + (childCount / 2);
- }
- } else if (mContentType == ContentType.Widgets) {
- int numApps = mApps.size();
- PagedViewGridLayout layout = (PagedViewGridLayout) getPageAt(currentPage);
- int numItemsPerPage = mWidgetCountX * mWidgetCountY;
- int childCount = layout.getChildCount();
- if (childCount > 0) {
- i = numApps +
- (currentPage * numItemsPerPage) + (childCount / 2);
- }
- } else {
- throw new RuntimeException("Invalid ContentType");
- }
- }
- return i;
- }
-
- /** Get the index of the item to restore to if we need to restore the current page. */
- int getSaveInstanceStateIndex() {
- if (mSaveInstanceStateItemIndex == -1) {
- mSaveInstanceStateItemIndex = getMiddleComponentIndexOnCurrentPage();
- }
- return mSaveInstanceStateItemIndex;
- }
-
- /** Returns the page in the current orientation which is expected to contain the specified
- * item index. */
- int getPageForComponent(int index) {
- if (index < 0) return 0;
-
- if (index < mApps.size()) {
- int numItemsPerPage = mCellCountX * mCellCountY;
- return (index / numItemsPerPage);
- } else {
- int numItemsPerPage = mWidgetCountX * mWidgetCountY;
- return (index - mApps.size()) / numItemsPerPage;
- }
- }
-
- /** Restores the page for an item at the specified index */
- void restorePageForIndex(int index) {
- if (index < 0) return;
- mSaveInstanceStateItemIndex = index;
- }
-
- private void updatePageCounts() {
- mNumWidgetPages = (int) Math.ceil(mWidgets.size() /
- (float) (mWidgetCountX * mWidgetCountY));
- mNumAppsPages = (int) Math.ceil((float) mApps.size() / (mCellCountX * mCellCountY));
- }
-
- protected void onDataReady(int width, int height) {
- // Now that the data is ready, we can calculate the content width, the number of cells to
- // use for each page
- LauncherAppState app = LauncherAppState.getInstance();
- DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
- mCellCountX = (int) grid.allAppsNumCols;
- mCellCountY = (int) grid.allAppsNumRows;
- updatePageCounts();
-
- // Force a measure to update recalculate the gaps
- mContentWidth = getMeasuredWidth() - getPaddingLeft() - getPaddingRight();
- mContentHeight = getMeasuredHeight() - getPaddingTop() - getPaddingBottom();
- int widthSpec = MeasureSpec.makeMeasureSpec(mContentWidth, MeasureSpec.AT_MOST);
- int heightSpec = MeasureSpec.makeMeasureSpec(mContentHeight, MeasureSpec.AT_MOST);
- mWidgetSpacingLayout.measure(widthSpec, heightSpec);
-
- final boolean hostIsTransitioning = getTabHost().isInTransition();
- int page = getPageForComponent(mSaveInstanceStateItemIndex);
- invalidatePageData(Math.max(0, page), hostIsTransitioning);
- }
-
- protected void onLayout(boolean changed, int l, int t, int r, int b) {
- super.onLayout(changed, l, t, r, b);
-
- if (!isDataReady()) {
- if ((LauncherAppState.isDisableAllApps() || !mApps.isEmpty()) && !mWidgets.isEmpty()) {
- post(new Runnable() {
- // This code triggers requestLayout so must be posted outside of the
- // layout pass.
- public void run() {
- if (Utilities.isViewAttachedToWindow(AppsCustomizePagedView.this)) {
- setDataIsReady();
- onDataReady(getMeasuredWidth(), getMeasuredHeight());
- }
- }
- });
- }
- }
- }
-
- public void onPackagesUpdated(ArrayList<Object> widgetsAndShortcuts) {
- LauncherAppState app = LauncherAppState.getInstance();
- DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
-
- // Get the list of widgets and shortcuts
- mWidgets.clear();
- for (Object o : widgetsAndShortcuts) {
- if (o instanceof AppWidgetProviderInfo) {
- AppWidgetProviderInfo widget = (AppWidgetProviderInfo) o;
- if (!app.shouldShowAppOrWidgetProvider(widget.provider)) {
- continue;
- }
- if (widget.minWidth > 0 && widget.minHeight > 0) {
- // Ensure that all widgets we show can be added on a workspace of this size
- int[] spanXY = Launcher.getSpanForWidget(mLauncher, widget);
- int[] minSpanXY = Launcher.getMinSpanForWidget(mLauncher, widget);
- int minSpanX = Math.min(spanXY[0], minSpanXY[0]);
- int minSpanY = Math.min(spanXY[1], minSpanXY[1]);
- if (minSpanX <= (int) grid.numColumns &&
- minSpanY <= (int) grid.numRows) {
- mWidgets.add(widget);
- } else {
- Log.e(TAG, "Widget " + widget.provider + " can not fit on this device (" +
- widget.minWidth + ", " + widget.minHeight + ")");
- }
- } else {
- Log.e(TAG, "Widget " + widget.provider + " has invalid dimensions (" +
- widget.minWidth + ", " + widget.minHeight + ")");
- }
- } else {
- // just add shortcuts
- mWidgets.add(o);
- }
- }
- updatePageCountsAndInvalidateData();
- }
-
- public void setBulkBind(boolean bulkBind) {
- if (bulkBind) {
- mInBulkBind = true;
- } else {
- mInBulkBind = false;
- if (mNeedToUpdatePageCountsAndInvalidateData) {
- updatePageCountsAndInvalidateData();
- }
- }
- }
-
- private void updatePageCountsAndInvalidateData() {
- if (mInBulkBind) {
- mNeedToUpdatePageCountsAndInvalidateData = true;
- } else {
- updatePageCounts();
- invalidateOnDataChange();
- mNeedToUpdatePageCountsAndInvalidateData = false;
- }
- }
-
- @Override
- public void onClick(View v) {
- // When we have exited all apps or are in transition, disregard clicks
- if (!mLauncher.isAllAppsVisible()
- || mLauncher.getWorkspace().isSwitchingState()
- || !(v instanceof PagedViewWidget)) return;
-
- // Let the user know that they have to long press to add a widget
- if (mWidgetInstructionToast != null) {
- mWidgetInstructionToast.cancel();
- }
- mWidgetInstructionToast = Toast.makeText(getContext(),R.string.long_press_widget_to_add,
- Toast.LENGTH_SHORT);
- mWidgetInstructionToast.show();
-
- // Create a little animation to show that the widget can move
- float offsetY = getResources().getDimensionPixelSize(R.dimen.dragViewOffsetY);
- final ImageView p = (ImageView) v.findViewById(R.id.widget_preview);
- AnimatorSet bounce = LauncherAnimUtils.createAnimatorSet();
- ValueAnimator tyuAnim = LauncherAnimUtils.ofFloat(p, "translationY", offsetY);
- tyuAnim.setDuration(125);
- ValueAnimator tydAnim = LauncherAnimUtils.ofFloat(p, "translationY", 0f);
- tydAnim.setDuration(100);
- bounce.play(tyuAnim).before(tydAnim);
- bounce.setInterpolator(new AccelerateInterpolator());
- bounce.start();
- }
-
- public boolean onKey(View v, int keyCode, KeyEvent event) {
- return FocusHelper.handleAppsCustomizeKeyEvent(v, keyCode, event);
- }
-
- /*
- * PagedViewWithDraggableItems implementation
- */
- @Override
- protected void determineDraggingStart(android.view.MotionEvent ev) {
- // Disable dragging by pulling an app down for now.
- }
-
- private void beginDraggingApplication(View v) {
- mLauncher.getWorkspace().beginDragShared(v, this);
- }
-
- static Bundle getDefaultOptionsForWidget(Launcher launcher, PendingAddWidgetInfo info) {
- Bundle options = null;
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
- AppWidgetResizeFrame.getWidgetSizeRanges(launcher, info.spanX, info.spanY, sTmpRect);
- Rect padding = AppWidgetHostView.getDefaultPaddingForWidget(launcher,
- info.componentName, null);
-
- float density = launcher.getResources().getDisplayMetrics().density;
- int xPaddingDips = (int) ((padding.left + padding.right) / density);
- int yPaddingDips = (int) ((padding.top + padding.bottom) / density);
-
- options = new Bundle();
- options.putInt(AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH,
- sTmpRect.left - xPaddingDips);
- options.putInt(AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT,
- sTmpRect.top - yPaddingDips);
- options.putInt(AppWidgetManager.OPTION_APPWIDGET_MAX_WIDTH,
- sTmpRect.right - xPaddingDips);
- options.putInt(AppWidgetManager.OPTION_APPWIDGET_MAX_HEIGHT,
- sTmpRect.bottom - yPaddingDips);
- }
- return options;
- }
-
- private void preloadWidget(final PendingAddWidgetInfo info) {
- final AppWidgetProviderInfo pInfo = info.info;
- final Bundle options = getDefaultOptionsForWidget(mLauncher, info);
-
- if (pInfo.configure != null) {
- info.bindOptions = options;
- return;
- }
-
- mWidgetCleanupState = WIDGET_PRELOAD_PENDING;
- mBindWidgetRunnable = new Runnable() {
- @Override
- public void run() {
- mWidgetLoadingId = mLauncher.getAppWidgetHost().allocateAppWidgetId();
- if(AppWidgetManagerCompat.getInstance(mLauncher).bindAppWidgetIdIfAllowed(
- mWidgetLoadingId, pInfo, options)) {
- mWidgetCleanupState = WIDGET_BOUND;
- }
- }
- };
- post(mBindWidgetRunnable);
-
- mInflateWidgetRunnable = new Runnable() {
- @Override
- public void run() {
- if (mWidgetCleanupState != WIDGET_BOUND) {
- return;
- }
- AppWidgetHostView hostView = mLauncher.
- getAppWidgetHost().createView(getContext(), mWidgetLoadingId, pInfo);
- info.boundWidget = hostView;
- mWidgetCleanupState = WIDGET_INFLATED;
- hostView.setVisibility(INVISIBLE);
- int[] unScaledSize = mLauncher.getWorkspace().estimateItemSize(info.spanX,
- info.spanY, info, false);
-
- // We want the first widget layout to be the correct size. This will be important
- // for width size reporting to the AppWidgetManager.
- DragLayer.LayoutParams lp = new DragLayer.LayoutParams(unScaledSize[0],
- unScaledSize[1]);
- lp.x = lp.y = 0;
- lp.customPosition = true;
- hostView.setLayoutParams(lp);
- mLauncher.getDragLayer().addView(hostView);
- }
- };
- post(mInflateWidgetRunnable);
- }
-
- @Override
- public void onShortPress(View v) {
- // We are anticipating a long press, and we use this time to load bind and instantiate
- // the widget. This will need to be cleaned up if it turns out no long press occurs.
- if (mCreateWidgetInfo != null) {
- // Just in case the cleanup process wasn't properly executed. This shouldn't happen.
- cleanupWidgetPreloading(false);
- }
- mCreateWidgetInfo = new PendingAddWidgetInfo((PendingAddWidgetInfo) v.getTag());
- preloadWidget(mCreateWidgetInfo);
- }
-
- private void cleanupWidgetPreloading(boolean widgetWasAdded) {
- if (!widgetWasAdded) {
- // If the widget was not added, we may need to do further cleanup.
- PendingAddWidgetInfo info = mCreateWidgetInfo;
- mCreateWidgetInfo = null;
-
- if (mWidgetCleanupState == WIDGET_PRELOAD_PENDING) {
- // We never did any preloading, so just remove pending callbacks to do so
- removeCallbacks(mBindWidgetRunnable);
- removeCallbacks(mInflateWidgetRunnable);
- } else if (mWidgetCleanupState == WIDGET_BOUND) {
- // Delete the widget id which was allocated
- if (mWidgetLoadingId != -1) {
- mLauncher.getAppWidgetHost().deleteAppWidgetId(mWidgetLoadingId);
- }
-
- // We never got around to inflating the widget, so remove the callback to do so.
- removeCallbacks(mInflateWidgetRunnable);
- } else if (mWidgetCleanupState == WIDGET_INFLATED) {
- // Delete the widget id which was allocated
- if (mWidgetLoadingId != -1) {
- mLauncher.getAppWidgetHost().deleteAppWidgetId(mWidgetLoadingId);
- }
-
- // The widget was inflated and added to the DragLayer -- remove it.
- AppWidgetHostView widget = info.boundWidget;
- mLauncher.getDragLayer().removeView(widget);
- }
- }
- mWidgetCleanupState = WIDGET_NO_CLEANUP_REQUIRED;
- mWidgetLoadingId = -1;
- mCreateWidgetInfo = null;
- PagedViewWidget.resetShortPressTarget();
- }
-
- @Override
- public void cleanUpShortPress(View v) {
- if (!mDraggingWidget) {
- cleanupWidgetPreloading(false);
- }
- }
-
- private boolean beginDraggingWidget(View v) {
- mDraggingWidget = true;
- // Get the widget preview as the drag representation
- ImageView image = (ImageView) v.findViewById(R.id.widget_preview);
- PendingAddItemInfo createItemInfo = (PendingAddItemInfo) v.getTag();
-
- // If the ImageView doesn't have a drawable yet, the widget preview hasn't been loaded and
- // we abort the drag.
- if (image.getDrawable() == null) {
- mDraggingWidget = false;
- return false;
- }
-
- // Compose the drag image
- Bitmap preview;
- Bitmap outline;
- float scale = 1f;
- Point previewPadding = null;
-
- if (createItemInfo instanceof PendingAddWidgetInfo) {
- // This can happen in some weird cases involving multi-touch. We can't start dragging
- // the widget if this is null, so we break out.
- if (mCreateWidgetInfo == null) {
- return false;
- }
-
- PendingAddWidgetInfo createWidgetInfo = mCreateWidgetInfo;
- createItemInfo = createWidgetInfo;
- int spanX = createItemInfo.spanX;
- int spanY = createItemInfo.spanY;
- int[] size = mLauncher.getWorkspace().estimateItemSize(spanX, spanY,
- createWidgetInfo, true);
-
- FastBitmapDrawable previewDrawable = (FastBitmapDrawable) image.getDrawable();
- float minScale = 1.25f;
- int maxWidth, maxHeight;
- maxWidth = Math.min((int) (previewDrawable.getIntrinsicWidth() * minScale), size[0]);
- maxHeight = Math.min((int) (previewDrawable.getIntrinsicHeight() * minScale), size[1]);
-
- int[] previewSizeBeforeScale = new int[1];
-
- preview = getWidgetPreviewLoader().generateWidgetPreview(createWidgetInfo.info,
- spanX, spanY, maxWidth, maxHeight, null, previewSizeBeforeScale);
-
- // Compare the size of the drag preview to the preview in the AppsCustomize tray
- int previewWidthInAppsCustomize = Math.min(previewSizeBeforeScale[0],
- getWidgetPreviewLoader().maxWidthForWidgetPreview(spanX));
- scale = previewWidthInAppsCustomize / (float) preview.getWidth();
-
- // The bitmap in the AppsCustomize tray is always the the same size, so there
- // might be extra pixels around the preview itself - this accounts for that
- if (previewWidthInAppsCustomize < previewDrawable.getIntrinsicWidth()) {
- int padding =
- (previewDrawable.getIntrinsicWidth() - previewWidthInAppsCustomize) / 2;
- previewPadding = new Point(padding, 0);
- }
- } else {
- PendingAddShortcutInfo createShortcutInfo = (PendingAddShortcutInfo) v.getTag();
- Drawable icon = mIconCache.getFullResIcon(createShortcutInfo.shortcutActivityInfo);
- preview = Utilities.createIconBitmap(icon, mLauncher);
- createItemInfo.spanX = createItemInfo.spanY = 1;
- }
-
- // Don't clip alpha values for the drag outline if we're using the default widget preview
- boolean clipAlpha = !(createItemInfo instanceof PendingAddWidgetInfo &&
- (((PendingAddWidgetInfo) createItemInfo).previewImage == 0));
-
- // Save the preview for the outline generation, then dim the preview
- outline = Bitmap.createScaledBitmap(preview, preview.getWidth(), preview.getHeight(),
- false);
-
- // Start the drag
- mLauncher.lockScreenOrientation();
- mLauncher.getWorkspace().onDragStartedWithItem(createItemInfo, outline, clipAlpha);
- mDragController.startDrag(image, preview, this, createItemInfo,
- DragController.DRAG_ACTION_COPY, previewPadding, scale);
- outline.recycle();
- preview.recycle();
- return true;
- }
-
- @Override
- protected boolean beginDragging(final View v) {
- if (!super.beginDragging(v)) return false;
-
- if (v instanceof BubbleTextView) {
- beginDraggingApplication(v);
- } else if (v instanceof PagedViewWidget) {
- if (!beginDraggingWidget(v)) {
- return false;
- }
- }
-
- // We delay entering spring-loaded mode slightly to make sure the UI
- // thready is free of any work.
- postDelayed(new Runnable() {
- @Override
- public void run() {
- // We don't enter spring-loaded mode if the drag has been cancelled
- if (mLauncher.getDragController().isDragging()) {
- // Go into spring loaded mode (must happen before we startDrag())
- mLauncher.enterSpringLoadedDragMode();
- }
- }
- }, 150);
-
- return true;
- }
-
- /**
- * Clean up after dragging.
- *
- * @param target where the item was dragged to (can be null if the item was flung)
- */
- private void endDragging(View target, boolean isFlingToDelete, boolean success) {
- 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
- // drop in Workspace
- mLauncher.exitSpringLoadedDragModeDelayed(true,
- Launcher.EXIT_SPRINGLOADED_MODE_SHORT_TIMEOUT, null);
- mLauncher.unlockScreenOrientation(false);
- } else {
- mLauncher.unlockScreenOrientation(false);
- }
- }
-
- @Override
- public View getContent() {
- if (getChildCount() > 0) {
- return getChildAt(0);
- }
- return null;
- }
-
- @Override
- public void onLauncherTransitionPrepare(Launcher l, boolean animated, boolean toWorkspace) {
- mInTransition = true;
- if (toWorkspace) {
- cancelAllTasks();
- }
- }
-
- @Override
- public void onLauncherTransitionStart(Launcher l, boolean animated, boolean toWorkspace) {
- }
-
- @Override
- public void onLauncherTransitionStep(Launcher l, float t) {
- }
-
- @Override
- public void onLauncherTransitionEnd(Launcher l, boolean animated, boolean toWorkspace) {
- mInTransition = false;
- for (AsyncTaskPageData d : mDeferredSyncWidgetPageItems) {
- onSyncWidgetPageItems(d, false);
- }
- mDeferredSyncWidgetPageItems.clear();
- for (Runnable r : mDeferredPrepareLoadWidgetPreviewsTasks) {
- r.run();
- }
- mDeferredPrepareLoadWidgetPreviewsTasks.clear();
- mForceDrawAllChildrenNextFrame = !toWorkspace;
- }
-
- @Override
- public void onDropCompleted(View target, DragObject d, boolean isFlingToDelete,
- boolean success) {
- // Return early and wait for onFlingToDeleteCompleted if this was the result of a fling
- if (isFlingToDelete) return;
-
- endDragging(target, false, success);
-
- // Display an error message if the drag failed due to there not being enough space on the
- // target layout we were dropping on.
- if (!success) {
- boolean showOutOfSpaceMessage = false;
- if (target instanceof Workspace) {
- int currentScreen = mLauncher.getCurrentWorkspaceScreen();
- Workspace workspace = (Workspace) target;
- CellLayout layout = (CellLayout) workspace.getChildAt(currentScreen);
- ItemInfo itemInfo = (ItemInfo) d.dragInfo;
- if (layout != null) {
- layout.calculateSpans(itemInfo);
- showOutOfSpaceMessage =
- !layout.findCellForSpan(null, itemInfo.spanX, itemInfo.spanY);
- }
- }
- if (showOutOfSpaceMessage) {
- mLauncher.showOutOfSpaceMessage(false);
- }
-
- d.deferDragViewCleanupPostAnimation = false;
- }
- cleanupWidgetPreloading(success);
- mDraggingWidget = false;
- }
-
- @Override
- public void onFlingToDeleteCompleted() {
- // We just dismiss the drag when we fling, so cleanup here
- endDragging(null, true, true);
- cleanupWidgetPreloading(false);
- mDraggingWidget = false;
- }
-
- @Override
- public boolean supportsFlingToDelete() {
- return true;
- }
-
- @Override
- public boolean supportsAppInfoDropTarget() {
- return true;
- }
-
- @Override
- public boolean supportsDeleteDropTarget() {
- return false;
- }
-
- @Override
- public float getIntrinsicIconScaleFactor() {
- LauncherAppState app = LauncherAppState.getInstance();
- DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
- return (float) grid.allAppsIconSizePx / grid.iconSizePx;
- }
-
- @Override
- protected void onDetachedFromWindow() {
- super.onDetachedFromWindow();
- cancelAllTasks();
- }
-
- @Override
- public void trimMemory() {
- super.trimMemory();
- clearAllWidgetPages();
- }
-
- public void clearAllWidgetPages() {
- cancelAllTasks();
- int count = getChildCount();
- for (int i = 0; i < count; i++) {
- View v = getPageAt(i);
- if (v instanceof PagedViewGridLayout) {
- ((PagedViewGridLayout) v).removeAllViewsOnPage();
- mDirtyPageContent.set(i, true);
- }
- }
- }
-
- private void cancelAllTasks() {
- // Clean up all the async tasks
- Iterator<AppsCustomizeAsyncTask> iter = mRunningTasks.iterator();
- while (iter.hasNext()) {
- AppsCustomizeAsyncTask task = (AppsCustomizeAsyncTask) iter.next();
- task.cancel(false);
- iter.remove();
- mDirtyPageContent.set(task.page, true);
-
- // We've already preallocated the views for the data to load into, so clear them as well
- View v = getPageAt(task.page);
- if (v instanceof PagedViewGridLayout) {
- ((PagedViewGridLayout) v).removeAllViewsOnPage();
- }
- }
- mDeferredSyncWidgetPageItems.clear();
- mDeferredPrepareLoadWidgetPreviewsTasks.clear();
- }
-
- public void setContentType(ContentType type) {
- // Widgets appear to be cleared every time you leave, always force invalidate for them
- if (mContentType != type || type == ContentType.Widgets) {
- int page = (mContentType != type) ? 0 : getCurrentPage();
- mContentType = type;
- invalidatePageData(page, true);
- }
- }
-
- public ContentType getContentType() {
- return mContentType;
- }
-
- protected void snapToPage(int whichPage, int delta, int duration) {
- super.snapToPage(whichPage, delta, duration);
-
- // Update the thread priorities given the direction lookahead
- Iterator<AppsCustomizeAsyncTask> iter = mRunningTasks.iterator();
- while (iter.hasNext()) {
- AppsCustomizeAsyncTask task = (AppsCustomizeAsyncTask) iter.next();
- int pageIndex = task.page;
- if ((mNextPage > mCurrentPage && pageIndex >= mCurrentPage) ||
- (mNextPage < mCurrentPage && pageIndex <= mCurrentPage)) {
- task.setThreadPriority(getThreadPriorityForPage(pageIndex));
- } else {
- task.setThreadPriority(Process.THREAD_PRIORITY_LOWEST);
- }
- }
- }
-
- /*
- * Apps PagedView implementation
- */
- private void setVisibilityOnChildren(ViewGroup layout, int visibility) {
- int childCount = layout.getChildCount();
- for (int i = 0; i < childCount; ++i) {
- layout.getChildAt(i).setVisibility(visibility);
- }
- }
- private void setupPage(AppsCustomizeCellLayout layout) {
- layout.setGridSize(mCellCountX, mCellCountY);
-
- // Note: We force a measure here to get around the fact that when we do layout calculations
- // immediately after syncing, we don't have a proper width. That said, we already know the
- // expected page width, so we can actually optimize by hiding all the TextView-based
- // children that are expensive to measure, and let that happen naturally later.
- setVisibilityOnChildren(layout, View.GONE);
- int widthSpec = MeasureSpec.makeMeasureSpec(mContentWidth, MeasureSpec.AT_MOST);
- int heightSpec = MeasureSpec.makeMeasureSpec(mContentHeight, MeasureSpec.AT_MOST);
- layout.measure(widthSpec, heightSpec);
-
- Drawable bg = getContext().getResources().getDrawable(R.drawable.quantum_panel);
- if (bg != null) {
- bg.setAlpha(mPageBackgroundsVisible ? 255: 0);
- layout.setBackground(bg);
- }
-
- setVisibilityOnChildren(layout, View.VISIBLE);
- }
-
- public void setPageBackgroundsVisible(boolean visible) {
- mPageBackgroundsVisible = visible;
- int childCount = getChildCount();
- for (int i = 0; i < childCount; ++i) {
- Drawable bg = getChildAt(i).getBackground();
- if (bg != null) {
- bg.setAlpha(visible ? 255 : 0);
- }
- }
- }
-
- public void syncAppsPageItems(int page, boolean immediate) {
- // ensure that we have the right number of items on the pages
- final boolean isRtl = isLayoutRtl();
- int numCells = mCellCountX * mCellCountY;
- int startIndex = page * numCells;
- int endIndex = Math.min(startIndex + numCells, mApps.size());
- AppsCustomizeCellLayout layout = (AppsCustomizeCellLayout) getPageAt(page);
-
- layout.removeAllViewsOnPage();
- ArrayList<Object> items = new ArrayList<Object>();
- ArrayList<Bitmap> images = new ArrayList<Bitmap>();
- for (int i = startIndex; i < endIndex; ++i) {
- AppInfo info = mApps.get(i);
- BubbleTextView icon = (BubbleTextView) mLayoutInflater.inflate(
- R.layout.apps_customize_application, layout, false);
- icon.applyFromApplicationInfo(info);
- icon.setOnClickListener(mLauncher);
- icon.setOnLongClickListener(this);
- icon.setOnTouchListener(this);
- icon.setOnKeyListener(this);
- icon.setOnFocusChangeListener(layout.mFocusHandlerView);
-
- int index = i - startIndex;
- int x = index % mCellCountX;
- int y = index / mCellCountX;
- if (isRtl) {
- x = mCellCountX - x - 1;
- }
- layout.addViewToCellLayout(icon, -1, i, new CellLayout.LayoutParams(x,y, 1,1), false);
-
- items.add(info);
- images.add(info.iconBitmap);
- }
-
- enableHwLayersOnVisiblePages();
- }
-
- /**
- * A helper to return the priority for loading of the specified widget page.
- */
- private int getWidgetPageLoadPriority(int page) {
- // If we are snapping to another page, use that index as the target page index
- int toPage = mCurrentPage;
- if (mNextPage > -1) {
- toPage = mNextPage;
- }
-
- // We use the distance from the target page as an initial guess of priority, but if there
- // are no pages of higher priority than the page specified, then bump up the priority of
- // the specified page.
- Iterator<AppsCustomizeAsyncTask> iter = mRunningTasks.iterator();
- int minPageDiff = Integer.MAX_VALUE;
- while (iter.hasNext()) {
- AppsCustomizeAsyncTask task = (AppsCustomizeAsyncTask) iter.next();
- minPageDiff = Math.abs(task.page - toPage);
- }
-
- int rawPageDiff = Math.abs(page - toPage);
- return rawPageDiff - Math.min(rawPageDiff, minPageDiff);
- }
- /**
- * Return the appropriate thread priority for loading for a given page (we give the current
- * page much higher priority)
- */
- private int getThreadPriorityForPage(int page) {
- // TODO-APPS_CUSTOMIZE: detect number of cores and set thread priorities accordingly below
- int pageDiff = getWidgetPageLoadPriority(page);
- if (pageDiff <= 0) {
- return Process.THREAD_PRIORITY_LESS_FAVORABLE;
- } else if (pageDiff <= 1) {
- return Process.THREAD_PRIORITY_LOWEST;
- } else {
- return Process.THREAD_PRIORITY_LOWEST;
- }
- }
- private int getSleepForPage(int page) {
- int pageDiff = getWidgetPageLoadPriority(page);
- return Math.max(0, pageDiff * sPageSleepDelay);
- }
- /**
- * Creates and executes a new AsyncTask to load a page of widget previews.
- */
- private void prepareLoadWidgetPreviewsTask(int page, ArrayList<Object> widgets,
- int cellWidth, int cellHeight, int cellCountX) {
-
- // Prune all tasks that are no longer needed
- Iterator<AppsCustomizeAsyncTask> iter = mRunningTasks.iterator();
- while (iter.hasNext()) {
- AppsCustomizeAsyncTask task = (AppsCustomizeAsyncTask) iter.next();
- int taskPage = task.page;
- if (taskPage < getAssociatedLowerPageBound(mCurrentPage) ||
- taskPage > getAssociatedUpperPageBound(mCurrentPage)) {
- task.cancel(false);
- iter.remove();
- } else {
- task.setThreadPriority(getThreadPriorityForPage(taskPage));
- }
- }
-
- // We introduce a slight delay to order the loading of side pages so that we don't thrash
- final int sleepMs = getSleepForPage(page);
- AsyncTaskPageData pageData = new AsyncTaskPageData(page, widgets, cellWidth, cellHeight,
- new AsyncTaskCallback() {
- @Override
- public void run(AppsCustomizeAsyncTask task, AsyncTaskPageData data) {
- try {
- try {
- Thread.sleep(sleepMs);
- } catch (Exception e) {}
- loadWidgetPreviewsInBackground(task, data);
- } finally {
- if (task.isCancelled()) {
- data.cleanup(true);
- }
- }
- }
- },
- new AsyncTaskCallback() {
- @Override
- public void run(AppsCustomizeAsyncTask task, AsyncTaskPageData data) {
- mRunningTasks.remove(task);
- if (task.isCancelled()) return;
- // do cleanup inside onSyncWidgetPageItems
- onSyncWidgetPageItems(data, false);
- }
- }, getWidgetPreviewLoader());
-
- // Ensure that the task is appropriately prioritized and runs in parallel
- AppsCustomizeAsyncTask t = new AppsCustomizeAsyncTask(page,
- AsyncTaskPageData.Type.LoadWidgetPreviewData);
- t.setThreadPriority(getThreadPriorityForPage(page));
- t.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, pageData);
- mRunningTasks.add(t);
- }
-
- /*
- * Widgets PagedView implementation
- */
- private void setupPage(PagedViewGridLayout layout) {
- // Note: We force a measure here to get around the fact that when we do layout calculations
- // immediately after syncing, we don't have a proper width.
- int widthSpec = MeasureSpec.makeMeasureSpec(mContentWidth, MeasureSpec.AT_MOST);
- int heightSpec = MeasureSpec.makeMeasureSpec(mContentHeight, MeasureSpec.AT_MOST);
-
- Drawable bg = getContext().getResources().getDrawable(R.drawable.quantum_panel_dark);
- if (bg != null) {
- bg.setAlpha(mPageBackgroundsVisible ? 255 : 0);
- layout.setBackground(bg);
- }
- layout.measure(widthSpec, heightSpec);
- }
-
- public void syncWidgetPageItems(final int page, final boolean immediate) {
- int numItemsPerPage = mWidgetCountX * mWidgetCountY;
-
- final PagedViewGridLayout layout = (PagedViewGridLayout) getPageAt(page);
-
- // Calculate the dimensions of each cell we are giving to each widget
- final ArrayList<Object> items = new ArrayList<Object>();
- int contentWidth = mContentWidth - layout.getPaddingLeft() - layout.getPaddingRight();
- final int cellWidth = contentWidth / mWidgetCountX;
- int contentHeight = mContentHeight - layout.getPaddingTop() - layout.getPaddingBottom();
-
- final int cellHeight = contentHeight / mWidgetCountY;
-
- // Prepare the set of widgets to load previews for in the background
- int offset = page * numItemsPerPage;
- for (int i = offset; i < Math.min(offset + numItemsPerPage, mWidgets.size()); ++i) {
- items.add(mWidgets.get(i));
- }
-
- // Prepopulate the pages with the other widget info, and fill in the previews later
- layout.setColumnCount(layout.getCellCountX());
- for (int i = 0; i < items.size(); ++i) {
- Object rawInfo = items.get(i);
- PendingAddItemInfo createItemInfo = null;
- PagedViewWidget widget = (PagedViewWidget) mLayoutInflater.inflate(
- R.layout.apps_customize_widget, layout, false);
- if (rawInfo instanceof AppWidgetProviderInfo) {
- // Fill in the widget information
- AppWidgetProviderInfo info = (AppWidgetProviderInfo) rawInfo;
- createItemInfo = new PendingAddWidgetInfo(info, null, null);
-
- // Determine the widget spans and min resize spans.
- int[] spanXY = Launcher.getSpanForWidget(mLauncher, info);
- createItemInfo.spanX = spanXY[0];
- createItemInfo.spanY = spanXY[1];
- int[] minSpanXY = Launcher.getMinSpanForWidget(mLauncher, info);
- createItemInfo.minSpanX = minSpanXY[0];
- createItemInfo.minSpanY = minSpanXY[1];
-
- widget.applyFromAppWidgetProviderInfo(info, -1, spanXY, getWidgetPreviewLoader());
- widget.setTag(createItemInfo);
- widget.setShortPressListener(this);
- } else if (rawInfo instanceof ResolveInfo) {
- // Fill in the shortcuts information
- ResolveInfo info = (ResolveInfo) rawInfo;
- createItemInfo = new PendingAddShortcutInfo(info.activityInfo);
- createItemInfo.itemType = LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT;
- createItemInfo.componentName = new ComponentName(info.activityInfo.packageName,
- info.activityInfo.name);
- widget.applyFromResolveInfo(mPackageManager, info, getWidgetPreviewLoader());
- widget.setTag(createItemInfo);
- }
- widget.setOnClickListener(this);
- widget.setOnLongClickListener(this);
- widget.setOnTouchListener(this);
- widget.setOnKeyListener(this);
-
- // Layout each widget
- int ix = i % mWidgetCountX;
- int iy = i / mWidgetCountX;
-
- if (ix > 0) {
- View border = widget.findViewById(R.id.left_border);
- border.setVisibility(View.VISIBLE);
- }
- if (ix < mWidgetCountX - 1) {
- View border = widget.findViewById(R.id.right_border);
- border.setVisibility(View.VISIBLE);
- }
-
- GridLayout.LayoutParams lp = new GridLayout.LayoutParams(
- GridLayout.spec(iy, GridLayout.START),
- GridLayout.spec(ix, GridLayout.TOP));
- lp.width = cellWidth;
- lp.height = cellHeight;
- lp.setGravity(Gravity.TOP | Gravity.START);
- layout.addView(widget, lp);
- }
-
- // wait until a call on onLayout to start loading, because
- // PagedViewWidget.getPreviewSize() will return 0 if it hasn't been laid out
- // TODO: can we do a measure/layout immediately?
- layout.setOnLayoutListener(new Runnable() {
- public void run() {
- // Load the widget previews
- int maxPreviewWidth = cellWidth;
- int maxPreviewHeight = cellHeight;
- if (layout.getChildCount() > 0) {
- PagedViewWidget w = (PagedViewWidget) layout.getChildAt(0);
- int[] maxSize = w.getPreviewSize();
- maxPreviewWidth = maxSize[0];
- maxPreviewHeight = maxSize[1];
- }
-
- getWidgetPreviewLoader().setPreviewSize(
- maxPreviewWidth, maxPreviewHeight, mWidgetSpacingLayout);
- if (immediate) {
- AsyncTaskPageData data = new AsyncTaskPageData(page, items,
- maxPreviewWidth, maxPreviewHeight, null, null, getWidgetPreviewLoader());
- loadWidgetPreviewsInBackground(null, data);
- onSyncWidgetPageItems(data, immediate);
- } else {
- if (mInTransition) {
- mDeferredPrepareLoadWidgetPreviewsTasks.add(this);
- } else {
- prepareLoadWidgetPreviewsTask(page, items,
- maxPreviewWidth, maxPreviewHeight, mWidgetCountX);
- }
- }
- layout.setOnLayoutListener(null);
- }
- });
- }
- private void loadWidgetPreviewsInBackground(AppsCustomizeAsyncTask task,
- AsyncTaskPageData data) {
- // loadWidgetPreviewsInBackground can be called without a task to load a set of widget
- // previews synchronously
- if (task != null) {
- // Ensure that this task starts running at the correct priority
- task.syncThreadPriority();
- }
-
- // Load each of the widget/shortcut previews
- ArrayList<Object> items = data.items;
- ArrayList<Bitmap> images = data.generatedImages;
- int count = items.size();
- for (int i = 0; i < count; ++i) {
- if (task != null) {
- // Ensure we haven't been cancelled yet
- if (task.isCancelled()) break;
- // Before work on each item, ensure that this task is running at the correct
- // priority
- task.syncThreadPriority();
- }
-
- images.add(getWidgetPreviewLoader().getPreview(items.get(i)));
- }
- }
-
- private void onSyncWidgetPageItems(AsyncTaskPageData data, boolean immediatelySyncItems) {
- if (!immediatelySyncItems && mInTransition) {
- mDeferredSyncWidgetPageItems.add(data);
- return;
- }
- try {
- int page = data.page;
- PagedViewGridLayout layout = (PagedViewGridLayout) getPageAt(page);
-
- ArrayList<Object> items = data.items;
- int count = items.size();
- for (int i = 0; i < count; ++i) {
- PagedViewWidget widget = (PagedViewWidget) layout.getChildAt(i);
- if (widget != null) {
- Bitmap preview = data.generatedImages.get(i);
- widget.applyPreview(new FastBitmapDrawable(preview), i);
- }
- }
-
- enableHwLayersOnVisiblePages();
-
- // Update all thread priorities
- Iterator<AppsCustomizeAsyncTask> iter = mRunningTasks.iterator();
- while (iter.hasNext()) {
- AppsCustomizeAsyncTask task = (AppsCustomizeAsyncTask) iter.next();
- int pageIndex = task.page;
- task.setThreadPriority(getThreadPriorityForPage(pageIndex));
- }
- } finally {
- data.cleanup(false);
- }
- }
-
- @Override
- public void syncPages() {
- disablePagedViewAnimations();
-
- removeAllViews();
- cancelAllTasks();
-
- Context context = getContext();
- if (mContentType == ContentType.Applications) {
- for (int i = 0; i < mNumAppsPages; ++i) {
- AppsCustomizeCellLayout layout = new AppsCustomizeCellLayout(context);
- setupPage(layout);
- addView(layout, new PagedView.LayoutParams(LayoutParams.MATCH_PARENT,
- LayoutParams.MATCH_PARENT));
- }
- } else if (mContentType == ContentType.Widgets) {
- for (int j = 0; j < mNumWidgetPages; ++j) {
- PagedViewGridLayout layout = new PagedViewGridLayout(context, mWidgetCountX,
- mWidgetCountY);
- setupPage(layout);
- addView(layout, new PagedView.LayoutParams(LayoutParams.MATCH_PARENT,
- LayoutParams.MATCH_PARENT));
- }
- } else {
- throw new RuntimeException("Invalid ContentType");
- }
-
- enablePagedViewAnimations();
- }
-
- @Override
- public void syncPageItems(int page, boolean immediate) {
- if (mContentType == ContentType.Widgets) {
- syncWidgetPageItems(page, immediate);
- } else {
- syncAppsPageItems(page, immediate);
- }
- }
-
- // We want our pages to be z-ordered such that the further a page is to the left, the higher
- // it is in the z-order. This is important to insure touch events are handled correctly.
- View getPageAt(int index) {
- return getChildAt(indexToPage(index));
- }
-
- @Override
- protected int indexToPage(int index) {
- return getChildCount() - index - 1;
- }
-
- // In apps customize, we have a scrolling effect which emulates pulling cards off of a stack.
- @Override
- protected void screenScrolled(int screenCenter) {
- super.screenScrolled(screenCenter);
- enableHwLayersOnVisiblePages();
- }
-
- private void enableHwLayersOnVisiblePages() {
- final int screenCount = getChildCount();
-
- getVisiblePages(mTempVisiblePagesRange);
- int leftScreen = mTempVisiblePagesRange[0];
- int rightScreen = mTempVisiblePagesRange[1];
- int forceDrawScreen = -1;
- if (leftScreen == rightScreen) {
- // make sure we're caching at least two pages always
- if (rightScreen < screenCount - 1) {
- rightScreen++;
- forceDrawScreen = rightScreen;
- } else if (leftScreen > 0) {
- leftScreen--;
- forceDrawScreen = leftScreen;
- }
- } else {
- forceDrawScreen = leftScreen + 1;
- }
-
- for (int i = 0; i < screenCount; i++) {
- final View layout = (View) getPageAt(i);
- if (!(leftScreen <= i && i <= rightScreen &&
- (i == forceDrawScreen || shouldDrawChild(layout)))) {
- layout.setLayerType(LAYER_TYPE_NONE, null);
- }
- }
-
- for (int i = 0; i < screenCount; i++) {
- final View layout = (View) getPageAt(i);
-
- if (leftScreen <= i && i <= rightScreen &&
- (i == forceDrawScreen || shouldDrawChild(layout))) {
- if (layout.getLayerType() != LAYER_TYPE_HARDWARE) {
- layout.setLayerType(LAYER_TYPE_HARDWARE, null);
- }
- }
- }
- }
-
- protected void overScroll(float amount) {
- dampedOverScroll(amount);
- }
-
- /**
- * Used by the parent to get the content width to set the tab bar to
- * @return
- */
- public int getPageContentWidth() {
- return mContentWidth;
- }
-
- @Override
- protected void onPageEndMoving() {
- super.onPageEndMoving();
- mForceDrawAllChildrenNextFrame = true;
- // We reset the save index when we change pages so that it will be recalculated on next
- // rotation
- mSaveInstanceStateItemIndex = -1;
- }
-
- /*
- * AllAppsView implementation
- */
- public void setup(Launcher launcher, DragController dragController) {
- mLauncher = launcher;
- mDragController = dragController;
- }
-
- /**
- * We should call thise method whenever the core data changes (mApps, mWidgets) so that we can
- * appropriately determine when to invalidate the PagedView page data. In cases where the data
- * has yet to be set, we can requestLayout() and wait for onDataReady() to be called in the
- * next onMeasure() pass, which will trigger an invalidatePageData() itself.
- */
- private void invalidateOnDataChange() {
- if (!isDataReady()) {
- // The next layout pass will trigger data-ready if both widgets and apps are set, so
- // request a layout to trigger the page data when ready.
- requestLayout();
- } else {
- cancelAllTasks();
- invalidatePageData();
- }
- }
-
- public void setApps(ArrayList<AppInfo> list) {
- if (!LauncherAppState.isDisableAllApps()) {
- mApps = list;
- Collections.sort(mApps, LauncherModel.getAppNameComparator());
- updatePageCountsAndInvalidateData();
- }
- }
- private void addAppsWithoutInvalidate(ArrayList<AppInfo> list) {
- // We add it in place, in alphabetical order
- int count = list.size();
- for (int i = 0; i < count; ++i) {
- AppInfo info = list.get(i);
- int index = Collections.binarySearch(mApps, info, LauncherModel.getAppNameComparator());
- if (index < 0) {
- mApps.add(-(index + 1), info);
- }
- }
- }
- public void addApps(ArrayList<AppInfo> list) {
- if (!LauncherAppState.isDisableAllApps()) {
- addAppsWithoutInvalidate(list);
- updatePageCountsAndInvalidateData();
- }
- }
- private int findAppByComponent(List<AppInfo> list, AppInfo item) {
- ComponentName removeComponent = item.intent.getComponent();
- int length = list.size();
- for (int i = 0; i < length; ++i) {
- AppInfo info = list.get(i);
- if (info.user.equals(item.user)
- && info.intent.getComponent().equals(removeComponent)) {
- return i;
- }
- }
- return -1;
- }
- private void removeAppsWithoutInvalidate(ArrayList<AppInfo> list) {
- // loop through all the apps and remove apps that have the same component
- int length = list.size();
- for (int i = 0; i < length; ++i) {
- AppInfo info = list.get(i);
- int removeIndex = findAppByComponent(mApps, info);
- if (removeIndex > -1) {
- mApps.remove(removeIndex);
- }
- }
- }
- public void removeApps(ArrayList<AppInfo> appInfos) {
- if (!LauncherAppState.isDisableAllApps()) {
- removeAppsWithoutInvalidate(appInfos);
- updatePageCountsAndInvalidateData();
- }
- }
- public void updateApps(ArrayList<AppInfo> list) {
- // We remove and re-add the updated applications list because it's properties may have
- // changed (ie. the title), and this will ensure that the items will be in their proper
- // place in the list.
- if (!LauncherAppState.isDisableAllApps()) {
- removeAppsWithoutInvalidate(list);
- addAppsWithoutInvalidate(list);
- updatePageCountsAndInvalidateData();
- }
- }
-
- public void reset() {
- // If we have reset, then we should not continue to restore the previous state
- mSaveInstanceStateItemIndex = -1;
-
- if (mContentType != ContentType.Applications) {
- setContentType(ContentType.Applications);
- }
-
- if (mCurrentPage != 0) {
- invalidatePageData(0);
- }
- }
-
- private AppsCustomizeTabHost getTabHost() {
- return (AppsCustomizeTabHost) mLauncher.findViewById(R.id.apps_customize_pane);
- }
-
- public void dumpState() {
- // TODO: Dump information related to current list of Applications, Widgets, etc.
- AppInfo.dumpApplicationInfoList(TAG, "mApps", mApps);
- dumpAppWidgetProviderInfoList(TAG, "mWidgets", mWidgets);
- }
-
- private void dumpAppWidgetProviderInfoList(String tag, String label,
- ArrayList<Object> list) {
- Log.d(tag, label + " size=" + list.size());
- for (Object i: list) {
- if (i instanceof AppWidgetProviderInfo) {
- AppWidgetProviderInfo info = (AppWidgetProviderInfo) i;
- Log.d(tag, " label=\"" + info.label + "\" previewImage=" + info.previewImage
- + " resizeMode=" + info.resizeMode + " configure=" + info.configure
- + " initialLayout=" + info.initialLayout
- + " minWidth=" + info.minWidth + " minHeight=" + info.minHeight);
- } else if (i instanceof ResolveInfo) {
- ResolveInfo info = (ResolveInfo) i;
- Log.d(tag, " label=\"" + info.loadLabel(mPackageManager) + "\" icon="
- + info.icon);
- }
- }
- }
-
- public void surrender() {
- // TODO: If we are in the middle of any process (ie. for holographic outlines, etc) we
- // should stop this now.
-
- // Stop all background tasks
- cancelAllTasks();
- }
-
- /*
- * We load an extra page on each side to prevent flashes from scrolling and loading of the
- * widget previews in the background with the AsyncTasks.
- */
- final static int sLookBehindPageCount = 2;
- final static int sLookAheadPageCount = 2;
- protected int getAssociatedLowerPageBound(int page) {
- final int count = getChildCount();
- int windowSize = Math.min(count, sLookBehindPageCount + sLookAheadPageCount + 1);
- int windowMinIndex = Math.max(Math.min(page - sLookBehindPageCount, count - windowSize), 0);
- return windowMinIndex;
- }
- protected int getAssociatedUpperPageBound(int page) {
- final int count = getChildCount();
- int windowSize = Math.min(count, sLookBehindPageCount + sLookAheadPageCount + 1);
- int windowMaxIndex = Math.min(Math.max(page + sLookAheadPageCount, windowSize - 1),
- count - 1);
- return windowMaxIndex;
- }
-
- protected String getCurrentPageDescription() {
- int page = (mNextPage != INVALID_PAGE) ? mNextPage : mCurrentPage;
- int stringId = R.string.default_scroll_format;
- int count = 0;
-
- if (mContentType == ContentType.Applications) {
- stringId = R.string.apps_customize_apps_scroll_format;
- count = mNumAppsPages;
- } else if (mContentType == ContentType.Widgets) {
- stringId = R.string.apps_customize_widgets_scroll_format;
- count = mNumWidgetPages;
- } else {
- throw new RuntimeException("Invalid ContentType");
- }
-
- return String.format(getContext().getString(stringId), page + 1, count);
- }
-}
diff --git a/src/com/android/launcher3/AppsCustomizeTabHost.java b/src/com/android/launcher3/AppsCustomizeTabHost.java
deleted file mode 100644
index a2717126d..000000000
--- a/src/com/android/launcher3/AppsCustomizeTabHost.java
+++ /dev/null
@@ -1,220 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.launcher3;
-
-import android.content.Context;
-import android.graphics.Rect;
-import android.util.AttributeSet;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.accessibility.AccessibilityManager;
-import android.widget.FrameLayout;
-
-public class AppsCustomizeTabHost extends FrameLayout implements LauncherTransitionable, Insettable {
- static final String LOG_TAG = "AppsCustomizeTabHost";
-
- private static final String APPS_TAB_TAG = "APPS";
- private static final String WIDGETS_TAB_TAG = "WIDGETS";
-
- private AppsCustomizePagedView mPagedView;
- private View mContent;
- private boolean mInTransition = false;
-
- private final Rect mInsets = new Rect();
-
- public AppsCustomizeTabHost(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- /**
- * Convenience methods to select specific tabs. We want to set the content type immediately
- * in these cases, but we note that we still call setCurrentTabByTag() so that the tab view
- * reflects the new content (but doesn't do the animation and logic associated with changing
- * tabs manually).
- */
- void setContentTypeImmediate(AppsCustomizePagedView.ContentType type) {
- mPagedView.setContentType(type);
- }
-
- public void setCurrentTabFromContent(AppsCustomizePagedView.ContentType type) {
- setContentTypeImmediate(type);
- }
-
- @Override
- public void setInsets(Rect insets) {
- mInsets.set(insets);
- LayoutParams flp = (LayoutParams) mContent.getLayoutParams();
- flp.topMargin = insets.top;
- flp.bottomMargin = insets.bottom;
- flp.leftMargin = insets.left;
- flp.rightMargin = insets.right;
- mContent.setLayoutParams(flp);
- }
-
- /**
- * Setup the tab host and create all necessary tabs.
- */
- @Override
- protected void onFinishInflate() {
- mPagedView = (AppsCustomizePagedView) findViewById(R.id.apps_customize_pane_content);
- mContent = findViewById(R.id.content);
- }
-
- public String getContentTag() {
- return getTabTagForContentType(mPagedView.getContentType());
- }
-
- /**
- * Returns the content type for the specified tab tag.
- */
- public AppsCustomizePagedView.ContentType getContentTypeForTabTag(String tag) {
- if (tag.equals(APPS_TAB_TAG)) {
- return AppsCustomizePagedView.ContentType.Applications;
- } else if (tag.equals(WIDGETS_TAB_TAG)) {
- return AppsCustomizePagedView.ContentType.Widgets;
- }
- return AppsCustomizePagedView.ContentType.Applications;
- }
-
- /**
- * Returns the tab tag for a given content type.
- */
- public String getTabTagForContentType(AppsCustomizePagedView.ContentType type) {
- if (type == AppsCustomizePagedView.ContentType.Applications) {
- return APPS_TAB_TAG;
- } else if (type == AppsCustomizePagedView.ContentType.Widgets) {
- return WIDGETS_TAB_TAG;
- }
- return APPS_TAB_TAG;
- }
-
- /**
- * Disable focus on anything under this view in the hierarchy if we are not visible.
- */
- @Override
- public int getDescendantFocusability() {
- if (getVisibility() != View.VISIBLE) {
- return ViewGroup.FOCUS_BLOCK_DESCENDANTS;
- }
- return super.getDescendantFocusability();
- }
-
- void reset() {
- // Reset immediately
- mPagedView.reset();
- }
-
- void trimMemory() {
- mPagedView.trimMemory();
- }
-
- public void onWindowVisible() {
- if (getVisibility() == VISIBLE) {
- mContent.setVisibility(VISIBLE);
- // We unload the widget previews when the UI is hidden, so need to reload pages
- // Load the current page synchronously, and the neighboring pages asynchronously
- mPagedView.loadAssociatedPages(mPagedView.getCurrentPage(), true);
- mPagedView.loadAssociatedPages(mPagedView.getCurrentPage());
- }
- }
- @Override
- public ViewGroup getContent() {
- return mPagedView;
- }
-
- public boolean isInTransition() {
- return mInTransition;
- }
-
- /* LauncherTransitionable overrides */
- @Override
- public void onLauncherTransitionPrepare(Launcher l, boolean animated, boolean toWorkspace) {
- mPagedView.onLauncherTransitionPrepare(l, animated, toWorkspace);
- mInTransition = true;
-
- if (toWorkspace) {
- // Going from All Apps -> Workspace
- setVisibilityOfSiblingsWithLowerZOrder(VISIBLE);
- } else {
- // Going from Workspace -> All Apps
- mContent.setVisibility(VISIBLE);
-
- // Make sure the current page is loaded (we start loading the side pages after the
- // transition to prevent slowing down the animation)
- // TODO: revisit this
- mPagedView.loadAssociatedPages(mPagedView.getCurrentPage());
- }
- }
-
- @Override
- public void onLauncherTransitionStart(Launcher l, boolean animated, boolean toWorkspace) {
- mPagedView.onLauncherTransitionStart(l, animated, toWorkspace);
- }
-
- @Override
- public void onLauncherTransitionStep(Launcher l, float t) {
- mPagedView.onLauncherTransitionStep(l, t);
- }
-
- @Override
- public void onLauncherTransitionEnd(Launcher l, boolean animated, boolean toWorkspace) {
- mPagedView.onLauncherTransitionEnd(l, animated, toWorkspace);
- mInTransition = false;
-
- if (!toWorkspace) {
- // Make sure adjacent pages are loaded (we wait until after the transition to
- // prevent slowing down the animation)
- mPagedView.loadAssociatedPages(mPagedView.getCurrentPage());
-
- // Opening apps, need to announce what page we are on.
- AccessibilityManager am = (AccessibilityManager)
- getContext().getSystemService(Context.ACCESSIBILITY_SERVICE);
- if (am.isEnabled()) {
- // Notify the user when the page changes
- announceForAccessibility(mPagedView.getCurrentPageDescription());
- }
-
- // Going from Workspace -> All Apps
- // NOTE: We should do this at the end since we check visibility state in some of the
- // cling initialization/dismiss code above.
- setVisibilityOfSiblingsWithLowerZOrder(INVISIBLE);
- }
- }
-
- private void setVisibilityOfSiblingsWithLowerZOrder(int visibility) {
- ViewGroup parent = (ViewGroup) getParent();
- if (parent == null) return;
-
- View overviewPanel = ((Launcher) getContext()).getOverviewPanel();
- final int count = parent.getChildCount();
- if (!isChildrenDrawingOrderEnabled()) {
- for (int i = 0; i < count; i++) {
- final View child = parent.getChildAt(i);
- if (child == this) {
- break;
- } else {
- if (child.getVisibility() == GONE || child == overviewPanel) {
- continue;
- }
- child.setVisibility(visibility);
- }
- }
- } else {
- throw new RuntimeException("Failed; can't get z-order of views");
- }
- }
-}
diff --git a/src/com/android/launcher3/AutoInstallsLayout.java b/src/com/android/launcher3/AutoInstallsLayout.java
index a5d22286d..99a98ddac 100644
--- a/src/com/android/launcher3/AutoInstallsLayout.java
+++ b/src/com/android/launcher3/AutoInstallsLayout.java
@@ -37,6 +37,7 @@ import android.util.Patterns;
import com.android.launcher3.LauncherProvider.SqlArguments;
import com.android.launcher3.LauncherSettings.Favorites;
+import com.android.launcher3.util.Thunk;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -44,6 +45,7 @@ import org.xmlpull.v1.XmlPullParserException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
+import java.util.Locale;
/**
* Layout parsing code for auto installs layout
@@ -56,6 +58,11 @@ public class AutoInstallsLayout {
static final String ACTION_LAUNCHER_CUSTOMIZATION =
"android.autoinstalls.config.action.PLAY_AUTO_INSTALL";
+ /**
+ * Layout resource which also includes grid size and hotseat count, e.g., default_layout_6x6_h5
+ */
+ private static final String FORMATTED_LAYOUT_RES_WITH_HOSTEAT = "default_layout_%dx%d_h%s";
+ private static final String FORMATTED_LAYOUT_RES = "default_layout_%dx%d";
private static final String LAYOUT_RES = "default_layout";
static AutoInstallsLayout get(Context context, AppWidgetHost appWidgetHost,
@@ -65,19 +72,44 @@ public class AutoInstallsLayout {
if (customizationApkInfo == null) {
return null;
}
+ return get(context, customizationApkInfo.first, customizationApkInfo.second,
+ appWidgetHost, callback);
+ }
+
+ static AutoInstallsLayout get(Context context, String pkg, Resources targetRes,
+ AppWidgetHost appWidgetHost, LayoutParserCallback callback) {
+ InvariantDeviceProfile grid = LauncherAppState.getInstance().getInvariantDeviceProfile();
+
+ // Try with grid size and hotseat count
+ String layoutName = String.format(Locale.ENGLISH, FORMATTED_LAYOUT_RES_WITH_HOSTEAT,
+ (int) grid.numColumns, (int) grid.numRows, (int) grid.numHotseatIcons);
+ int layoutId = targetRes.getIdentifier(layoutName, "xml", pkg);
+
+ // Try with only grid size
+ if (layoutId == 0) {
+ Log.d(TAG, "Formatted layout: " + layoutName
+ + " not found. Trying layout without hosteat");
+ layoutName = String.format(Locale.ENGLISH, FORMATTED_LAYOUT_RES,
+ (int) grid.numColumns, (int) grid.numRows);
+ layoutId = targetRes.getIdentifier(layoutName, "xml", pkg);
+ }
+
+ // Try the default layout
+ if (layoutId == 0) {
+ Log.d(TAG, "Formatted layout: " + layoutName + " not found. Trying the default layout");
+ layoutId = targetRes.getIdentifier(LAYOUT_RES, "xml", pkg);
+ }
- String pkg = customizationApkInfo.first;
- Resources res = customizationApkInfo.second;
- int layoutId = res.getIdentifier(LAYOUT_RES, "xml", pkg);
if (layoutId == 0) {
Log.e(TAG, "Layout definition not found in package: " + pkg);
return null;
}
- return new AutoInstallsLayout(context, appWidgetHost, callback, res, layoutId,
+ return new AutoInstallsLayout(context, appWidgetHost, callback, targetRes, layoutId,
TAG_WORKSPACE);
}
// Object Tags
+ private static final String TAG_INCLUDE = "include";
private static final String TAG_WORKSPACE = "workspace";
private static final String TAG_APP_ICON = "appicon";
private static final String TAG_AUTO_INSTALL = "autoinstall";
@@ -100,6 +132,9 @@ public class AutoInstallsLayout {
private static final String ATTR_ICON = "icon";
private static final String ATTR_URL = "url";
+ // Attrs for "Include"
+ private static final String ATTR_WORKSPACE = "workspace";
+
// Style attrs -- "Extra"
private static final String ATTR_KEY = "key";
private static final String ATTR_VALUE = "value";
@@ -110,9 +145,9 @@ public class AutoInstallsLayout {
private static final String ACTION_APPWIDGET_DEFAULT_WORKSPACE_CONFIGURE =
"com.android.launcher.action.APPWIDGET_DEFAULT_WORKSPACE_CONFIGURE";
- private final Context mContext;
- private final AppWidgetHost mAppWidgetHost;
- private final LayoutParserCallback mCallback;
+ @Thunk final Context mContext;
+ @Thunk final AppWidgetHost mAppWidgetHost;
+ protected final LayoutParserCallback mCallback;
protected final PackageManager mPackageManager;
protected final Resources mSourceRes;
@@ -121,14 +156,21 @@ public class AutoInstallsLayout {
private final int mHotseatAllAppsRank;
private final long[] mTemp = new long[2];
- private final ContentValues mValues;
- private final String mRootTag;
+ @Thunk final ContentValues mValues;
+ protected final String mRootTag;
protected SQLiteDatabase mDb;
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;
@@ -139,8 +181,7 @@ public class AutoInstallsLayout {
mSourceRes = res;
mLayoutId = layoutId;
- mHotseatAllAppsRank = LauncherAppState.getInstance()
- .getDynamicGrid().getDeviceProfile().hotseatAllAppsRank;
+ mHotseatAllAppsRank = hotseatAllAppsRank;
}
/**
@@ -202,6 +243,17 @@ public class AutoInstallsLayout {
HashMap<String, TagParser> tagParserMap,
ArrayList<Long> screenIds)
throws XmlPullParserException, IOException {
+
+ if (TAG_INCLUDE.equals(parser.getName())) {
+ final int resId = getAttributeResourceValue(parser, ATTR_WORKSPACE, 0);
+ if (resId != 0) {
+ // recursively load some more favorites, why not?
+ return parseLayout(resId, screenIds);
+ } else {
+ return 0;
+ }
+ }
+
mValues.clear();
parseContainerAndScreen(parser, mTemp);
final long container = mTemp[0];
@@ -528,6 +580,7 @@ public class AutoInstallsLayout {
int type;
int folderDepth = parser.getDepth();
+ int rank = 0;
while ((type = parser.next()) != XmlPullParser.END_TAG ||
parser.getDepth() > folderDepth) {
if (type != XmlPullParser.START_TAG) {
@@ -535,12 +588,14 @@ public class AutoInstallsLayout {
}
mValues.clear();
mValues.put(Favorites.CONTAINER, folderId);
+ mValues.put(Favorites.RANK, rank);
TagParser tagParser = mFolderElements.get(parser.getName());
if (tagParser != null) {
final long id = tagParser.parseAndAdd(parser);
if (id >= 0) {
folderItems.add(id);
+ rank++;
}
} else {
throw new RuntimeException("Invalid folder item " + parser.getName());
@@ -554,7 +609,7 @@ public class AutoInstallsLayout {
// failed to add, and less than 2 were actually added
if (folderItems.size() < 2) {
// Delete the folder
- Uri uri = Favorites.getContentUri(folderId, false);
+ Uri uri = Favorites.getContentUri(folderId);
SqlArguments args = new SqlArguments(uri, null, null);
mDb.delete(args.table, args.where, args.args);
addedId = -1;
@@ -627,7 +682,7 @@ public class AutoInstallsLayout {
long insertAndCheck(SQLiteDatabase db, ContentValues values);
}
- private static void copyInteger(ContentValues from, ContentValues to, String key) {
+ @Thunk static void copyInteger(ContentValues from, ContentValues to, String key) {
to.put(key, from.getAsInteger(key));
}
}
diff --git a/src/com/android/launcher3/BaseContainerView.java b/src/com/android/launcher3/BaseContainerView.java
new file mode 100644
index 000000000..c8de9df10
--- /dev/null
+++ b/src/com/android/launcher3/BaseContainerView.java
@@ -0,0 +1,137 @@
+/*
+ * 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;
+
+import android.content.Context;
+import android.graphics.Rect;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.widget.LinearLayout;
+
+/**
+ * A base container view, which supports resizing.
+ */
+public abstract class BaseContainerView extends LinearLayout implements Insettable {
+
+ private final static String TAG = "BaseContainerView";
+
+ // The window insets
+ private Rect mInsets = new Rect();
+ // The bounds of the search bar. Only the left, top, right are used to inset the
+ // search bar and the height is determined by the measurement of the layout
+ private Rect mFixedSearchBarBounds = new Rect();
+ // The bounds of the container
+ protected Rect mContentBounds = new Rect();
+ // The padding to apply to the container to achieve the bounds
+ protected Rect mContentPadding = new Rect();
+ // The inset to apply to the edges and between the search bar and the container
+ private int mContainerBoundsInset;
+ private boolean mHasSearchBar;
+
+ public BaseContainerView(Context context) {
+ this(context, null);
+ }
+
+ public BaseContainerView(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public BaseContainerView(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ mContainerBoundsInset = getResources().getDimensionPixelSize(R.dimen.container_bounds_inset);
+ }
+
+ @Override
+ final public void setInsets(Rect insets) {
+ mInsets.set(insets);
+ updateBackgroundAndPaddings();
+ }
+
+ protected void setHasSearchBar() {
+ mHasSearchBar = true;
+ }
+
+ /**
+ * Sets the search bar bounds for this container view to match.
+ */
+ final public void setSearchBarBounds(Rect bounds) {
+ if (LauncherAppState.isDogfoodBuild() && !isValidSearchBarBounds(bounds)) {
+ Log.e(TAG, "Invalid search bar bounds: " + bounds);
+ }
+
+ mFixedSearchBarBounds.set(bounds);
+
+ // Post the updates since they can trigger a relayout, and this call can be triggered from
+ // a layout pass itself.
+ post(new Runnable() {
+ @Override
+ public void run() {
+ updateBackgroundAndPaddings();
+ }
+ });
+ }
+
+ /**
+ * Update the backgrounds and padding in response to a change in the bounds or insets.
+ */
+ protected void updateBackgroundAndPaddings() {
+ Rect padding;
+ Rect searchBarBounds = new Rect(mFixedSearchBarBounds);
+ if (!isValidSearchBarBounds(mFixedSearchBarBounds)) {
+ // Use the default bounds
+ padding = new Rect(mInsets.left + mContainerBoundsInset,
+ (mHasSearchBar ? 0 : (mInsets.top + mContainerBoundsInset)),
+ mInsets.right + mContainerBoundsInset,
+ mInsets.bottom + mContainerBoundsInset);
+
+ // Special case -- we have the search bar, but no specific bounds, so just give it
+ // the inset bounds without a height.
+ searchBarBounds.set(mInsets.left + mContainerBoundsInset,
+ mInsets.top + mContainerBoundsInset,
+ getMeasuredWidth() - (mInsets.right + mContainerBoundsInset), 0);
+ } else {
+ // Use the search bounds, if there is a search bar, the bounds will contain
+ // the offsets for the insets so we can ignore that
+ padding = new Rect(mFixedSearchBarBounds.left,
+ (mHasSearchBar ? 0 : (mInsets.top + mContainerBoundsInset)),
+ getMeasuredWidth() - mFixedSearchBarBounds.right,
+ mInsets.bottom + mContainerBoundsInset);
+ }
+ if (!padding.equals(mContentPadding) || !searchBarBounds.equals(mFixedSearchBarBounds)) {
+ mContentPadding.set(padding);
+ mContentBounds.set(padding.left, padding.top,
+ getMeasuredWidth() - padding.right,
+ getMeasuredHeight() - padding.bottom);
+ mFixedSearchBarBounds.set(searchBarBounds);
+ onUpdateBackgroundAndPaddings(mFixedSearchBarBounds, padding);
+ }
+ }
+
+ /**
+ * To be implemented by container views to update themselves when the bounds changes.
+ */
+ protected abstract void onUpdateBackgroundAndPaddings(Rect searchBarBounds, Rect padding);
+
+ /**
+ * Returns whether the search bar bounds we got are considered valid.
+ */
+ private boolean isValidSearchBarBounds(Rect searchBarBounds) {
+ return !searchBarBounds.isEmpty() &&
+ searchBarBounds.right <= getMeasuredWidth() &&
+ searchBarBounds.bottom <= getMeasuredHeight();
+ }
+} \ No newline at end of file
diff --git a/src/com/android/launcher3/BaseRecyclerView.java b/src/com/android/launcher3/BaseRecyclerView.java
new file mode 100644
index 000000000..0fae427e8
--- /dev/null
+++ b/src/com/android/launcher3/BaseRecyclerView.java
@@ -0,0 +1,285 @@
+/*
+ * 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;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Rect;
+import android.support.v7.widget.RecyclerView;
+import android.util.AttributeSet;
+import android.view.MotionEvent;
+import com.android.launcher3.util.Thunk;
+
+
+/**
+ * A base {@link RecyclerView}, which does the following:
+ * <ul>
+ * <li> NOT intercept a touch unless the scrolling velocity is below a predefined threshold.
+ * <li> Enable fast scroller.
+ * </ul>
+ */
+public abstract class BaseRecyclerView extends RecyclerView
+ implements RecyclerView.OnItemTouchListener {
+
+ private static final int SCROLL_DELTA_THRESHOLD_DP = 4;
+
+ /** Keeps the last known scrolling delta/velocity along y-axis. */
+ @Thunk int mDy = 0;
+ private float mDeltaThreshold;
+
+ /**
+ * The current scroll state of the recycler view. We use this in onUpdateScrollbar()
+ * and scrollToPositionAtProgress() to determine the scroll position of the recycler view so
+ * that we can calculate what the scroll bar looks like, and where to jump to from the fast
+ * scroller.
+ */
+ public static class ScrollPositionState {
+ // The index of the first visible row
+ 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;
+ }
+
+ protected BaseRecyclerViewFastScrollBar mScrollbar;
+
+ private int mDownX;
+ private int mDownY;
+ private int mLastY;
+ protected Rect mBackgroundPadding = new Rect();
+
+ public BaseRecyclerView(Context context) {
+ this(context, null);
+ }
+
+ public BaseRecyclerView(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public BaseRecyclerView(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ mDeltaThreshold = getResources().getDisplayMetrics().density * SCROLL_DELTA_THRESHOLD_DP;
+ mScrollbar = new BaseRecyclerViewFastScrollBar(this, getResources());
+
+ ScrollListener listener = new ScrollListener();
+ setOnScrollListener(listener);
+ }
+
+ private class ScrollListener extends OnScrollListener {
+ public ScrollListener() {
+ // Do nothing
+ }
+
+ @Override
+ public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
+ mDy = dy;
+
+ // TODO(winsonc): If we want to animate the section heads while scrolling, we can
+ // initiate that here if the recycler view scroll state is not
+ // RecyclerView.SCROLL_STATE_IDLE.
+ }
+ }
+
+ @Override
+ protected void onFinishInflate() {
+ super.onFinishInflate();
+ addOnItemTouchListener(this);
+ }
+
+ /**
+ * We intercept the touch handling only to support fast scrolling when initiated from the
+ * scroll bar. Otherwise, we fall back to the default RecyclerView touch handling.
+ */
+ @Override
+ public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent ev) {
+ return handleTouchEvent(ev);
+ }
+
+ @Override
+ public void onTouchEvent(RecyclerView rv, MotionEvent ev) {
+ handleTouchEvent(ev);
+ }
+
+ /**
+ * Handles the touch event and determines whether to show the fast scroller (or updates it if
+ * it is already showing).
+ */
+ private boolean handleTouchEvent(MotionEvent ev) {
+ int action = ev.getAction();
+ int x = (int) ev.getX();
+ int y = (int) ev.getY();
+ switch (action) {
+ case MotionEvent.ACTION_DOWN:
+ // Keep track of the down positions
+ mDownX = x;
+ mDownY = mLastY = y;
+ if (shouldStopScroll(ev)) {
+ stopScroll();
+ }
+ mScrollbar.handleTouchEvent(ev, mDownX, mDownY, mLastY);
+ break;
+ case MotionEvent.ACTION_MOVE:
+ mLastY = y;
+ mScrollbar.handleTouchEvent(ev, mDownX, mDownY, mLastY);
+ break;
+ case MotionEvent.ACTION_UP:
+ case MotionEvent.ACTION_CANCEL:
+ onFastScrollCompleted();
+ mScrollbar.handleTouchEvent(ev, mDownX, mDownY, mLastY);
+ break;
+ }
+ return mScrollbar.isDragging();
+ }
+
+ public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {
+ // DO NOT REMOVE, NEEDED IMPLEMENTATION FOR M BUILDS
+ }
+
+ /**
+ * Returns whether this {@link MotionEvent} should trigger the scroll to be stopped.
+ */
+ protected boolean shouldStopScroll(MotionEvent ev) {
+ if (ev.getAction() == MotionEvent.ACTION_DOWN) {
+ if ((Math.abs(mDy) < mDeltaThreshold &&
+ getScrollState() != RecyclerView.SCROLL_STATE_IDLE)) {
+ // now the touch events are being passed to the {@link WidgetCell} until the
+ // touch sequence goes over the touch slop.
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public void updateBackgroundPadding(Rect padding) {
+ mBackgroundPadding.set(padding);
+ }
+
+ public Rect getBackgroundPadding() {
+ return mBackgroundPadding;
+ }
+
+ /**
+ * Returns the scroll bar width when the user is scrolling.
+ */
+ public int getMaxScrollbarWidth() {
+ return mScrollbar.getThumbMaxWidth();
+ }
+
+ /**
+ * Returns the available scroll height:
+ * AvailableScrollHeight = Total height of the all items - last page height
+ *
+ * This assumes that all rows are the same height.
+ *
+ * @param yOffset the offset from the top of the recycler view to start tracking.
+ */
+ protected int getAvailableScrollHeight(int rowCount, int rowHeight, int yOffset) {
+ int visibleHeight = getHeight() - mBackgroundPadding.top - mBackgroundPadding.bottom;
+ int scrollHeight = getPaddingTop() + yOffset + rowCount * rowHeight + getPaddingBottom();
+ int availableScrollHeight = scrollHeight - visibleHeight;
+ return availableScrollHeight;
+ }
+
+ /**
+ * Returns the available scroll bar height:
+ * AvailableScrollBarHeight = Total height of the visible view - thumb height
+ */
+ protected int getAvailableScrollBarHeight() {
+ int visibleHeight = getHeight() - mBackgroundPadding.top - mBackgroundPadding.bottom;
+ int availableScrollBarHeight = visibleHeight - mScrollbar.getThumbHeight();
+ return availableScrollBarHeight;
+ }
+
+ /**
+ * Returns the track color (ignoring alpha), can be overridden by each subclass.
+ */
+ public int getFastScrollerTrackColor(int defaultTrackColor) {
+ return defaultTrackColor;
+ }
+
+ /**
+ * Returns the inactive thumb color, can be overridden by each subclass.
+ */
+ public int getFastScrollerThumbInactiveColor(int defaultInactiveThumbColor) {
+ return defaultInactiveThumbColor;
+ }
+
+ @Override
+ protected void dispatchDraw(Canvas canvas) {
+ super.dispatchDraw(canvas);
+ onUpdateScrollbar();
+ mScrollbar.draw(canvas);
+ }
+
+ /**
+ * Updates the scrollbar thumb offset to match the visible scroll of the recycler view. It does
+ * this by mapping the available scroll area of the recycler view to the available space for the
+ * scroll bar.
+ *
+ * @param scrollPosState the current scroll position
+ * @param rowCount the number of rows, used to calculate the total scroll height (assumes that
+ * all rows are the same height)
+ * @param yOffset the offset to start tracking in the recycler view (only used for all apps)
+ */
+ protected void synchronizeScrollBarThumbOffsetToViewScroll(ScrollPositionState scrollPosState,
+ int rowCount, int yOffset) {
+ int availableScrollHeight = getAvailableScrollHeight(rowCount, scrollPosState.rowHeight,
+ yOffset);
+ int availableScrollBarHeight = getAvailableScrollBarHeight();
+
+ // Only show the scrollbar if there is height to be scrolled
+ if (availableScrollHeight <= 0) {
+ mScrollbar.setScrollbarThumbOffset(-1, -1);
+ return;
+ }
+
+ // 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() + yOffset +
+ (scrollPosState.rowIndex * scrollPosState.rowHeight) - scrollPosState.rowTopOffset;
+ int scrollBarY = mBackgroundPadding.top +
+ (int) (((float) scrollY / availableScrollHeight) * availableScrollBarHeight);
+
+ // Calculate the position and size of the scroll bar
+ int scrollBarX;
+ if (Utilities.isRtl(getResources())) {
+ scrollBarX = mBackgroundPadding.left;
+ } else {
+ scrollBarX = getWidth() - mBackgroundPadding.right - mScrollbar.getWidth();
+ }
+ mScrollbar.setScrollbarThumbOffset(scrollBarX, scrollBarY);
+ }
+
+ /**
+ * 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);
+
+ /**
+ * Updates the bounds for the scrollbar.
+ * <p>Override in each subclass of this base class.
+ */
+ public abstract void onUpdateScrollbar();
+
+ /**
+ * <p>Override in each subclass of this base class.
+ */
+ public void onFastScrollCompleted() {}
+} \ No newline at end of file
diff --git a/src/com/android/launcher3/BaseRecyclerViewFastScrollBar.java b/src/com/android/launcher3/BaseRecyclerViewFastScrollBar.java
new file mode 100644
index 000000000..2c4184dc4
--- /dev/null
+++ b/src/com/android/launcher3/BaseRecyclerViewFastScrollBar.java
@@ -0,0 +1,235 @@
+/*
+ * 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;
+
+import android.animation.AnimatorSet;
+import android.animation.ArgbEvaluator;
+import android.animation.ObjectAnimator;
+import android.animation.ValueAnimator;
+import android.content.res.Resources;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.Point;
+import android.graphics.Rect;
+import android.view.MotionEvent;
+import android.view.ViewConfiguration;
+
+import com.android.launcher3.util.Thunk;
+
+/**
+ * The track and scrollbar that shows when you scroll the list.
+ */
+public class BaseRecyclerViewFastScrollBar {
+
+ public interface FastScrollFocusableView {
+ void setFastScrollFocused(boolean focused, boolean animated);
+ }
+
+ private final static int MAX_TRACK_ALPHA = 30;
+ private final static int SCROLL_BAR_VIS_DURATION = 150;
+
+ @Thunk BaseRecyclerView mRv;
+ private BaseRecyclerViewFastScrollPopup mPopup;
+
+ private AnimatorSet mScrollbarAnimator;
+
+ private int mThumbInactiveColor;
+ private int mThumbActiveColor;
+ @Thunk Point mThumbOffset = new Point(-1, -1);
+ @Thunk Paint mThumbPaint;
+ private Paint mTrackPaint;
+ private int mThumbMinWidth;
+ private int mThumbMaxWidth;
+ @Thunk int mThumbWidth;
+ @Thunk int mThumbHeight;
+ // The inset is the buffer around which a point will still register as a click on the scrollbar
+ private int mTouchInset;
+ private boolean mIsDragging;
+
+ // This is the offset from the top of the scrollbar when the user first starts touching. To
+ // prevent jumping, this offset is applied as the user scrolls.
+ private int mTouchOffset;
+
+ private Rect mInvalidateRect = new Rect();
+ private Rect mTmpRect = new Rect();
+
+ public BaseRecyclerViewFastScrollBar(BaseRecyclerView rv, Resources res) {
+ mRv = rv;
+ mPopup = new BaseRecyclerViewFastScrollPopup(rv, res);
+ mTrackPaint = new Paint();
+ mTrackPaint.setColor(rv.getFastScrollerTrackColor(Color.BLACK));
+ mTrackPaint.setAlpha(0);
+ mThumbInactiveColor = rv.getFastScrollerThumbInactiveColor(
+ res.getColor(R.color.container_fastscroll_thumb_inactive_color));
+ mThumbActiveColor = res.getColor(R.color.container_fastscroll_thumb_active_color);
+ mThumbPaint = new Paint();
+ mThumbPaint.setColor(mThumbInactiveColor);
+ mThumbWidth = mThumbMinWidth = res.getDimensionPixelSize(R.dimen.container_fastscroll_thumb_min_width);
+ mThumbMaxWidth = res.getDimensionPixelSize(R.dimen.container_fastscroll_thumb_max_width);
+ mThumbHeight = res.getDimensionPixelSize(R.dimen.container_fastscroll_thumb_height);
+ mTouchInset = res.getDimensionPixelSize(R.dimen.container_fastscroll_thumb_touch_inset);
+ }
+
+ public void setScrollbarThumbOffset(int x, int y) {
+ if (mThumbOffset.x == x && mThumbOffset.y == y) {
+ return;
+ }
+ mInvalidateRect.set(mThumbOffset.x, 0, mThumbOffset.x + mThumbWidth, mRv.getHeight());
+ mThumbOffset.set(x, y);
+ mInvalidateRect.union(new Rect(mThumbOffset.x, 0, mThumbOffset.x + mThumbWidth,
+ mRv.getHeight()));
+ mRv.invalidate(mInvalidateRect);
+ }
+
+ // Setter/getter for the search bar width for animations
+ public void setWidth(int width) {
+ mInvalidateRect.set(mThumbOffset.x, 0, mThumbOffset.x + mThumbWidth, mRv.getHeight());
+ mThumbWidth = width;
+ mInvalidateRect.union(new Rect(mThumbOffset.x, 0, mThumbOffset.x + mThumbWidth,
+ mRv.getHeight()));
+ mRv.invalidate(mInvalidateRect);
+ }
+
+ public int getWidth() {
+ return mThumbWidth;
+ }
+
+ // Setter/getter for the track background alpha for animations
+ public void setTrackAlpha(int alpha) {
+ mTrackPaint.setAlpha(alpha);
+ mInvalidateRect.set(mThumbOffset.x, 0, mThumbOffset.x + mThumbWidth, mRv.getHeight());
+ mRv.invalidate(mInvalidateRect);
+ }
+
+ public int getTrackAlpha() {
+ return mTrackPaint.getAlpha();
+ }
+
+ public int getThumbHeight() {
+ return mThumbHeight;
+ }
+
+ public int getThumbMaxWidth() {
+ return mThumbMaxWidth;
+ }
+
+ public boolean isDragging() {
+ return mIsDragging;
+ }
+
+ /**
+ * Handles the touch event and determines whether to show the fast scroller (or updates it if
+ * it is already showing).
+ */
+ public void handleTouchEvent(MotionEvent ev, int downX, int downY, int lastY) {
+ ViewConfiguration config = ViewConfiguration.get(mRv.getContext());
+
+ int action = ev.getAction();
+ int y = (int) ev.getY();
+ switch (action) {
+ case MotionEvent.ACTION_DOWN:
+ if (isNearPoint(downX, downY)) {
+ mTouchOffset = downY - mThumbOffset.y;
+ }
+ break;
+ case MotionEvent.ACTION_MOVE:
+ // Check if we should start scrolling
+ if (!mIsDragging && isNearPoint(downX, downY) &&
+ Math.abs(y - downY) > config.getScaledTouchSlop()) {
+ mRv.getParent().requestDisallowInterceptTouchEvent(true);
+ mIsDragging = true;
+ mTouchOffset += (lastY - downY);
+ mPopup.animateVisibility(true);
+ animateScrollbar(true);
+ }
+ if (mIsDragging) {
+ // Update the fastscroller section name at this touch position
+ int top = mRv.getBackgroundPadding().top;
+ int bottom = mRv.getHeight() - mRv.getBackgroundPadding().bottom - mThumbHeight;
+ float boundedY = (float) Math.max(top, Math.min(bottom, y - mTouchOffset));
+ String sectionName = mRv.scrollToPositionAtProgress((boundedY - top) /
+ (bottom - top));
+ mPopup.setSectionName(sectionName);
+ mPopup.animateVisibility(!sectionName.isEmpty());
+ mRv.invalidate(mPopup.updateFastScrollerBounds(mRv, lastY));
+ }
+ break;
+ case MotionEvent.ACTION_UP:
+ case MotionEvent.ACTION_CANCEL:
+ mTouchOffset = 0;
+ if (mIsDragging) {
+ mIsDragging = false;
+ mPopup.animateVisibility(false);
+ animateScrollbar(false);
+ }
+ break;
+ }
+ }
+
+ public void draw(Canvas canvas) {
+ if (mThumbOffset.x < 0 || mThumbOffset.y < 0) {
+ return;
+ }
+
+ // Draw the scroll bar track and thumb
+ if (mTrackPaint.getAlpha() > 0) {
+ canvas.drawRect(mThumbOffset.x, 0, mThumbOffset.x + mThumbWidth, mRv.getHeight(), mTrackPaint);
+ }
+ canvas.drawRect(mThumbOffset.x, mThumbOffset.y, mThumbOffset.x + mThumbWidth,
+ mThumbOffset.y + mThumbHeight, mThumbPaint);
+
+ // Draw the popup
+ mPopup.draw(canvas);
+ }
+
+ /**
+ * Animates the width and color of the scrollbar.
+ */
+ private void animateScrollbar(boolean isScrolling) {
+ if (mScrollbarAnimator != null) {
+ mScrollbarAnimator.cancel();
+ }
+ ObjectAnimator trackAlphaAnim = ObjectAnimator.ofInt(this, "trackAlpha",
+ isScrolling ? MAX_TRACK_ALPHA : 0);
+ ObjectAnimator thumbWidthAnim = ObjectAnimator.ofInt(this, "width",
+ isScrolling ? mThumbMaxWidth : mThumbMinWidth);
+ ValueAnimator colorAnimation = ValueAnimator.ofObject(new ArgbEvaluator(),
+ mThumbPaint.getColor(), isScrolling ? mThumbActiveColor : mThumbInactiveColor);
+ colorAnimation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+ @Override
+ public void onAnimationUpdate(ValueAnimator animator) {
+ mThumbPaint.setColor((Integer) animator.getAnimatedValue());
+ mRv.invalidate(mThumbOffset.x, mThumbOffset.y, mThumbOffset.x + mThumbWidth,
+ mThumbOffset.y + mThumbHeight);
+ }
+ });
+ mScrollbarAnimator = new AnimatorSet();
+ mScrollbarAnimator.playTogether(trackAlphaAnim, thumbWidthAnim, colorAnimation);
+ mScrollbarAnimator.setDuration(SCROLL_BAR_VIS_DURATION);
+ mScrollbarAnimator.start();
+ }
+
+ /**
+ * Returns whether the specified points are near the scroll bar bounds.
+ */
+ private boolean isNearPoint(int x, int y) {
+ mTmpRect.set(mThumbOffset.x, mThumbOffset.y, mThumbOffset.x + mThumbWidth,
+ mThumbOffset.y + mThumbHeight);
+ mTmpRect.inset(mTouchInset, mTouchInset);
+ return mTmpRect.contains(x, y);
+ }
+}
diff --git a/src/com/android/launcher3/BaseRecyclerViewFastScrollPopup.java b/src/com/android/launcher3/BaseRecyclerViewFastScrollPopup.java
new file mode 100644
index 000000000..aeeb5156d
--- /dev/null
+++ b/src/com/android/launcher3/BaseRecyclerViewFastScrollPopup.java
@@ -0,0 +1,160 @@
+/*
+ * 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;
+
+import android.animation.Animator;
+import android.animation.ObjectAnimator;
+import android.content.res.Resources;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+
+/**
+ * The fast scroller popup that shows the section name the list will jump to.
+ */
+public class BaseRecyclerViewFastScrollPopup {
+
+ private static final float FAST_SCROLL_OVERLAY_Y_OFFSET_FACTOR = 1.5f;
+
+ private Resources mRes;
+ private BaseRecyclerView mRv;
+
+ private Drawable mBg;
+ // The absolute bounds of the fast scroller bg
+ private Rect mBgBounds = new Rect();
+ private int mBgOriginalSize;
+ private Rect mInvalidateRect = new Rect();
+ private Rect mTmpRect = new Rect();
+
+ private String mSectionName;
+ private Paint mTextPaint;
+ private Rect mTextBounds = new Rect();
+ private float mAlpha;
+
+ private Animator mAlphaAnimator;
+ private boolean mVisible;
+
+ public BaseRecyclerViewFastScrollPopup(BaseRecyclerView rv, Resources res) {
+ mRes = res;
+ mRv = rv;
+ mBgOriginalSize = res.getDimensionPixelSize(R.dimen.container_fastscroll_popup_size);
+ mBg = res.getDrawable(R.drawable.container_fastscroll_popup_bg);
+ mBg.setBounds(0, 0, mBgOriginalSize, mBgOriginalSize);
+ mTextPaint = new Paint();
+ mTextPaint.setColor(Color.WHITE);
+ mTextPaint.setAntiAlias(true);
+ mTextPaint.setTextSize(res.getDimensionPixelSize(R.dimen.container_fastscroll_popup_text_size));
+ }
+
+ /**
+ * Sets the section name.
+ */
+ public void setSectionName(String sectionName) {
+ if (!sectionName.equals(mSectionName)) {
+ mSectionName = sectionName;
+ mTextPaint.getTextBounds(sectionName, 0, sectionName.length(), mTextBounds);
+ // Update the width to use measureText since that is more accurate
+ mTextBounds.right = (int) (mTextBounds.left + mTextPaint.measureText(sectionName));
+ }
+ }
+
+ /**
+ * Updates the bounds for the fast scroller.
+ * @return the invalidation rect for this update.
+ */
+ public Rect updateFastScrollerBounds(BaseRecyclerView rv, int lastTouchY) {
+ mInvalidateRect.set(mBgBounds);
+
+ if (isVisible()) {
+ // Calculate the dimensions and position of the fast scroller popup
+ int edgePadding = rv.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.right = mBgBounds.left + bgWidth;
+ } else {
+ mBgBounds.right = rv.getWidth() - rv.getBackgroundPadding().right -
+ (2 * rv.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));
+ mBgBounds.bottom = mBgBounds.top + bgHeight;
+ } else {
+ mBgBounds.setEmpty();
+ }
+
+ // Combine the old and new fast scroller bounds to create the full invalidate rect
+ mInvalidateRect.union(mBgBounds);
+ return mInvalidateRect;
+ }
+
+ /**
+ * Animates the visibility of the fast scroller popup.
+ */
+ public void animateVisibility(boolean visible) {
+ if (mVisible != visible) {
+ mVisible = visible;
+ if (mAlphaAnimator != null) {
+ mAlphaAnimator.cancel();
+ }
+ mAlphaAnimator = ObjectAnimator.ofFloat(this, "alpha", visible ? 1f : 0f);
+ mAlphaAnimator.setDuration(visible ? 200 : 150);
+ mAlphaAnimator.start();
+ }
+ }
+
+ // Setter/getter for the popup alpha for animations
+ public void setAlpha(float alpha) {
+ mAlpha = alpha;
+ mRv.invalidate(mBgBounds);
+ }
+
+ public float getAlpha() {
+ return mAlpha;
+ }
+
+ public int getHeight() {
+ return mBgOriginalSize;
+ }
+
+ public void draw(Canvas c) {
+ if (isVisible()) {
+ // Draw the fast scroller popup
+ int restoreCount = c.save(Canvas.MATRIX_SAVE_FLAG);
+ c.translate(mBgBounds.left, mBgBounds.top);
+ mTmpRect.set(mBgBounds);
+ mTmpRect.offsetTo(0, 0);
+ mBg.setBounds(mTmpRect);
+ mBg.setAlpha((int) (mAlpha * 255));
+ mBg.draw(c);
+ mTextPaint.setAlpha((int) (mAlpha * 255));
+ c.drawText(mSectionName, (mBgBounds.width() - mTextBounds.width()) / 2,
+ mBgBounds.height() - (mBgBounds.height() - mTextBounds.height()) / 2,
+ mTextPaint);
+ c.restoreToCount(restoreCount);
+ }
+ }
+
+ public boolean isVisible() {
+ return (mAlpha > 0f) && (mSectionName != null);
+ }
+}
diff --git a/src/com/android/launcher3/BubbleTextView.java b/src/com/android/launcher3/BubbleTextView.java
index 07f3045a5..a0be8ea2b 100644
--- a/src/com/android/launcher3/BubbleTextView.java
+++ b/src/com/android/launcher3/BubbleTextView.java
@@ -16,6 +16,8 @@
package com.android.launcher3;
+import android.animation.ObjectAnimator;
+import android.annotation.TargetApi;
import android.content.Context;
import android.content.res.ColorStateList;
import android.content.res.Resources;
@@ -23,22 +25,30 @@ import android.content.res.Resources.Theme;
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.Drawable;
+import android.os.Build;
import android.util.AttributeSet;
import android.util.SparseArray;
import android.util.TypedValue;
import android.view.KeyEvent;
import android.view.MotionEvent;
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;
/**
* 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
* too aggressive.
*/
-public class BubbleTextView extends TextView {
+public class BubbleTextView extends TextView
+ implements BaseRecyclerViewFastScrollBar.FastScrollFocusableView {
private static SparseArray<Theme> sPreloaderThemes = new SparseArray<Theme>(2);
@@ -47,25 +57,47 @@ public class BubbleTextView extends TextView {
private static final float SHADOW_Y_OFFSET = 2.0f;
private static final int SHADOW_LARGE_COLOUR = 0xDD000000;
private static final int SHADOW_SMALL_COLOUR = 0xCC000000;
- static final float PADDING_V = 3.0f;
- private HolographicOutlineHelper mOutlineHelper;
+ 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;
+ private final CheckLongPressHelper mLongPressHelper;
+ private final HolographicOutlineHelper mOutlineHelper;
+ private final StylusEventHelper mStylusEventHelper;
+
+ private boolean mBackgroundSizeChanged;
+
private Bitmap mPressedBackground;
private float mSlop;
- private int mTextColor;
+ private final boolean mDeferShadowGenerationOnTouch;
private final boolean mCustomShadowsEnabled;
- private boolean mIsTextVisible;
-
- // TODO: Remove custom background handling code, as no instance of BubbleTextView use any
- // background.
- private boolean mBackgroundSizeChanged;
- private final Drawable mBackground;
+ private final boolean mLayoutHorizontal;
+ private final int mIconSize;
+ private int mTextColor;
private boolean mStayPressed;
private boolean mIgnorePressedStateChange;
- private CheckLongPressHelper mLongPressHelper;
+ 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) {
this(context, null, 0);
@@ -77,10 +109,28 @@ public class BubbleTextView extends TextView {
public BubbleTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
+ mLauncher = (Launcher) context;
+ DeviceProfile grid = mLauncher.getDeviceProfile();
TypedArray a = context.obtainStyledAttributes(attrs,
R.styleable.BubbleTextView, defStyle, 0);
mCustomShadowsEnabled = a.getBoolean(R.styleable.BubbleTextView_customShadows, true);
+ mLayoutHorizontal = a.getBoolean(R.styleable.BubbleTextView_layoutHorizontal, false);
+ mDeferShadowGenerationOnTouch =
+ a.getBoolean(R.styleable.BubbleTextView_deferShadowGeneration, false);
+
+ int display = a.getInteger(R.styleable.BubbleTextView_iconDisplay, DISPLAY_WORKSPACE);
+ int defaultIconSize = grid.iconSizePx;
+ if (display == DISPLAY_WORKSPACE) {
+ setTextSize(TypedValue.COMPLEX_UNIT_PX, grid.iconTextSizePx);
+ } else if (display == DISPLAY_ALL_APPS) {
+ setTextSize(TypedValue.COMPLEX_UNIT_PX, grid.allAppsIconTextSizePx);
+ defaultIconSize = grid.allAppsIconSizePx;
+ }
+
+ mIconSize = a.getDimensionPixelSize(R.styleable.BubbleTextView_iconSizeOverride,
+ defaultIconSize);
+
a.recycle();
if (mCustomShadowsEnabled) {
@@ -90,45 +140,37 @@ public class BubbleTextView extends TextView {
} else {
mBackground = null;
}
- init();
- }
-
- public void onFinishInflate() {
- super.onFinishInflate();
-
- // Ensure we are using the right text size
- LauncherAppState app = LauncherAppState.getInstance();
- DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
- setTextSize(TypedValue.COMPLEX_UNIT_PX, grid.iconTextSizePx);
- }
- private void init() {
mLongPressHelper = new CheckLongPressHelper(this);
+ mStylusEventHelper = new StylusEventHelper(this);
mOutlineHelper = HolographicOutlineHelper.obtain(getContext());
if (mCustomShadowsEnabled) {
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());
}
- public void applyFromShortcutInfo(ShortcutInfo info, IconCache iconCache,
- boolean setDefaultPadding) {
- applyFromShortcutInfo(info, iconCache, setDefaultPadding, false);
+ public void applyFromShortcutInfo(ShortcutInfo info, IconCache iconCache) {
+ applyFromShortcutInfo(info, iconCache, false);
}
public void applyFromShortcutInfo(ShortcutInfo info, IconCache iconCache,
- boolean setDefaultPadding, boolean promiseStateChanged) {
+ boolean promiseStateChanged) {
Bitmap b = info.getIcon(iconCache);
- LauncherAppState app = LauncherAppState.getInstance();
- FastBitmapDrawable iconDrawable = Utilities.createIconDrawable(b);
+ FastBitmapDrawable iconDrawable = mLauncher.createIconDrawable(b);
iconDrawable.setGhostModeEnabled(info.isDisabled != 0);
- setCompoundDrawables(null, iconDrawable, null, null);
- if (setDefaultPadding) {
- DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
- setCompoundDrawablePadding(grid.iconDrawablePaddingPx);
- }
+ setIcon(iconDrawable, mIconSize);
if (info.contentDescription != null) {
setContentDescription(info.contentDescription);
}
@@ -141,20 +183,37 @@ public class BubbleTextView extends TextView {
}
public void applyFromApplicationInfo(AppInfo info) {
- LauncherAppState app = LauncherAppState.getInstance();
- DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
+ setIcon(mLauncher.createIconDrawable(info.iconBitmap), mIconSize);
+ setText(info.title);
+ if (info.contentDescription != null) {
+ setContentDescription(info.contentDescription);
+ }
+ // We don't need to check the info since it's not a ShortcutInfo
+ super.setTag(info);
+
+ // Verify high res immediately
+ verifyHighRes();
+ }
- Drawable topDrawable = Utilities.createIconDrawable(info.iconBitmap);
- topDrawable.setBounds(0, 0, grid.allAppsIconSizePx, grid.allAppsIconSizePx);
- setCompoundDrawables(null, topDrawable, null, null);
- setCompoundDrawablePadding(grid.iconDrawablePaddingPx);
+ public void applyFromPackageItemInfo(PackageItemInfo info) {
+ setIcon(mLauncher.createIconDrawable(info.iconBitmap), mIconSize);
setText(info.title);
if (info.contentDescription != null) {
setContentDescription(info.contentDescription);
}
- setTag(info);
+ // We don't need to check the info since it's not a ShortcutInfo
+ super.setTag(info);
+
+ // Verify high res immediately
+ verifyHighRes();
}
+ /**
+ * Overrides the default long press timeout.
+ */
+ public void setLongPressTimeout(int longPressTimeout) {
+ mLongPressHelper.setLongPressTimeout(longPressTimeout);
+ }
@Override
protected boolean setFrame(int left, int top, int right, int bottom) {
@@ -186,10 +245,19 @@ public class BubbleTextView extends TextView {
}
}
+ /** Returns the icon for this view. */
+ public Drawable getIcon() {
+ return mIcon;
+ }
+
+ /** Returns whether the layout is horizontal. */
+ public boolean isLayoutHorizontal() {
+ return mLayoutHorizontal;
+ }
+
private void updateIconState() {
- Drawable top = getCompoundDrawables()[1];
- if (top instanceof FastBitmapDrawable) {
- ((FastBitmapDrawable) top).setPressed(isPressed() || mStayPressed);
+ if (mIcon instanceof FastBitmapDrawable) {
+ ((FastBitmapDrawable) mIcon).setPressed(isPressed() || mStayPressed);
}
}
@@ -199,16 +267,25 @@ public class BubbleTextView extends TextView {
// isPressed() on an ACTION_UP
boolean result = super.onTouchEvent(event);
+ // Check for a stylus button press, if it occurs cancel any long press checks.
+ if (mStylusEventHelper.checkAndPerformStylusEvent(event)) {
+ mLongPressHelper.cancelLongPress();
+ result = true;
+ }
+
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
// So that the pressed outline is visible immediately on setStayPressed(),
// we pre-create it on ACTION_DOWN (it takes a small but perceptible amount of time
// to create it)
- if (mPressedBackground == null) {
+ if (!mDeferShadowGenerationOnTouch && mPressedBackground == null) {
mPressedBackground = mOutlineHelper.createMediumDropShadow(this);
}
- mLongPressHelper.postCheckForLongPress();
+ // If we're in a stylus button press, don't check for long press.
+ if (!mStylusEventHelper.inStylusButtonPressed()) {
+ mLongPressHelper.postCheckForLongPress();
+ }
break;
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP:
@@ -233,12 +310,17 @@ public class BubbleTextView extends TextView {
mStayPressed = stayPressed;
if (!stayPressed) {
mPressedBackground = null;
+ } else {
+ if (mPressedBackground == null) {
+ mPressedBackground = mOutlineHelper.createMediumDropShadow(this);
+ }
}
// Only show the shadow effect when persistent pressed state is set.
- if (getParent() instanceof ShortcutAndWidgetContainer) {
- CellLayout layout = (CellLayout) getParent().getParent();
- layout.setPressedIcon(this, mPressedBackground, mOutlineHelper.shadowBitmapPadding);
+ ViewParent parent = getParent();
+ if (parent != null && parent.getParent() instanceof BubbleTextShadowHandler) {
+ ((BubbleTextShadowHandler) parent.getParent()).setPressedIcon(
+ this, mPressedBackground);
}
updateIconState();
@@ -278,7 +360,18 @@ public class BubbleTextView extends TextView {
@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;
}
@@ -325,10 +418,9 @@ public class BubbleTextView extends TextView {
super.onAttachedToWindow();
if (mBackground != null) mBackground.setCallback(this);
- Drawable top = getCompoundDrawables()[1];
- if (top instanceof PreloadIconDrawable) {
- ((PreloadIconDrawable) top).applyTheme(getPreloaderTheme());
+ if (mIcon instanceof PreloadIconDrawable) {
+ ((PreloadIconDrawable) mIcon).applyPreloaderTheme(getPreloaderTheme());
}
mSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
}
@@ -358,16 +450,6 @@ public class BubbleTextView extends TextView {
} else {
super.setTextColor(res.getColor(android.R.color.transparent));
}
- mIsTextVisible = visible;
- }
-
- public boolean isTextVisible() {
- return mIsTextVisible;
- }
-
- @Override
- protected boolean onSetAlpha(int alpha) {
- return true;
}
@Override
@@ -385,15 +467,13 @@ public class BubbleTextView extends TextView {
((info.hasStatusFlag(ShortcutInfo.FLAG_INSTALL_SESSION_ACTIVE) ?
info.getInstallProgress() : 0)) : 100;
- Drawable[] drawables = getCompoundDrawables();
- Drawable top = drawables[1];
- if (top != null) {
+ if (mIcon != null) {
final PreloadIconDrawable preloadDrawable;
- if (top instanceof PreloadIconDrawable) {
- preloadDrawable = (PreloadIconDrawable) top;
+ if (mIcon instanceof PreloadIconDrawable) {
+ preloadDrawable = (PreloadIconDrawable) mIcon;
} else {
- preloadDrawable = new PreloadIconDrawable(top, getPreloaderTheme());
- setCompoundDrawables(drawables[0], preloadDrawable, drawables[2], drawables[3]);
+ preloadDrawable = new PreloadIconDrawable(mIcon, getPreloaderTheme());
+ setIcon(preloadDrawable, mIconSize);
}
preloadDrawable.setLevel(progressLevel);
@@ -417,4 +497,132 @@ public class BubbleTextView extends TextView {
}
return theme;
}
+
+ /**
+ * Sets the icon for this view based on the layout direction.
+ */
+ @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
+ private Drawable setIcon(Drawable icon, int iconSize) {
+ mIcon = icon;
+ if (iconSize != -1) {
+ mIcon.setBounds(0, 0, iconSize, iconSize);
+ }
+ if (mLayoutHorizontal) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
+ setCompoundDrawablesRelative(mIcon, null, null, null);
+ } else {
+ setCompoundDrawables(mIcon, null, null, null);
+ }
+ } else {
+ setCompoundDrawables(null, mIcon, null, null);
+ }
+ return icon;
+ }
+
+ @Override
+ public void requestLayout() {
+ if (!mDisableRelayout) {
+ super.requestLayout();
+ }
+ }
+
+ /**
+ * Applies the item info if it is same as what the view is pointing to currently.
+ */
+ public void reapplyItemInfo(final ItemInfo info) {
+ if (getTag() == info) {
+ mIconLoadRequest = null;
+ mDisableRelayout = true;
+ if (info instanceof AppInfo) {
+ applyFromApplicationInfo((AppInfo) info);
+ } else if (info instanceof ShortcutInfo) {
+ applyFromShortcutInfo((ShortcutInfo) info,
+ LauncherAppState.getInstance().getIconCache());
+ } else if (info instanceof PackageItemInfo) {
+ applyFromPackageItemInfo((PackageItemInfo) info);
+ }
+ mDisableRelayout = false;
+ }
+ }
+
+ /**
+ * Verifies that the current icon is high-res otherwise posts a request to load the icon.
+ */
+ public void verifyHighRes() {
+ if (mIconLoadRequest != null) {
+ mIconLoadRequest.cancel();
+ mIconLoadRequest = null;
+ }
+ if (getTag() instanceof AppInfo) {
+ AppInfo info = (AppInfo) getTag();
+ if (info.usingLowResIcon) {
+ mIconLoadRequest = LauncherAppState.getInstance().getIconCache()
+ .updateIconInBackground(BubbleTextView.this, info);
+ }
+ } else if (getTag() instanceof ShortcutInfo) {
+ ShortcutInfo info = (ShortcutInfo) getTag();
+ if (info.usingLowResIcon) {
+ mIconLoadRequest = LauncherAppState.getInstance().getIconCache()
+ .updateIconInBackground(BubbleTextView.this, info);
+ }
+ } else if (getTag() instanceof PackageItemInfo) {
+ PackageItemInfo info = (PackageItemInfo) getTag();
+ if (info.usingLowResIcon) {
+ mIconLoadRequest = LauncherAppState.getInstance().getIconCache()
+ .updateIconInBackground(BubbleTextView.this, info);
+ }
+ }
+ }
+
+ // 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) {
+ 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;
+ }
+ }
+ }
+
+ /**
+ * Interface to be implemented by the grand parent to allow click shadow effect.
+ */
+ public static 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 019f86c21..b7f89d02a 100644
--- a/src/com/android/launcher3/ButtonDropTarget.java
+++ b/src/com/android/launcher3/ButtonDropTarget.java
@@ -16,26 +16,41 @@
package com.android.launcher3;
+import android.animation.AnimatorSet;
+import android.animation.FloatArrayEvaluator;
+import android.animation.ObjectAnimator;
+import android.animation.ValueAnimator;
+import android.animation.ValueAnimator.AnimatorUpdateListener;
+import android.annotation.TargetApi;
import android.content.Context;
-import android.content.res.Resources;
+import android.content.res.ColorStateList;
+import android.content.res.Configuration;
+import android.graphics.ColorMatrix;
+import android.graphics.ColorMatrixColorFilter;
import android.graphics.PointF;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
+import android.os.Build;
import android.util.AttributeSet;
import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.ViewGroup;
+import android.view.animation.DecelerateInterpolator;
+import android.view.animation.LinearInterpolator;
import android.widget.TextView;
+import com.android.launcher3.util.Thunk;
/**
* Implements a DropTarget.
*/
-public class ButtonDropTarget extends TextView implements DropTarget, DragController.DragListener {
+public abstract class ButtonDropTarget extends TextView
+ implements DropTarget, DragController.DragListener, OnClickListener {
- protected final int mTransitionDuration;
+ private static int DRAG_VIEW_DROP_DURATION = 285;
protected Launcher mLauncher;
private int mBottomDragPadding;
- protected TextView mText;
protected SearchDropTargetBar mSearchDropTargetBar;
/** Whether this drop target is active for the current drag */
@@ -44,72 +59,197 @@ public class ButtonDropTarget extends TextView implements DropTarget, DragContro
/** The paint applied to the drag view on hover */
protected int mHoverColor = 0;
+ protected ColorStateList mOriginalTextColor;
+ protected Drawable mDrawable;
+
+ private AnimatorSet mCurrentColorAnim;
+ @Thunk ColorMatrix mSrcFilter, mDstFilter, mCurrentFilter;
+
+
public ButtonDropTarget(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public ButtonDropTarget(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
+ mBottomDragPadding = getResources().getDimensionPixelSize(R.dimen.drop_target_drag_padding);
+ }
- Resources r = getResources();
- mTransitionDuration = r.getInteger(R.integer.config_dropTargetBgTransitionDuration);
- mBottomDragPadding = r.getDimensionPixelSize(R.dimen.drop_target_drag_padding);
+ @Override
+ protected void onFinishInflate() {
+ super.onFinishInflate();
+ mOriginalTextColor = getTextColors();
+
+ // Remove the text in the Phone UI in landscape
+ DeviceProfile grid = ((Launcher) getContext()).getDeviceProfile();
+ if (grid.isVerticalBarLayout()) {
+ setText("");
+ }
}
- void setLauncher(Launcher launcher) {
- mLauncher = launcher;
+ @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
+ protected void setDrawable(int resId) {
+ // We do not set the drawable in the xml as that inflates two drawables corresponding to
+ // drawableLeft and drawableStart.
+ mDrawable = getResources().getDrawable(resId);
+
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
+ setCompoundDrawablesRelativeWithIntrinsicBounds(mDrawable, null, null, null);
+ } else {
+ setCompoundDrawablesWithIntrinsicBounds(mDrawable, null, null, null);
+ }
}
- public boolean acceptDrop(DragObject d) {
- return false;
+ public void setLauncher(Launcher launcher) {
+ mLauncher = launcher;
}
public void setSearchDropTargetBar(SearchDropTargetBar searchDropTargetBar) {
mSearchDropTargetBar = searchDropTargetBar;
}
- protected Drawable getCurrentDrawable() {
- Drawable[] drawables = getCompoundDrawablesRelative();
- for (int i = 0; i < drawables.length; ++i) {
- if (drawables[i] != null) {
- return drawables[i];
+ @Override
+ public void onFlingToDelete(DragObject d, PointF vec) { }
+
+ @Override
+ public final void onDragEnter(DragObject d) {
+ d.dragView.setColor(mHoverColor);
+ if (Utilities.isLmpOrAbove()) {
+ animateTextColor(mHoverColor);
+ } else {
+ if (mCurrentFilter == null) {
+ mCurrentFilter = new ColorMatrix();
}
+ DragView.setColorScale(mHoverColor, mCurrentFilter);
+ mDrawable.setColorFilter(new ColorMatrixColorFilter(mCurrentFilter));
+ setTextColor(mHoverColor);
}
- return null;
}
- public void onDrop(DragObject d) {
+ @Override
+ public void onDragOver(DragObject d) {
+ // Do nothing
}
- public void onFlingToDelete(DragObject d, int x, int y, PointF vec) {
- // Do nothing
+ protected void resetHoverColor() {
+ if (Utilities.isLmpOrAbove()) {
+ animateTextColor(mOriginalTextColor.getDefaultColor());
+ } else {
+ mDrawable.setColorFilter(null);
+ setTextColor(mOriginalTextColor);
+ }
}
- public void onDragEnter(DragObject d) {
- d.dragView.setColor(mHoverColor);
+ @TargetApi(Build.VERSION_CODES.LOLLIPOP)
+ private void animateTextColor(int targetColor) {
+ if (mCurrentColorAnim != null) {
+ mCurrentColorAnim.cancel();
+ }
+
+ mCurrentColorAnim = new AnimatorSet();
+ mCurrentColorAnim.setDuration(DragView.COLOR_CHANGE_DURATION);
+
+ if (mSrcFilter == null) {
+ mSrcFilter = new ColorMatrix();
+ mDstFilter = new ColorMatrix();
+ mCurrentFilter = new ColorMatrix();
+ }
+
+ DragView.setColorScale(getTextColor(), mSrcFilter);
+ DragView.setColorScale(targetColor, mDstFilter);
+ ValueAnimator anim1 = ValueAnimator.ofObject(
+ new FloatArrayEvaluator(mCurrentFilter.getArray()),
+ mSrcFilter.getArray(), mDstFilter.getArray());
+ anim1.addUpdateListener(new AnimatorUpdateListener() {
+
+ @Override
+ public void onAnimationUpdate(ValueAnimator animation) {
+ mDrawable.setColorFilter(new ColorMatrixColorFilter(mCurrentFilter));
+ invalidate();
+ }
+ });
+
+ mCurrentColorAnim.play(anim1);
+ mCurrentColorAnim.play(ObjectAnimator.ofArgb(this, "textColor", targetColor));
+ mCurrentColorAnim.start();
}
- public void onDragOver(DragObject d) {
- // Do nothing
+ @Override
+ public final void onDragExit(DragObject d) {
+ if (!d.dragComplete) {
+ d.dragView.setColor(0);
+ resetHoverColor();
+ } else {
+ // Restore the hover color
+ d.dragView.setColor(mHoverColor);
+ }
}
- public void onDragExit(DragObject d) {
- d.dragView.setColor(0);
+ @Override
+ public final void onDragStart(DragSource source, Object info, int dragAction) {
+ mActive = supportsDrop(source, info);
+ mDrawable.setColorFilter(null);
+ if (mCurrentColorAnim != null) {
+ mCurrentColorAnim.cancel();
+ mCurrentColorAnim = null;
+ }
+ setTextColor(mOriginalTextColor);
+ ((ViewGroup) getParent()).setVisibility(mActive ? View.VISIBLE : View.GONE);
}
- public void onDragStart(DragSource source, Object info, int dragAction) {
- // Do nothing
+ @Override
+ public final boolean acceptDrop(DragObject dragObject) {
+ return supportsDrop(dragObject.dragSource, dragObject.dragInfo);
}
+ protected abstract boolean supportsDrop(DragSource source, Object info);
+
+ @Override
public boolean isDropEnabled() {
return mActive;
}
+ @Override
public void onDragEnd() {
- // Do nothing
+ mActive = false;
+ }
+
+ /**
+ * On drop animate the dropView to the icon.
+ */
+ @Override
+ public void onDrop(final DragObject d) {
+ final DragLayer dragLayer = mLauncher.getDragLayer();
+ final Rect from = new Rect();
+ dragLayer.getViewRectRelativeToSelf(d.dragView, from);
+
+ int width = mDrawable.getIntrinsicWidth();
+ int height = mDrawable.getIntrinsicHeight();
+ final Rect to = getIconRect(d.dragView.getMeasuredWidth(), d.dragView.getMeasuredHeight(),
+ width, height);
+ final float scale = (float) to.width() / from.width();
+ mSearchDropTargetBar.deferOnDragEnd();
+
+ Runnable onAnimationEndRunnable = new Runnable() {
+ @Override
+ public void run() {
+ completeDrop(d);
+ mSearchDropTargetBar.onDragEnd();
+ mLauncher.exitSpringLoadedDragModeDelayed(true, 0, null);
+ }
+ };
+ dragLayer.animateView(d.dragView, from, to, scale, 1f, 1f, 0.1f, 0.1f,
+ DRAG_VIEW_DROP_DURATION, new DecelerateInterpolator(2),
+ new LinearInterpolator(), onAnimationEndRunnable,
+ DragLayer.ANIMATION_END_DISAPPEAR, null);
}
@Override
+ public void prepareAccessibilityDrop() { }
+
+ @Thunk abstract void completeDrop(DragObject d);
+
+ @Override
public void getHitRectRelativeToDragLayer(android.graphics.Rect outRect) {
super.getHitRect(outRect);
outRect.bottom += mBottomDragPadding;
@@ -119,11 +259,7 @@ public class ButtonDropTarget extends TextView implements DropTarget, DragContro
outRect.offsetTo(coords[0], coords[1]);
}
- private boolean isRtl() {
- return (getLayoutDirection() == View.LAYOUT_DIRECTION_RTL);
- }
-
- Rect getIconRect(int viewWidth, int viewHeight, int drawableWidth, int drawableHeight) {
+ protected Rect getIconRect(int viewWidth, int viewHeight, int drawableWidth, int drawableHeight) {
DragLayer dragLayer = mLauncher.getDragLayer();
// Find the rect to animate to (the view is center aligned)
@@ -136,7 +272,7 @@ public class ButtonDropTarget extends TextView implements DropTarget, DragContro
final int left;
final int right;
- if (isRtl()) {
+ if (Utilities.isRtl(getResources())) {
right = to.right - getPaddingRight();
left = right - width;
} else {
@@ -157,7 +293,26 @@ public class ButtonDropTarget extends TextView implements DropTarget, DragContro
return to;
}
+ @Override
public void getLocationInDragLayer(int[] loc) {
mLauncher.getDragLayer().getLocationInDragLayer(this, loc);
}
+
+ public void enableAccessibleDrag(boolean enable) {
+ setOnClickListener(enable ? this : null);
+ }
+
+ protected String getAccessibilityDropConfirmation() {
+ return null;
+ }
+
+ @Override
+ public void onClick(View v) {
+ LauncherAppState.getInstance().getAccessibilityDelegate()
+ .handleAccessibleDrop(this, null, getAccessibilityDropConfirmation());
+ }
+
+ public int getTextColor() {
+ return getTextColors().getDefaultColor();
+ }
}
diff --git a/src/com/android/launcher3/CellLayout.java b/src/com/android/launcher3/CellLayout.java
index 0ff1ef4ad..809688712 100644
--- a/src/com/android/launcher3/CellLayout.java
+++ b/src/com/android/launcher3/CellLayout.java
@@ -22,6 +22,7 @@ import android.animation.AnimatorSet;
import android.animation.TimeInterpolator;
import android.animation.ValueAnimator;
import android.animation.ValueAnimator.AnimatorUpdateListener;
+import android.annotation.TargetApi;
import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
@@ -33,7 +34,10 @@ import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
+import android.graphics.drawable.TransitionDrawable;
+import android.os.Build;
import android.os.Parcelable;
+import android.support.v4.view.ViewCompat;
import android.util.AttributeSet;
import android.util.Log;
import android.util.SparseArray;
@@ -41,11 +45,16 @@ import android.view.MotionEvent;
import android.view.View;
import android.view.ViewDebug;
import android.view.ViewGroup;
-import android.view.animation.Animation;
+import android.view.accessibility.AccessibilityEvent;
import android.view.animation.DecelerateInterpolator;
-import android.view.animation.LayoutAnimationController;
+import com.android.launcher3.BubbleTextView.BubbleTextShadowHandler;
import com.android.launcher3.FolderIcon.FolderRingAnimator;
+import com.android.launcher3.accessibility.DragAndDropAccessibilityDelegate;
+import com.android.launcher3.accessibility.FolderAccessibilityHelper;
+import com.android.launcher3.accessibility.WorkspaceAccessibilityHelper;
+import com.android.launcher3.util.Thunk;
+import com.android.launcher3.widget.PendingAddWidgetInfo;
import java.util.ArrayList;
import java.util.Arrays;
@@ -54,55 +63,47 @@ import java.util.Comparator;
import java.util.HashMap;
import java.util.Stack;
-public class CellLayout extends ViewGroup {
+public class CellLayout extends ViewGroup implements BubbleTextShadowHandler {
+ public static final int WORKSPACE_ACCESSIBILITY_DRAG = 2;
+ public static final int FOLDER_ACCESSIBILITY_DRAG = 1;
+
static final String TAG = "CellLayout";
private Launcher mLauncher;
- private int mCellWidth;
- private int mCellHeight;
+ @Thunk int mCellWidth;
+ @Thunk int mCellHeight;
private int mFixedCellWidth;
private int mFixedCellHeight;
- private int mCountX;
- private int mCountY;
+ @Thunk int mCountX;
+ @Thunk int mCountY;
private int mOriginalWidthGap;
private int mOriginalHeightGap;
- private int mWidthGap;
- private int mHeightGap;
+ @Thunk int mWidthGap;
+ @Thunk int mHeightGap;
private int mMaxGap;
private boolean mDropPending = false;
private boolean mIsDragTarget = 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.
- private final int[] mTmpXY = new int[2];
- private final int[] mTmpPoint = new int[2];
- int[] mTempLocation = new int[2];
+ @Thunk final int[] mTmpPoint = new int[2];
+ @Thunk final int[] mTempLocation = new int[2];
boolean[][] mOccupied;
boolean[][] mTmpOccupied;
- private boolean mLastDownOnOccupiedCell = false;
private OnTouchListener mInterceptTouchListener;
+ private StylusEventHelper mStylusEventHelper;
private ArrayList<FolderRingAnimator> mFolderOuterRings = new ArrayList<FolderRingAnimator>();
private int[] mFolderLeaveBehindCell = {-1, -1};
- private float FOREGROUND_ALPHA_DAMPER = 0.65f;
- private int mForegroundAlpha = 0;
private float mBackgroundAlpha;
- private float mBackgroundAlphaMultiplier = 1.0f;
- private boolean mDrawBackground = true;
-
- private Drawable mNormalBackground;
- private Drawable mActiveGlowBackground;
- private Drawable mOverScrollForegroundDrawable;
- private Drawable mOverScrollLeft;
- private Drawable mOverScrollRight;
- private Rect mBackgroundRect;
- private Rect mForegroundRect;
- private int mForegroundPadding;
+
+ private static final int BACKGROUND_ACTIVATE_DURATION = 120;
+ private final TransitionDrawable mBackground;
// These values allow a fixed measurement to be set on the CellLayout.
private int mFixedWidth = -1;
@@ -110,12 +111,11 @@ public class CellLayout extends ViewGroup {
// If we're actively dragging something over this screen, mIsDragOverlapping is true
private boolean mIsDragOverlapping = false;
- boolean mUseActiveGlowBackground = false;
// These arrays are used to implement the drag visualization on x-large screens.
// They are used as circular arrays, indexed by mDragOutlineCurrent.
- private Rect[] mDragOutlines = new Rect[4];
- private float[] mDragOutlineAlphas = new float[mDragOutlines.length];
+ @Thunk Rect[] mDragOutlines = new Rect[4];
+ @Thunk float[] mDragOutlineAlphas = new float[mDragOutlines.length];
private InterruptibleInOutAnimator[] mDragOutlineAnims =
new InterruptibleInOutAnimator[mDragOutlines.length];
@@ -123,12 +123,10 @@ public class CellLayout extends ViewGroup {
private int mDragOutlineCurrent = 0;
private final Paint mDragOutlinePaint = new Paint();
- private final FastBitmapView mTouchFeedbackView;
+ private final ClickShadowView mTouchFeedbackView;
- private HashMap<CellLayout.LayoutParams, Animator> mReorderAnimators = new
- HashMap<CellLayout.LayoutParams, Animator>();
- private HashMap<View, ReorderPreviewAnimation>
- mShakeAnimators = new HashMap<View, ReorderPreviewAnimation>();
+ @Thunk HashMap<CellLayout.LayoutParams, Animator> mReorderAnimators = new HashMap<>();
+ @Thunk HashMap<View, ReorderPreviewAnimation> mShakeAnimators = new HashMap<>();
private boolean mItemPlacementDirty = false;
@@ -156,19 +154,22 @@ public class CellLayout extends ViewGroup {
private static final float REORDER_PREVIEW_MAGNITUDE = 0.12f;
private static final int REORDER_ANIMATION_DURATION = 150;
- private float mReorderPreviewAnimationMagnitude;
+ @Thunk float mReorderPreviewAnimationMagnitude;
private ArrayList<View> mIntersectingViews = new ArrayList<View>();
private Rect mOccupiedRect = new Rect();
private int[] mDirectionVector = new int[2];
int[] mPreviousReorderDirection = new int[2];
private static final int INVALID_DIRECTION = -100;
- private DropTarget.DragEnforcer mDragEnforcer;
- private Rect mTempRect = new Rect();
+ private final Rect mTempRect = new Rect();
private final static Paint sPaint = new Paint();
+ // Related to accessible drag and drop
+ private DragAndDropAccessibilityDelegate mTouchHelper;
+ private boolean mUseTouchHelper = false;
+
public CellLayout(Context context) {
this(context, null);
}
@@ -179,7 +180,6 @@ public class CellLayout extends ViewGroup {
public CellLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
- mDragEnforcer = new DropTarget.DragEnforcer(context);
// A ViewGroup usually does not draw, but CellLayout needs to draw a rectangle to show
// the user where a dragged item will land when dropped.
@@ -187,8 +187,7 @@ public class CellLayout extends ViewGroup {
setClipToPadding(false);
mLauncher = (Launcher) context;
- LauncherAppState app = LauncherAppState.getInstance();
- DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
+ DeviceProfile grid = mLauncher.getDeviceProfile();
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CellLayout, defStyle, 0);
mCellWidth = mCellHeight = -1;
@@ -196,8 +195,8 @@ public class CellLayout extends ViewGroup {
mWidthGap = mOriginalWidthGap = 0;
mHeightGap = mOriginalHeightGap = 0;
mMaxGap = Integer.MAX_VALUE;
- mCountX = (int) grid.numColumns;
- mCountY = (int) grid.numRows;
+ mCountX = (int) grid.inv.numColumns;
+ mCountY = (int) grid.inv.numRows;
mOccupied = new boolean[mCountX][mCountY];
mTmpOccupied = new boolean[mCountX][mCountY];
mPreviousReorderDirection[0] = INVALID_DIRECTION;
@@ -210,20 +209,12 @@ public class CellLayout extends ViewGroup {
final Resources res = getResources();
mHotseatScale = (float) grid.hotseatIconSizePx / grid.iconSizePx;
- mNormalBackground = res.getDrawable(R.drawable.screenpanel);
- mActiveGlowBackground = res.getDrawable(R.drawable.screenpanel_hover);
-
- mOverScrollLeft = res.getDrawable(R.drawable.overscroll_glow_left);
- mOverScrollRight = res.getDrawable(R.drawable.overscroll_glow_right);
- mForegroundPadding =
- res.getDimensionPixelSize(R.dimen.workspace_overscroll_drawable_padding);
+ mBackground = (TransitionDrawable) res.getDrawable(R.drawable.bg_screenpanel);
+ mBackground.setCallback(this);
mReorderPreviewAnimationMagnitude = (REORDER_PREVIEW_MAGNITUDE *
grid.iconSizePx);
- mNormalBackground.setFilterBitmap(true);
- mActiveGlowBackground.setFilterBitmap(true);
-
// Initialize the data structures used for the drag visualization.
mEaseOutInterpolator = new DecelerateInterpolator(2.5f); // Quint ease out
mDragCell[0] = mDragCell[1] = -1;
@@ -281,19 +272,78 @@ public class CellLayout extends ViewGroup {
mDragOutlineAnims[i] = anim;
}
- mBackgroundRect = new Rect();
- mForegroundRect = new Rect();
-
mShortcutsAndWidgets = new ShortcutAndWidgetContainer(context);
mShortcutsAndWidgets.setCellDimensions(mCellWidth, mCellHeight, mWidthGap, mHeightGap,
mCountX, mCountY);
- mTouchFeedbackView = new FastBitmapView(context);
- // Make the feedback view large enough to hold the blur bitmap.
- addView(mTouchFeedbackView, (int) (grid.cellWidthPx * 1.5), (int) (grid.cellHeightPx * 1.5));
+ mStylusEventHelper = new StylusEventHelper(this);
+
+ mTouchFeedbackView = new ClickShadowView(context);
+ addView(mTouchFeedbackView);
addView(mShortcutsAndWidgets);
}
+ @TargetApi(Build.VERSION_CODES.LOLLIPOP)
+ public void enableAccessibleDrag(boolean enable, int dragType) {
+ mUseTouchHelper = enable;
+ if (!enable) {
+ ViewCompat.setAccessibilityDelegate(this, null);
+ setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_NO);
+ getShortcutsAndWidgets().setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_NO);
+ setOnClickListener(mLauncher);
+ } else {
+ if (dragType == WORKSPACE_ACCESSIBILITY_DRAG &&
+ !(mTouchHelper instanceof WorkspaceAccessibilityHelper)) {
+ mTouchHelper = new WorkspaceAccessibilityHelper(this);
+ } else if (dragType == FOLDER_ACCESSIBILITY_DRAG &&
+ !(mTouchHelper instanceof FolderAccessibilityHelper)) {
+ mTouchHelper = new FolderAccessibilityHelper(this);
+ }
+ ViewCompat.setAccessibilityDelegate(this, mTouchHelper);
+ setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
+ getShortcutsAndWidgets().setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
+ setOnClickListener(mTouchHelper);
+ }
+
+ // Invalidate the accessibility hierarchy
+ if (getParent() != null) {
+ getParent().notifySubtreeAccessibilityStateChanged(
+ this, this, AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE);
+ }
+ }
+
+ @Override
+ public boolean dispatchHoverEvent(MotionEvent event) {
+ // Always attempt to dispatch hover events to accessibility first.
+ if (mUseTouchHelper && mTouchHelper.dispatchHoverEvent(event)) {
+ return true;
+ }
+ return super.dispatchHoverEvent(event);
+ }
+
+ @Override
+ public boolean onInterceptTouchEvent(MotionEvent ev) {
+ if (mUseTouchHelper ||
+ (mInterceptTouchListener != null && mInterceptTouchListener.onTouch(this, ev))) {
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public boolean onTouchEvent(MotionEvent ev) {
+ boolean handled = super.onTouchEvent(ev);
+ // Stylus button press on a home screen should not switch between overview mode and
+ // the home screen mode, however, once in overview mode stylus button press should be
+ // enabled to allow rearranging the different home screens. So check what mode
+ // the workspace is in, and only perform stylus button presses while in overview mode.
+ if (mLauncher.mWorkspace.isInOverviewMode()
+ && mStylusEventHelper.checkAndPerformStylusEvent(ev)) {
+ return true;
+ }
+ return handled;
+ }
+
public void enableHardwareLayer(boolean hasLayer) {
mShortcutsAndWidgets.setLayerType(hasLayer ? LAYER_TYPE_HARDWARE : LAYER_TYPE_NONE, sPaint);
}
@@ -337,47 +387,19 @@ public class CellLayout extends ViewGroup {
return mDropPending;
}
- void setOverScrollAmount(float r, boolean left) {
- if (left && mOverScrollForegroundDrawable != mOverScrollLeft) {
- mOverScrollForegroundDrawable = mOverScrollLeft;
- } else if (!left && mOverScrollForegroundDrawable != mOverScrollRight) {
- mOverScrollForegroundDrawable = mOverScrollRight;
- }
-
- r *= FOREGROUND_ALPHA_DAMPER;
- mForegroundAlpha = (int) Math.round((r * 255));
- mOverScrollForegroundDrawable.setAlpha(mForegroundAlpha);
- invalidate();
- }
-
- void setPressedIcon(BubbleTextView icon, Bitmap background, int padding) {
+ @Override
+ public void setPressedIcon(BubbleTextView icon, Bitmap background) {
if (icon == null || background == null) {
mTouchFeedbackView.setBitmap(null);
mTouchFeedbackView.animate().cancel();
} else {
- int offset = getMeasuredWidth() - getPaddingLeft() - getPaddingRight()
- - (mCountX * mCellWidth);
- mTouchFeedbackView.setTranslationX(icon.getLeft() + (int) Math.ceil(offset / 2f)
- - padding);
- mTouchFeedbackView.setTranslationY(icon.getTop() - padding);
if (mTouchFeedbackView.setBitmap(background)) {
- mTouchFeedbackView.setAlpha(0);
- mTouchFeedbackView.animate().alpha(1)
- .setDuration(FastBitmapDrawable.CLICK_FEEDBACK_DURATION)
- .setInterpolator(FastBitmapDrawable.CLICK_FEEDBACK_INTERPOLATOR)
- .start();
+ mTouchFeedbackView.alignWithIconView(icon, mShortcutsAndWidgets);
+ mTouchFeedbackView.animateShadow();
}
}
}
- void setUseActiveGlowBackground(boolean use) {
- mUseActiveGlowBackground = use;
- }
-
- void disableBackground() {
- mDrawBackground = false;
- }
-
void disableDragTarget() {
mIsDragTarget = false;
}
@@ -389,7 +411,11 @@ public class CellLayout extends ViewGroup {
void setIsDragOverlapping(boolean isDragOverlapping) {
if (mIsDragOverlapping != isDragOverlapping) {
mIsDragOverlapping = isDragOverlapping;
- setUseActiveGlowBackground(mIsDragOverlapping);
+ if (mIsDragOverlapping) {
+ mBackground.startTransition(BACKGROUND_ACTIVATE_DURATION);
+ } else {
+ mBackground.reverseTransition(BACKGROUND_ACTIVATE_DURATION);
+ }
invalidate();
}
}
@@ -400,24 +426,17 @@ public class CellLayout extends ViewGroup {
@Override
protected void onDraw(Canvas canvas) {
+ if (!mIsDragTarget) {
+ return;
+ }
+
// When we're large, we are either drawn in a "hover" state (ie when dragging an item to
// a neighboring page) or with just a normal background (if backgroundAlpha > 0.0f)
// When we're small, we are either drawn normally or in the "accepts drops" state (during
// a drag). However, we also drag the mini hover background *over* one of those two
// backgrounds
- if (mDrawBackground && mBackgroundAlpha > 0.0f) {
- Drawable bg;
-
- if (mUseActiveGlowBackground) {
- // In the mini case, we draw the active_glow bg *over* the active background
- bg = mActiveGlowBackground;
- } else {
- bg = mNormalBackground;
- }
-
- bg.setAlpha((int) (mBackgroundAlpha * mBackgroundAlphaMultiplier * 255));
- bg.setBounds(mBackgroundRect);
- bg.draw(canvas);
+ if (mBackgroundAlpha > 0.0f) {
+ mBackground.draw(canvas);
}
final Paint paint = mDragOutlinePaint;
@@ -453,8 +472,7 @@ public class CellLayout extends ViewGroup {
int previewOffset = FolderRingAnimator.sPreviewSize;
// The folder outer / inner ring image(s)
- LauncherAppState app = LauncherAppState.getInstance();
- DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
+ DeviceProfile grid = mLauncher.getDeviceProfile();
for (int i = 0; i < mFolderOuterRings.size(); i++) {
FolderRingAnimator fra = mFolderOuterRings.get(i);
@@ -513,15 +531,6 @@ public class CellLayout extends ViewGroup {
}
}
- @Override
- protected void dispatchDraw(Canvas canvas) {
- super.dispatchDraw(canvas);
- if (mForegroundAlpha > 0) {
- mOverScrollForegroundDrawable.setBounds(mForegroundRect);
- mOverScrollForegroundDrawable.draw(canvas);
- }
- }
-
public void showFolderAccept(FolderRingAnimator fra) {
mFolderOuterRings.add(fra);
}
@@ -578,11 +587,11 @@ public class CellLayout extends ViewGroup {
mInterceptTouchListener = listener;
}
- int getCountX() {
+ public int getCountX() {
return mCountX;
}
- int getCountY() {
+ public int getCountY() {
return mCountY;
}
@@ -591,6 +600,10 @@ public class CellLayout extends ViewGroup {
mShortcutsAndWidgets.setIsHotseat(isHotseat);
}
+ public boolean isHotseat() {
+ return mIsHotseat;
+ }
+
public boolean addViewToCellLayout(View child, int index, int childId, LayoutParams params,
boolean markCells) {
final LayoutParams lp = params;
@@ -613,7 +626,6 @@ public class CellLayout extends ViewGroup {
if (lp.cellVSpan < 0) lp.cellVSpan = mCountY;
child.setId(childId);
-
mShortcutsAndWidgets.addView(child, index, lp);
if (markCells) markCellsAsOccupiedForView(child);
@@ -637,10 +649,6 @@ public class CellLayout extends ViewGroup {
}
}
- public void removeViewWithoutMarkingCells(View view) {
- mShortcutsAndWidgets.removeView(view);
- }
-
@Override
public void removeView(View view) {
markCellsAsUnoccupiedForView(view);
@@ -675,25 +683,13 @@ public class CellLayout extends ViewGroup {
mShortcutsAndWidgets.removeViewsInLayout(start, count);
}
- @Override
- public boolean onInterceptTouchEvent(MotionEvent ev) {
- // First we clear the tag to ensure that on every touch down we start with a fresh slate,
- // even in the case where we return early. Not clearing here was causing bugs whereby on
- // long-press we'd end up picking up an item from a previous drag operation.
- if (mInterceptTouchListener != null && mInterceptTouchListener.onTouch(this, ev)) {
- return true;
- }
-
- return false;
- }
-
/**
* Given a point, return the cell that strictly encloses that point
* @param x X coordinate of the point
* @param y Y coordinate of the point
* @param result Array of 2 ints to hold the x and y coordinate of the cell
*/
- void pointToCellExact(int x, int y, int[] result) {
+ public void pointToCellExact(int x, int y, int[] result) {
final int hStartPadding = getPaddingLeft();
final int vStartPadding = getPaddingTop();
@@ -782,9 +778,7 @@ public class CellLayout extends ViewGroup {
public float getDistanceFromCell(float x, float y, int[] cell) {
cellToCenterPoint(cell[0], cell[1], mTmpPoint);
- float distance = (float) Math.sqrt( Math.pow(x - mTmpPoint[0], 2) +
- Math.pow(y - mTmpPoint[1], 2));
- return distance;
+ return (float) Math.hypot(x - mTmpPoint[0], y - mTmpPoint[1]);
}
int getCellWidth() {
@@ -803,28 +797,6 @@ public class CellLayout extends ViewGroup {
return mHeightGap;
}
- Rect getContentRect(Rect r) {
- if (r == null) {
- r = new Rect();
- }
- int left = getPaddingLeft();
- int top = getPaddingTop();
- int right = left + getWidth() - getPaddingLeft() - getPaddingRight();
- int bottom = top + getHeight() - getPaddingTop() - getPaddingBottom();
- r.set(left, top, right, bottom);
- return r;
- }
-
- /** Return a rect that has the cellWidth/cellHeight (left, top), and
- * widthGap/heightGap (right, bottom) */
- static void getMetrics(Rect metrics, int paddedMeasureWidth,
- int paddedMeasureHeight, int countX, int countY) {
- LauncherAppState app = LauncherAppState.getInstance();
- DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
- metrics.set(grid.calculateCellWidth(paddedMeasureWidth, countX),
- grid.calculateCellHeight(paddedMeasureHeight, countY), 0, 0);
- }
-
public void setFixedSize(int width, int height) {
mFixedWidth = width;
mFixedHeight = height;
@@ -832,9 +804,6 @@ public class CellLayout extends ViewGroup {
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- LauncherAppState app = LauncherAppState.getInstance();
- DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
-
int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec);
int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
@@ -842,8 +811,8 @@ public class CellLayout extends ViewGroup {
int childWidthSize = widthSize - (getPaddingLeft() + getPaddingRight());
int childHeightSize = heightSize - (getPaddingTop() + getPaddingBottom());
if (mFixedCellWidth < 0 || mFixedCellHeight < 0) {
- int cw = grid.calculateCellWidth(childWidthSize, mCountX);
- int ch = grid.calculateCellHeight(childHeightSize, mCountY);
+ int cw = DeviceProfile.calculateCellWidth(childWidthSize, mCountX);
+ int ch = DeviceProfile.calculateCellHeight(childHeightSize, mCountY);
if (cw != mCellWidth || ch != mCellHeight) {
mCellWidth = cw;
mCellHeight = ch;
@@ -877,19 +846,20 @@ public class CellLayout extends ViewGroup {
mWidthGap = mOriginalWidthGap;
mHeightGap = mOriginalHeightGap;
}
- int count = getChildCount();
- int maxWidth = 0;
- int maxHeight = 0;
- for (int i = 0; i < count; i++) {
- View child = getChildAt(i);
- int childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(newWidth,
- MeasureSpec.EXACTLY);
- int childheightMeasureSpec = MeasureSpec.makeMeasureSpec(newHeight,
- MeasureSpec.EXACTLY);
- child.measure(childWidthMeasureSpec, childheightMeasureSpec);
- maxWidth = Math.max(maxWidth, child.getMeasuredWidth());
- maxHeight = Math.max(maxHeight, child.getMeasuredHeight());
- }
+
+ // Make the feedback view large enough to hold the blur bitmap.
+ mTouchFeedbackView.measure(
+ MeasureSpec.makeMeasureSpec(mCellWidth + mTouchFeedbackView.getExtraSize(),
+ MeasureSpec.EXACTLY),
+ MeasureSpec.makeMeasureSpec(mCellHeight + mTouchFeedbackView.getExtraSize(),
+ MeasureSpec.EXACTLY));
+
+ mShortcutsAndWidgets.measure(
+ MeasureSpec.makeMeasureSpec(newWidth, MeasureSpec.EXACTLY),
+ MeasureSpec.makeMeasureSpec(newHeight, MeasureSpec.EXACTLY));
+
+ int maxWidth = mShortcutsAndWidgets.getMeasuredWidth();
+ int maxHeight = mShortcutsAndWidgets.getMeasuredHeight();
if (mFixedWidth > 0 && mFixedHeight > 0) {
setMeasuredDimension(maxWidth, maxHeight);
} else {
@@ -903,13 +873,13 @@ public class CellLayout extends ViewGroup {
(mCountX * mCellWidth);
int left = getPaddingLeft() + (int) Math.ceil(offset / 2f);
int top = getPaddingTop();
- int count = getChildCount();
- for (int i = 0; i < count; i++) {
- View child = getChildAt(i);
- child.layout(left, top,
- left + r - l,
- top + b - t);
- }
+
+ mTouchFeedbackView.layout(left, top,
+ left + mTouchFeedbackView.getMeasuredWidth(),
+ top + mTouchFeedbackView.getMeasuredHeight());
+ mShortcutsAndWidgets.layout(left, top,
+ left + r - l,
+ top + b - t);
}
@Override
@@ -917,12 +887,9 @@ public class CellLayout extends ViewGroup {
super.onSizeChanged(w, h, oldw, oldh);
// Expand the background drawing bounds by the padding baked into the background drawable
- Rect padding = new Rect();
- mNormalBackground.getPadding(padding);
- mBackgroundRect.set(-padding.left, -padding.top, w + padding.right, h + padding.bottom);
-
- mForegroundRect.set(mForegroundPadding, mForegroundPadding,
- w - mForegroundPadding, h - mForegroundPadding);
+ mBackground.getPadding(mTempRect);
+ mBackground.setBounds(-mTempRect.left, -mTempRect.top,
+ w + mTempRect.right, h + mTempRect.bottom);
}
@Override
@@ -939,25 +906,18 @@ public class CellLayout extends ViewGroup {
return mBackgroundAlpha;
}
- public void setBackgroundAlphaMultiplier(float multiplier) {
-
- if (mBackgroundAlphaMultiplier != multiplier) {
- mBackgroundAlphaMultiplier = multiplier;
- invalidate();
- }
- }
-
- public float getBackgroundAlphaMultiplier() {
- return mBackgroundAlphaMultiplier;
- }
-
public void setBackgroundAlpha(float alpha) {
if (mBackgroundAlpha != alpha) {
mBackgroundAlpha = alpha;
- invalidate();
+ mBackground.setAlpha((int) (mBackgroundAlpha * 255));
}
}
+ @Override
+ protected boolean verifyDrawable(Drawable who) {
+ return super.verifyDrawable(who) || (mIsDragTarget && who == mBackground);
+ }
+
public void setShortcutAndWidgetAlpha(float alpha) {
mShortcutsAndWidgets.setAlpha(alpha);
}
@@ -1054,36 +1014,6 @@ public class CellLayout extends ViewGroup {
return false;
}
- /**
- * Estimate where the top left cell of the dragged item will land if it is dropped.
- *
- * @param originX The X value of the top left corner of the item
- * @param originY The Y value of the top left corner of the item
- * @param spanX The number of horizontal cells that the item spans
- * @param spanY The number of vertical cells that the item spans
- * @param result The estimated drop cell X and Y.
- */
- void estimateDropCell(int originX, int originY, int spanX, int spanY, int[] result) {
- final int countX = mCountX;
- final int countY = mCountY;
-
- // pointToCellRounded takes the top left of a cell but will pad that with
- // cellWidth/2 and cellHeight/2 when finding the matching cell
- pointToCellRounded(originX, originY, result);
-
- // If the item isn't fully on this screen, snap to the edges
- int rightOverhang = result[0] + spanX - countX;
- if (rightOverhang > 0) {
- result[0] -= rightOverhang; // Snap to right
- }
- result[0] = Math.max(0, result[0]); // Snap to left
- int bottomOverhang = result[1] + spanY - countY;
- if (bottomOverhang > 0) {
- result[1] -= bottomOverhang; // Snap to bottom
- }
- result[1] = Math.max(0, result[1]); // Snap to top
- }
-
void visualizeDropLocation(View v, Bitmap dragOutline, int originX, int originY, int cellX,
int cellY, int spanX, int spanY, boolean resize, Point dragOffset, Rect dragRegion) {
final int oldDragCellX = mDragCell[0];
@@ -1167,9 +1097,8 @@ public class CellLayout extends ViewGroup {
* @return The X, Y cell of a vacant area that can contain this object,
* nearest the requested location.
*/
- int[] findNearestVacantArea(int pixelX, int pixelY, int spanX, int spanY,
- int[] result) {
- return findNearestVacantArea(pixelX, pixelY, spanX, spanY, null, result);
+ int[] findNearestVacantArea(int pixelX, int pixelY, int spanX, int spanY, int[] result) {
+ return findNearestVacantArea(pixelX, pixelY, spanX, spanY, spanX, spanY, result, null);
}
/**
@@ -1189,30 +1118,10 @@ public class CellLayout extends ViewGroup {
*/
int[] findNearestVacantArea(int pixelX, int pixelY, int minSpanX, int minSpanY, int spanX,
int spanY, int[] result, int[] resultSpan) {
- return findNearestVacantArea(pixelX, pixelY, minSpanX, minSpanY, spanX, spanY, null,
+ return findNearestArea(pixelX, pixelY, minSpanX, minSpanY, spanX, spanY, true,
result, resultSpan);
}
- /**
- * Find a vacant area that will fit the given bounds nearest the requested
- * cell location. Uses Euclidean distance to score multiple vacant areas.
- *
- * @param pixelX The X location at which you want to search for a vacant area.
- * @param pixelY The Y location at which you want to search for a vacant area.
- * @param spanX Horizontal span of the object.
- * @param spanY Vertical span of the object.
- * @param ignoreOccupied If true, the result can be an occupied cell
- * @param result Array in which to place the result, or null (in which case a new array will
- * be allocated)
- * @return The X, Y cell of a vacant area that can contain this object,
- * nearest the requested location.
- */
- int[] findNearestArea(int pixelX, int pixelY, int spanX, int spanY, View ignoreView,
- boolean ignoreOccupied, int[] result) {
- return findNearestArea(pixelX, pixelY, spanX, spanY,
- spanX, spanY, ignoreView, ignoreOccupied, result, null, mOccupied);
- }
-
private final Stack<Rect> mTempRectStack = new Stack<Rect>();
private void lazyInitTempRectStack() {
if (mTempRectStack.isEmpty()) {
@@ -1244,12 +1153,9 @@ public class CellLayout extends ViewGroup {
* @return The X, Y cell of a vacant area that can contain this object,
* nearest the requested location.
*/
- int[] findNearestArea(int pixelX, int pixelY, int minSpanX, int minSpanY, int spanX, int spanY,
- View ignoreView, boolean ignoreOccupied, int[] result, int[] resultSpan,
- boolean[][] occupied) {
+ private int[] findNearestArea(int pixelX, int pixelY, int minSpanX, int minSpanY, int spanX,
+ int spanY, boolean ignoreOccupied, int[] result, int[] resultSpan) {
lazyInitTempRectStack();
- // mark space take by ignoreView as available (method checks if ignoreView is null)
- markCellsAsUnoccupiedForView(ignoreView, occupied);
// For items with a spanX / spanY > 1, the passed in point (pixelX, pixelY) corresponds
// to the center of the item, but we are searching based on the top-left cell, so
@@ -1280,7 +1186,7 @@ public class CellLayout extends ViewGroup {
// First, let's see if this thing fits anywhere
for (int i = 0; i < minSpanX; i++) {
for (int j = 0; j < minSpanY; j++) {
- if (occupied[x + i][y + j]) {
+ if (mOccupied[x + i][y + j]) {
continue inner;
}
}
@@ -1297,7 +1203,7 @@ public class CellLayout extends ViewGroup {
while (!(hitMaxX && hitMaxY)) {
if (incX && !hitMaxX) {
for (int j = 0; j < ySize; j++) {
- if (x + xSize > countX -1 || occupied[x + xSize][y + j]) {
+ if (x + xSize > countX -1 || mOccupied[x + xSize][y + j]) {
// We can't move out horizontally
hitMaxX = true;
}
@@ -1307,7 +1213,7 @@ public class CellLayout extends ViewGroup {
}
} else if (!hitMaxY) {
for (int i = 0; i < xSize; i++) {
- if (y + ySize > countY - 1 || occupied[x + i][y + ySize]) {
+ if (y + ySize > countY - 1 || mOccupied[x + i][y + ySize]) {
// We can't move out vertically
hitMaxY = true;
}
@@ -1324,7 +1230,7 @@ public class CellLayout extends ViewGroup {
hitMaxX = xSize >= spanX;
hitMaxY = ySize >= spanY;
}
- final int[] cellXY = mTmpXY;
+ final int[] cellXY = mTmpPoint;
cellToCenterPoint(x, y, cellXY);
// We verify that the current rect is not a sub-rect of any of our previous
@@ -1340,8 +1246,7 @@ public class CellLayout extends ViewGroup {
}
}
validRegions.push(currentRect);
- double distance = Math.sqrt(Math.pow(cellXY[0] - pixelX, 2)
- + Math.pow(cellXY[1] - pixelY, 2));
+ double distance = Math.hypot(cellXY[0] - pixelX, cellXY[1] - pixelY);
if ((distance <= bestDistance && !contained) ||
currentRect.contains(bestRect)) {
@@ -1356,8 +1261,6 @@ public class CellLayout extends ViewGroup {
}
}
}
- // re-mark space taken by ignoreView as occupied
- markCellsAsOccupiedForView(ignoreView, occupied);
// Return -1, -1 if no suitable location found
if (bestDistance == Double.MAX_VALUE) {
@@ -1411,8 +1314,7 @@ public class CellLayout extends ViewGroup {
}
}
- float distance = (float)
- Math.sqrt((x - cellX) * (x - cellX) + (y - cellY) * (y - cellY));
+ float distance = (float) Math.hypot(x - cellX, y - cellY);
int[] curDirection = mTmpPoint;
computeDirectionVector(x - cellX, y - cellY, curDirection);
// The direction score is just the dot product of the two candidate direction
@@ -2028,7 +1930,7 @@ public class CellLayout extends ViewGroup {
}
}
- ItemConfiguration findReorderSolution(int pixelX, int pixelY, int minSpanX, int minSpanY,
+ private ItemConfiguration findReorderSolution(int pixelX, int pixelY, int minSpanX, int minSpanY,
int spanX, int spanY, int[] direction, View dragView, boolean decX,
ItemConfiguration solution) {
// Copy the current state into the solution. This solution will be manipulated as necessary.
@@ -2264,7 +2166,7 @@ public class CellLayout extends ViewGroup {
}
}
- private void completeAnimationImmediately() {
+ @Thunk void completeAnimationImmediately() {
if (a != null) {
a.cancel();
}
@@ -2317,7 +2219,7 @@ public class CellLayout extends ViewGroup {
mLauncher.getWorkspace().updateItemLocationsInDatabase(this);
}
- public void setUseTempCoords(boolean useTempCoords) {
+ private void setUseTempCoords(boolean useTempCoords) {
int childCount = mShortcutsAndWidgets.getChildCount();
for (int i = 0; i < childCount; i++) {
LayoutParams lp = (LayoutParams) mShortcutsAndWidgets.getChildAt(i).getLayoutParams();
@@ -2325,11 +2227,11 @@ public class CellLayout extends ViewGroup {
}
}
- ItemConfiguration findConfigurationNoShuffle(int pixelX, int pixelY, int minSpanX, int minSpanY,
+ private ItemConfiguration findConfigurationNoShuffle(int pixelX, int pixelY, int minSpanX, int minSpanY,
int spanX, int spanY, View dragView, ItemConfiguration solution) {
int[] result = new int[2];
int[] resultSpan = new int[2];
- findNearestVacantArea(pixelX, pixelY, minSpanX, minSpanY, spanX, spanY, null, result,
+ findNearestVacantArea(pixelX, pixelY, minSpanX, minSpanY, spanX, spanY, result,
resultSpan);
if (result[0] >= 0 && result[1] >= 0) {
copyCurrentStateToSolution(solution, false);
@@ -2585,7 +2487,7 @@ public class CellLayout extends ViewGroup {
return mItemPlacementDirty;
}
- private class ItemConfiguration {
+ @Thunk class ItemConfiguration {
HashMap<View, CellAndSpan> map = new HashMap<View, CellAndSpan>();
private HashMap<View, CellAndSpan> savedMap = new HashMap<View, CellAndSpan>();
ArrayList<View> sortedViews = new ArrayList<View>();
@@ -2646,45 +2548,6 @@ public class CellLayout extends ViewGroup {
}
/**
- * Find a vacant area that will fit the given bounds nearest the requested
- * cell location. Uses Euclidean distance to score multiple vacant areas.
- *
- * @param pixelX The X location at which you want to search for a vacant area.
- * @param pixelY The Y location at which you want to search for a vacant area.
- * @param spanX Horizontal span of the object.
- * @param spanY Vertical span of the object.
- * @param ignoreView Considers space occupied by this view as unoccupied
- * @param result Previously returned value to possibly recycle.
- * @return The X, Y cell of a vacant area that can contain this object,
- * nearest the requested location.
- */
- int[] findNearestVacantArea(
- int pixelX, int pixelY, int spanX, int spanY, View ignoreView, int[] result) {
- return findNearestArea(pixelX, pixelY, spanX, spanY, ignoreView, true, result);
- }
-
- /**
- * Find a vacant area that will fit the given bounds nearest the requested
- * cell location. Uses Euclidean distance to score multiple vacant areas.
- *
- * @param pixelX The X location at which you want to search for a vacant area.
- * @param pixelY The Y location at which you want to search for a vacant area.
- * @param minSpanX The minimum horizontal span required
- * @param minSpanY The minimum vertical span required
- * @param spanX Horizontal span of the object.
- * @param spanY Vertical span of the object.
- * @param ignoreView Considers space occupied by this view as unoccupied
- * @param result Previously returned value to possibly recycle.
- * @return The X, Y cell of a vacant area that can contain this object,
- * nearest the requested location.
- */
- int[] findNearestVacantArea(int pixelX, int pixelY, int minSpanX, int minSpanY,
- int spanX, int spanY, View ignoreView, int[] result, int[] resultSpan) {
- return findNearestArea(pixelX, pixelY, minSpanX, minSpanY, spanX, spanY, ignoreView, true,
- result, resultSpan, mOccupied);
- }
-
- /**
* Find a starting cell position that will fit the given bounds nearest the requested
* cell location. Uses Euclidean distance to score multiple vacant areas.
*
@@ -2697,9 +2560,8 @@ public class CellLayout extends ViewGroup {
* @return The X, Y cell of a vacant area that can contain this object,
* nearest the requested location.
*/
- int[] findNearestArea(
- int pixelX, int pixelY, int spanX, int spanY, int[] result) {
- return findNearestArea(pixelX, pixelY, spanX, spanY, null, false, result);
+ int[] findNearestArea(int pixelX, int pixelY, int spanX, int spanY, int[] result) {
+ return findNearestArea(pixelX, pixelY, spanX, spanY, spanX, spanY, false, result, null);
}
boolean existsEmptyCell() {
@@ -2719,104 +2581,33 @@ public class CellLayout extends ViewGroup {
*
* @return True if a vacant cell of the specified dimension was found, false otherwise.
*/
- boolean findCellForSpan(int[] cellXY, int spanX, int spanY) {
- return findCellForSpanThatIntersectsIgnoring(cellXY, spanX, spanY, -1, -1, null, mOccupied);
- }
-
- /**
- * Like above, but ignores any cells occupied by the item "ignoreView"
- *
- * @param cellXY The array that will contain the position of a vacant cell if such a cell
- * can be found.
- * @param spanX The horizontal span of the cell we want to find.
- * @param spanY The vertical span of the cell we want to find.
- * @param ignoreView The home screen item we should treat as not occupying any space
- * @return
- */
- boolean findCellForSpanIgnoring(int[] cellXY, int spanX, int spanY, View ignoreView) {
- return findCellForSpanThatIntersectsIgnoring(cellXY, spanX, spanY, -1, -1,
- ignoreView, mOccupied);
- }
-
- /**
- * Like above, but if intersectX and intersectY are not -1, then this method will try to
- * return coordinates for rectangles that contain the cell [intersectX, intersectY]
- *
- * @param spanX The horizontal span of the cell we want to find.
- * @param spanY The vertical span of the cell we want to find.
- * @param ignoreView The home screen item we should treat as not occupying any space
- * @param intersectX The X coordinate of the cell that we should try to overlap
- * @param intersectX The Y coordinate of the cell that we should try to overlap
- *
- * @return True if a vacant cell of the specified dimension was found, false otherwise.
- */
- boolean findCellForSpanThatIntersects(int[] cellXY, int spanX, int spanY,
- int intersectX, int intersectY) {
- return findCellForSpanThatIntersectsIgnoring(
- cellXY, spanX, spanY, intersectX, intersectY, null, mOccupied);
- }
-
- /**
- * The superset of the above two methods
- */
- boolean findCellForSpanThatIntersectsIgnoring(int[] cellXY, int spanX, int spanY,
- int intersectX, int intersectY, View ignoreView, boolean occupied[][]) {
- // mark space take by ignoreView as available (method checks if ignoreView is null)
- markCellsAsUnoccupiedForView(ignoreView, occupied);
-
+ public boolean findCellForSpan(int[] cellXY, int spanX, int spanY) {
boolean foundCell = false;
- while (true) {
- int startX = 0;
- if (intersectX >= 0) {
- startX = Math.max(startX, intersectX - (spanX - 1));
- }
- int endX = mCountX - (spanX - 1);
- if (intersectX >= 0) {
- endX = Math.min(endX, intersectX + (spanX - 1) + (spanX == 1 ? 1 : 0));
- }
- int startY = 0;
- if (intersectY >= 0) {
- startY = Math.max(startY, intersectY - (spanY - 1));
- }
- int endY = mCountY - (spanY - 1);
- if (intersectY >= 0) {
- endY = Math.min(endY, intersectY + (spanY - 1) + (spanY == 1 ? 1 : 0));
- }
-
- for (int y = startY; y < endY && !foundCell; y++) {
- inner:
- for (int x = startX; x < endX; x++) {
- for (int i = 0; i < spanX; i++) {
- for (int j = 0; j < spanY; j++) {
- if (occupied[x + i][y + j]) {
- // small optimization: we can skip to after the column we just found
- // an occupied cell
- x += i;
- continue inner;
- }
+ final int endX = mCountX - (spanX - 1);
+ final int endY = mCountY - (spanY - 1);
+
+ for (int y = 0; y < endY && !foundCell; y++) {
+ inner:
+ for (int x = 0; x < endX; x++) {
+ for (int i = 0; i < spanX; i++) {
+ for (int j = 0; j < spanY; j++) {
+ if (mOccupied[x + i][y + j]) {
+ // small optimization: we can skip to after the column we just found
+ // an occupied cell
+ x += i;
+ continue inner;
}
}
- if (cellXY != null) {
- cellXY[0] = x;
- cellXY[1] = y;
- }
- foundCell = true;
- break;
}
- }
- if (intersectX == -1 && intersectY == -1) {
+ if (cellXY != null) {
+ cellXY[0] = x;
+ cellXY[1] = y;
+ }
+ foundCell = true;
break;
- } else {
- // if we failed to find anything, try again but without any requirements of
- // intersecting
- intersectX = -1;
- intersectY = -1;
- continue;
}
}
- // re-mark space taken by ignoreView as occupied
- markCellsAsOccupiedForView(ignoreView, occupied);
return foundCell;
}
@@ -2826,7 +2617,6 @@ public class CellLayout extends ViewGroup {
* or it may have begun on another layout.
*/
void onDragEnter() {
- mDragEnforcer.onDragEnter();
mDragging = true;
}
@@ -2834,7 +2624,6 @@ public class CellLayout extends ViewGroup {
* Called when drag has left this CellLayout or has been completed (successfully or not)
*/
void onDragExit() {
- mDragEnforcer.onDragExit();
// This can actually be called when we aren't in a drag, e.g. when adding a new
// item to this layout via the customize drawer.
// Guard against that case.
@@ -2900,18 +2689,20 @@ public class CellLayout extends ViewGroup {
* @param height Height in pixels
* @param result An array of length 2 in which to store the result (may be null).
*/
- public static int[] rectToCell(int width, int height, int[] result) {
- LauncherAppState app = LauncherAppState.getInstance();
- DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
- Rect padding = grid.getWorkspacePadding(grid.isLandscape ?
- CellLayout.LANDSCAPE : CellLayout.PORTRAIT);
+ public static int[] rectToCell(Launcher launcher, int width, int height, int[] result) {
+ return rectToCell(launcher.getDeviceProfile(), launcher, width, height, result);
+ }
+
+ public static int[] rectToCell(DeviceProfile grid, Context context, int width, int height,
+ int[] result) {
+ Rect padding = grid.getWorkspacePadding(Utilities.isRtl(context.getResources()));
// Always assume we're working with the smallest span to make sure we
// reserve enough space in both orientations.
- int parentWidth = grid.calculateCellWidth(grid.widthPx
- - padding.left - padding.right, (int) grid.numColumns);
- int parentHeight = grid.calculateCellHeight(grid.heightPx
- - padding.top - padding.bottom, (int) grid.numRows);
+ int parentWidth = DeviceProfile.calculateCellWidth(grid.widthPx
+ - padding.left - padding.right, (int) grid.inv.numColumns);
+ int parentHeight = DeviceProfile.calculateCellHeight(grid.heightPx
+ - padding.top - padding.bottom, (int) grid.inv.numRows);
int smallerSize = Math.min(parentWidth, parentHeight);
// Always round up to next largest cell
@@ -2926,13 +2717,6 @@ public class CellLayout extends ViewGroup {
return result;
}
- public int[] cellSpansToSize(int hSpans, int vSpans) {
- int[] size = new int[2];
- size[0] = hSpans * mCellWidth + (hSpans - 1) * mWidthGap;
- size[1] = vSpans * mCellHeight + (vSpans - 1) * mHeightGap;
- return size;
- }
-
/**
* Calculate the grid spans needed to fit given item
*/
@@ -2951,49 +2735,11 @@ public class CellLayout extends ViewGroup {
info.spanX = info.spanY = 1;
return;
}
- int[] spans = rectToCell(minWidth, minHeight, null);
+ int[] spans = rectToCell(mLauncher, minWidth, minHeight, null);
info.spanX = spans[0];
info.spanY = spans[1];
}
- /**
- * Find the first vacant cell, if there is one.
- *
- * @param vacant Holds the x and y coordinate of the vacant cell
- * @param spanX Horizontal cell span.
- * @param spanY Vertical cell span.
- *
- * @return True if a vacant cell was found
- */
- public boolean getVacantCell(int[] vacant, int spanX, int spanY) {
-
- return findVacantCell(vacant, spanX, spanY, mCountX, mCountY, mOccupied);
- }
-
- static boolean findVacantCell(int[] vacant, int spanX, int spanY,
- int xCount, int yCount, boolean[][] occupied) {
-
- for (int y = 0; y < yCount; y++) {
- for (int x = 0; x < xCount; x++) {
- boolean available = !occupied[x][y];
-out: for (int i = x; i < x + spanX - 1 && x < xCount; i++) {
- for (int j = y; j < y + spanY - 1 && y < yCount; j++) {
- available = available && !occupied[i][j];
- if (!available) break out;
- }
- }
-
- if (available) {
- vacant[0] = x;
- vacant[1] = y;
- return true;
- }
- }
- }
-
- return false;
- }
-
private void clearOccupiedCells() {
for (int x = 0; x < mCountX; x++) {
for (int y = 0; y < mCountY; y++) {
@@ -3002,27 +2748,16 @@ out: for (int i = x; i < x + spanX - 1 && x < xCount; i++) {
}
}
- public void onMove(View view, int newCellX, int newCellY, int newSpanX, int newSpanY) {
- markCellsAsUnoccupiedForView(view);
- markCellsForView(newCellX, newCellY, newSpanX, newSpanY, mOccupied, true);
- }
-
public void markCellsAsOccupiedForView(View view) {
- markCellsAsOccupiedForView(view, mOccupied);
- }
- public void markCellsAsOccupiedForView(View view, boolean[][] occupied) {
if (view == null || view.getParent() != mShortcutsAndWidgets) return;
LayoutParams lp = (LayoutParams) view.getLayoutParams();
- markCellsForView(lp.cellX, lp.cellY, lp.cellHSpan, lp.cellVSpan, occupied, true);
+ markCellsForView(lp.cellX, lp.cellY, lp.cellHSpan, lp.cellVSpan, mOccupied, true);
}
public void markCellsAsUnoccupiedForView(View view) {
- markCellsAsUnoccupiedForView(view, mOccupied);
- }
- public void markCellsAsUnoccupiedForView(View view, boolean occupied[][]) {
if (view == null || view.getParent() != mShortcutsAndWidgets) return;
LayoutParams lp = (LayoutParams) view.getLayoutParams();
- markCellsForView(lp.cellX, lp.cellY, lp.cellHSpan, lp.cellVSpan, occupied, false);
+ markCellsForView(lp.cellX, lp.cellY, lp.cellHSpan, lp.cellVSpan, mOccupied, false);
}
private void markCellsForView(int cellX, int cellY, int spanX, int spanY, boolean[][] occupied,
@@ -3068,17 +2803,6 @@ out: for (int i = x; i < x + spanX - 1 && x < xCount; i++) {
return new CellLayout.LayoutParams(p);
}
- public static class CellLayoutAnimationController extends LayoutAnimationController {
- public CellLayoutAnimationController(Animation animation, float delay) {
- super(animation, delay);
- }
-
- @Override
- protected long getDelayForView(View view) {
- return (int) (Math.random() * 150);
- }
- }
-
public static class LayoutParams extends ViewGroup.MarginLayoutParams {
/**
* Horizontal location of the item in the grid.
@@ -3237,7 +2961,7 @@ out: for (int i = x; i < x + spanX - 1 && x < xCount; i++) {
// 2. When long clicking on an empty cell in a CellLayout, we save information about the
// cellX and cellY coordinates and which page was clicked. We then set this as a tag on
// the CellLayout that was long clicked
- static final class CellInfo {
+ public static final class CellInfo {
View cell;
int cellX = -1;
int cellY = -1;
@@ -3246,7 +2970,7 @@ out: for (int i = x; i < x + spanX - 1 && x < xCount; i++) {
long screenId;
long container;
- CellInfo(View v, ItemInfo info) {
+ public CellInfo(View v, ItemInfo info) {
cell = v;
cellX = info.cellX;
cellY = info.cellY;
@@ -3263,7 +2987,24 @@ out: for (int i = x; i < x + spanX - 1 && x < xCount; i++) {
}
}
- public boolean lastDownOnOccupiedCell() {
- return mLastDownOnOccupiedCell;
+ public boolean findVacantCell(int spanX, int spanY, int[] outXY) {
+ return Utilities.findVacantCell(outXY, spanX, spanY, mCountX, mCountY, mOccupied);
+ }
+
+ public boolean isRegionVacant(int x, int y, int spanX, int spanY) {
+ int x2 = x + spanX - 1;
+ int y2 = y + spanY - 1;
+ if (x < 0 || y < 0 || x2 >= mCountX || y2 >= mCountY) {
+ return false;
+ }
+ for (int i = x; i <= x2; i++) {
+ for (int j = y; j <= y2; j++) {
+ if (mOccupied[i][j]) {
+ return false;
+ }
+ }
+ }
+
+ return true;
}
}
diff --git a/src/com/android/launcher3/CheckLongPressHelper.java b/src/com/android/launcher3/CheckLongPressHelper.java
index 81149793d..483c62249 100644
--- a/src/com/android/launcher3/CheckLongPressHelper.java
+++ b/src/com/android/launcher3/CheckLongPressHelper.java
@@ -18,16 +18,27 @@ package com.android.launcher3;
import android.view.View;
+import com.android.launcher3.util.Thunk;
+
public class CheckLongPressHelper {
- private View mView;
- private boolean mHasPerformedLongPress;
+
+ @Thunk View mView;
+ @Thunk View.OnLongClickListener mListener;
+ @Thunk boolean mHasPerformedLongPress;
+ private int mLongPressTimeout = 300;
private CheckForLongPress mPendingCheckForLongPress;
class CheckForLongPress implements Runnable {
public void run() {
if ((mView.getParent() != null) && mView.hasWindowFocus()
&& !mHasPerformedLongPress) {
- if (mView.performLongClick()) {
+ boolean handled;
+ if (mListener != null) {
+ handled = mListener.onLongClick(mView);
+ } else {
+ handled = mView.performLongClick();
+ }
+ if (handled) {
mView.setPressed(false);
mHasPerformedLongPress = true;
}
@@ -39,14 +50,25 @@ public class CheckLongPressHelper {
mView = v;
}
+ public CheckLongPressHelper(View v, View.OnLongClickListener listener) {
+ mView = v;
+ mListener = listener;
+ }
+
+ /**
+ * Overrides the default long press timeout.
+ */
+ public void setLongPressTimeout(int longPressTimeout) {
+ mLongPressTimeout = longPressTimeout;
+ }
+
public void postCheckForLongPress() {
mHasPerformedLongPress = false;
if (mPendingCheckForLongPress == null) {
mPendingCheckForLongPress = new CheckForLongPress();
}
- mView.postDelayed(mPendingCheckForLongPress,
- LauncherAppState.getInstance().getLongPressTimeout());
+ mView.postDelayed(mPendingCheckForLongPress, mLongPressTimeout);
}
public void cancelLongPress() {
diff --git a/src/com/android/launcher3/ClickShadowView.java b/src/com/android/launcher3/ClickShadowView.java
new file mode 100644
index 000000000..e31d7f7f6
--- /dev/null
+++ b/src/com/android/launcher3/ClickShadowView.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2014 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;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.view.View;
+import android.view.ViewGroup;
+
+public class ClickShadowView extends View {
+
+ private static final int SHADOW_SIZE_FACTOR = 3;
+ private static final int SHADOW_LOW_ALPHA = 30;
+ private static final int SHADOW_HIGH_ALPHA = 60;
+
+ private final Paint mPaint;
+
+ private final float mShadowOffset;
+ private final float mShadowPadding;
+
+ private Bitmap mBitmap;
+
+ public ClickShadowView(Context context) {
+ super(context);
+ mPaint = new Paint(Paint.FILTER_BITMAP_FLAG);
+ mPaint.setColor(Color.BLACK);
+
+ mShadowPadding = getResources().getDimension(R.dimen.blur_size_click_shadow);
+ mShadowOffset = getResources().getDimension(R.dimen.click_shadow_high_shift);
+ }
+
+ /**
+ * @return extra space required by the view to show the shadow.
+ */
+ public int getExtraSize() {
+ return (int) (SHADOW_SIZE_FACTOR * mShadowPadding);
+ }
+
+ /**
+ * Applies the new bitmap.
+ * @return true if the view was invalidated.
+ */
+ public boolean setBitmap(Bitmap b) {
+ if (b != mBitmap){
+ mBitmap = b;
+ invalidate();
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ if (mBitmap != null) {
+ mPaint.setAlpha(SHADOW_LOW_ALPHA);
+ canvas.drawBitmap(mBitmap, 0, 0, mPaint);
+ mPaint.setAlpha(SHADOW_HIGH_ALPHA);
+ canvas.drawBitmap(mBitmap, 0, mShadowOffset, mPaint);
+ }
+ }
+
+ public void animateShadow() {
+ setAlpha(0);
+ animate().alpha(1)
+ .setDuration(FastBitmapDrawable.CLICK_FEEDBACK_DURATION)
+ .setInterpolator(FastBitmapDrawable.CLICK_FEEDBACK_INTERPOLATOR)
+ .start();
+ }
+
+ /**
+ * Aligns the shadow with {@param view}
+ * @param viewParent immediate parent of {@param view}. It must be a sibling of this view.
+ */
+ public void alignWithIconView(BubbleTextView view, ViewGroup viewParent) {
+ float leftShift = view.getLeft() + viewParent.getLeft() - getLeft();
+ float topShift = view.getTop() + viewParent.getTop() - getTop();
+ int iconWidth = view.getRight() - view.getLeft();
+ int iconHSpace = iconWidth - view.getCompoundPaddingRight() - view.getCompoundPaddingLeft();
+ float drawableWidth = view.getIcon().getBounds().width();
+
+ setTranslationX(leftShift
+ + viewParent.getTranslationX()
+ + view.getCompoundPaddingLeft() * view.getScaleX()
+ + (iconHSpace - drawableWidth) * view.getScaleX() / 2 /* drawable gap */
+ + iconWidth * (1 - view.getScaleX()) / 2 /* gap due to scale */
+ - mShadowPadding /* extra shadow size */
+ );
+ setTranslationY(topShift
+ + viewParent.getTranslationY()
+ + view.getPaddingTop() * view.getScaleY() /* drawable gap */
+ + view.getHeight() * (1 - view.getScaleY()) / 2 /* gap due to scale */
+ - mShadowPadding /* extra shadow size */
+ );
+ }
+}
diff --git a/src/com/android/launcher3/CommonAppTypeParser.java b/src/com/android/launcher3/CommonAppTypeParser.java
new file mode 100644
index 000000000..5314ecff1
--- /dev/null
+++ b/src/com/android/launcher3/CommonAppTypeParser.java
@@ -0,0 +1,153 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3;
+
+import android.content.ContentValues;
+import android.content.Context;
+import android.content.Intent;
+import android.content.res.XmlResourceParser;
+import android.database.sqlite.SQLiteDatabase;
+import android.util.Log;
+
+import com.android.launcher3.AutoInstallsLayout.LayoutParserCallback;
+import com.android.launcher3.LauncherSettings.Favorites;
+import com.android.launcher3.backup.BackupProtos.Favorite;
+import com.android.launcher3.util.Thunk;
+
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
+
+/**
+ * A class that parses content values corresponding to some common app types.
+ */
+public class CommonAppTypeParser implements LayoutParserCallback {
+ private static final String TAG = "CommonAppTypeParser";
+
+ // Including TARGET_NONE
+ public static final int SUPPORTED_TYPE_COUNT = 7;
+
+ private static final int RESTORE_FLAG_BIT_SHIFT = 4;
+
+
+ private final long mItemId;
+ @Thunk final int mResId;
+ @Thunk final Context mContext;
+
+ ContentValues parsedValues;
+ Intent parsedIntent;
+ String parsedTitle;
+
+ public CommonAppTypeParser(long itemId, int itemType, Context context) {
+ mItemId = itemId;
+ mContext = context;
+ mResId = getResourceForItemType(itemType);
+ }
+
+ @Override
+ public long generateNewItemId() {
+ return mItemId;
+ }
+
+ @Override
+ public long insertAndCheck(SQLiteDatabase db, ContentValues values) {
+ parsedValues = values;
+
+ // Remove unwanted values
+ values.put(Favorites.ICON_TYPE, (Integer) null);
+ values.put(Favorites.ICON_PACKAGE, (String) null);
+ values.put(Favorites.ICON_RESOURCE, (String) null);
+ values.put(Favorites.ICON, (byte[]) null);
+ return 1;
+ }
+
+ /**
+ * Tries to find a suitable app to the provided app type.
+ */
+ public boolean findDefaultApp() {
+ if (mResId == 0) {
+ return false;
+ }
+
+ parsedIntent = null;
+ parsedValues = null;
+ new MyLayoutParser().parseValues();
+ return (parsedValues != null) && (parsedIntent != null);
+ }
+
+ private class MyLayoutParser extends DefaultLayoutParser {
+
+ public MyLayoutParser() {
+ super(CommonAppTypeParser.this.mContext, null, CommonAppTypeParser.this,
+ CommonAppTypeParser.this.mContext.getResources(), mResId, TAG_RESOLVE, 0);
+ }
+
+ @Override
+ protected long addShortcut(String title, Intent intent, int type) {
+ if (type == Favorites.ITEM_TYPE_APPLICATION) {
+ parsedIntent = intent;
+ parsedTitle = title;
+ }
+ return super.addShortcut(title, intent, type);
+ }
+
+ public void parseValues() {
+ XmlResourceParser parser = mSourceRes.getXml(mLayoutId);
+ try {
+ beginDocument(parser, mRootTag);
+ new ResolveParser().parseAndAdd(parser);
+ } catch (IOException | XmlPullParserException e) {
+ Log.e(TAG, "Unable to parse default app info", e);
+ }
+ parser.close();
+ }
+ }
+
+ public static int getResourceForItemType(int type) {
+ switch (type) {
+ case Favorite.TARGET_PHONE:
+ return R.xml.app_target_phone;
+
+ case Favorite.TARGET_MESSENGER:
+ return R.xml.app_target_messenger;
+
+ case Favorite.TARGET_EMAIL:
+ return R.xml.app_target_email;
+
+ case Favorite.TARGET_BROWSER:
+ return R.xml.app_target_browser;
+
+ case Favorite.TARGET_GALLERY:
+ return R.xml.app_target_gallery;
+
+ case Favorite.TARGET_CAMERA:
+ return R.xml.app_target_camera;
+
+ default:
+ return 0;
+ }
+ }
+
+ public static int encodeItemTypeToFlag(int itemType) {
+ return itemType << RESTORE_FLAG_BIT_SHIFT;
+ }
+
+ public static int decodeItemTypeFromFlag(int flag) {
+ return (flag & ShortcutInfo.FLAG_RESTORED_APP_TYPE) >> RESTORE_FLAG_BIT_SHIFT;
+ }
+
+}
diff --git a/src/com/android/launcher3/CustomAppWidget.java b/src/com/android/launcher3/CustomAppWidget.java
new file mode 100644
index 000000000..1b4ed79c0
--- /dev/null
+++ b/src/com/android/launcher3/CustomAppWidget.java
@@ -0,0 +1,14 @@
+package com.android.launcher3;
+
+public interface CustomAppWidget {
+ public String getLabel();
+ public int getPreviewImage();
+ public int getIcon();
+ public int getWidgetLayout();
+
+ public int getSpanX();
+ public int getSpanY();
+ public int getMinSpanX();
+ public int getMinSpanY();
+ public int getResizeMode();
+}
diff --git a/src/com/android/launcher3/DefaultLayoutParser.java b/src/com/android/launcher3/DefaultLayoutParser.java
index e3ea40ebb..7b91c675b 100644
--- a/src/com/android/launcher3/DefaultLayoutParser.java
+++ b/src/com/android/launcher3/DefaultLayoutParser.java
@@ -13,13 +13,13 @@ import android.text.TextUtils;
import android.util.Log;
import com.android.launcher3.LauncherSettings.Favorites;
+import com.android.launcher3.util.Thunk;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import java.io.IOException;
import java.net.URISyntaxException;
-import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@@ -29,17 +29,15 @@ import java.util.List;
public class DefaultLayoutParser extends AutoInstallsLayout {
private static final String TAG = "DefaultLayoutParser";
- private static final String TAG_RESOLVE = "resolve";
+ protected static final String TAG_RESOLVE = "resolve";
private static final String TAG_FAVORITES = "favorites";
- private static final String TAG_FAVORITE = "favorite";
+ protected static final String TAG_FAVORITE = "favorite";
private static final String TAG_APPWIDGET = "appwidget";
private static final String TAG_SHORTCUT = "shortcut";
private static final String TAG_FOLDER = "folder";
private static final String TAG_PARTNER_FOLDER = "partner-folder";
- private static final String TAG_INCLUDE = "include";
- private static final String ATTR_URI = "uri";
- private static final String ATTR_WORKSPACE = "workspace";
+ protected static final String ATTR_URI = "uri";
private static final String ATTR_CONTAINER = "container";
private static final String ATTR_SCREEN = "screen";
private static final String ATTR_FOLDER_ITEMS = "folderItems";
@@ -47,7 +45,12 @@ public class DefaultLayoutParser extends AutoInstallsLayout {
public DefaultLayoutParser(Context context, AppWidgetHost appWidgetHost,
LayoutParserCallback callback, Resources sourceRes, int layoutId) {
super(context, appWidgetHost, callback, sourceRes, layoutId, TAG_FAVORITES);
- Log.e(TAG, "Default layout parser initialized");
+ }
+
+ public DefaultLayoutParser(Context context, AppWidgetHost appWidgetHost,
+ LayoutParserCallback callback, Resources sourceRes, int layoutId, String rootTag,
+ int hotseatAllAppsRank) {
+ super(context, appWidgetHost, callback, sourceRes, layoutId, rootTag, hotseatAllAppsRank);
}
@Override
@@ -55,7 +58,7 @@ public class DefaultLayoutParser extends AutoInstallsLayout {
return getFolderElementsMap(mSourceRes);
}
- private HashMap<String, TagParser> getFolderElementsMap(Resources res) {
+ @Thunk HashMap<String, TagParser> getFolderElementsMap(Resources res) {
HashMap<String, TagParser> parsers = new HashMap<String, TagParser>();
parsers.put(TAG_FAVORITE, new AppShortcutWithUriParser());
parsers.put(TAG_SHORTCUT, new UriShortcutParser(res));
@@ -84,29 +87,10 @@ public class DefaultLayoutParser extends AutoInstallsLayout {
out[1] = Long.parseLong(getAttributeValue(parser, ATTR_SCREEN));
}
- @Override
- protected int parseAndAddNode(
- XmlResourceParser parser,
- HashMap<String, TagParser> tagParserMap,
- ArrayList<Long> screenIds)
- throws XmlPullParserException, IOException {
- if (TAG_INCLUDE.equals(parser.getName())) {
- final int resId = getAttributeResourceValue(parser, ATTR_WORKSPACE, 0);
- if (resId != 0) {
- // recursively load some more favorites, why not?
- return parseLayout(resId, screenIds);
- } else {
- return 0;
- }
- } else {
- return super.parseAndAddNode(parser, tagParserMap, screenIds);
- }
- }
-
/**
* AppShortcutParser which also supports adding URI based intents
*/
- private class AppShortcutWithUriParser extends AppShortcutParser {
+ @Thunk class AppShortcutWithUriParser extends AppShortcutParser {
@Override
protected long invalidPackageOrClass(XmlResourceParser parser) {
@@ -218,7 +202,7 @@ public class DefaultLayoutParser extends AutoInstallsLayout {
/**
* Contains a list of <favorite> nodes, and accepts the first successfully parsed node.
*/
- private class ResolveParser implements TagParser {
+ protected class ResolveParser implements TagParser {
private final AppShortcutWithUriParser mChildParser = new AppShortcutWithUriParser();
@@ -248,7 +232,7 @@ public class DefaultLayoutParser extends AutoInstallsLayout {
/**
* A parser which adds a folder whose contents come from partner apk.
*/
- private class PartnerFolderParser implements TagParser {
+ @Thunk class PartnerFolderParser implements TagParser {
@Override
public long parseAndAdd(XmlResourceParser parser) throws XmlPullParserException,
@@ -274,7 +258,7 @@ public class DefaultLayoutParser extends AutoInstallsLayout {
/**
* An extension of FolderParser which allows adding items from a different xml.
*/
- private class MyFolderParser extends FolderParser {
+ @Thunk class MyFolderParser extends FolderParser {
@Override
public long parseAndAdd(XmlResourceParser parser) throws XmlPullParserException,
diff --git a/src/com/android/launcher3/DeferredHandler.java b/src/com/android/launcher3/DeferredHandler.java
index a2d121d63..a43ab6723 100644
--- a/src/com/android/launcher3/DeferredHandler.java
+++ b/src/com/android/launcher3/DeferredHandler.java
@@ -20,10 +20,10 @@ import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.MessageQueue;
-import android.util.Pair;
+
+import com.android.launcher3.util.Thunk;
import java.util.LinkedList;
-import java.util.ListIterator;
/**
* Queue of things to run on a looper thread. Items posted with {@link #post} will not
@@ -33,20 +33,18 @@ import java.util.ListIterator;
* This class is fifo.
*/
public class DeferredHandler {
- private LinkedList<Pair<Runnable, Integer>> mQueue = new LinkedList<Pair<Runnable, Integer>>();
+ @Thunk LinkedList<Runnable> mQueue = new LinkedList<>();
private MessageQueue mMessageQueue = Looper.myQueue();
private Impl mHandler = new Impl();
- private class Impl extends Handler implements MessageQueue.IdleHandler {
+ @Thunk class Impl extends Handler implements MessageQueue.IdleHandler {
public void handleMessage(Message msg) {
- Pair<Runnable, Integer> p;
Runnable r;
synchronized (mQueue) {
if (mQueue.size() == 0) {
return;
}
- p = mQueue.removeFirst();
- r = p.first;
+ r = mQueue.removeFirst();
}
r.run();
synchronized (mQueue) {
@@ -77,11 +75,8 @@ public class DeferredHandler {
/** Schedule runnable to run after everything that's on the queue right now. */
public void post(Runnable runnable) {
- post(runnable, 0);
- }
- public void post(Runnable runnable, int type) {
synchronized (mQueue) {
- mQueue.add(new Pair<Runnable, Integer>(runnable, type));
+ mQueue.add(runnable);
if (mQueue.size() == 1) {
scheduleNextLocked();
}
@@ -90,31 +85,10 @@ public class DeferredHandler {
/** Schedule runnable to run when the queue goes idle. */
public void postIdle(final Runnable runnable) {
- postIdle(runnable, 0);
- }
- public void postIdle(final Runnable runnable, int type) {
- post(new IdleRunnable(runnable), type);
+ post(new IdleRunnable(runnable));
}
- public void cancelRunnable(Runnable runnable) {
- synchronized (mQueue) {
- while (mQueue.remove(runnable)) { }
- }
- }
- public void cancelAllRunnablesOfType(int type) {
- synchronized (mQueue) {
- ListIterator<Pair<Runnable, Integer>> iter = mQueue.listIterator();
- Pair<Runnable, Integer> p;
- while (iter.hasNext()) {
- p = iter.next();
- if (p.second == type) {
- iter.remove();
- }
- }
- }
- }
-
- public void cancel() {
+ public void cancelAll() {
synchronized (mQueue) {
mQueue.clear();
}
@@ -122,20 +96,19 @@ public class DeferredHandler {
/** Runs all queued Runnables from the calling thread. */
public void flush() {
- LinkedList<Pair<Runnable, Integer>> queue = new LinkedList<Pair<Runnable, Integer>>();
+ LinkedList<Runnable> queue = new LinkedList<>();
synchronized (mQueue) {
queue.addAll(mQueue);
mQueue.clear();
}
- for (Pair<Runnable, Integer> p : queue) {
- p.first.run();
+ for (Runnable r : queue) {
+ r.run();
}
}
void scheduleNextLocked() {
if (mQueue.size() > 0) {
- Pair<Runnable, Integer> p = mQueue.getFirst();
- Runnable peek = p.first;
+ Runnable peek = mQueue.getFirst();
if (peek instanceof IdleRunnable) {
mMessageQueue.addIdleHandler(mHandler);
} else {
diff --git a/src/com/android/launcher3/DeleteDropTarget.java b/src/com/android/launcher3/DeleteDropTarget.java
index ea058ea71..9c8659c29 100644
--- a/src/com/android/launcher3/DeleteDropTarget.java
+++ b/src/com/android/launcher3/DeleteDropTarget.java
@@ -17,45 +17,17 @@
package com.android.launcher3;
import android.animation.TimeInterpolator;
-import android.animation.ValueAnimator;
-import android.animation.ValueAnimator.AnimatorUpdateListener;
-import android.content.ComponentName;
import android.content.Context;
-import android.content.res.ColorStateList;
-import android.content.res.Configuration;
-import android.content.res.Resources;
import android.graphics.PointF;
-import android.graphics.Rect;
-import android.graphics.drawable.TransitionDrawable;
import android.os.AsyncTask;
-import android.os.Build;
-import android.os.Bundle;
-import android.os.UserManager;
import android.util.AttributeSet;
import android.view.View;
-import android.view.ViewConfiguration;
-import android.view.ViewGroup;
import android.view.animation.AnimationUtils;
-import android.view.animation.DecelerateInterpolator;
-import android.view.animation.LinearInterpolator;
-import com.android.launcher3.compat.UserHandleCompat;
+import com.android.launcher3.util.FlingAnimation;
+import com.android.launcher3.util.Thunk;
public class DeleteDropTarget extends ButtonDropTarget {
- private static int DELETE_ANIMATION_DURATION = 285;
- private static int FLING_DELETE_ANIMATION_DURATION = 350;
- private static float FLING_TO_DELETE_FRICTION = 0.035f;
- private static int MODE_FLING_DELETE_TO_TRASH = 0;
- private static int MODE_FLING_DELETE_ALONG_VECTOR = 1;
-
- private final int mFlingDeleteMode = MODE_FLING_DELETE_ALONG_VECTOR;
-
- private ColorStateList mOriginalTextColor;
- private TransitionDrawable mUninstallDrawable;
- private TransitionDrawable mRemoveDrawable;
- private TransitionDrawable mCurrentDrawable;
-
- private boolean mWaitingForUninstall = false;
public DeleteDropTarget(Context context, AttributeSet attrs) {
this(context, attrs, 0);
@@ -68,442 +40,86 @@ public class DeleteDropTarget extends ButtonDropTarget {
@Override
protected void onFinishInflate() {
super.onFinishInflate();
-
- // Get the drawable
- mOriginalTextColor = getTextColors();
-
// Get the hover color
- Resources r = getResources();
- mHoverColor = r.getColor(R.color.delete_target_hover_tint);
- mUninstallDrawable = (TransitionDrawable)
- r.getDrawable(R.drawable.uninstall_target_selector);
- mRemoveDrawable = (TransitionDrawable) r.getDrawable(R.drawable.remove_target_selector);
-
- mRemoveDrawable.setCrossFadeEnabled(true);
- mUninstallDrawable.setCrossFadeEnabled(true);
-
- // The current drawable is set to either the remove drawable or the uninstall drawable
- // and is initially set to the remove drawable, as set in the layout xml.
- mCurrentDrawable = (TransitionDrawable) getCurrentDrawable();
-
- // Remove the text in the Phone UI in landscape
- int orientation = getResources().getConfiguration().orientation;
- if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
- if (!LauncherAppState.getInstance().isScreenLarge()) {
- setText("");
- }
- }
- }
+ mHoverColor = getResources().getColor(R.color.delete_target_hover_tint);
- private boolean isAllAppsApplication(DragSource source, Object info) {
- return source.supportsAppInfoDropTarget() && (info instanceof AppInfo);
- }
- private boolean isAllAppsWidget(DragSource source, Object info) {
- if (source instanceof AppsCustomizePagedView) {
- if (info instanceof PendingAddItemInfo) {
- PendingAddItemInfo addInfo = (PendingAddItemInfo) info;
- switch (addInfo.itemType) {
- case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
- case LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET:
- return true;
- }
- }
- }
- return false;
- }
- private boolean isDragSourceWorkspaceOrFolder(DragObject d) {
- return (d.dragSource instanceof Workspace) || (d.dragSource instanceof Folder);
- }
- private boolean isWorkspaceOrFolderApplication(DragObject d) {
- return isDragSourceWorkspaceOrFolder(d) && (d.dragInfo instanceof ShortcutInfo);
- }
- private boolean isWorkspaceOrFolderWidget(DragObject d) {
- return isDragSourceWorkspaceOrFolder(d) && (d.dragInfo instanceof LauncherAppWidgetInfo);
- }
- private boolean isWorkspaceFolder(DragObject d) {
- return (d.dragSource instanceof Workspace) && (d.dragInfo instanceof FolderInfo);
+ setDrawable(R.drawable.ic_remove_launcher);
}
- private void setHoverColor() {
- if (mCurrentDrawable != null) {
- mCurrentDrawable.startTransition(mTransitionDuration);
- }
- setTextColor(mHoverColor);
- }
- private void resetHoverColor() {
- if (mCurrentDrawable != null) {
- mCurrentDrawable.resetTransition();
- }
- setTextColor(mOriginalTextColor);
+ public static boolean supportsDrop(Object info) {
+ return (info instanceof ShortcutInfo)
+ || (info instanceof LauncherAppWidgetInfo)
+ || (info instanceof FolderInfo);
}
@Override
- public boolean acceptDrop(DragObject d) {
- return willAcceptDrop(d.dragInfo);
- }
-
- public static boolean willAcceptDrop(Object info) {
- if (info instanceof ItemInfo) {
- ItemInfo item = (ItemInfo) info;
- if (item.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET ||
- item.itemType == LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT) {
- return true;
- }
-
- if (!LauncherAppState.isDisableAllApps() &&
- item.itemType == LauncherSettings.Favorites.ITEM_TYPE_FOLDER) {
- return true;
- }
-
- if (!LauncherAppState.isDisableAllApps() &&
- item.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION &&
- item instanceof AppInfo) {
- AppInfo appInfo = (AppInfo) info;
- return (appInfo.flags & AppInfo.DOWNLOADED_FLAG) != 0;
- }
-
- if (item.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION &&
- item instanceof ShortcutInfo) {
- if (LauncherAppState.isDisableAllApps()) {
- ShortcutInfo shortcutInfo = (ShortcutInfo) info;
- return (shortcutInfo.flags & AppInfo.DOWNLOADED_FLAG) != 0;
- } else {
- return true;
- }
- }
- }
- return false;
- }
-
- @Override
- public void onDragStart(DragSource source, Object info, int dragAction) {
- boolean isVisible = true;
- boolean useUninstallLabel = !LauncherAppState.isDisableAllApps() &&
- isAllAppsApplication(source, info);
- boolean useDeleteLabel = !useUninstallLabel && source.supportsDeleteDropTarget();
-
- // If we are dragging an application from AppsCustomize, only show the control if we can
- // delete the app (it was downloaded), and rename the string to "uninstall" in such a case.
- // Hide the delete target if it is a widget from AppsCustomize.
- if (!willAcceptDrop(info) || isAllAppsWidget(source, info)) {
- isVisible = false;
- }
- if (useUninstallLabel) {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
- UserManager userManager = (UserManager)
- getContext().getSystemService(Context.USER_SERVICE);
- Bundle restrictions = userManager.getUserRestrictions();
- if (restrictions.getBoolean(UserManager.DISALLOW_APPS_CONTROL, false)
- || restrictions.getBoolean(UserManager.DISALLOW_UNINSTALL_APPS, false)) {
- isVisible = false;
- }
- }
- }
-
- if (useUninstallLabel) {
- setCompoundDrawablesRelativeWithIntrinsicBounds(mUninstallDrawable, null, null, null);
- } else if (useDeleteLabel) {
- setCompoundDrawablesRelativeWithIntrinsicBounds(mRemoveDrawable, null, null, null);
- } else {
- isVisible = false;
- }
- mCurrentDrawable = (TransitionDrawable) getCurrentDrawable();
-
- mActive = isVisible;
- resetHoverColor();
- ((ViewGroup) getParent()).setVisibility(isVisible ? View.VISIBLE : View.GONE);
- if (isVisible && getText().length() > 0) {
- setText(useUninstallLabel ? R.string.delete_target_uninstall_label
- : R.string.delete_target_label);
- }
+ protected boolean supportsDrop(DragSource source, Object info) {
+ return source.supportsDeleteDropTarget() && supportsDrop(info);
}
@Override
- public void onDragEnd() {
- super.onDragEnd();
- mActive = false;
- }
-
- public void onDragEnter(DragObject d) {
- super.onDragEnter(d);
-
- setHoverColor();
- }
-
- public void onDragExit(DragObject d) {
- super.onDragExit(d);
-
- if (!d.dragComplete) {
- resetHoverColor();
- } else {
- // Restore the hover color if we are deleting
- d.dragView.setColor(mHoverColor);
- }
- }
-
- private void animateToTrashAndCompleteDrop(final DragObject d) {
- final DragLayer dragLayer = mLauncher.getDragLayer();
- final Rect from = new Rect();
- dragLayer.getViewRectRelativeToSelf(d.dragView, from);
-
- int width = mCurrentDrawable == null ? 0 : mCurrentDrawable.getIntrinsicWidth();
- int height = mCurrentDrawable == null ? 0 : mCurrentDrawable.getIntrinsicHeight();
- final Rect to = getIconRect(d.dragView.getMeasuredWidth(), d.dragView.getMeasuredHeight(),
- width, height);
- final float scale = (float) to.width() / from.width();
-
- mSearchDropTargetBar.deferOnDragEnd();
- deferCompleteDropIfUninstalling(d);
-
- Runnable onAnimationEndRunnable = new Runnable() {
- @Override
- public void run() {
- completeDrop(d);
- mSearchDropTargetBar.onDragEnd();
- mLauncher.exitSpringLoadedDragModeDelayed(true, 0, null);
- }
- };
- dragLayer.animateView(d.dragView, from, to, scale, 1f, 1f, 0.1f, 0.1f,
- DELETE_ANIMATION_DURATION, new DecelerateInterpolator(2),
- new LinearInterpolator(), onAnimationEndRunnable,
- DragLayer.ANIMATION_END_DISAPPEAR, null);
- }
-
- private void deferCompleteDropIfUninstalling(DragObject d) {
- mWaitingForUninstall = false;
- if (isUninstallFromWorkspace(d)) {
- if (d.dragSource instanceof Folder) {
- ((Folder) d.dragSource).deferCompleteDropAfterUninstallActivity();
- } else if (d.dragSource instanceof Workspace) {
- ((Workspace) d.dragSource).deferCompleteDropAfterUninstallActivity();
- }
- mWaitingForUninstall = true;
+ @Thunk void completeDrop(DragObject d) {
+ ItemInfo item = (ItemInfo) d.dragInfo;
+ if ((d.dragSource instanceof Workspace) || (d.dragSource instanceof Folder)) {
+ removeWorkspaceOrFolderItem(mLauncher, item, null);
}
}
- private boolean isUninstallFromWorkspace(DragObject d) {
- if (LauncherAppState.isDisableAllApps() && isWorkspaceOrFolderApplication(d)) {
- ShortcutInfo shortcut = (ShortcutInfo) d.dragInfo;
- // Only allow manifest shortcuts to initiate an un-install.
- return !InstallShortcutReceiver.isValidShortcutLaunchIntent(shortcut.intent);
- }
- return false;
- }
+ /**
+ * 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;
- private void completeDrop(DragObject d) {
- ItemInfo item = (ItemInfo) d.dragInfo;
- boolean wasWaitingForUninstall = mWaitingForUninstall;
- mWaitingForUninstall = false;
- if (isAllAppsApplication(d.dragSource, item)) {
- // Uninstall the application if it is being dragged from AppsCustomize
- AppInfo appInfo = (AppInfo) item;
- mLauncher.startApplicationUninstallActivity(appInfo.componentName, appInfo.flags,
- appInfo.user);
- } else if (isUninstallFromWorkspace(d)) {
- ShortcutInfo shortcut = (ShortcutInfo) item;
- if (shortcut.intent != null && shortcut.intent.getComponent() != null) {
- final ComponentName componentName = shortcut.intent.getComponent();
- final DragSource dragSource = d.dragSource;
- final UserHandleCompat user = shortcut.user;
- mWaitingForUninstall = mLauncher.startApplicationUninstallActivity(
- componentName, shortcut.flags, user);
- if (mWaitingForUninstall) {
- final Runnable checkIfUninstallWasSuccess = new Runnable() {
- @Override
- public void run() {
- mWaitingForUninstall = false;
- String packageName = componentName.getPackageName();
- boolean uninstallSuccessful = !AllAppsList.packageHasActivities(
- getContext(), packageName, user);
- if (dragSource instanceof Folder) {
- ((Folder) dragSource).
- onUninstallActivityReturned(uninstallSuccessful);
- } else if (dragSource instanceof Workspace) {
- ((Workspace) dragSource).
- onUninstallActivityReturned(uninstallSuccessful);
- }
- }
- };
- mLauncher.addOnResumeCallback(checkIfUninstallWasSuccess);
- }
- }
- } else if (isWorkspaceOrFolderApplication(d)) {
- LauncherModel.deleteItemFromDatabase(mLauncher, item);
- } else if (isWorkspaceFolder(d)) {
- // Remove the folder from the workspace and delete the contents from launcher model
- FolderInfo folderInfo = (FolderInfo) item;
- mLauncher.removeFolder(folderInfo);
- LauncherModel.deleteFolderContentsFromDatabase(mLauncher, folderInfo);
- } else if (isWorkspaceOrFolderWidget(d)) {
// Remove the widget from the workspace
- mLauncher.removeAppWidget((LauncherAppWidgetInfo) item);
- LauncherModel.deleteItemFromDatabase(mLauncher, item);
+ launcher.removeAppWidget(widget);
+ LauncherModel.deleteItemFromDatabase(launcher, widget);
+
+ final LauncherAppWidgetHost appWidgetHost = launcher.getAppWidgetHost();
- final LauncherAppWidgetInfo launcherAppWidgetInfo = (LauncherAppWidgetInfo) item;
- final LauncherAppWidgetHost appWidgetHost = mLauncher.getAppWidgetHost();
- if ((appWidgetHost != null) && launcherAppWidgetInfo.isWidgetIdValid()) {
+ 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(launcherAppWidgetInfo.appWidgetId);
+ appWidgetHost.deleteAppWidgetId(widget.appWidgetId);
return null;
}
- }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void) null);
+ }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
+ } else {
+ return false;
}
- if (wasWaitingForUninstall && !mWaitingForUninstall) {
- if (d.dragSource instanceof Folder) {
- ((Folder) d.dragSource).onUninstallActivityReturned(false);
- } else if (d.dragSource instanceof Workspace) {
- ((Workspace) d.dragSource).onUninstallActivityReturned(false);
- }
- }
- }
-
- public void onDrop(DragObject d) {
- animateToTrashAndCompleteDrop(d);
- }
-
- /**
- * Creates an animation from the current drag view to the delete trash icon.
- */
- private AnimatorUpdateListener createFlingToTrashAnimatorListener(final DragLayer dragLayer,
- DragObject d, PointF vel, ViewConfiguration config) {
-
- int width = mCurrentDrawable == null ? 0 : mCurrentDrawable.getIntrinsicWidth();
- int height = mCurrentDrawable == null ? 0 : mCurrentDrawable.getIntrinsicHeight();
- final Rect to = getIconRect(d.dragView.getMeasuredWidth(), d.dragView.getMeasuredHeight(),
- width, height);
- final Rect from = new Rect();
- dragLayer.getViewRectRelativeToSelf(d.dragView, from);
-
- // Calculate how far along the velocity vector we should put the intermediate point on
- // the bezier curve
- float velocity = Math.abs(vel.length());
- float vp = Math.min(1f, velocity / (config.getScaledMaximumFlingVelocity() / 2f));
- int offsetY = (int) (-from.top * vp);
- int offsetX = (int) (offsetY / (vel.y / vel.x));
- final float y2 = from.top + offsetY; // intermediate t/l
- final float x2 = from.left + offsetX;
- final float x1 = from.left; // drag view t/l
- final float y1 = from.top;
- final float x3 = to.left; // delete target t/l
- final float y3 = to.top;
-
- final TimeInterpolator scaleAlphaInterpolator = new TimeInterpolator() {
- @Override
- public float getInterpolation(float t) {
- return t * t * t * t * t * t * t * t;
- }
- };
- return new AnimatorUpdateListener() {
- @Override
- public void onAnimationUpdate(ValueAnimator animation) {
- final DragView dragView = (DragView) dragLayer.getAnimatedView();
- float t = ((Float) animation.getAnimatedValue()).floatValue();
- float tp = scaleAlphaInterpolator.getInterpolation(t);
- float initialScale = dragView.getInitialScale();
- float finalAlpha = 0.5f;
- float scale = dragView.getScaleX();
- float x1o = ((1f - scale) * dragView.getMeasuredWidth()) / 2f;
- float y1o = ((1f - scale) * dragView.getMeasuredHeight()) / 2f;
- float x = (1f - t) * (1f - t) * (x1 - x1o) + 2 * (1f - t) * t * (x2 - x1o) +
- (t * t) * x3;
- float y = (1f - t) * (1f - t) * (y1 - y1o) + 2 * (1f - t) * t * (y2 - x1o) +
- (t * t) * y3;
-
- dragView.setTranslationX(x);
- dragView.setTranslationY(y);
- dragView.setScaleX(initialScale * (1f - tp));
- dragView.setScaleY(initialScale * (1f - tp));
- dragView.setAlpha(finalAlpha + (1f - finalAlpha) * (1f - tp));
- }
- };
- }
-
- /**
- * Creates an animation from the current drag view along its current velocity vector.
- * For this animation, the alpha runs for a fixed duration and we update the position
- * progressively.
- */
- private static class FlingAlongVectorAnimatorUpdateListener implements AnimatorUpdateListener {
- private DragLayer mDragLayer;
- private PointF mVelocity;
- private Rect mFrom;
- private long mPrevTime;
- private boolean mHasOffsetForScale;
- private float mFriction;
-
- private final TimeInterpolator mAlphaInterpolator = new DecelerateInterpolator(0.75f);
-
- public FlingAlongVectorAnimatorUpdateListener(DragLayer dragLayer, PointF vel, Rect from,
- long startTime, float friction) {
- mDragLayer = dragLayer;
- mVelocity = vel;
- mFrom = from;
- mPrevTime = startTime;
- mFriction = 1f - (dragLayer.getResources().getDisplayMetrics().density * friction);
- }
-
- @Override
- public void onAnimationUpdate(ValueAnimator animation) {
- final DragView dragView = (DragView) mDragLayer.getAnimatedView();
- float t = ((Float) animation.getAnimatedValue()).floatValue();
- long curTime = AnimationUtils.currentAnimationTimeMillis();
-
- if (!mHasOffsetForScale) {
- mHasOffsetForScale = true;
- float scale = dragView.getScaleX();
- float xOffset = ((scale - 1f) * dragView.getMeasuredWidth()) / 2f;
- float yOffset = ((scale - 1f) * dragView.getMeasuredHeight()) / 2f;
-
- mFrom.left += xOffset;
- mFrom.top += yOffset;
- }
-
- mFrom.left += (mVelocity.x * (curTime - mPrevTime) / 1000f);
- mFrom.top += (mVelocity.y * (curTime - mPrevTime) / 1000f);
- dragView.setTranslationX(mFrom.left);
- dragView.setTranslationY(mFrom.top);
- dragView.setAlpha(1f - mAlphaInterpolator.getInterpolation(t));
-
- mVelocity.x *= mFriction;
- mVelocity.y *= mFriction;
- mPrevTime = curTime;
+ if (view != null) {
+ launcher.getWorkspace().removeWorkspaceItem(view);
+ launcher.getWorkspace().stripEmptyScreens();
}
- };
- private AnimatorUpdateListener createFlingAlongVectorAnimatorListener(final DragLayer dragLayer,
- DragObject d, PointF vel, final long startTime, final int duration,
- ViewConfiguration config) {
- final Rect from = new Rect();
- dragLayer.getViewRectRelativeToSelf(d.dragView, from);
-
- return new FlingAlongVectorAnimatorUpdateListener(dragLayer, vel, from, startTime,
- FLING_TO_DELETE_FRICTION);
+ return true;
}
- public void onFlingToDelete(final DragObject d, int x, int y, PointF vel) {
- final boolean isAllApps = d.dragSource instanceof AppsCustomizePagedView;
-
+ @Override
+ public void onFlingToDelete(final DragObject d, PointF vel) {
// Don't highlight the icon as it's animating
d.dragView.setColor(0);
d.dragView.updateInitialScaleToCurrentScale();
- // Don't highlight the target if we are flinging from AllApps
- if (isAllApps) {
- resetHoverColor();
- }
-
- if (mFlingDeleteMode == MODE_FLING_DELETE_TO_TRASH) {
- // Defer animating out the drop target if we are animating to it
- mSearchDropTargetBar.deferOnDragEnd();
- mSearchDropTargetBar.finishAnimations();
- }
- final ViewConfiguration config = ViewConfiguration.get(mLauncher);
final DragLayer dragLayer = mLauncher.getDragLayer();
- final int duration = FLING_DELETE_ANIMATION_DURATION;
+ FlingAnimation fling = new FlingAnimation(d, vel,
+ getIconRect(d.dragView.getMeasuredWidth(), d.dragView.getMeasuredHeight(),
+ mDrawable.getIntrinsicWidth(), mDrawable.getIntrinsicHeight()),
+ dragLayer);
+
+ final int duration = fling.getDuration();
final long startTime = AnimationUtils.currentAnimationTimeMillis();
// NOTE: Because it takes time for the first frame of animation to actually be
@@ -527,28 +143,22 @@ public class DeleteDropTarget extends ButtonDropTarget {
return Math.min(1f, mOffset + t);
}
};
- AnimatorUpdateListener updateCb = null;
- if (mFlingDeleteMode == MODE_FLING_DELETE_TO_TRASH) {
- updateCb = createFlingToTrashAnimatorListener(dragLayer, d, vel, config);
- } else if (mFlingDeleteMode == MODE_FLING_DELETE_ALONG_VECTOR) {
- updateCb = createFlingAlongVectorAnimatorListener(dragLayer, d, vel, startTime,
- duration, config);
- }
- deferCompleteDropIfUninstalling(d);
Runnable onAnimationEndRunnable = new Runnable() {
@Override
public void run() {
- // If we are dragging from AllApps, then we allow AppsCustomizePagedView to clean up
- // itself, otherwise, complete the drop to initiate the deletion process
- if (!isAllApps) {
- mLauncher.exitSpringLoadedDragMode();
- completeDrop(d);
- }
+ mLauncher.exitSpringLoadedDragMode();
+ completeDrop(d);
mLauncher.getDragController().onDeferredEndFling(d);
}
};
- dragLayer.animateView(d.dragView, updateCb, duration, tInterpolator, onAnimationEndRunnable,
+
+ 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 d6aadcee1..62b05b0d6 100644
--- a/src/com/android/launcher3/DeviceProfile.java
+++ b/src/com/android/launcher3/DeviceProfile.java
@@ -19,155 +19,103 @@ package com.android.launcher3;
import android.appwidget.AppWidgetHostView;
import android.content.ComponentName;
import android.content.Context;
-import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Paint;
import android.graphics.Paint.FontMetrics;
import android.graphics.Point;
-import android.graphics.PointF;
import android.graphics.Rect;
import android.util.DisplayMetrics;
-import android.view.Display;
import android.view.Gravity;
-import android.view.Surface;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.view.ViewGroup.MarginLayoutParams;
-import android.view.WindowManager;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
-
-
-class DeviceProfileQuery {
- DeviceProfile profile;
- float widthDps;
- float heightDps;
- float value;
- PointF dimens;
-
- DeviceProfileQuery(DeviceProfile p, float v) {
- widthDps = p.minWidthDps;
- heightDps = p.minHeightDps;
- value = v;
- dimens = new PointF(widthDps, heightDps);
- profile = p;
- }
-}
-
public class DeviceProfile {
- public static interface DeviceProfileCallbacks {
- public void onAvailableSizeChanged(DeviceProfile grid);
- }
- String name;
- float minWidthDps;
- float minHeightDps;
- float numRows;
- float numColumns;
- float numHotseatIcons;
- float iconSize;
- private float iconTextSize;
- private int iconDrawablePaddingOriginalPx;
- private float hotseatIconSize;
-
- int defaultLayoutId;
-
- boolean isLandscape;
- boolean isTablet;
- boolean isLargeTablet;
- boolean isLayoutRtl;
- boolean transposeLayoutWithOrientation;
-
- int desiredWorkspaceLeftRightMarginPx;
- int edgeMarginPx;
- Rect defaultWidgetPadding;
-
- int widthPx;
- int heightPx;
- int availableWidthPx;
- int availableHeightPx;
- int defaultPageSpacingPx;
-
- int overviewModeMinIconZoneHeightPx;
- int overviewModeMaxIconZoneHeightPx;
- int overviewModeBarItemWidthPx;
- int overviewModeBarSpacerWidthPx;
- float overviewModeIconZoneRatio;
- float overviewModeScaleFactor;
-
- int iconSizePx;
- int iconTextSizePx;
- int iconDrawablePaddingPx;
- int cellWidthPx;
- int cellHeightPx;
- int allAppsIconSizePx;
- int allAppsIconTextSizePx;
- int allAppsCellWidthPx;
- int allAppsCellHeightPx;
- int allAppsCellPaddingPx;
- int folderBackgroundOffset;
- int folderIconSizePx;
- int folderCellWidthPx;
- int folderCellHeightPx;
- int hotseatCellWidthPx;
- int hotseatCellHeightPx;
- int hotseatIconSizePx;
- int hotseatBarHeightPx;
- int hotseatAllAppsRank;
- int allAppsNumRows;
- int allAppsNumCols;
- int searchBarSpaceWidthPx;
- int searchBarSpaceHeightPx;
- int pageIndicatorHeightPx;
- int allAppsButtonVisualSize;
-
- float dragViewScale;
-
- int allAppsShortEdgeCount = -1;
- int allAppsLongEdgeCount = -1;
-
- private ArrayList<DeviceProfileCallbacks> mCallbacks = new ArrayList<DeviceProfileCallbacks>();
-
- DeviceProfile(String n, float w, float h, float r, float c,
- float is, float its, float hs, float his, int dlId) {
- // Ensure that we have an odd number of hotseat items (since we need to place all apps)
- if (!LauncherAppState.isDisableAllApps() && hs % 2 == 0) {
- throw new RuntimeException("All Device Profiles must have an odd number of hotseat spaces");
- }
+ public final InvariantDeviceProfile inv;
+
+ // Device properties
+ public final boolean isTablet;
+ public final boolean isLargeTablet;
+ public final boolean isPhone;
+ public final boolean transposeLayoutWithOrientation;
+
+ // Device properties in current orientation
+ public final boolean isLandscape;
+ public final int widthPx;
+ public final int heightPx;
+ public final int availableWidthPx;
+ public final int availableHeightPx;
+
+ // Overview mode
+ private final int overviewModeMinIconZoneHeightPx;
+ private final int overviewModeMaxIconZoneHeightPx;
+ private final int overviewModeBarItemWidthPx;
+ private final int overviewModeBarSpacerWidthPx;
+ private final float overviewModeIconZoneRatio;
+ private final float overviewModeScaleFactor;
+
+ // Workspace
+ private int desiredWorkspaceLeftRightMarginPx;
+ public final int edgeMarginPx;
+ public final Rect defaultWidgetPadding;
+ private final int pageIndicatorHeightPx;
+ private final int defaultPageSpacingPx;
+ private float dragViewScale;
+
+ // Workspace icons
+ public int iconSizePx;
+ public int iconTextSizePx;
+ public int iconDrawablePaddingPx;
+ public int iconDrawablePaddingOriginalPx;
+
+ public int cellWidthPx;
+ public int cellHeightPx;
+
+ // Folder
+ public int folderBackgroundOffset;
+ public int folderIconSizePx;
+ public int folderCellWidthPx;
+ public int folderCellHeightPx;
+
+ // Hotseat
+ public int hotseatCellWidthPx;
+ public int hotseatCellHeightPx;
+ public int hotseatIconSizePx;
+ private int hotseatBarHeightPx;
+
+ // All apps
+ public int allAppsNumCols;
+ public int allAppsNumPredictiveCols;
+ public int allAppsButtonVisualSize;
+ public final int allAppsIconSizePx;
+ public final int allAppsIconTextSizePx;
+
+ // QSB
+ private int searchBarSpaceWidthPx;
+ private int searchBarSpaceHeightPx;
+
+ public DeviceProfile(Context context, InvariantDeviceProfile inv,
+ Point minSize, Point maxSize,
+ int width, int height, boolean isLandscape) {
+
+ this.inv = inv;
+ this.isLandscape = isLandscape;
- name = n;
- minWidthDps = w;
- minHeightDps = h;
- numRows = r;
- numColumns = c;
- iconSize = is;
- iconTextSize = its;
- numHotseatIcons = hs;
- hotseatIconSize = his;
- defaultLayoutId = dlId;
- }
+ Resources res = context.getResources();
+ DisplayMetrics dm = res.getDisplayMetrics();
- DeviceProfile() {
- }
+ // Constants from resources
+ isTablet = res.getBoolean(R.bool.is_tablet);
+ isLargeTablet = res.getBoolean(R.bool.is_large_tablet);
+ isPhone = !isTablet && !isLargeTablet;
- DeviceProfile(Context context,
- ArrayList<DeviceProfile> profiles,
- float minWidth, float minHeight,
- int wPx, int hPx,
- int awPx, int ahPx,
- Resources res) {
- DisplayMetrics dm = res.getDisplayMetrics();
- ArrayList<DeviceProfileQuery> points =
- new ArrayList<DeviceProfileQuery>();
+ // Some more constants
transposeLayoutWithOrientation =
res.getBoolean(R.bool.hotseat_transpose_layout_with_orientation);
- minWidthDps = minWidth;
- minHeightDps = minHeight;
ComponentName cn = new ComponentName(context.getPackageName(),
this.getClass().getName());
@@ -178,8 +126,6 @@ public class DeviceProfile {
res.getDimensionPixelSize(R.dimen.dynamic_grid_page_indicator_height);
defaultPageSpacingPx =
res.getDimensionPixelSize(R.dimen.dynamic_grid_workspace_page_spacing);
- allAppsCellPaddingPx =
- res.getDimensionPixelSize(R.dimen.dynamic_grid_all_apps_cell_padding);
overviewModeMinIconZoneHeightPx =
res.getDimensionPixelSize(R.dimen.dynamic_grid_overview_min_icon_zone_height);
overviewModeMaxIconZoneHeightPx =
@@ -192,188 +138,71 @@ public class DeviceProfile {
res.getInteger(R.integer.config_dynamic_grid_overview_icon_zone_percentage) / 100f;
overviewModeScaleFactor =
res.getInteger(R.integer.config_dynamic_grid_overview_scale_percentage) / 100f;
-
- // Find the closes profile given the width/height
- for (DeviceProfile p : profiles) {
- points.add(new DeviceProfileQuery(p, 0f));
- }
- DeviceProfile closestProfile = findClosestDeviceProfile(minWidth, minHeight, points);
-
- // Snap to the closest row count
- numRows = closestProfile.numRows;
-
- // Snap to the closest column count
- numColumns = closestProfile.numColumns;
-
- // Snap to the closest hotseat size
- numHotseatIcons = closestProfile.numHotseatIcons;
- hotseatAllAppsRank = (int) (numHotseatIcons / 2);
-
- // Snap to the closest default layout id
- defaultLayoutId = closestProfile.defaultLayoutId;
-
- // Interpolate the icon size
- points.clear();
- for (DeviceProfile p : profiles) {
- points.add(new DeviceProfileQuery(p, p.iconSize));
- }
- iconSize = invDistWeightedInterpolate(minWidth, minHeight, points);
-
- // AllApps uses the original non-scaled icon size
- allAppsIconSizePx = DynamicGrid.pxFromDp(iconSize, dm);
-
- // Interpolate the icon text size
- points.clear();
- for (DeviceProfile p : profiles) {
- points.add(new DeviceProfileQuery(p, p.iconTextSize));
- }
- iconTextSize = invDistWeightedInterpolate(minWidth, minHeight, points);
iconDrawablePaddingOriginalPx =
res.getDimensionPixelSize(R.dimen.dynamic_grid_icon_drawable_padding);
+
// AllApps uses the original non-scaled icon text size
- allAppsIconTextSizePx = DynamicGrid.pxFromDp(iconTextSize, dm);
+ allAppsIconTextSizePx = Utilities.pxFromDp(inv.iconTextSize, dm);
- // Interpolate the hotseat icon size
- points.clear();
- for (DeviceProfile p : profiles) {
- points.add(new DeviceProfileQuery(p, p.hotseatIconSize));
+ // AllApps uses the original non-scaled icon size
+ allAppsIconSizePx = Utilities.pxFromDp(inv.iconSize, dm);
+
+ // Determine sizes.
+ widthPx = width;
+ heightPx = height;
+ if (isLandscape) {
+ availableWidthPx = maxSize.x;
+ availableHeightPx = minSize.y;
+ } else {
+ availableWidthPx = minSize.x;
+ availableHeightPx = maxSize.y;
}
- // Hotseat
- hotseatIconSize = invDistWeightedInterpolate(minWidth, minHeight, points);
-
- // If the partner customization apk contains any grid overrides, apply them
- applyPartnerDeviceProfileOverrides(context, dm);
// Calculate the remaining vars
- updateFromConfiguration(context, res, wPx, hPx, awPx, ahPx);
- updateAvailableDimensions(context);
+ updateAvailableDimensions(dm, res);
computeAllAppsButtonSize(context);
}
/**
- * Apply any Partner customization grid overrides.
- *
- * Currently we support: all apps row / column count.
- */
- private void applyPartnerDeviceProfileOverrides(Context ctx, DisplayMetrics dm) {
- Partner p = Partner.get(ctx.getPackageManager());
- if (p != null) {
- DeviceProfile partnerDp = p.getDeviceProfileOverride(dm);
- if (partnerDp != null) {
- if (partnerDp.numRows > 0 && partnerDp.numColumns > 0) {
- numRows = partnerDp.numRows;
- numColumns = partnerDp.numColumns;
- }
- if (partnerDp.allAppsShortEdgeCount > 0 && partnerDp.allAppsLongEdgeCount > 0) {
- allAppsShortEdgeCount = partnerDp.allAppsShortEdgeCount;
- allAppsLongEdgeCount = partnerDp.allAppsLongEdgeCount;
- }
- if (partnerDp.iconSize > 0) {
- iconSize = partnerDp.iconSize;
- // AllApps uses the original non-scaled icon size
- allAppsIconSizePx = DynamicGrid.pxFromDp(iconSize, dm);
- }
- }
- }
- }
-
- /**
* Determine the exact visual footprint of the all apps button, taking into account scaling
* and internal padding of the drawable.
*/
private void computeAllAppsButtonSize(Context context) {
Resources res = context.getResources();
float padding = res.getInteger(R.integer.config_allAppsButtonPaddingPercent) / 100f;
- LauncherAppState app = LauncherAppState.getInstance();
allAppsButtonVisualSize = (int) (hotseatIconSizePx * (1 - padding));
}
- void addCallback(DeviceProfileCallbacks cb) {
- mCallbacks.add(cb);
- cb.onAvailableSizeChanged(this);
- }
- void removeCallback(DeviceProfileCallbacks cb) {
- mCallbacks.remove(cb);
- }
-
- private int getDeviceOrientation(Context context) {
- WindowManager windowManager = (WindowManager)
- context.getSystemService(Context.WINDOW_SERVICE);
- Resources resources = context.getResources();
- DisplayMetrics dm = resources.getDisplayMetrics();
- Configuration config = resources.getConfiguration();
- int rotation = windowManager.getDefaultDisplay().getRotation();
-
- boolean isLandscape = (config.orientation == Configuration.ORIENTATION_LANDSCAPE) &&
- (rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_180);
- boolean isRotatedPortrait = (config.orientation == Configuration.ORIENTATION_PORTRAIT) &&
- (rotation == Surface.ROTATION_90 || rotation == Surface.ROTATION_270);
- if (isLandscape || isRotatedPortrait) {
- return CellLayout.LANDSCAPE;
- } else {
- return CellLayout.PORTRAIT;
- }
- }
-
- private void updateAvailableDimensions(Context context) {
- WindowManager windowManager = (WindowManager)
- context.getSystemService(Context.WINDOW_SERVICE);
- Display display = windowManager.getDefaultDisplay();
- Resources resources = context.getResources();
- DisplayMetrics dm = resources.getDisplayMetrics();
- Configuration config = resources.getConfiguration();
-
- // There are three possible configurations that the dynamic grid accounts for, portrait,
- // landscape with the nav bar at the bottom, and landscape with the nav bar at the side.
- // To prevent waiting for fitSystemWindows(), we make the observation that in landscape,
- // the height is the smallest height (either with the nav bar at the bottom or to the
- // side) and otherwise, the height is simply the largest possible height for a portrait
- // device.
- Point size = new Point();
- Point smallestSize = new Point();
- Point largestSize = new Point();
- display.getSize(size);
- display.getCurrentSizeRange(smallestSize, largestSize);
- availableWidthPx = size.x;
- if (config.orientation == Configuration.ORIENTATION_LANDSCAPE) {
- availableHeightPx = smallestSize.y;
- } else {
- availableHeightPx = largestSize.y;
- }
-
+ private void updateAvailableDimensions(DisplayMetrics dm, Resources res) {
// Check to see if the icons fit in the new available height. If not, then we need to
// shrink the icon size.
float scale = 1f;
int drawablePadding = iconDrawablePaddingOriginalPx;
- updateIconSize(1f, drawablePadding, resources, dm);
- float usedHeight = (cellHeightPx * numRows);
+ updateIconSize(1f, drawablePadding, res, dm);
+ float usedHeight = (cellHeightPx * inv.numRows);
- Rect workspacePadding = getWorkspacePadding();
+ // We only care about the top and bottom workspace padding, which is not affected by RTL.
+ Rect workspacePadding = getWorkspacePadding(false /* isLayoutRtl */);
int maxHeight = (availableHeightPx - workspacePadding.top - workspacePadding.bottom);
if (usedHeight > maxHeight) {
scale = maxHeight / usedHeight;
drawablePadding = 0;
}
- updateIconSize(scale, drawablePadding, resources, dm);
-
- // Make the callbacks
- for (DeviceProfileCallbacks cb : mCallbacks) {
- cb.onAvailableSizeChanged(this);
- }
+ updateIconSize(scale, drawablePadding, res, dm);
}
- private void updateIconSize(float scale, int drawablePadding, Resources resources,
+ private void updateIconSize(float scale, int drawablePadding, Resources res,
DisplayMetrics dm) {
- iconSizePx = (int) (DynamicGrid.pxFromDp(iconSize, dm) * scale);
- iconTextSizePx = (int) (DynamicGrid.pxFromSp(iconTextSize, dm) * scale);
+ iconSizePx = (int) (Utilities.pxFromDp(inv.iconSize, dm) * scale);
+ iconTextSizePx = (int) (Utilities.pxFromSp(inv.iconTextSize, dm) * scale);
iconDrawablePaddingPx = drawablePadding;
- hotseatIconSizePx = (int) (DynamicGrid.pxFromDp(hotseatIconSize, dm) * scale);
+ hotseatIconSizePx = (int) (Utilities.pxFromDp(inv.hotseatIconSize, dm) * scale);
// Search Bar
searchBarSpaceWidthPx = Math.min(widthPx,
- resources.getDimensionPixelSize(R.dimen.dynamic_grid_search_bar_max_width));
+ res.getDimensionPixelSize(R.dimen.dynamic_grid_search_bar_max_width));
searchBarSpaceHeightPx = getSearchBarTopOffset()
- + resources.getDimensionPixelSize(R.dimen.dynamic_grid_search_bar_height);
+ + res.getDimensionPixelSize(R.dimen.dynamic_grid_search_bar_height);
// Calculate the actual text height
Paint textPaint = new Paint();
@@ -381,7 +210,7 @@ public class DeviceProfile {
FontMetrics fm = textPaint.getFontMetrics();
cellWidthPx = iconSizePx;
cellHeightPx = iconSizePx + iconDrawablePaddingPx + (int) Math.ceil(fm.bottom - fm.top);
- final float scaleDps = resources.getDimensionPixelSize(R.dimen.dragViewScale);
+ final float scaleDps = res.getDimensionPixelSize(R.dimen.dragViewScale);
dragViewScale = (iconSizePx + scaleDps) / iconSizePx;
// Hotseat
@@ -394,123 +223,27 @@ public class DeviceProfile {
folderCellHeightPx = cellHeightPx + edgeMarginPx;
folderBackgroundOffset = -edgeMarginPx;
folderIconSizePx = iconSizePx + 2 * -folderBackgroundOffset;
-
- // All Apps
- allAppsCellWidthPx = allAppsIconSizePx;
- allAppsCellHeightPx = allAppsIconSizePx + drawablePadding + iconTextSizePx;
- int maxLongEdgeCellCount =
- resources.getInteger(R.integer.config_dynamic_grid_max_long_edge_cell_count);
- int maxShortEdgeCellCount =
- resources.getInteger(R.integer.config_dynamic_grid_max_short_edge_cell_count);
- int minEdgeCellCount =
- resources.getInteger(R.integer.config_dynamic_grid_min_edge_cell_count);
- int maxRows = (isLandscape ? maxShortEdgeCellCount : maxLongEdgeCellCount);
- int maxCols = (isLandscape ? maxLongEdgeCellCount : maxShortEdgeCellCount);
-
- if (allAppsShortEdgeCount > 0 && allAppsLongEdgeCount > 0) {
- allAppsNumRows = isLandscape ? allAppsShortEdgeCount : allAppsLongEdgeCount;
- allAppsNumCols = isLandscape ? allAppsLongEdgeCount : allAppsShortEdgeCount;
- } else {
- allAppsNumRows = (availableHeightPx - pageIndicatorHeightPx) /
- (allAppsCellHeightPx + allAppsCellPaddingPx);
- allAppsNumRows = Math.max(minEdgeCellCount, Math.min(maxRows, allAppsNumRows));
- allAppsNumCols = (availableWidthPx) /
- (allAppsCellWidthPx + allAppsCellPaddingPx);
- allAppsNumCols = Math.max(minEdgeCellCount, Math.min(maxCols, allAppsNumCols));
- }
- }
-
- void updateFromConfiguration(Context context, Resources resources, int wPx, int hPx,
- int awPx, int ahPx) {
- Configuration configuration = resources.getConfiguration();
- isLandscape = (configuration.orientation == Configuration.ORIENTATION_LANDSCAPE);
- isTablet = resources.getBoolean(R.bool.is_tablet);
- isLargeTablet = resources.getBoolean(R.bool.is_large_tablet);
- if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR1) {
- isLayoutRtl = (configuration.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL);
- } else {
- isLayoutRtl = false;
- }
- widthPx = wPx;
- heightPx = hPx;
- availableWidthPx = awPx;
- availableHeightPx = ahPx;
-
- updateAvailableDimensions(context);
}
- private float dist(PointF p0, PointF p1) {
- return (float) Math.sqrt((p1.x - p0.x)*(p1.x-p0.x) +
- (p1.y-p0.y)*(p1.y-p0.y));
- }
-
- private float weight(PointF a, PointF b,
- float pow) {
- float d = dist(a, b);
- if (d == 0f) {
- return Float.POSITIVE_INFINITY;
- }
- return (float) (1f / Math.pow(d, pow));
- }
-
- /** Returns the closest device profile given the width and height and a list of profiles */
- private DeviceProfile findClosestDeviceProfile(float width, float height,
- ArrayList<DeviceProfileQuery> points) {
- return findClosestDeviceProfiles(width, height, points).get(0).profile;
- }
-
- /** Returns the closest device profiles ordered by closeness to the specified width and height */
- private ArrayList<DeviceProfileQuery> findClosestDeviceProfiles(float width, float height,
- ArrayList<DeviceProfileQuery> points) {
- final PointF xy = new PointF(width, height);
-
- // Sort the profiles by their closeness to the dimensions
- ArrayList<DeviceProfileQuery> pointsByNearness = points;
- Collections.sort(pointsByNearness, new Comparator<DeviceProfileQuery>() {
- public int compare(DeviceProfileQuery a, DeviceProfileQuery b) {
- return (int) (dist(xy, a.dimens) - dist(xy, b.dimens));
- }
- });
-
- return pointsByNearness;
- }
-
- private float invDistWeightedInterpolate(float width, float height,
- ArrayList<DeviceProfileQuery> points) {
- float sum = 0;
- float weights = 0;
- float pow = 5;
- float kNearestNeighbors = 3;
- final PointF xy = new PointF(width, height);
-
- ArrayList<DeviceProfileQuery> pointsByNearness = findClosestDeviceProfiles(width, height,
- points);
-
- for (int i = 0; i < pointsByNearness.size(); ++i) {
- DeviceProfileQuery p = pointsByNearness.get(i);
- if (i < kNearestNeighbors) {
- float w = weight(xy, p.dimens, pow);
- if (w == Float.POSITIVE_INFINITY) {
- return p.value;
- }
- weights += w;
- }
- }
-
- for (int i = 0; i < pointsByNearness.size(); ++i) {
- DeviceProfileQuery p = pointsByNearness.get(i);
- if (i < kNearestNeighbors) {
- float w = weight(xy, p.dimens, pow);
- sum += w * p.value / weights;
- }
- }
-
- return sum;
+ /**
+ * @param recyclerViewWidth the available width of the AllAppsRecyclerView
+ */
+ public void updateAppsViewNumCols(Resources res, int recyclerViewWidth) {
+ int appsViewLeftMarginPx =
+ res.getDimensionPixelSize(R.dimen.all_apps_grid_view_start_margin);
+ int allAppsCellWidthGap =
+ res.getDimensionPixelSize(R.dimen.all_apps_icon_width_gap);
+ int availableAppsWidthPx = (recyclerViewWidth > 0) ? recyclerViewWidth : availableWidthPx;
+ int numAppsCols = (availableAppsWidthPx - appsViewLeftMarginPx) /
+ (allAppsIconSizePx + allAppsCellWidthGap);
+ int numPredictiveAppCols = Math.max(inv.minAllAppsPredictionColumns, numAppsCols);
+ allAppsNumCols = numAppsCols;
+ allAppsNumPredictiveCols = numPredictiveAppCols;
}
/** Returns the search bar top offset */
- int getSearchBarTopOffset() {
- if (isTablet() && !isVerticalBarLayout()) {
+ private int getSearchBarTopOffset() {
+ if (isTablet && !isVerticalBarLayout()) {
return 4 * edgeMarginPx;
} else {
return 2 * edgeMarginPx;
@@ -518,14 +251,9 @@ public class DeviceProfile {
}
/** Returns the search bar bounds in the current orientation */
- Rect getSearchBarBounds() {
- return getSearchBarBounds(isLandscape ? CellLayout.LANDSCAPE : CellLayout.PORTRAIT);
- }
- /** Returns the search bar bounds in the specified orientation */
- Rect getSearchBarBounds(int orientation) {
+ public Rect getSearchBarBounds(boolean isLayoutRtl) {
Rect bounds = new Rect();
- if (orientation == CellLayout.LANDSCAPE &&
- transposeLayoutWithOrientation) {
+ if (isLandscape && transposeLayoutWithOrientation) {
if (isLayoutRtl) {
bounds.set(availableWidthPx - searchBarSpaceHeightPx, edgeMarginPx,
availableWidthPx, availableHeightPx - edgeMarginPx);
@@ -534,16 +262,14 @@ public class DeviceProfile {
availableHeightPx - edgeMarginPx);
}
} else {
- if (isTablet()) {
+ if (isTablet) {
// Pad the left and right of the workspace to ensure consistent spacing
// between all icons
- int width = (orientation == CellLayout.LANDSCAPE)
- ? Math.max(widthPx, heightPx)
- : Math.min(widthPx, heightPx);
+ int width = getCurrentWidth();
// XXX: If the icon size changes across orientations, we will have to take
// that into account here too.
int gap = (int) ((width - 2 * edgeMarginPx -
- (numColumns * cellWidthPx)) / (2 * (numColumns + 1)));
+ (inv.numColumns * cellWidthPx)) / (2 * (inv.numColumns + 1)));
bounds.set(edgeMarginPx + gap, getSearchBarTopOffset(),
availableWidthPx - (edgeMarginPx + gap),
searchBarSpaceHeightPx);
@@ -557,36 +283,11 @@ public class DeviceProfile {
return bounds;
}
- /** Returns the bounds of the workspace page indicators. */
- Rect getWorkspacePageIndicatorBounds(Rect insets) {
- Rect workspacePadding = getWorkspacePadding();
- if (isLandscape && transposeLayoutWithOrientation) {
- if (isLayoutRtl) {
- return new Rect(workspacePadding.left, workspacePadding.top,
- workspacePadding.left + pageIndicatorHeightPx,
- heightPx - workspacePadding.bottom - insets.bottom);
- } else {
- int pageIndicatorLeft = widthPx - workspacePadding.right;
- return new Rect(pageIndicatorLeft, workspacePadding.top,
- pageIndicatorLeft + pageIndicatorHeightPx,
- heightPx - workspacePadding.bottom - insets.bottom);
- }
- } else {
- int pageIndicatorTop = heightPx - insets.bottom - workspacePadding.bottom;
- return new Rect(workspacePadding.left, pageIndicatorTop,
- widthPx - workspacePadding.right, pageIndicatorTop + pageIndicatorHeightPx);
- }
- }
-
/** Returns the workspace padding in the specified orientation */
- Rect getWorkspacePadding() {
- return getWorkspacePadding(isLandscape ? CellLayout.LANDSCAPE : CellLayout.PORTRAIT);
- }
- Rect getWorkspacePadding(int orientation) {
- Rect searchBarBounds = getSearchBarBounds(orientation);
+ Rect getWorkspacePadding(boolean isLayoutRtl) {
+ Rect searchBarBounds = getSearchBarBounds(isLayoutRtl);
Rect padding = new Rect();
- if (orientation == CellLayout.LANDSCAPE &&
- transposeLayoutWithOrientation) {
+ if (isLandscape && transposeLayoutWithOrientation) {
// Pad the left and right of the workspace with search/hotseat bar sizes
if (isLayoutRtl) {
padding.set(hotseatBarHeightPx, edgeMarginPx,
@@ -596,22 +297,18 @@ public class DeviceProfile {
hotseatBarHeightPx, edgeMarginPx);
}
} else {
- if (isTablet()) {
+ 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 = (orientation == CellLayout.LANDSCAPE)
- ? Math.max(widthPx, heightPx)
- : Math.min(widthPx, heightPx);
- int height = (orientation != CellLayout.LANDSCAPE)
- ? Math.max(widthPx, heightPx)
- : Math.min(widthPx, heightPx);
+ int width = getCurrentWidth();
+ int height = getCurrentHeight();
int paddingTop = searchBarBounds.bottom;
int paddingBottom = hotseatBarHeightPx + pageIndicatorHeightPx;
- int availableWidth = Math.max(0, width - (int) ((numColumns * cellWidthPx) +
- (numColumns * gapScale * cellWidthPx)));
+ int availableWidth = Math.max(0, width - (int) ((inv.numColumns * cellWidthPx) +
+ (inv.numColumns * gapScale * cellWidthPx)));
int availableHeight = Math.max(0, height - paddingTop - paddingBottom
- - (int) (2 * numRows * cellHeightPx));
+ - (int) (2 * inv.numRows * cellHeightPx));
padding.set(availableWidth / 2, paddingTop + availableHeight / 2,
availableWidth / 2, paddingBottom + availableHeight / 2);
} else {
@@ -625,16 +322,15 @@ public class DeviceProfile {
return padding;
}
- int getWorkspacePageSpacing(int orientation) {
- if ((orientation == CellLayout.LANDSCAPE &&
- transposeLayoutWithOrientation) || isLargeTablet()) {
+ private int getWorkspacePageSpacing(boolean isLayoutRtl) {
+ if ((isLandscape && transposeLayoutWithOrientation) || isLargeTablet) {
// In landscape mode the page spacing is set to the default.
return defaultPageSpacingPx;
} else {
// In portrait, we want the pages spaced such that there is no
// overhang of the previous / next page into the current page viewport.
// We assume symmetrical padding in portrait mode.
- return Math.max(defaultPageSpacingPx, 2 * getWorkspacePadding().left);
+ return Math.max(defaultPageSpacingPx, 2 * getWorkspacePadding(isLayoutRtl).left);
}
}
@@ -645,8 +341,8 @@ public class DeviceProfile {
return new Rect(0, availableHeightPx - zoneHeight, 0, availableHeightPx);
}
- float getOverviewModeScale() {
- Rect workspacePadding = getWorkspacePadding();
+ public float getOverviewModeScale(boolean isLayoutRtl) {
+ Rect workspacePadding = getWorkspacePadding(isLayoutRtl);
Rect overviewBar = getOverviewModeButtonBarRect();
int pageSpace = availableHeightPx - workspacePadding.top - workspacePadding.bottom;
return (overviewModeScaleFactor * (pageSpace - overviewBar.height())) / pageSpace;
@@ -663,32 +359,26 @@ public class DeviceProfile {
}
}
- int calculateCellWidth(int width, int countX) {
+ public static int calculateCellWidth(int width, int countX) {
return width / countX;
}
- int calculateCellHeight(int height, int countY) {
+ public static int calculateCellHeight(int height, int countY) {
return height / countY;
}
- boolean isPhone() {
- return !isTablet && !isLargeTablet;
- }
- boolean isTablet() {
- return isTablet;
- }
- boolean isLargeTablet() {
- return isLargeTablet;
- }
-
+ /**
+ * When {@code true}, hotseat is on the bottom row when in landscape mode.
+ * If {@code false}, hotseat is on the right column when in landscape mode.
+ */
boolean isVerticalBarLayout() {
return isLandscape && transposeLayoutWithOrientation;
}
boolean shouldFadeAdjacentWorkspaceScreens() {
- return isVerticalBarLayout() || isLargeTablet();
+ return isVerticalBarLayout() || isLargeTablet;
}
- int getVisibleChildCount(ViewGroup parent) {
+ private int getVisibleChildCount(ViewGroup parent) {
int visibleChildren = 0;
for (int i = 0; i < parent.getChildCount(); i++) {
if (parent.getChildAt(i).getVisibility() != View.GONE) {
@@ -700,25 +390,31 @@ public class DeviceProfile {
public void layout(Launcher launcher) {
FrameLayout.LayoutParams lp;
- Resources res = launcher.getResources();
boolean hasVerticalBarLayout = isVerticalBarLayout();
+ final boolean isLayoutRtl = Utilities.isRtl(launcher.getResources());
// Layout the search bar space
View searchBar = launcher.getSearchBar();
lp = (FrameLayout.LayoutParams) searchBar.getLayoutParams();
if (hasVerticalBarLayout) {
- // Vertical search bar space
- lp.gravity = Gravity.TOP | Gravity.LEFT;
+ // 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 = searchBarSpaceHeightPx;
- lp.height = LayoutParams.WRAP_CONTENT;
LinearLayout targets = (LinearLayout) searchBar.findViewById(R.id.drag_target_bar);
targets.setOrientation(LinearLayout.VERTICAL);
+ FrameLayout.LayoutParams targetsLp = (FrameLayout.LayoutParams) targets.getLayoutParams();
+ targetsLp.gravity = Gravity.TOP;
+ targetsLp.height = LayoutParams.WRAP_CONTENT;
+
} else {
// Horizontal search bar space
- lp.gravity = Gravity.TOP | Gravity.CENTER_HORIZONTAL;
- lp.width = searchBarSpaceWidthPx;
+ lp.gravity = Gravity.TOP;
lp.height = searchBarSpaceHeightPx;
+
+ LinearLayout targets = (LinearLayout) searchBar.findViewById(R.id.drag_target_bar);
+ targets.getLayoutParams().width = searchBarSpaceWidthPx;
}
searchBar.setLayoutParams(lp);
@@ -726,22 +422,22 @@ public class DeviceProfile {
PagedView workspace = (PagedView) launcher.findViewById(R.id.workspace);
lp = (FrameLayout.LayoutParams) workspace.getLayoutParams();
lp.gravity = Gravity.CENTER;
- int orientation = isLandscape ? CellLayout.LANDSCAPE : CellLayout.PORTRAIT;
- Rect padding = getWorkspacePadding(orientation);
+ Rect padding = getWorkspacePadding(isLayoutRtl);
workspace.setLayoutParams(lp);
workspace.setPadding(padding.left, padding.top, padding.right, padding.bottom);
- workspace.setPageSpacing(getWorkspacePageSpacing(orientation));
+ workspace.setPageSpacing(getWorkspacePageSpacing(isLayoutRtl));
// Layout the hotseat
View hotseat = launcher.findViewById(R.id.hotseat);
lp = (FrameLayout.LayoutParams) hotseat.getLayoutParams();
if (hasVerticalBarLayout) {
- // Vertical hotseat
- lp.gravity = Gravity.END;
+ // 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 = hotseatBarHeightPx;
lp.height = LayoutParams.MATCH_PARENT;
hotseat.findViewById(R.id.layout).setPadding(0, 2 * edgeMarginPx, 0, 2 * edgeMarginPx);
- } else if (isTablet()) {
+ } else if (isTablet) {
// Pad the hotseat with the workspace padding calculated above
lp.gravity = Gravity.BOTTOM;
lp.width = LayoutParams.MATCH_PARENT;
@@ -777,64 +473,6 @@ public class DeviceProfile {
}
}
- // Layout AllApps
- AppsCustomizeTabHost host = (AppsCustomizeTabHost)
- launcher.findViewById(R.id.apps_customize_pane);
- if (host != null) {
- // Center the all apps page indicator
- int pageIndicatorHeight = (int) (pageIndicatorHeightPx * Math.min(1f,
- (allAppsIconSizePx / DynamicGrid.DEFAULT_ICON_SIZE_PX)));
- pageIndicator = host.findViewById(R.id.apps_customize_page_indicator);
- if (pageIndicator != null) {
- LinearLayout.LayoutParams lllp = (LinearLayout.LayoutParams) pageIndicator.getLayoutParams();
- lllp.width = LayoutParams.WRAP_CONTENT;
- lllp.height = pageIndicatorHeight;
- pageIndicator.setLayoutParams(lllp);
- }
-
- AppsCustomizePagedView pagedView = (AppsCustomizePagedView)
- host.findViewById(R.id.apps_customize_pane_content);
-
- FrameLayout fakePageContainer = (FrameLayout)
- host.findViewById(R.id.fake_page_container);
- FrameLayout fakePage = (FrameLayout) host.findViewById(R.id.fake_page);
-
- padding = new Rect();
- if (pagedView != null) {
- // Constrain the dimensions of all apps so that it does not span the full width
- int paddingLR = (availableWidthPx - (allAppsCellWidthPx * allAppsNumCols)) /
- (2 * (allAppsNumCols + 1));
- int paddingTB = (availableHeightPx - (allAppsCellHeightPx * allAppsNumRows)) /
- (2 * (allAppsNumRows + 1));
- paddingLR = Math.min(paddingLR, (int)((paddingLR + paddingTB) * 0.75f));
- paddingTB = Math.min(paddingTB, (int)((paddingLR + paddingTB) * 0.75f));
- int maxAllAppsWidth = (allAppsNumCols * (allAppsCellWidthPx + 2 * paddingLR));
- int gridPaddingLR = (availableWidthPx - maxAllAppsWidth) / 2;
- // Only adjust the side paddings on landscape phones, or tablets
- if ((isTablet() || isLandscape) && gridPaddingLR > (allAppsCellWidthPx / 4)) {
- padding.left = padding.right = gridPaddingLR;
- }
-
- // The icons are centered, so we can't just offset by the page indicator height
- // because the empty space will actually be pageIndicatorHeight + paddingTB
- padding.bottom = Math.max(0, pageIndicatorHeight - paddingTB);
-
- pagedView.setWidgetsPageIndicatorPadding(pageIndicatorHeight);
- fakePage.setBackground(res.getDrawable(R.drawable.quantum_panel));
-
- // Horizontal padding for the whole paged view
- int pagedFixedViewPadding =
- res.getDimensionPixelSize(R.dimen.apps_customize_horizontal_padding);
-
- padding.left += pagedFixedViewPadding;
- padding.right += pagedFixedViewPadding;
-
- pagedView.setPadding(padding.left, padding.top, padding.right, padding.bottom);
- fakePageContainer.setPadding(padding.left, padding.top, padding.right, padding.bottom);
-
- }
- }
-
// Layout the Overview Mode
ViewGroup overviewMode = launcher.getOverviewPanel();
if (overviewMode != null) {
@@ -875,4 +513,16 @@ public class DeviceProfile {
}
}
}
+
+ private int getCurrentWidth() {
+ return isLandscape
+ ? Math.max(widthPx, heightPx)
+ : Math.min(widthPx, heightPx);
+ }
+
+ private int getCurrentHeight() {
+ return isLandscape
+ ? Math.min(widthPx, heightPx)
+ : Math.max(widthPx, heightPx);
+ }
}
diff --git a/src/com/android/launcher3/DragController.java b/src/com/android/launcher3/DragController.java
index 480dce999..2191455d5 100644
--- a/src/com/android/launcher3/DragController.java
+++ b/src/com/android/launcher3/DragController.java
@@ -34,6 +34,8 @@ import android.view.View;
import android.view.ViewConfiguration;
import android.view.inputmethod.InputMethodManager;
+import com.android.launcher3.util.Thunk;
+
import java.util.ArrayList;
import java.util.HashSet;
@@ -49,8 +51,8 @@ public class DragController {
/** Indicates the drag is a copy. */
public static int DRAG_ACTION_COPY = 1;
- private static final int SCROLL_DELAY = 500;
- private static final int RESCROLL_DELAY = PagedView.PAGE_SNAP_ANIMATION_DURATION + 150;
+ public static final int SCROLL_DELAY = 500;
+ public static final int RESCROLL_DELAY = PagedView.PAGE_SNAP_ANIMATION_DURATION + 150;
private static final boolean PROFILE_DRAWING_DURING_DRAG = false;
@@ -63,16 +65,20 @@ public class DragController {
private static final float MAX_FLING_DEGREES = 35f;
- private Launcher mLauncher;
+ @Thunk Launcher mLauncher;
private Handler mHandler;
// temporaries to avoid gc thrash
private Rect mRectTemp = new Rect();
private final int[] mCoordinatesTemp = new int[2];
+ private final boolean mIsRtl;
/** Whether or not we're dragging. */
private boolean mDragging;
+ /** Whether or not this is an accessible drag operation */
+ private boolean mIsAccessibleDrag;
+
/** X coordinate of the down event. */
private int mMotionDownX;
@@ -99,17 +105,17 @@ public class DragController {
private View mMoveTarget;
- private DragScroller mDragScroller;
- private int mScrollState = SCROLL_OUTSIDE_ZONE;
+ @Thunk DragScroller mDragScroller;
+ @Thunk int mScrollState = SCROLL_OUTSIDE_ZONE;
private ScrollRunnable mScrollRunnable = new ScrollRunnable();
private DropTarget mLastDropTarget;
private InputMethodManager mInputMethodManager;
- private int mLastTouch[] = new int[2];
- private long mLastTouchUpTime = -1;
- private int mDistanceSinceScroll = 0;
+ @Thunk int mLastTouch[] = new int[2];
+ @Thunk long mLastTouchUpTime = -1;
+ @Thunk int mDistanceSinceScroll = 0;
private int mTmpPoint[] = new int[2];
private Rect mDragLayerRect = new Rect();
@@ -120,7 +126,7 @@ public class DragController {
/**
* Interface to receive notifications when a drag starts or stops
*/
- interface DragListener {
+ public interface DragListener {
/**
* A drag has begun
*
@@ -152,6 +158,7 @@ public class DragController {
float density = r.getDisplayMetrics().density;
mFlingToDeleteThresholdVelocity =
(int) (r.getInteger(R.integer.config_flingToDeleteMinVelocity) * density);
+ mIsRtl = Utilities.isRtl(r);
}
public boolean dragging() {
@@ -167,22 +174,21 @@ public class DragController {
* @param dragInfo The data associated with the object that is being dragged
* @param dragAction The drag action: either {@link #DRAG_ACTION_MOVE} or
* {@link #DRAG_ACTION_COPY}
+ * @param viewImageBounds the position of the image inside the view
* @param dragRegion Coordinates within the bitmap b for the position of item being dragged.
* Makes dragging feel more precise, e.g. you can clip out a transparent border
*/
- public void startDrag(View v, Bitmap bmp, DragSource source, Object dragInfo, int dragAction,
- Point extraPadding, float initialDragViewScale) {
+ public void startDrag(View v, Bitmap bmp, DragSource source, Object dragInfo,
+ Rect viewImageBounds, int dragAction, float initialDragViewScale) {
int[] loc = mCoordinatesTemp;
mLauncher.getDragLayer().getLocationInDragLayer(v, loc);
- int viewExtraPaddingLeft = extraPadding != null ? extraPadding.x : 0;
- int viewExtraPaddingTop = extraPadding != null ? extraPadding.y : 0;
- int dragLayerX = loc[0] + v.getPaddingLeft() + viewExtraPaddingLeft +
- (int) ((initialDragViewScale * bmp.getWidth() - bmp.getWidth()) / 2);
- int dragLayerY = loc[1] + v.getPaddingTop() + viewExtraPaddingTop +
- (int) ((initialDragViewScale * bmp.getHeight() - bmp.getHeight()) / 2);
+ int dragLayerX = loc[0] + viewImageBounds.left
+ + (int) ((initialDragViewScale * bmp.getWidth() - bmp.getWidth()) / 2);
+ int dragLayerY = loc[1] + viewImageBounds.top
+ + (int) ((initialDragViewScale * bmp.getHeight() - bmp.getHeight()) / 2);
startDrag(bmp, dragLayerX, dragLayerY, source, dragInfo, dragAction, null,
- null, initialDragViewScale);
+ null, initialDragViewScale, false);
if (dragAction == DRAG_ACTION_MOVE) {
v.setVisibility(View.GONE);
@@ -202,10 +208,11 @@ public class DragController {
* {@link #DRAG_ACTION_COPY}
* @param dragRegion Coordinates within the bitmap b for the position of item being dragged.
* Makes dragging feel more precise, e.g. you can clip out a transparent border
+ * @param accessible whether this drag should occur in accessibility mode
*/
public DragView startDrag(Bitmap b, int dragLayerX, int dragLayerY,
DragSource source, Object dragInfo, int dragAction, Point dragOffset, Rect dragRegion,
- float initialDragViewScale) {
+ float initialDragViewScale, boolean accessible) {
if (PROFILE_DRAWING_DURING_DRAG) {
android.os.Debug.startMethodTracing("Launcher");
}
@@ -228,12 +235,21 @@ public class DragController {
final int dragRegionTop = dragRegion == null ? 0 : dragRegion.top;
mDragging = true;
+ mIsAccessibleDrag = accessible;
mDragObject = new DropTarget.DragObject();
mDragObject.dragComplete = false;
- mDragObject.xOffset = mMotionDownX - (dragLayerX + dragRegionLeft);
- mDragObject.yOffset = mMotionDownY - (dragLayerY + dragRegionTop);
+ if (mIsAccessibleDrag) {
+ // For an accessible drag, we assume the view is being dragged from the center.
+ mDragObject.xOffset = b.getWidth() / 2;
+ mDragObject.yOffset = b.getHeight() / 2;
+ mDragObject.accessibleDrag = true;
+ } else {
+ mDragObject.xOffset = mMotionDownX - (dragLayerX + dragRegionLeft);
+ mDragObject.yOffset = mMotionDownY - (dragLayerY + dragRegionTop);
+ }
+
mDragObject.dragSource = source;
mDragObject.dragInfo = dragInfo;
@@ -349,6 +365,7 @@ public class DragController {
private void endDrag() {
if (mDragging) {
mDragging = false;
+ mIsAccessibleDrag = false;
clearScrollRunnable();
boolean isDeferred = false;
if (mDragObject.dragView != null) {
@@ -361,7 +378,7 @@ public class DragController {
// Only end the drag if we are not deferred
if (!isDeferred) {
- for (DragListener listener : mListeners) {
+ for (DragListener listener : new ArrayList<>(mListeners)) {
listener.onDragEnd();
}
}
@@ -378,13 +395,13 @@ public class DragController {
if (mDragObject.deferDragViewCleanupPostAnimation) {
// If we skipped calling onDragEnd() before, do it now
- for (DragListener listener : mListeners) {
+ for (DragListener listener : new ArrayList<>(mListeners)) {
listener.onDragEnd();
}
}
}
- void onDeferredEndFling(DropTarget.DragObject d) {
+ public void onDeferredEndFling(DropTarget.DragObject d) {
d.dragSource.onFlingToDeleteCompleted();
}
@@ -421,6 +438,10 @@ public class DragController {
+ mDragging);
}
+ if (mIsAccessibleDrag) {
+ return false;
+ }
+
// Update the velocity tracker
acquireVelocityTrackerAndAddMovement(ev);
@@ -442,7 +463,7 @@ public class DragController {
mLastTouchUpTime = System.currentTimeMillis();
if (mDragging) {
PointF vec = isFlingingToDelete(mDragObject.dragSource);
- if (!DeleteDropTarget.willAcceptDrop(mDragObject.dragInfo)) {
+ if (!DeleteDropTarget.supportsDrop(mDragObject.dragInfo)) {
vec = null;
}
if (vec != null) {
@@ -493,8 +514,7 @@ public class DragController {
checkTouchMove(dropTarget);
// Check if we are hovering over the scroll areas
- mDistanceSinceScroll +=
- Math.sqrt(Math.pow(mLastTouch[0] - x, 2) + Math.pow(mLastTouch[1] - y, 2));
+ mDistanceSinceScroll += Math.hypot(mLastTouch[0] - x, mLastTouch[1] - y);
mLastTouch[0] = x;
mLastTouch[1] = y;
checkScrollState(x, y);
@@ -525,13 +545,12 @@ public class DragController {
mLastDropTarget = dropTarget;
}
- private void checkScrollState(int x, int y) {
+ @Thunk void checkScrollState(int x, int y) {
final int slop = ViewConfiguration.get(mLauncher).getScaledWindowTouchSlop();
final int delay = mDistanceSinceScroll < slop ? RESCROLL_DELAY : SCROLL_DELAY;
final DragLayer dragLayer = mLauncher.getDragLayer();
- final boolean isRtl = (dragLayer.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL);
- final int forwardDirection = isRtl ? SCROLL_RIGHT : SCROLL_LEFT;
- final int backwardsDirection = isRtl ? SCROLL_LEFT : SCROLL_RIGHT;
+ final int forwardDirection = mIsRtl ? SCROLL_RIGHT : SCROLL_LEFT;
+ final int backwardsDirection = mIsRtl ? SCROLL_LEFT : SCROLL_RIGHT;
if (x < mScrollZone) {
if (mScrollState == SCROLL_OUTSIDE_ZONE) {
@@ -560,7 +579,7 @@ public class DragController {
* Call this from a drag source view.
*/
public boolean onTouchEvent(MotionEvent ev) {
- if (!mDragging) {
+ if (!mDragging || mIsAccessibleDrag) {
return false;
}
@@ -596,7 +615,7 @@ public class DragController {
if (mDragging) {
PointF vec = isFlingingToDelete(mDragObject.dragSource);
- if (!DeleteDropTarget.willAcceptDrop(mDragObject.dragInfo)) {
+ if (!DeleteDropTarget.supportsDrop(mDragObject.dragInfo)) {
vec = null;
}
if (vec != null) {
@@ -617,6 +636,35 @@ public class DragController {
}
/**
+ * Since accessible drag and drop won't cause the same sequence of touch events, we manually
+ * inject the appropriate state.
+ */
+ public void prepareAccessibleDrag(int x, int y) {
+ mMotionDownX = x;
+ mMotionDownY = y;
+ mLastDropTarget = null;
+ }
+
+ /**
+ * As above, since accessible drag and drop won't cause the same sequence of touch events,
+ * we manually ensure appropriate drag and drop events get emulated for accessible drag.
+ */
+ public void completeAccessibleDrag(int[] location) {
+ final int[] coordinates = mCoordinatesTemp;
+
+ // We make sure that we prime the target for drop.
+ DropTarget dropTarget = findDropTarget(location[0], location[1], coordinates);
+ mDragObject.x = coordinates[0];
+ mDragObject.y = coordinates[1];
+ checkTouchMove(dropTarget);
+
+ dropTarget.prepareAccessibilityDrop();
+ // Perform the drop
+ drop(location[0], location[1]);
+ endDrag();
+ }
+
+ /**
* Determines whether the user flung the current item to delete it.
*
* @return the vector at which the item was flung, or null if no fling was detected.
@@ -662,8 +710,7 @@ public class DragController {
mDragObject.dragComplete = true;
mFlingToDeleteDropTarget.onDragExit(mDragObject);
if (mFlingToDeleteDropTarget.acceptDrop(mDragObject)) {
- mFlingToDeleteDropTarget.onFlingToDelete(mDragObject, mDragObject.x, mDragObject.y,
- vel);
+ mFlingToDeleteDropTarget.onFlingToDelete(mDragObject, vel);
accepted = true;
}
mDragObject.dragSource.onDropCompleted((View) mFlingToDeleteDropTarget, mDragObject, true,
diff --git a/src/com/android/launcher3/DragLayer.java b/src/com/android/launcher3/DragLayer.java
index a352b7914..aaa14e6a6 100644
--- a/src/com/android/launcher3/DragLayer.java
+++ b/src/com/android/launcher3/DragLayer.java
@@ -24,6 +24,7 @@ import android.animation.ValueAnimator.AnimatorUpdateListener;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Canvas;
+import android.graphics.Color;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
@@ -38,7 +39,8 @@ import android.view.animation.Interpolator;
import android.widget.FrameLayout;
import android.widget.TextView;
-import com.android.launcher3.InsettableFrameLayout.LayoutParams;
+import com.android.launcher3.accessibility.LauncherAccessibilityDelegate;
+import com.android.launcher3.util.Thunk;
import java.util.ArrayList;
@@ -46,30 +48,34 @@ import java.util.ArrayList;
* A ViewGroup that coordinates dragging across its descendants
*/
public class DragLayer extends InsettableFrameLayout {
- private DragController mDragController;
- private int[] mTmpXY = new int[2];
+
+ public static final int ANIMATION_END_DISAPPEAR = 0;
+ public static final int ANIMATION_END_REMAIN_VISIBLE = 2;
+
+ // Scrim color without any alpha component.
+ private static final int SCRIM_COLOR = Color.BLACK & 0x00FFFFFF;
+
+ private final int[] mTmpXY = new int[2];
+
+ @Thunk DragController mDragController;
private int mXDown, mYDown;
private Launcher mLauncher;
// Variables relating to resizing widgets
- private final ArrayList<AppWidgetResizeFrame> mResizeFrames =
- new ArrayList<AppWidgetResizeFrame>();
+ private final ArrayList<AppWidgetResizeFrame> mResizeFrames = new ArrayList<>();
+ private final boolean mIsRtl;
private AppWidgetResizeFrame mCurrentResizeFrame;
// Variables relating to animation of views after drop
private ValueAnimator mDropAnim = null;
- private ValueAnimator mFadeOutAnim = null;
- private TimeInterpolator mCubicEaseOutInterpolator = new DecelerateInterpolator(1.5f);
- private DragView mDropView = null;
- private int mAnchorViewInitialScrollX = 0;
- private View mAnchorView = null;
+ private final TimeInterpolator mCubicEaseOutInterpolator = new DecelerateInterpolator(1.5f);
+ @Thunk DragView mDropView = null;
+ @Thunk int mAnchorViewInitialScrollX = 0;
+ @Thunk View mAnchorView = null;
private boolean mHoverPointClosesFolder = false;
- private Rect mHitRect = new Rect();
- public static final int ANIMATION_END_DISAPPEAR = 0;
- public static final int ANIMATION_END_FADE_OUT = 1;
- public static final int ANIMATION_END_REMAIN_VISIBLE = 2;
+ private final Rect mHitRect = new Rect();
private TouchCompleteListener mTouchCompleteListener;
@@ -78,10 +84,10 @@ public class DragLayer extends InsettableFrameLayout {
private int mChildCountOnLastUpdate = -1;
// Darkening scrim
- private Drawable mBackground;
private float mBackgroundAlpha = 0;
// Related to adjacent page hints
+ private final Rect mScrollChildPosition = new Rect();
private boolean mInScrollArea;
private boolean mShowPageHints;
private Drawable mLeftHoverDrawable;
@@ -109,7 +115,7 @@ public class DragLayer extends InsettableFrameLayout {
mRightHoverDrawable = res.getDrawable(R.drawable.page_hover_right);
mLeftHoverDrawableActive = res.getDrawable(R.drawable.page_hover_left_active);
mRightHoverDrawableActive = res.getDrawable(R.drawable.page_hover_right_active);
- mBackground = res.getDrawable(R.drawable.apps_customize_bg);
+ mIsRtl = Utilities.isRtl(res);
}
public void setup(Launcher launcher, DragController controller) {
@@ -152,6 +158,14 @@ public class DragLayer extends InsettableFrameLayout {
return false;
}
+ private boolean isEventOverDropTargetBar(MotionEvent ev) {
+ getDescendantRectRelativeToSelf(mLauncher.getSearchBar(), mHitRect);
+ if (mHitRect.contains((int) ev.getX(), (int) ev.getY())) {
+ return true;
+ }
+ return false;
+ }
+
public void setBlockTouch(boolean block) {
mBlockTouches = block;
}
@@ -187,10 +201,16 @@ public class DragLayer extends InsettableFrameLayout {
}
}
- getDescendantRectRelativeToSelf(currentFolder, hitRect);
if (!isEventOverFolder(currentFolder, ev)) {
- mLauncher.closeFolder();
- return true;
+ if (isInAccessibleDrag()) {
+ // Do not close the folder if in drag and drop.
+ if (!isEventOverDropTargetBar(ev)) {
+ return true;
+ }
+ } else {
+ mLauncher.closeFolder();
+ return true;
+ }
}
}
return false;
@@ -227,11 +247,12 @@ public class DragLayer extends InsettableFrameLayout {
getContext().getSystemService(Context.ACCESSIBILITY_SERVICE);
if (accessibilityManager.isTouchExplorationEnabled()) {
final int action = ev.getAction();
- boolean isOverFolder;
+ boolean isOverFolderOrSearchBar;
switch (action) {
case MotionEvent.ACTION_HOVER_ENTER:
- isOverFolder = isEventOverFolder(currentFolder, ev);
- if (!isOverFolder) {
+ isOverFolderOrSearchBar = isEventOverFolder(currentFolder, ev) ||
+ (isInAccessibleDrag() && isEventOverDropTargetBar(ev));
+ if (!isOverFolderOrSearchBar) {
sendTapOutsideFolderAccessibilityEvent(currentFolder.isEditingName());
mHoverPointClosesFolder = true;
return true;
@@ -239,12 +260,13 @@ public class DragLayer extends InsettableFrameLayout {
mHoverPointClosesFolder = false;
break;
case MotionEvent.ACTION_HOVER_MOVE:
- isOverFolder = isEventOverFolder(currentFolder, ev);
- if (!isOverFolder && !mHoverPointClosesFolder) {
+ isOverFolderOrSearchBar = isEventOverFolder(currentFolder, ev) ||
+ (isInAccessibleDrag() && isEventOverDropTargetBar(ev));
+ if (!isOverFolderOrSearchBar && !mHoverPointClosesFolder) {
sendTapOutsideFolderAccessibilityEvent(currentFolder.isEditingName());
mHoverPointClosesFolder = true;
return true;
- } else if (!isOverFolder) {
+ } else if (!isOverFolderOrSearchBar) {
return true;
}
mHoverPointClosesFolder = false;
@@ -267,6 +289,12 @@ public class DragLayer extends InsettableFrameLayout {
}
}
+ private boolean isInAccessibleDrag() {
+ LauncherAccessibilityDelegate delegate = LauncherAppState
+ .getInstance().getAccessibilityDelegate();
+ return delegate != null && delegate.isInAccessibleDrag();
+ }
+
@Override
public boolean onRequestSendAccessibilityEvent(View child, AccessibilityEvent event) {
Folder currentFolder = mLauncher.getWorkspace().getOpenFolder();
@@ -274,6 +302,10 @@ public class DragLayer extends InsettableFrameLayout {
if (child == currentFolder) {
return super.onRequestSendAccessibilityEvent(child, event);
}
+
+ if (isInAccessibleDrag() && child instanceof SearchDropTargetBar) {
+ return super.onRequestSendAccessibilityEvent(child, event);
+ }
// Skip propagating onRequestSendAccessibilityEvent all for other children
// when a folder is open
return false;
@@ -287,6 +319,10 @@ public class DragLayer extends InsettableFrameLayout {
if (currentFolder != null) {
// Only add the folder as a child for accessibility when it is open
childrenForAccessibility.add(currentFolder);
+
+ if (isInAccessibleDrag()) {
+ childrenForAccessibility.add(mLauncher.getSearchBar());
+ }
} else {
super.addChildrenForAccessibility(childrenForAccessibility);
}
@@ -656,8 +692,7 @@ public class DragLayer extends InsettableFrameLayout {
final Runnable onCompleteRunnable, final int animationEndStyle, View anchorView) {
// Calculate the duration of the animation based on the object's distance
- final float dist = (float) Math.sqrt(Math.pow(to.left - from.left, 2) +
- Math.pow(to.top - from.top, 2));
+ final float dist = (float) Math.hypot(to.left - from.left, to.top - from.top);
final Resources res = getResources();
final float maxDist = (float) res.getInteger(R.integer.config_dropAnimMaxDist);
@@ -725,7 +760,6 @@ public class DragLayer extends InsettableFrameLayout {
final int animationEndStyle, View anchorView) {
// Clean up the previous animations
if (mDropAnim != null) mDropAnim.cancel();
- if (mFadeOutAnim != null) mFadeOutAnim.cancel();
// Show the drop view if it was previously hidden
mDropView = view;
@@ -753,9 +787,6 @@ public class DragLayer extends InsettableFrameLayout {
case ANIMATION_END_DISAPPEAR:
clearAnimatedView();
break;
- case ANIMATION_END_FADE_OUT:
- fadeOutDragView();
- break;
case ANIMATION_END_REMAIN_VISIBLE:
break;
}
@@ -779,31 +810,6 @@ public class DragLayer extends InsettableFrameLayout {
return mDropView;
}
- private void fadeOutDragView() {
- mFadeOutAnim = new ValueAnimator();
- mFadeOutAnim.setDuration(150);
- mFadeOutAnim.setFloatValues(0f, 1f);
- mFadeOutAnim.removeAllUpdateListeners();
- mFadeOutAnim.addUpdateListener(new AnimatorUpdateListener() {
- public void onAnimationUpdate(ValueAnimator animation) {
- final float percent = (Float) animation.getAnimatedValue();
-
- float alpha = 1 - percent;
- mDropView.setAlpha(alpha);
- }
- });
- mFadeOutAnim.addListener(new AnimatorListenerAdapter() {
- public void onAnimationEnd(Animator animation) {
- if (mDropView != null) {
- mDragController.onDeferredEndDrag(mDropView);
- }
- mDropView = null;
- invalidate();
- }
- });
- mFadeOutAnim.start();
- }
-
@Override
public void onChildViewAdded(View parent, View child) {
super.onChildViewAdded(parent, child);
@@ -880,6 +886,9 @@ public class DragLayer extends InsettableFrameLayout {
void showPageHints() {
mShowPageHints = true;
+ Workspace workspace = mLauncher.getWorkspace();
+ getDescendantRectRelativeToSelf(workspace.getChildAt(workspace.numCustomPages()),
+ mScrollChildPosition);
invalidate();
}
@@ -888,21 +897,12 @@ public class DragLayer extends InsettableFrameLayout {
invalidate();
}
- /**
- * Note: this is a reimplementation of View.isLayoutRtl() since that is currently hidden api.
- */
- private boolean isLayoutRtl() {
- return (getLayoutDirection() == LAYOUT_DIRECTION_RTL);
- }
-
@Override
protected void dispatchDraw(Canvas canvas) {
- // Draw the background gradient below children.
- if (mBackground != null && mBackgroundAlpha > 0.0f) {
+ // Draw the background below children.
+ if (mBackgroundAlpha > 0.0f) {
int alpha = (int) (mBackgroundAlpha * 255);
- mBackground.setAlpha(alpha);
- mBackground.setBounds(0, 0, getMeasuredWidth(), getMeasuredHeight());
- mBackground.draw(canvas);
+ canvas.drawColor((alpha << 24) | SCRIM_COLOR);
}
super.dispatchDraw(canvas);
@@ -912,27 +912,22 @@ public class DragLayer extends InsettableFrameLayout {
if (mShowPageHints) {
Workspace workspace = mLauncher.getWorkspace();
int width = getMeasuredWidth();
- Rect childRect = new Rect();
- getDescendantRectRelativeToSelf(workspace.getChildAt(workspace.getChildCount() - 1),
- childRect);
-
int page = workspace.getNextPage();
- final boolean isRtl = isLayoutRtl();
- CellLayout leftPage = (CellLayout) workspace.getChildAt(isRtl ? page + 1 : page - 1);
- CellLayout rightPage = (CellLayout) workspace.getChildAt(isRtl ? page - 1 : page + 1);
+ CellLayout leftPage = (CellLayout) workspace.getChildAt(mIsRtl ? page + 1 : page - 1);
+ CellLayout rightPage = (CellLayout) workspace.getChildAt(mIsRtl ? page - 1 : page + 1);
if (leftPage != null && leftPage.isDragTarget()) {
Drawable left = mInScrollArea && leftPage.getIsDragOverlapping() ?
mLeftHoverDrawableActive : mLeftHoverDrawable;
- left.setBounds(0, childRect.top,
- left.getIntrinsicWidth(), childRect.bottom);
+ left.setBounds(0, mScrollChildPosition.top,
+ left.getIntrinsicWidth(), mScrollChildPosition.bottom);
left.draw(canvas);
}
if (rightPage != null && rightPage.isDragTarget()) {
Drawable right = mInScrollArea && rightPage.getIsDragOverlapping() ?
mRightHoverDrawableActive : mRightHoverDrawable;
right.setBounds(width - right.getIntrinsicWidth(),
- childRect.top, width, childRect.bottom);
+ mScrollChildPosition.top, width, mScrollChildPosition.bottom);
right.draw(canvas);
}
}
diff --git a/src/com/android/launcher3/DragSource.java b/src/com/android/launcher3/DragSource.java
index 7369eeac2..2a1346ef5 100644
--- a/src/com/android/launcher3/DragSource.java
+++ b/src/com/android/launcher3/DragSource.java
@@ -22,9 +22,9 @@ import com.android.launcher3.DropTarget.DragObject;
/**
* Interface defining an object that can originate a drag.
- *
*/
public interface DragSource {
+
/**
* @return whether items dragged from this source supports
*/
diff --git a/src/com/android/launcher3/DragView.java b/src/com/android/launcher3/DragView.java
index ea34e46f9..dfa8202a7 100644
--- a/src/com/android/launcher3/DragView.java
+++ b/src/com/android/launcher3/DragView.java
@@ -16,25 +16,35 @@
package com.android.launcher3;
+import android.animation.FloatArrayEvaluator;
import android.animation.ValueAnimator;
import android.animation.ValueAnimator.AnimatorUpdateListener;
+import android.annotation.TargetApi;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.ColorMatrix;
+import android.graphics.ColorMatrixColorFilter;
import android.graphics.Paint;
import android.graphics.Point;
-import android.graphics.PorterDuff;
-import android.graphics.PorterDuffColorFilter;
import android.graphics.Rect;
+import android.os.Build;
import android.view.View;
import android.view.animation.DecelerateInterpolator;
+import com.android.launcher3.util.Thunk;
+
+import java.util.Arrays;
+
public class DragView extends View {
- private static float sDragAlpha = 1f;
+ public static int COLOR_CHANGE_DURATION = 120;
+
+ @Thunk static float sDragAlpha = 1f;
private Bitmap mBitmap;
private Bitmap mCrossFadeBitmap;
- private Paint mPaint;
+ @Thunk Paint mPaint;
private int mRegistrationX;
private int mRegistrationY;
@@ -42,16 +52,19 @@ public class DragView extends View {
private Rect mDragRegion = null;
private DragLayer mDragLayer = null;
private boolean mHasDrawn = false;
- private float mCrossFadeProgress = 0f;
+ @Thunk float mCrossFadeProgress = 0f;
ValueAnimator mAnim;
- private float mOffsetX = 0.0f;
- private float mOffsetY = 0.0f;
+ @Thunk float mOffsetX = 0.0f;
+ @Thunk float mOffsetY = 0.0f;
private float mInitialScale = 1f;
// The intrinsic icon scale factor is the scale factor for a drag icon over the workspace
// size. This is ignored for non-icons.
private float mIntrinsicIconScale = 1f;
+ @Thunk float[] mCurrentFilter;
+ private ValueAnimator mFilterAnimator;
+
/**
* Construct the drag view.
* <p>
@@ -63,6 +76,7 @@ public class DragView extends View {
* @param registrationX The x coordinate of the registration point.
* @param registrationY The y coordinate of the registration point.
*/
+ @TargetApi(Build.VERSION_CODES.LOLLIPOP)
public DragView(Launcher launcher, Bitmap bitmap, int registrationX, int registrationY,
int left, int top, int width, int height, final float initialScale) {
super(launcher);
@@ -70,8 +84,6 @@ public class DragView extends View {
mInitialScale = initialScale;
final Resources res = getResources();
- final float offsetX = res.getDimensionPixelSize(R.dimen.dragViewOffsetX);
- final float offsetY = res.getDimensionPixelSize(R.dimen.dragViewOffsetY);
final float scaleDps = res.getDimensionPixelSize(R.dimen.dragViewScale);
final float scale = (width + scaleDps) / width;
@@ -87,8 +99,8 @@ public class DragView extends View {
public void onAnimationUpdate(ValueAnimator animation) {
final float value = (Float) animation.getAnimatedValue();
- final int deltaX = (int) ((value * offsetX) - mOffsetX);
- final int deltaY = (int) ((value * offsetY) - mOffsetY);
+ final int deltaX = (int) (-mOffsetX);
+ final int deltaY = (int) (-mOffsetY);
mOffsetX += deltaX;
mOffsetY += deltaY;
@@ -118,6 +130,10 @@ public class DragView extends View {
int ms = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
measure(ms, ms);
mPaint = new Paint(Paint.FILTER_BITMAP_FLAG);
+
+ if (Utilities.isLmpOrAbove()) {
+ setElevation(getResources().getDimension(R.dimen.drag_elevation));
+ }
}
/** Sets the scale of the view over the normal workspace icon size. */
@@ -229,11 +245,49 @@ public class DragView extends View {
mPaint = new Paint(Paint.FILTER_BITMAP_FLAG);
}
if (color != 0) {
- mPaint.setColorFilter(new PorterDuffColorFilter(color, PorterDuff.Mode.SRC_ATOP));
+ ColorMatrix m1 = new ColorMatrix();
+ m1.setSaturation(0);
+
+ ColorMatrix m2 = new ColorMatrix();
+ setColorScale(color, m2);
+ m1.postConcat(m2);
+
+ if (Utilities.isLmpOrAbove()) {
+ animateFilterTo(m1.getArray());
+ } else {
+ mPaint.setColorFilter(new ColorMatrixColorFilter(m1));
+ invalidate();
+ }
} else {
- mPaint.setColorFilter(null);
+ if (!Utilities.isLmpOrAbove() || mCurrentFilter == null) {
+ mPaint.setColorFilter(null);
+ invalidate();
+ } else {
+ animateFilterTo(new ColorMatrix().getArray());
+ }
}
- invalidate();
+ }
+
+ @TargetApi(Build.VERSION_CODES.LOLLIPOP)
+ private void animateFilterTo(float[] targetFilter) {
+ float[] oldFilter = mCurrentFilter == null ? new ColorMatrix().getArray() : mCurrentFilter;
+ mCurrentFilter = Arrays.copyOf(oldFilter, oldFilter.length);
+
+ if (mFilterAnimator != null) {
+ mFilterAnimator.cancel();
+ }
+ mFilterAnimator = ValueAnimator.ofObject(new FloatArrayEvaluator(mCurrentFilter),
+ oldFilter, targetFilter);
+ mFilterAnimator.setDuration(COLOR_CHANGE_DURATION);
+ mFilterAnimator.addUpdateListener(new AnimatorUpdateListener() {
+
+ @Override
+ public void onAnimationUpdate(ValueAnimator animation) {
+ mPaint.setColorFilter(new ColorMatrixColorFilter(mCurrentFilter));
+ invalidate();
+ }
+ });
+ mFilterAnimator.start();
}
public boolean hasDrawn() {
@@ -300,5 +354,9 @@ public class DragView extends View {
mDragLayer.removeView(DragView.this);
}
}
-}
+ public static void setColorScale(int color, ColorMatrix target) {
+ target.setScale(Color.red(color) / 255f, Color.green(color) / 255f,
+ Color.blue(color) / 255f, Color.alpha(color) / 255f);
+ }
+}
diff --git a/src/com/android/launcher3/DropTarget.java b/src/com/android/launcher3/DropTarget.java
index 64f0ac867..c8fac5466 100644
--- a/src/com/android/launcher3/DropTarget.java
+++ b/src/com/android/launcher3/DropTarget.java
@@ -16,10 +16,8 @@
package com.android.launcher3;
-import android.content.Context;
import android.graphics.PointF;
import android.graphics.Rect;
-import android.util.Log;
/**
* Interface defining an object that can receive a drag.
@@ -29,7 +27,7 @@ public interface DropTarget {
public static final String TAG = "DropTarget";
- class DragObject {
+ public static class DragObject {
public int x = -1;
public int y = -1;
@@ -54,6 +52,9 @@ public interface DropTarget {
/** Where the drag originated */
public DragSource dragSource = null;
+ /** The object is part of an accessible drag operation */
+ public boolean accessibleDrag;
+
/** Post drag animation runnable */
public Runnable postAnimationRunnable = null;
@@ -65,42 +66,28 @@ public interface DropTarget {
public DragObject() {
}
- }
-
- public static class DragEnforcer implements DragController.DragListener {
- int dragParity = 0;
-
- public DragEnforcer(Context context) {
- Launcher launcher = (Launcher) context;
- launcher.getDragController().addDragListener(this);
- }
- void onDragEnter() {
- dragParity++;
- if (dragParity != 1) {
- Log.e(TAG, "onDragEnter: Drag contract violated: " + dragParity);
- }
- }
+ /**
+ * This is used to compute the visual center of the dragView. This point is then
+ * used to visualize drop locations and determine where to drop an item. The idea is that
+ * the visual center represents the user's interpretation of where the item is, and hence
+ * is the appropriate point to use when determining drop location.
+ */
+ public final float[] getVisualCenter(float[] recycle) {
+ final float res[] = (recycle == null) ? new float[2] : recycle;
- void onDragExit() {
- dragParity--;
- if (dragParity != 0) {
- Log.e(TAG, "onDragExit: Drag contract violated: " + dragParity);
- }
- }
+ // These represent the visual top and left of drag view if a dragRect was provided.
+ // If a dragRect was not provided, then they correspond to the actual view left and
+ // top, as the dragRect is in that case taken to be the entire dragView.
+ // R.dimen.dragViewOffsetY.
+ int left = x - xOffset;
+ int top = y - yOffset;
- @Override
- public void onDragStart(DragSource source, Object info, int dragAction) {
- if (dragParity != 0) {
- Log.e(TAG, "onDragEnter: Drag contract violated: " + dragParity);
- }
- }
+ // In order to find the visual center, we shift by half the dragRect
+ res[0] = left + dragView.getDragRegion().width() / 2;
+ res[1] = top + dragView.getDragRegion().height() / 2;
- @Override
- public void onDragEnd() {
- if (dragParity != 0) {
- Log.e(TAG, "onDragExit: Drag contract violated: " + dragParity);
- }
+ return res;
}
}
@@ -113,7 +100,7 @@ public interface DropTarget {
/**
* Handle an object being dropped on the DropTarget
- *
+ *
* @param source DragSource where the drag started
* @param x X coordinate of the drop location
* @param y Y coordinate of the drop location
@@ -138,12 +125,12 @@ public interface DropTarget {
* of onDrop(). (This is only called on objects that are set as the DragController's
* fling-to-delete target.
*/
- void onFlingToDelete(DragObject dragObject, int x, int y, PointF vec);
+ void onFlingToDelete(DragObject dragObject, PointF vec);
/**
* Check if a drop action can occur at, or near, the requested location.
* This will be called just before onDrop.
- *
+ *
* @param source DragSource where the drag started
* @param x X coordinate of the drop location
* @param y Y coordinate of the drop location
@@ -157,6 +144,8 @@ public interface DropTarget {
*/
boolean acceptDrop(DragObject dragObject);
+ void prepareAccessibilityDrop();
+
// These methods are implemented in Views
void getHitRectRelativeToDragLayer(Rect outRect);
void getLocationInDragLayer(int[] loc);
diff --git a/src/com/android/launcher3/DummyWidget.java b/src/com/android/launcher3/DummyWidget.java
new file mode 100644
index 000000000..59cd80501
--- /dev/null
+++ b/src/com/android/launcher3/DummyWidget.java
@@ -0,0 +1,50 @@
+package com.android.launcher3;
+
+import android.appwidget.AppWidgetProviderInfo;
+
+public class DummyWidget implements CustomAppWidget {
+ @Override
+ public String getLabel() {
+ return "Dumb Launcher Widget";
+ }
+
+ @Override
+ public int getPreviewImage() {
+ return 0;
+ }
+
+ @Override
+ public int getIcon() {
+ return 0;
+ }
+
+ @Override
+ public int getWidgetLayout() {
+ return R.layout.dummy_widget;
+ }
+
+ @Override
+ public int getSpanX() {
+ return 2;
+ }
+
+ @Override
+ public int getSpanY() {
+ return 2;
+ }
+
+ @Override
+ public int getMinSpanX() {
+ return 1;
+ }
+
+ @Override
+ public int getMinSpanY() {
+ return 1;
+ }
+
+ @Override
+ public int getResizeMode() {
+ return AppWidgetProviderInfo.RESIZE_BOTH;
+ }
+}
diff --git a/src/com/android/launcher3/DynamicGrid.java b/src/com/android/launcher3/DynamicGrid.java
deleted file mode 100644
index aa08148d2..000000000
--- a/src/com/android/launcher3/DynamicGrid.java
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.launcher3;
-
-import android.content.Context;
-import android.content.res.Resources;
-import android.util.DisplayMetrics;
-import android.util.TypedValue;
-
-import java.util.ArrayList;
-
-
-public class DynamicGrid {
- @SuppressWarnings("unused")
- private static final String TAG = "DynamicGrid";
-
- private DeviceProfile mProfile;
- private float mMinWidth;
- private float mMinHeight;
-
- // This is a static that we use for the default icon size on a 4/5-inch phone
- static float DEFAULT_ICON_SIZE_DP = 60;
- static float DEFAULT_ICON_SIZE_PX = 0;
-
- public static float dpiFromPx(int size, DisplayMetrics metrics){
- float densityRatio = (float) metrics.densityDpi / DisplayMetrics.DENSITY_DEFAULT;
- return (size / densityRatio);
- }
- public static int pxFromDp(float size, DisplayMetrics metrics) {
- return (int) Math.round(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
- size, metrics));
- }
- public static int pxFromSp(float size, DisplayMetrics metrics) {
- return (int) Math.round(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,
- size, metrics));
- }
-
- public DynamicGrid(Context context, Resources resources,
- int minWidthPx, int minHeightPx,
- int widthPx, int heightPx,
- int awPx, int ahPx) {
- DisplayMetrics dm = resources.getDisplayMetrics();
- ArrayList<DeviceProfile> deviceProfiles =
- new ArrayList<DeviceProfile>();
- boolean hasAA = !LauncherAppState.isDisableAllApps();
- DEFAULT_ICON_SIZE_PX = pxFromDp(DEFAULT_ICON_SIZE_DP, dm);
- // Our phone profiles include the bar sizes in each orientation
- deviceProfiles.add(new DeviceProfile("Super Short Stubby",
- 255, 300, 2, 3, 48, 13, (hasAA ? 3 : 5), 48, R.xml.default_workspace_4x4));
- deviceProfiles.add(new DeviceProfile("Shorter Stubby",
- 255, 400, 3, 3, 48, 13, (hasAA ? 3 : 5), 48, R.xml.default_workspace_4x4));
- deviceProfiles.add(new DeviceProfile("Short Stubby",
- 275, 420, 3, 4, 48, 13, (hasAA ? 5 : 5), 48, R.xml.default_workspace_4x4));
- deviceProfiles.add(new DeviceProfile("Stubby",
- 255, 450, 3, 4, 48, 13, (hasAA ? 5 : 5), 48, R.xml.default_workspace_4x4));
- deviceProfiles.add(new DeviceProfile("Nexus S",
- 296, 491.33f, 4, 4, 48, 13, (hasAA ? 5 : 5), 48, R.xml.default_workspace_4x4));
- deviceProfiles.add(new DeviceProfile("Nexus 4",
- 335, 567, 4, 4, DEFAULT_ICON_SIZE_DP, 13, (hasAA ? 5 : 5), 56, R.xml.default_workspace_4x4));
- deviceProfiles.add(new DeviceProfile("Nexus 5",
- 359, 567, 4, 4, DEFAULT_ICON_SIZE_DP, 13, (hasAA ? 5 : 5), 56, R.xml.default_workspace_4x4));
- deviceProfiles.add(new DeviceProfile("Large Phone",
- 406, 694, 5, 5, 64, 14.4f, 5, 56, R.xml.default_workspace_5x5));
- // The tablet profile is odd in that the landscape orientation
- // also includes the nav bar on the side
- deviceProfiles.add(new DeviceProfile("Nexus 7",
- 575, 904, 5, 6, 72, 14.4f, 7, 60, R.xml.default_workspace_5x6));
- // Larger tablet profiles always have system bars on the top & bottom
- deviceProfiles.add(new DeviceProfile("Nexus 10",
- 727, 1207, 5, 6, 76, 14.4f, 7, 64, R.xml.default_workspace_5x6));
- deviceProfiles.add(new DeviceProfile("20-inch Tablet",
- 1527, 2527, 7, 7, 100, 20, 7, 72, R.xml.default_workspace_4x4));
- mMinWidth = dpiFromPx(minWidthPx, dm);
- mMinHeight = dpiFromPx(minHeightPx, dm);
- mProfile = new DeviceProfile(context, deviceProfiles,
- mMinWidth, mMinHeight,
- widthPx, heightPx,
- awPx, ahPx,
- resources);
- }
-
- public DeviceProfile getDeviceProfile() {
- return mProfile;
- }
-
- public String toString() {
- return "-------- DYNAMIC GRID ------- \n" +
- "Wd: " + mProfile.minWidthDps + ", Hd: " + mProfile.minHeightDps +
- ", W: " + mProfile.widthPx + ", H: " + mProfile.heightPx +
- " [r: " + mProfile.numRows + ", c: " + mProfile.numColumns +
- ", is: " + mProfile.iconSizePx + ", its: " + mProfile.iconTextSizePx +
- ", cw: " + mProfile.cellWidthPx + ", ch: " + mProfile.cellHeightPx +
- ", hc: " + mProfile.numHotseatIcons + ", his: " + mProfile.hotseatIconSizePx + "]";
- }
-}
diff --git a/src/com/android/launcher3/FastBitmapDrawable.java b/src/com/android/launcher3/FastBitmapDrawable.java
index ff02bbbc3..28e923e67 100644
--- a/src/com/android/launcher3/FastBitmapDrawable.java
+++ b/src/com/android/launcher3/FastBitmapDrawable.java
@@ -32,7 +32,7 @@ import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.util.SparseArray;
-class FastBitmapDrawable extends Drawable {
+public class FastBitmapDrawable extends Drawable {
static final TimeInterpolator CLICK_FEEDBACK_INTERPOLATOR = new TimeInterpolator() {
@@ -72,7 +72,7 @@ class FastBitmapDrawable extends Drawable {
private boolean mPressed = false;
private ObjectAnimator mPressedAnimator;
- FastBitmapDrawable(Bitmap b) {
+ public FastBitmapDrawable(Bitmap b) {
mAlpha = 255;
mBitmap = b;
setBounds(0, 0, b.getWidth(), b.getHeight());
diff --git a/src/com/android/launcher3/FastBitmapView.java b/src/com/android/launcher3/FastBitmapView.java
deleted file mode 100644
index 0937eb75e..000000000
--- a/src/com/android/launcher3/FastBitmapView.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (C) 2014 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;
-
-import android.content.Context;
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.graphics.Paint;
-import android.view.View;
-
-public class FastBitmapView extends View {
-
- private final Paint mPaint = new Paint(Paint.FILTER_BITMAP_FLAG);
- private Bitmap mBitmap;
-
- public FastBitmapView(Context context) {
- super(context);
- }
-
- /**
- * Applies the new bitmap.
- * @return true if the view was invalidated.
- */
- public boolean setBitmap(Bitmap b) {
- if (b != mBitmap){
- if (mBitmap != null) {
- invalidate(0, 0, mBitmap.getWidth(), mBitmap.getHeight());
- }
- mBitmap = b;
- if (mBitmap != null) {
- invalidate(0, 0, mBitmap.getWidth(), mBitmap.getHeight());
- }
- return true;
- }
- return false;
- }
-
- @Override
- protected void onDraw(Canvas canvas) {
- if (mBitmap != null) {
- canvas.drawBitmap(mBitmap, 0, 0, mPaint);
- }
- }
-}
diff --git a/src/com/android/launcher3/FirstFrameAnimatorHelper.java b/src/com/android/launcher3/FirstFrameAnimatorHelper.java
index 095c5631d..a51ddd4b8 100644
--- a/src/com/android/launcher3/FirstFrameAnimatorHelper.java
+++ b/src/com/android/launcher3/FirstFrameAnimatorHelper.java
@@ -24,6 +24,8 @@ import android.view.View;
import android.view.ViewPropertyAnimator;
import android.view.ViewTreeObserver;
+import com.android.launcher3.util.Thunk;
+
/*
* This is a helper class that listens to updates from the corresponding animation.
* For the first two frames, it adjusts the current play time of the animation to
@@ -41,7 +43,7 @@ public class FirstFrameAnimatorHelper extends AnimatorListenerAdapter
private boolean mAdjustedSecondFrameTime;
private static ViewTreeObserver.OnDrawListener sGlobalDrawListener;
- private static long sGlobalFrameCounter;
+ @Thunk static long sGlobalFrameCounter;
private static boolean sVisible;
public FirstFrameAnimatorHelper(ValueAnimator animator, View target) {
diff --git a/src/com/android/launcher3/FocusHelper.java b/src/com/android/launcher3/FocusHelper.java
index e60704718..57aec3280 100644
--- a/src/com/android/launcher3/FocusHelper.java
+++ b/src/com/android/launcher3/FocusHelper.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011 The Android Open Source Project
+ * 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.
@@ -16,658 +16,445 @@
package com.android.launcher3;
-import android.content.res.Configuration;
+import android.util.Log;
import android.view.KeyEvent;
import android.view.SoundEffectConstants;
import android.view.View;
import android.view.ViewGroup;
-import android.widget.ScrollView;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
+import com.android.launcher3.util.FocusLogic;
+import com.android.launcher3.util.Thunk;
/**
* A keyboard listener we set on all the workspace icons.
*/
class IconKeyEventListener implements View.OnKeyListener {
+ @Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
return FocusHelper.handleIconKeyEvent(v, keyCode, event);
}
}
/**
- * A keyboard listener we set on all the workspace icons.
- */
-class FolderKeyEventListener implements View.OnKeyListener {
- public boolean onKey(View v, int keyCode, KeyEvent event) {
- return FocusHelper.handleFolderKeyEvent(v, keyCode, event);
- }
-}
-
-/**
* A keyboard listener we set on all the hotseat buttons.
*/
class HotseatIconKeyEventListener implements View.OnKeyListener {
+ @Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
- final Configuration configuration = v.getResources().getConfiguration();
- return FocusHelper.handleHotseatButtonKeyEvent(v, keyCode, event, configuration.orientation);
+ return FocusHelper.handleHotseatButtonKeyEvent(v, keyCode, event);
}
}
public class FocusHelper {
- /**
- * Returns the Viewgroup containing page contents for the page at the index specified.
- */
- private static ViewGroup getAppsCustomizePage(ViewGroup container, int index) {
- ViewGroup page = (ViewGroup) ((PagedView) container).getPageAt(index);
- if (page instanceof CellLayout) {
- // There are two layers, a PagedViewCellLayout and PagedViewCellLayoutChildren
- page = ((CellLayout) page).getShortcutsAndWidgets();
- }
- return page;
- }
+ private static final String TAG = "FocusHelper";
+ private static final boolean DEBUG = false;
/**
- * Handles key events in a PageViewCellLayout containing PagedViewIcons.
+ * Handles key events in paged folder.
*/
- static boolean handleAppsCustomizeKeyEvent(View v, int keyCode, KeyEvent e) {
- ViewGroup parentLayout;
- ViewGroup itemContainer;
- int countX;
- int countY;
- if (v.getParent() instanceof ShortcutAndWidgetContainer) {
- itemContainer = (ViewGroup) v.getParent();
- parentLayout = (ViewGroup) itemContainer.getParent();
- countX = ((CellLayout) parentLayout).getCountX();
- countY = ((CellLayout) parentLayout).getCountY();
- } else {
- itemContainer = parentLayout = (ViewGroup) v.getParent();
- countX = ((PagedViewGridLayout) parentLayout).getCellCountX();
- countY = ((PagedViewGridLayout) parentLayout).getCellCountY();
+ public static class PagedFolderKeyEventListener implements View.OnKeyListener {
+
+ private final Folder mFolder;
+
+ public PagedFolderKeyEventListener(Folder folder) {
+ mFolder = folder;
}
- // Note we have an extra parent because of the
- // PagedViewCellLayout/PagedViewCellLayoutChildren relationship
- final PagedView container = (PagedView) parentLayout.getParent();
- final int iconIndex = itemContainer.indexOfChild(v);
- final int itemCount = itemContainer.getChildCount();
- final int pageIndex = ((PagedView) container).indexToPage(container.indexOfChild(parentLayout));
- final int pageCount = container.getChildCount();
-
- final int x = iconIndex % countX;
- final int y = iconIndex / countX;
-
- final int action = e.getAction();
- final boolean handleKeyEvent = (action != KeyEvent.ACTION_UP);
- ViewGroup newParent = null;
- // Side pages do not always load synchronously, so check before focusing child siblings
- // willy-nilly
- View child = null;
- boolean wasHandled = false;
- switch (keyCode) {
- case KeyEvent.KEYCODE_DPAD_LEFT:
- if (handleKeyEvent) {
- // Select the previous icon or the last icon on the previous page
- if (iconIndex > 0) {
- itemContainer.getChildAt(iconIndex - 1).requestFocus();
- v.playSoundEffect(SoundEffectConstants.NAVIGATION_LEFT);
- } else {
- if (pageIndex > 0) {
- newParent = getAppsCustomizePage(container, pageIndex - 1);
- if (newParent != null) {
- container.snapToPage(pageIndex - 1);
- child = newParent.getChildAt(newParent.getChildCount() - 1);
- if (child != null) {
- child.requestFocus();
- v.playSoundEffect(SoundEffectConstants.NAVIGATION_LEFT);
- }
- }
- }
- }
+ @Override
+ public boolean onKey(View v, int keyCode, KeyEvent e) {
+ boolean consume = FocusLogic.shouldConsume(keyCode);
+ if (e.getAction() == KeyEvent.ACTION_UP) {
+ return consume;
+ }
+ if (DEBUG) {
+ Log.v(TAG, String.format("Handle ALL Folders keyevent=[%s].",
+ KeyEvent.keyCodeToString(keyCode)));
+ }
+
+
+ if (!(v.getParent() instanceof ShortcutAndWidgetContainer)) {
+ if (LauncherAppState.isDogfoodBuild()) {
+ throw new IllegalStateException("Parent of the focused item is not supported.");
+ } else {
+ return false;
}
- wasHandled = true;
- break;
- case KeyEvent.KEYCODE_DPAD_RIGHT:
- if (handleKeyEvent) {
- // Select the next icon or the first icon on the next page
- if (iconIndex < (itemCount - 1)) {
- itemContainer.getChildAt(iconIndex + 1).requestFocus();
- v.playSoundEffect(SoundEffectConstants.NAVIGATION_RIGHT);
- } else {
- if (pageIndex < (pageCount - 1)) {
- newParent = getAppsCustomizePage(container, pageIndex + 1);
- if (newParent != null) {
- container.snapToPage(pageIndex + 1);
- child = newParent.getChildAt(0);
- if (child != null) {
- child.requestFocus();
- v.playSoundEffect(SoundEffectConstants.NAVIGATION_RIGHT);
- }
- }
- }
+ }
+
+ // 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();
+
+ final int pageIndex = pagedView.indexOfChild(cellLayout);
+ final int pageCount = pagedView.getPageCount();
+ final boolean isLayoutRtl = Utilities.isRtl(v.getResources());
+
+ int[][] matrix = FocusLogic.createSparseMatrix(cellLayout);
+ // Process focus.
+ int newIconIndex = FocusLogic.handleKeyEvent(keyCode, countX,
+ countY, matrix, iconIndex, pageIndex, pageCount, isLayoutRtl);
+ if (newIconIndex == FocusLogic.NOOP) {
+ handleNoopKey(keyCode, v);
+ return consume;
+ }
+ ShortcutAndWidgetContainer newParent = null;
+ View child = null;
+
+ switch (newIconIndex) {
+ case FocusLogic.PREVIOUS_PAGE_RIGHT_COLUMN:
+ case FocusLogic.PREVIOUS_PAGE_LEFT_COLUMN:
+ newParent = getCellLayoutChildrenForIndex(pagedView, pageIndex - 1);
+ if (newParent != null) {
+ int row = ((CellLayout.LayoutParams) v.getLayoutParams()).cellY;
+ pagedView.snapToPage(pageIndex - 1);
+ child = newParent.getChildAt(
+ ((newIconIndex == FocusLogic.PREVIOUS_PAGE_LEFT_COLUMN)
+ ^ newParent.invertLayoutHorizontally()) ? 0 : countX - 1, row);
}
- }
- wasHandled = true;
- break;
- case KeyEvent.KEYCODE_DPAD_UP:
- if (handleKeyEvent) {
- // Select the closest icon in the previous row, otherwise select the tab bar
- if (y > 0) {
- int newiconIndex = ((y - 1) * countX) + x;
- itemContainer.getChildAt(newiconIndex).requestFocus();
- v.playSoundEffect(SoundEffectConstants.NAVIGATION_UP);
+ break;
+ case FocusLogic.PREVIOUS_PAGE_FIRST_ITEM:
+ newParent = getCellLayoutChildrenForIndex(pagedView, pageIndex - 1);
+ if (newParent != null) {
+ pagedView.snapToPage(pageIndex - 1);
+ child = newParent.getChildAt(0, 0);
}
- }
- wasHandled = true;
- break;
- case KeyEvent.KEYCODE_DPAD_DOWN:
- if (handleKeyEvent) {
- // Select the closest icon in the next row, otherwise do nothing
- if (y < (countY - 1)) {
- int newiconIndex = Math.min(itemCount - 1, ((y + 1) * countX) + x);
- int newIconY = newiconIndex / countX;
- if (newIconY != y) {
- itemContainer.getChildAt(newiconIndex).requestFocus();
- v.playSoundEffect(SoundEffectConstants.NAVIGATION_DOWN);
- }
+ break;
+ case FocusLogic.PREVIOUS_PAGE_LAST_ITEM:
+ newParent = getCellLayoutChildrenForIndex(pagedView, pageIndex - 1);
+ if (newParent != null) {
+ pagedView.snapToPage(pageIndex - 1);
+ child = newParent.getChildAt(countX - 1, countY - 1);
}
- }
- wasHandled = true;
- break;
- case KeyEvent.KEYCODE_PAGE_UP:
- if (handleKeyEvent) {
- // Select the first icon on the previous page, or the first icon on this page
- // if there is no previous page
- if (pageIndex > 0) {
- newParent = getAppsCustomizePage(container, pageIndex - 1);
- if (newParent != null) {
- container.snapToPage(pageIndex - 1);
- child = newParent.getChildAt(0);
- if (child != null) {
- child.requestFocus();
- v.playSoundEffect(SoundEffectConstants.NAVIGATION_UP);
- }
- }
- } else {
- itemContainer.getChildAt(0).requestFocus();
- v.playSoundEffect(SoundEffectConstants.NAVIGATION_UP);
+ break;
+ case FocusLogic.NEXT_PAGE_FIRST_ITEM:
+ newParent = getCellLayoutChildrenForIndex(pagedView, pageIndex + 1);
+ if (newParent != null) {
+ pagedView.snapToPage(pageIndex + 1);
+ child = newParent.getChildAt(0, 0);
}
- }
- wasHandled = true;
- break;
- case KeyEvent.KEYCODE_PAGE_DOWN:
- if (handleKeyEvent) {
- // Select the first icon on the next page, or the last icon on this page
- // if there is no next page
- if (pageIndex < (pageCount - 1)) {
- newParent = getAppsCustomizePage(container, pageIndex + 1);
- if (newParent != null) {
- container.snapToPage(pageIndex + 1);
- child = newParent.getChildAt(0);
- if (child != null) {
- child.requestFocus();
- v.playSoundEffect(SoundEffectConstants.NAVIGATION_DOWN);
- }
- }
- } else {
- itemContainer.getChildAt(itemCount - 1).requestFocus();
- v.playSoundEffect(SoundEffectConstants.NAVIGATION_DOWN);
+ break;
+ case FocusLogic.NEXT_PAGE_LEFT_COLUMN:
+ case FocusLogic.NEXT_PAGE_RIGHT_COLUMN:
+ newParent = getCellLayoutChildrenForIndex(pagedView, pageIndex + 1);
+ if (newParent != null) {
+ pagedView.snapToPage(pageIndex + 1);
+ child = FocusLogic.getAdjacentChildInNextPage(newParent, v, newIconIndex);
}
- }
- wasHandled = true;
- break;
- case KeyEvent.KEYCODE_MOVE_HOME:
- if (handleKeyEvent) {
- // Select the first icon on this page
- itemContainer.getChildAt(0).requestFocus();
- v.playSoundEffect(SoundEffectConstants.NAVIGATION_UP);
- }
- wasHandled = true;
- break;
- case KeyEvent.KEYCODE_MOVE_END:
- if (handleKeyEvent) {
- // Select the last icon on this page
- itemContainer.getChildAt(itemCount - 1).requestFocus();
- v.playSoundEffect(SoundEffectConstants.NAVIGATION_DOWN);
- }
- wasHandled = true;
- break;
- default: break;
+ break;
+ case FocusLogic.CURRENT_PAGE_FIRST_ITEM:
+ child = cellLayout.getChildAt(0, 0);
+ break;
+ case FocusLogic.CURRENT_PAGE_LAST_ITEM:
+ child = pagedView.getLastItem();
+ break;
+ default: // Go to some item on the current page.
+ child = itemContainer.getChildAt(newIconIndex);
+ break;
+ }
+ if (child != null) {
+ child.requestFocus();
+ playSoundEffect(keyCode, v);
+ } else {
+ handleNoopKey(keyCode, v);
+ }
+ return consume;
}
- return wasHandled;
- }
- /**
- * Handles key events in the workspace hotseat (bottom of the screen).
- */
- static boolean handleHotseatButtonKeyEvent(View v, int keyCode, KeyEvent e, int orientation) {
- ShortcutAndWidgetContainer parent = (ShortcutAndWidgetContainer) v.getParent();
- final CellLayout layout = (CellLayout) parent.getParent();
-
- // NOTE: 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.
- final int action = e.getAction();
- final boolean handleKeyEvent = (action != KeyEvent.ACTION_UP);
- boolean wasHandled = false;
- switch (keyCode) {
- case KeyEvent.KEYCODE_DPAD_LEFT:
- if (handleKeyEvent) {
- ArrayList<View> views = getCellLayoutChildrenSortedSpatially(layout, parent);
- int myIndex = views.indexOf(v);
- // Select the previous button, otherwise do nothing
- if (myIndex > 0) {
- views.get(myIndex - 1).requestFocus();
- v.playSoundEffect(SoundEffectConstants.NAVIGATION_LEFT);
- }
- }
- wasHandled = true;
- break;
- case KeyEvent.KEYCODE_DPAD_RIGHT:
- if (handleKeyEvent) {
- ArrayList<View> views = getCellLayoutChildrenSortedSpatially(layout, parent);
- int myIndex = views.indexOf(v);
- // Select the next button, otherwise do nothing
- if (myIndex < views.size() - 1) {
- views.get(myIndex + 1).requestFocus();
- v.playSoundEffect(SoundEffectConstants.NAVIGATION_RIGHT);
- }
- }
- wasHandled = true;
- break;
- case KeyEvent.KEYCODE_DPAD_UP:
- if (handleKeyEvent) {
- final Workspace workspace = (Workspace)
- v.getRootView().findViewById(R.id.workspace);
- if (workspace != null) {
- int pageIndex = workspace.getCurrentPage();
- CellLayout topLayout = (CellLayout) workspace.getChildAt(pageIndex);
- ShortcutAndWidgetContainer children = topLayout.getShortcutsAndWidgets();
- final View newIcon = getIconInDirection(layout, children, -1, 1);
- // Select the first bubble text view in the current page of the workspace
- if (newIcon != null) {
- newIcon.requestFocus();
- v.playSoundEffect(SoundEffectConstants.NAVIGATION_UP);
- } else {
- workspace.requestFocus();
- }
- }
- }
- wasHandled = true;
- break;
- case KeyEvent.KEYCODE_DPAD_DOWN:
- // Do nothing
- wasHandled = true;
- break;
- default: break;
+ public void handleNoopKey(int keyCode, View v) {
+ if (keyCode == KeyEvent.KEYCODE_DPAD_DOWN) {
+ mFolder.mFolderName.requestFocus();
+ playSoundEffect(keyCode, v);
+ }
}
- return wasHandled;
}
/**
- * Private helper method to get the CellLayoutChildren given a CellLayout index.
+ * Handles key events in the workspace hot seat (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.
*/
- private static ShortcutAndWidgetContainer getCellLayoutChildrenForIndex(
- ViewGroup container, int i) {
- CellLayout parent = (CellLayout) container.getChildAt(i);
- return parent.getShortcutsAndWidgets();
- }
+ static boolean handleHotseatButtonKeyEvent(View v, int keyCode, KeyEvent e) {
+ boolean consume = FocusLogic.shouldConsume(keyCode);
+ if (e.getAction() == KeyEvent.ACTION_UP || !consume) {
+ return consume;
+ }
- /**
- * Private helper method to sort all the CellLayout children in order of their (x,y) spatially
- * from top left to bottom right.
- */
- private static ArrayList<View> getCellLayoutChildrenSortedSpatially(CellLayout layout,
- ViewGroup parent) {
- // First we order each the CellLayout children by their x,y coordinates
- final int cellCountX = layout.getCountX();
- final int count = parent.getChildCount();
- ArrayList<View> views = new ArrayList<View>();
- for (int j = 0; j < count; ++j) {
- views.add(parent.getChildAt(j));
+ DeviceProfile profile = ((Launcher) v.getContext()).getDeviceProfile();
+
+ if (DEBUG) {
+ Log.v(TAG, String.format(
+ "Handle HOTSEAT BUTTONS keyevent=[%s] on hotseat buttons, isVertical=%s",
+ KeyEvent.keyCodeToString(keyCode), profile.isVerticalBarLayout()));
}
- Collections.sort(views, new Comparator<View>() {
- @Override
- public int compare(View lhs, View rhs) {
- CellLayout.LayoutParams llp = (CellLayout.LayoutParams) lhs.getLayoutParams();
- CellLayout.LayoutParams rlp = (CellLayout.LayoutParams) rhs.getLayoutParams();
- int lvIndex = (llp.cellY * cellCountX) + llp.cellX;
- int rvIndex = (rlp.cellY * cellCountX) + rlp.cellX;
- return lvIndex - rvIndex;
- }
- });
- return views;
- }
- /**
- * Private helper method to find the index of the next BubbleTextView or FolderIcon in the
- * direction delta.
- *
- * @param delta either -1 or 1 depending on the direction we want to search
- */
- private static View findIndexOfIcon(ArrayList<View> views, int i, int delta) {
- // Then we find the next BubbleTextView offset by delta from i
- final int count = views.size();
- int newI = i + delta;
- while (0 <= newI && newI < count) {
- View newV = views.get(newI);
- if (newV instanceof BubbleTextView || newV instanceof FolderIcon) {
- return newV;
- }
- newI += delta;
+
+ // Initialize the variables.
+ 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);
+ 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;
+
+ final CellLayout iconLayout = (CellLayout) workspace.getChildAt(pageIndex);
+ if (iconLayout == null) {
+ // This check is to guard against cases where key strokes rushes in when workspace
+ // child creation/deletion is still in flux. (e.g., during drop or fling
+ // animation.)
+ return consume;
}
- return null;
- }
- private static View getIconInDirection(CellLayout layout, ViewGroup parent, int i,
- int delta) {
- final ArrayList<View> views = getCellLayoutChildrenSortedSpatially(layout, parent);
- return findIndexOfIcon(views, i, delta);
- }
- private static View getIconInDirection(CellLayout layout, ViewGroup parent, View v,
- int delta) {
- final ArrayList<View> views = getCellLayoutChildrenSortedSpatially(layout, parent);
- return findIndexOfIcon(views, views.indexOf(v), delta);
- }
- /**
- * Private helper method to find the next closest BubbleTextView or FolderIcon in the direction
- * delta on the next line.
- *
- * @param delta either -1 or 1 depending on the line and direction we want to search
- */
- private static View getClosestIconOnLine(CellLayout layout, ViewGroup parent, View v,
- int lineDelta) {
- final ArrayList<View> views = getCellLayoutChildrenSortedSpatially(layout, parent);
- final CellLayout.LayoutParams lp = (CellLayout.LayoutParams) v.getLayoutParams();
- final int cellCountY = layout.getCountY();
- final int row = lp.cellY;
- final int newRow = row + lineDelta;
- if (0 <= newRow && newRow < cellCountY) {
- float closestDistance = Float.MAX_VALUE;
- int closestIndex = -1;
- int index = views.indexOf(v);
- int endIndex = (lineDelta < 0) ? -1 : views.size();
- while (index != endIndex) {
- View newV = views.get(index);
- CellLayout.LayoutParams tmpLp = (CellLayout.LayoutParams) newV.getLayoutParams();
- boolean satisfiesRow = (lineDelta < 0) ? (tmpLp.cellY < row) : (tmpLp.cellY > row);
- if (satisfiesRow &&
- (newV instanceof BubbleTextView || newV instanceof FolderIcon)) {
- float tmpDistance = (float) Math.sqrt(Math.pow(tmpLp.cellX - lp.cellX, 2) +
- Math.pow(tmpLp.cellY - lp.cellY, 2));
- if (tmpDistance < closestDistance) {
- closestIndex = index;
- closestDistance = tmpDistance;
- }
- }
- if (index <= endIndex) {
- ++index;
- } else {
- --index;
- }
+ final ViewGroup iconParent = iconLayout.getShortcutsAndWidgets();
+
+ ViewGroup parent = null;
+ int[][] matrix = null;
+
+ 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 */);
+ 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 */);
+ 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 {
+ // 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()));
+
+ 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);
+ }
+ if (parent == iconParent && newIconIndex >= iconParent.getChildCount()) {
+ newIconIndex -= iconParent.getChildCount();
+ }
+ if (parent != null) {
+ if (newIcon == null && newIconIndex >=0) {
+ newIcon = parent.getChildAt(newIconIndex);
}
- if (closestIndex > -1) {
- return views.get(closestIndex);
+ if (newIcon != null) {
+ newIcon.requestFocus();
+ playSoundEffect(keyCode, v);
}
}
- return null;
+ return consume;
}
/**
- * Handles key events in a Workspace containing.
+ * Handles key events in a workspace containing icons.
*/
static boolean handleIconKeyEvent(View v, int keyCode, KeyEvent e) {
+ boolean consume = FocusLogic.shouldConsume(keyCode);
+ if (e.getAction() == KeyEvent.ACTION_UP || !consume) {
+ return consume;
+ }
+
+ Launcher launcher = (Launcher) v.getContext();
+ DeviceProfile profile = launcher.getDeviceProfile();
+
+ if (DEBUG) {
+ Log.v(TAG, String.format("Handle WORKSPACE ICONS keyevent=[%s] isVerticalBar=%s",
+ KeyEvent.keyCodeToString(keyCode), profile.isVerticalBarLayout()));
+ }
+
+ // Initialize the variables.
ShortcutAndWidgetContainer parent = (ShortcutAndWidgetContainer) v.getParent();
- final CellLayout layout = (CellLayout) parent.getParent();
- final Workspace workspace = (Workspace) layout.getParent();
- final ViewGroup launcher = (ViewGroup) workspace.getParent();
- final ViewGroup tabs = (ViewGroup) launcher.findViewById(R.id.search_drop_target_bar);
- final ViewGroup hotseat = (ViewGroup) launcher.findViewById(R.id.hotseat);
- int pageIndex = workspace.indexOfChild(layout);
- int pageCount = workspace.getChildCount();
+ CellLayout iconLayout = (CellLayout) parent.getParent();
+ final Workspace workspace = (Workspace) iconLayout.getParent();
+ final ViewGroup dragLayer = (ViewGroup) workspace.getParent();
+ final ViewGroup tabs = (ViewGroup) dragLayer.findViewById(R.id.search_drop_target_bar);
+ final Hotseat hotseat = (Hotseat) dragLayer.findViewById(R.id.hotseat);
- final int action = e.getAction();
- final boolean handleKeyEvent = (action != KeyEvent.ACTION_UP);
- boolean wasHandled = false;
- switch (keyCode) {
- case KeyEvent.KEYCODE_DPAD_LEFT:
- if (handleKeyEvent) {
- // Select the previous icon or the last icon on the previous page if possible
- View newIcon = getIconInDirection(layout, parent, v, -1);
- if (newIcon != null) {
- newIcon.requestFocus();
- v.playSoundEffect(SoundEffectConstants.NAVIGATION_LEFT);
- } else {
- if (pageIndex > 0) {
- parent = getCellLayoutChildrenForIndex(workspace, pageIndex - 1);
- newIcon = getIconInDirection(layout, parent,
- parent.getChildCount(), -1);
- if (newIcon != null) {
- newIcon.requestFocus();
- } else {
- // Snap to the previous page
- workspace.snapToPage(pageIndex - 1);
- }
- v.playSoundEffect(SoundEffectConstants.NAVIGATION_LEFT);
- }
- }
+ 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();
+ int[][] matrix;
+
+ // KEYCODE_DPAD_DOWN in portrait (KEYCODE_DPAD_RIGHT in landscape) is the only key allowed
+ // 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;
+ } 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;
+ } else {
+ matrix = FocusLogic.createSparseMatrix(iconLayout);
+ }
+
+ // Process the focus.
+ int newIconIndex = FocusLogic.handleKeyEvent(keyCode, countX,
+ countY, matrix, iconIndex, pageIndex, pageCount, Utilities.isRtl(v.getResources()));
+ View newIcon = null;
+ switch (newIconIndex) {
+ case FocusLogic.NOOP:
+ if (keyCode == KeyEvent.KEYCODE_DPAD_UP) {
+ newIcon = tabs;
}
- wasHandled = true;
break;
- case KeyEvent.KEYCODE_DPAD_RIGHT:
- if (handleKeyEvent) {
- // Select the next icon or the first icon on the next page if possible
- View newIcon = getIconInDirection(layout, parent, v, 1);
- if (newIcon != null) {
- newIcon.requestFocus();
- v.playSoundEffect(SoundEffectConstants.NAVIGATION_RIGHT);
- } else {
- if (pageIndex < (pageCount - 1)) {
- parent = getCellLayoutChildrenForIndex(workspace, pageIndex + 1);
- newIcon = getIconInDirection(layout, parent, -1, 1);
- if (newIcon != null) {
- newIcon.requestFocus();
- } else {
- // Snap to the next page
- workspace.snapToPage(pageIndex + 1);
- }
- v.playSoundEffect(SoundEffectConstants.NAVIGATION_RIGHT);
- }
- }
+ case FocusLogic.PREVIOUS_PAGE_RIGHT_COLUMN:
+ case FocusLogic.NEXT_PAGE_RIGHT_COLUMN:
+ int newPageIndex = pageIndex - 1;
+ if (newIconIndex == FocusLogic.NEXT_PAGE_RIGHT_COLUMN) {
+ newPageIndex = pageIndex + 1;
}
- wasHandled = true;
- break;
- case KeyEvent.KEYCODE_DPAD_UP:
- if (handleKeyEvent) {
- // Select the closest icon in the previous line, otherwise select the tab bar
- View newIcon = getClosestIconOnLine(layout, parent, v, -1);
- if (newIcon != null) {
- newIcon.requestFocus();
- wasHandled = true;
- } else {
- tabs.requestFocus();
- }
- v.playSoundEffect(SoundEffectConstants.NAVIGATION_UP);
+ 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);
}
break;
- case KeyEvent.KEYCODE_DPAD_DOWN:
- if (handleKeyEvent) {
- // Select the closest icon in the next line, otherwise select the button bar
- View newIcon = getClosestIconOnLine(layout, parent, v, 1);
- if (newIcon != null) {
- newIcon.requestFocus();
- v.playSoundEffect(SoundEffectConstants.NAVIGATION_DOWN);
- wasHandled = true;
- } else if (hotseat != null) {
- hotseat.requestFocus();
- v.playSoundEffect(SoundEffectConstants.NAVIGATION_DOWN);
- }
- }
+ case FocusLogic.PREVIOUS_PAGE_FIRST_ITEM:
+ parent = getCellLayoutChildrenForIndex(workspace, pageIndex - 1);
+ newIcon = parent.getChildAt(0);
+ workspace.snapToPage(pageIndex - 1);
break;
- case KeyEvent.KEYCODE_PAGE_UP:
- if (handleKeyEvent) {
- // Select the first icon on the previous page or the first icon on this page
- // if there is no previous page
- if (pageIndex > 0) {
- parent = getCellLayoutChildrenForIndex(workspace, pageIndex - 1);
- View newIcon = getIconInDirection(layout, parent, -1, 1);
- if (newIcon != null) {
- newIcon.requestFocus();
- } else {
- // Snap to the previous page
- workspace.snapToPage(pageIndex - 1);
- }
- v.playSoundEffect(SoundEffectConstants.NAVIGATION_UP);
- } else {
- View newIcon = getIconInDirection(layout, parent, -1, 1);
- if (newIcon != null) {
- newIcon.requestFocus();
- v.playSoundEffect(SoundEffectConstants.NAVIGATION_UP);
- }
- }
- }
- wasHandled = true;
+ case FocusLogic.PREVIOUS_PAGE_LAST_ITEM:
+ parent = getCellLayoutChildrenForIndex(workspace, pageIndex - 1);
+ newIcon = parent.getChildAt(parent.getChildCount() - 1);
+ workspace.snapToPage(pageIndex - 1);
break;
- case KeyEvent.KEYCODE_PAGE_DOWN:
- if (handleKeyEvent) {
- // Select the first icon on the next page or the last icon on this page
- // if there is no previous page
- if (pageIndex < (pageCount - 1)) {
- parent = getCellLayoutChildrenForIndex(workspace, pageIndex + 1);
- View newIcon = getIconInDirection(layout, parent, -1, 1);
- if (newIcon != null) {
- newIcon.requestFocus();
- } else {
- // Snap to the next page
- workspace.snapToPage(pageIndex + 1);
- }
- v.playSoundEffect(SoundEffectConstants.NAVIGATION_DOWN);
- } else {
- View newIcon = getIconInDirection(layout, parent,
- parent.getChildCount(), -1);
- if (newIcon != null) {
- newIcon.requestFocus();
- v.playSoundEffect(SoundEffectConstants.NAVIGATION_DOWN);
- }
- }
- }
- wasHandled = true;
+ case FocusLogic.NEXT_PAGE_FIRST_ITEM:
+ parent = getCellLayoutChildrenForIndex(workspace, pageIndex + 1);
+ newIcon = parent.getChildAt(0);
+ workspace.snapToPage(pageIndex + 1);
break;
- case KeyEvent.KEYCODE_MOVE_HOME:
- if (handleKeyEvent) {
- // Select the first icon on this page
- View newIcon = getIconInDirection(layout, parent, -1, 1);
- if (newIcon != null) {
- newIcon.requestFocus();
- v.playSoundEffect(SoundEffectConstants.NAVIGATION_UP);
- }
+ case FocusLogic.NEXT_PAGE_LEFT_COLUMN:
+ case FocusLogic.PREVIOUS_PAGE_LEFT_COLUMN:
+ newPageIndex = pageIndex + 1;
+ 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);
}
- wasHandled = true;
break;
- case KeyEvent.KEYCODE_MOVE_END:
- if (handleKeyEvent) {
- // Select the last icon on this page
- View newIcon = getIconInDirection(layout, parent,
- parent.getChildCount(), -1);
- if (newIcon != null) {
- newIcon.requestFocus();
- v.playSoundEffect(SoundEffectConstants.NAVIGATION_DOWN);
- }
+ case FocusLogic.CURRENT_PAGE_FIRST_ITEM:
+ newIcon = parent.getChildAt(0);
+ break;
+ case FocusLogic.CURRENT_PAGE_LAST_ITEM:
+ newIcon = parent.getChildAt(parent.getChildCount() - 1);
+ break;
+ default:
+ // current page, some item.
+ if (0 <= newIconIndex && newIconIndex < parent.getChildCount()) {
+ newIcon = parent.getChildAt(newIconIndex);
+ } else if (parent.getChildCount() <= newIconIndex &&
+ newIconIndex < parent.getChildCount() + hotseatParent.getChildCount()) {
+ newIcon = hotseatParent.getChildAt(newIconIndex - parent.getChildCount());
}
- wasHandled = true;
break;
- default: break;
}
- return wasHandled;
+ if (newIcon != null) {
+ newIcon.requestFocus();
+ playSoundEffect(keyCode, v);
+ }
+ return consume;
}
+ //
+ // Helper methods.
+ //
+
/**
- * Handles key events for items in a Folder.
+ * Private helper method to get the CellLayoutChildren given a CellLayout index.
*/
- static boolean handleFolderKeyEvent(View v, int keyCode, KeyEvent e) {
- ShortcutAndWidgetContainer parent = (ShortcutAndWidgetContainer) v.getParent();
- final CellLayout layout = (CellLayout) parent.getParent();
- final ScrollView scrollView = (ScrollView) layout.getParent();
- final Folder folder = (Folder) scrollView.getParent();
- View title = folder.mFolderName;
-
- final int action = e.getAction();
- final boolean handleKeyEvent = (action != KeyEvent.ACTION_UP);
- boolean wasHandled = false;
+ @Thunk static ShortcutAndWidgetContainer getCellLayoutChildrenForIndex(
+ ViewGroup container, int i) {
+ CellLayout parent = (CellLayout) container.getChildAt(i);
+ return parent.getShortcutsAndWidgets();
+ }
+
+ /**
+ * Helper method to be used for playing sound effects.
+ */
+ @Thunk static void playSoundEffect(int keyCode, View v) {
switch (keyCode) {
case KeyEvent.KEYCODE_DPAD_LEFT:
- if (handleKeyEvent) {
- // Select the previous icon
- View newIcon = getIconInDirection(layout, parent, v, -1);
- if (newIcon != null) {
- newIcon.requestFocus();
- v.playSoundEffect(SoundEffectConstants.NAVIGATION_LEFT);
- }
- }
- wasHandled = true;
+ v.playSoundEffect(SoundEffectConstants.NAVIGATION_LEFT);
break;
case KeyEvent.KEYCODE_DPAD_RIGHT:
- if (handleKeyEvent) {
- // Select the next icon
- View newIcon = getIconInDirection(layout, parent, v, 1);
- if (newIcon != null) {
- newIcon.requestFocus();
- } else {
- title.requestFocus();
- }
- v.playSoundEffect(SoundEffectConstants.NAVIGATION_RIGHT);
- }
- wasHandled = true;
- break;
- case KeyEvent.KEYCODE_DPAD_UP:
- if (handleKeyEvent) {
- // Select the closest icon in the previous line
- View newIcon = getClosestIconOnLine(layout, parent, v, -1);
- if (newIcon != null) {
- newIcon.requestFocus();
- v.playSoundEffect(SoundEffectConstants.NAVIGATION_UP);
- }
- }
- wasHandled = true;
+ v.playSoundEffect(SoundEffectConstants.NAVIGATION_RIGHT);
break;
case KeyEvent.KEYCODE_DPAD_DOWN:
- if (handleKeyEvent) {
- // Select the closest icon in the next line
- View newIcon = getClosestIconOnLine(layout, parent, v, 1);
- if (newIcon != null) {
- newIcon.requestFocus();
- } else {
- title.requestFocus();
- }
- v.playSoundEffect(SoundEffectConstants.NAVIGATION_DOWN);
- }
- wasHandled = true;
+ case KeyEvent.KEYCODE_PAGE_DOWN:
+ case KeyEvent.KEYCODE_MOVE_END:
+ v.playSoundEffect(SoundEffectConstants.NAVIGATION_DOWN);
break;
+ case KeyEvent.KEYCODE_DPAD_UP:
+ case KeyEvent.KEYCODE_PAGE_UP:
case KeyEvent.KEYCODE_MOVE_HOME:
- if (handleKeyEvent) {
- // Select the first icon on this page
- View newIcon = getIconInDirection(layout, parent, -1, 1);
- if (newIcon != null) {
- newIcon.requestFocus();
- v.playSoundEffect(SoundEffectConstants.NAVIGATION_UP);
- }
- }
- wasHandled = true;
+ v.playSoundEffect(SoundEffectConstants.NAVIGATION_UP);
break;
- case KeyEvent.KEYCODE_MOVE_END:
- if (handleKeyEvent) {
- // Select the last icon on this page
- View newIcon = getIconInDirection(layout, parent,
- parent.getChildCount(), -1);
- if (newIcon != null) {
- newIcon.requestFocus();
- v.playSoundEffect(SoundEffectConstants.NAVIGATION_DOWN);
- }
- }
- wasHandled = true;
+ default:
break;
- default: break;
}
- return wasHandled;
}
}
diff --git a/src/com/android/launcher3/FocusIndicatorView.java b/src/com/android/launcher3/FocusIndicatorView.java
index 7d4664abb..ecf93e4b3 100644
--- a/src/com/android/launcher3/FocusIndicatorView.java
+++ b/src/com/android/launcher3/FocusIndicatorView.java
@@ -23,7 +23,8 @@ import android.graphics.Canvas;
import android.util.AttributeSet;
import android.util.Pair;
import android.view.View;
-import android.view.ViewParent;
+
+import com.android.launcher3.util.Thunk;
public class FocusIndicatorView extends View implements View.OnFocusChangeListener {
@@ -32,9 +33,6 @@ public class FocusIndicatorView extends View implements View.OnFocusChangeListen
private static final float MIN_VISIBLE_ALPHA = 0.2f;
private static final long ANIM_DURATION = 150;
- private static final int[] sTempPos = new int[2];
- private static final int[] sTempShift = new int[2];
-
private final int[] mIndicatorPos = new int[2];
private final int[] mTargetViewPos = new int[2];
@@ -80,7 +78,8 @@ public class FocusIndicatorView extends View implements View.OnFocusChangeListen
}
if (!mInitiated) {
- getLocationRelativeToParentPagedView(this, mIndicatorPos);
+ // The parent view should always the a parent of the target view.
+ computeLocationRelativeToParent(this, (View) getParent(), mIndicatorPos);
mInitiated = true;
}
@@ -93,7 +92,7 @@ public class FocusIndicatorView extends View implements View.OnFocusChangeListen
nextState.scaleX = v.getScaleX() * v.getWidth() / indicatorWidth;
nextState.scaleY = v.getScaleY() * v.getHeight() / indicatorHeight;
- getLocationRelativeToParentPagedView(v, mTargetViewPos);
+ computeLocationRelativeToParent(v, (View) getParent(), mTargetViewPos);
nextState.x = mTargetViewPos[0] - mIndicatorPos[0] - (1 - nextState.scaleX) * indicatorWidth / 2;
nextState.y = mTargetViewPos[1] - mIndicatorPos[1] - (1 - nextState.scaleY) * indicatorHeight / 2;
@@ -150,31 +149,36 @@ public class FocusIndicatorView extends View implements View.OnFocusChangeListen
}
/**
- * Gets the location of a view relative in the window, off-setting any shift due to
- * page view scroll
+ * Computes the location of a view relative to {@param parent}, off-setting
+ * any shift due to page view scroll.
+ * @param pos an array of two integers in which to hold the coordinates
*/
- private static void getLocationRelativeToParentPagedView(View v, int[] pos) {
- getPagedViewScrollShift(v, sTempShift);
- v.getLocationInWindow(sTempPos);
- pos[0] = sTempPos[0] + sTempShift[0];
- pos[1] = sTempPos[1] + sTempShift[1];
+ private static void computeLocationRelativeToParent(View v, View parent, int[] pos) {
+ pos[0] = pos[1] = 0;
+ computeLocationRelativeToParentHelper(v, parent, pos);
+
+ // If a view is scaled, its position will also shift accordingly. For optimization, only
+ // consider this for the last node.
+ pos[0] += (1 - v.getScaleX()) * v.getWidth() / 2;
+ pos[1] += (1 - v.getScaleY()) * v.getHeight() / 2;
}
- private static void getPagedViewScrollShift(View child, int[] shift) {
- ViewParent parent = child.getParent();
+ private static void computeLocationRelativeToParentHelper(View child,
+ View commonParent, int[] shift) {
+ View parent = (View) child.getParent();
+ shift[0] += child.getLeft();
+ shift[1] += child.getTop();
if (parent instanceof PagedView) {
- View parentView = (View) parent;
- child.getLocationInWindow(sTempPos);
- shift[0] = parentView.getPaddingLeft() - sTempPos[0];
- shift[1] = -(int) child.getTranslationY();
- } else if (parent instanceof View) {
- getPagedViewScrollShift((View) parent, shift);
- } else {
- shift[0] = shift[1] = 0;
+ PagedView page = (PagedView) parent;
+ shift[0] -= page.getScrollForPage(page.indexOfChild(child));
+ }
+
+ if (parent != commonParent) {
+ computeLocationRelativeToParentHelper(parent, commonParent, shift);
}
}
- private static final class ViewAnimState {
+ @Thunk static final class ViewAnimState {
float x, y, scaleX, scaleY;
}
}
diff --git a/src/com/android/launcher3/FocusOnlyTabWidget.java b/src/com/android/launcher3/FocusOnlyTabWidget.java
deleted file mode 100644
index 08fc311bc..000000000
--- a/src/com/android/launcher3/FocusOnlyTabWidget.java
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.launcher3;
-
-import android.content.Context;
-import android.util.AttributeSet;
-import android.view.View;
-import android.widget.TabWidget;
-
-public class FocusOnlyTabWidget extends TabWidget {
- public FocusOnlyTabWidget(Context context) {
- super(context);
- }
-
- public FocusOnlyTabWidget(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- public FocusOnlyTabWidget(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
- }
-
- public View getSelectedTab() {
- final int count = getTabCount();
- for (int i = 0; i < count; ++i) {
- View v = getChildTabViewAt(i);
- if (v.isSelected()) {
- return v;
- }
- }
- return null;
- }
-
- public int getChildTabIndex(View v) {
- final int tabCount = getTabCount();
- for (int i = 0; i < tabCount; ++i) {
- if (getChildTabViewAt(i) == v) {
- return i;
- }
- }
- return -1;
- }
-
- public void setCurrentTabToFocusedTab() {
- View tab = null;
- int index = -1;
- final int count = getTabCount();
- for (int i = 0; i < count; ++i) {
- View v = getChildTabViewAt(i);
- if (v.hasFocus()) {
- tab = v;
- index = i;
- break;
- }
- }
- if (index > -1) {
- super.setCurrentTab(index);
- super.onFocusChange(tab, true);
- }
- }
- public void superOnFocusChange(View v, boolean hasFocus) {
- super.onFocusChange(v, hasFocus);
- }
-
- @Override
- public void onFocusChange(android.view.View v, boolean hasFocus) {
- if (v == this && hasFocus && getTabCount() > 0) {
- getSelectedTab().requestFocus();
- return;
- }
- }
-}
diff --git a/src/com/android/launcher3/Folder.java b/src/com/android/launcher3/Folder.java
index 1890af47d..2e19f6eba 100644
--- a/src/com/android/launcher3/Folder.java
+++ b/src/com/android/launcher3/Folder.java
@@ -21,12 +21,15 @@ import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.animation.PropertyValuesHolder;
+import android.annotation.SuppressLint;
+import android.annotation.TargetApi;
import android.content.Context;
import android.content.res.Resources;
+import android.graphics.Point;
import android.graphics.PointF;
import android.graphics.Rect;
-import android.os.SystemClock;
-import android.support.v4.widget.AutoScrollHelper;
+import android.os.Build;
+import android.os.Bundle;
import android.text.InputType;
import android.text.Selection;
import android.text.Spannable;
@@ -34,21 +37,28 @@ import android.util.AttributeSet;
import android.util.Log;
import android.view.ActionMode;
import android.view.KeyEvent;
-import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
+import android.view.ViewGroup;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityManager;
import android.view.animation.AccelerateInterpolator;
+import android.view.animation.AnimationUtils;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodManager;
import android.widget.LinearLayout;
-import android.widget.ScrollView;
import android.widget.TextView;
+import com.android.launcher3.CellLayout.CellInfo;
+import com.android.launcher3.DragController.DragListener;
import com.android.launcher3.FolderInfo.FolderListener;
+import com.android.launcher3.UninstallDropTarget.UninstallSource;
+import com.android.launcher3.Workspace.ItemOperator;
+import com.android.launcher3.accessibility.LauncherAccessibilityDelegate.AccessibilityDragSource;
+import com.android.launcher3.util.Thunk;
+import com.android.launcher3.util.UiThreadCircularReveal;
import java.util.ArrayList;
import java.util.Collections;
@@ -59,106 +69,109 @@ import java.util.Comparator;
*/
public class Folder extends LinearLayout implements DragSource, View.OnClickListener,
View.OnLongClickListener, DropTarget, FolderListener, TextView.OnEditorActionListener,
- View.OnFocusChangeListener {
+ View.OnFocusChangeListener, DragListener, UninstallSource, AccessibilityDragSource,
+ Stats.LaunchSourceProvider {
private static final String TAG = "Launcher.Folder";
- protected DragController mDragController;
- protected Launcher mLauncher;
- protected FolderInfo mInfo;
+ /**
+ * We avoid measuring {@link #mContentWrapper} with a 0 width or height, as this
+ * results in CellLayout being measured as UNSPECIFIED, which it does not support.
+ */
+ private static final int MIN_CONTENT_DIMEN = 5;
static final int STATE_NONE = -1;
static final int STATE_SMALL = 0;
static final int STATE_ANIMATING = 1;
static final int STATE_OPEN = 2;
- private static final int CLOSE_FOLDER_DELAY_MS = 150;
-
- private int mExpandDuration;
- private int mMaterialExpandDuration;
- private int mMaterialExpandStagger;
- protected CellLayout mContent;
- private ScrollView mScrollView;
- private final LayoutInflater mInflater;
- private final IconCache mIconCache;
- private int mState = STATE_NONE;
- private static final int REORDER_ANIMATION_DURATION = 230;
+ /**
+ * Time for which the scroll hint is shown before automatically changing page.
+ */
+ public static final int SCROLL_HINT_DURATION = DragController.SCROLL_DELAY;
+
+ /**
+ * Fraction of icon width which behave as scroll region.
+ */
+ private static final float ICON_OVERSCROLL_WIDTH_FACTOR = 0.45f;
+
+ private static final int FOLDER_NAME_ANIMATION_DURATION = 633;
+
private static final int REORDER_DELAY = 250;
private static final int ON_EXIT_CLOSE_DELAY = 400;
+ private static final Rect sTempRect = new Rect();
+
+ private static String sDefaultFolderName;
+ private static String sHintText;
+
+ private final Alarm mReorderAlarm = new Alarm();
+ private final Alarm mOnExitAlarm = new Alarm();
+ private final Alarm mOnScrollHintAlarm = new Alarm();
+ @Thunk final Alarm mScrollPauseAlarm = new Alarm();
+
+ @Thunk final ArrayList<View> mItemsInReadingOrder = new ArrayList<View>();
+
+ private final int mExpandDuration;
+ private final int mMaterialExpandDuration;
+ private final int mMaterialExpandStagger;
+
+ private final InputMethodManager mInputMethodManager;
+
+ protected final Launcher mLauncher;
+ protected DragController mDragController;
+ protected FolderInfo mInfo;
+
+ @Thunk FolderIcon mFolderIcon;
+
+ @Thunk FolderPagedView mContent;
+ @Thunk View mContentWrapper;
+ FolderEditText mFolderName;
+
+ private View mFooter;
+ private int mFooterHeight;
+
+ // Cell ranks used for drag and drop
+ @Thunk int mTargetRank, mPrevTargetRank, mEmptyCellRank;
+
+ @Thunk int mState = STATE_NONE;
private boolean mRearrangeOnClose = false;
- private FolderIcon mFolderIcon;
- private int mMaxCountX;
- private int mMaxCountY;
- private int mMaxNumItems;
- private ArrayList<View> mItemsInReadingOrder = new ArrayList<View>();
boolean mItemsInvalidated = false;
private ShortcutInfo mCurrentDragInfo;
private View mCurrentDragView;
private boolean mIsExternalDrag;
boolean mSuppressOnAdd = false;
- private int[] mTargetCell = new int[2];
- private int[] mPreviousTargetCell = new int[2];
- private int[] mEmptyCell = new int[2];
- private Alarm mReorderAlarm = new Alarm();
- private Alarm mOnExitAlarm = new Alarm();
- private int mFolderNameHeight;
- private Rect mTempRect = new Rect();
private boolean mDragInProgress = false;
private boolean mDeleteFolderOnDropCompleted = false;
private boolean mSuppressFolderDeletion = false;
private boolean mItemAddedBackToSelfViaIcon = false;
- FolderEditText mFolderName;
- private float mFolderIconPivotX;
- private float mFolderIconPivotY;
-
+ @Thunk float mFolderIconPivotX;
+ @Thunk float mFolderIconPivotY;
private boolean mIsEditingName = false;
- private InputMethodManager mInputMethodManager;
-
- private static String sDefaultFolderName;
- private static String sHintText;
-
- private FocusIndicatorView mFocusIndicatorHandler;
-
- // We avoid measuring the scroll view with a 0 width or height, as this
- // results in CellLayout being measured as UNSPECIFIED, which it does
- // not support.
- private static final int MIN_CONTENT_DIMEN = 5;
private boolean mDestroyed;
- private AutoScrollHelper mAutoScrollHelper;
-
- private Runnable mDeferredAction;
+ @Thunk Runnable mDeferredAction;
private boolean mDeferDropAfterUninstall;
private boolean mUninstallSuccessful;
+ // Folder scrolling
+ private int mScrollAreaOffset;
+
+ @Thunk int mScrollHintDir = DragController.SCROLL_NONE;
+ @Thunk int mCurrentScrollDir = DragController.SCROLL_NONE;
+
/**
* Used to inflate the Workspace from XML.
*
* @param context The application's context.
- * @param attrs The attribtues set containing the Workspace's customization values.
+ * @param attrs The attributes set containing the Workspace's customization values.
*/
public Folder(Context context, AttributeSet attrs) {
super(context, attrs);
-
- LauncherAppState app = LauncherAppState.getInstance();
- DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
setAlwaysDrawnWithCacheEnabled(false);
- mInflater = LayoutInflater.from(context);
- mIconCache = app.getIconCache();
-
- Resources res = getResources();
- mMaxCountX = (int) grid.numColumns;
- // Allow scrolling folders when DISABLE_ALL_APPS is true.
- if (LauncherAppState.isDisableAllApps()) {
- mMaxCountY = mMaxNumItems = Integer.MAX_VALUE;
- } else {
- mMaxCountY = (int) grid.numRows;
- mMaxNumItems = mMaxCountX * mMaxCountY;
- }
-
mInputMethodManager = (InputMethodManager)
getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
+ Resources res = getResources();
mExpandDuration = res.getInteger(R.integer.config_folderExpandDuration);
mMaterialExpandDuration = res.getInteger(R.integer.config_materialFolderExpandDuration);
mMaterialExpandStagger = res.getInteger(R.integer.config_materialFolderExpandStagger);
@@ -172,45 +185,35 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
mLauncher = (Launcher) context;
// We need this view to be focusable in touch mode so that when text editing of the folder
// name is complete, we have something to focus on, thus hiding the cursor and giving
- // reliable behvior when clicking the text field (since it will always gain focus on click).
+ // reliable behavior when clicking the text field (since it will always gain focus on click).
setFocusableInTouchMode(true);
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
- mScrollView = (ScrollView) findViewById(R.id.scroll_view);
- mContent = (CellLayout) findViewById(R.id.folder_content);
-
- mFocusIndicatorHandler = new FocusIndicatorView(getContext());
- mContent.addView(mFocusIndicatorHandler, 0);
- mFocusIndicatorHandler.getLayoutParams().height = FocusIndicatorView.DEFAULT_LAYOUT_SIZE;
- mFocusIndicatorHandler.getLayoutParams().width = FocusIndicatorView.DEFAULT_LAYOUT_SIZE;
-
- LauncherAppState app = LauncherAppState.getInstance();
- DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
+ mContentWrapper = findViewById(R.id.folder_content_wrapper);
+ mContent = (FolderPagedView) findViewById(R.id.folder_content);
+ mContent.setFolder(this);
- mContent.setCellDimensions(grid.folderCellWidthPx, grid.folderCellHeightPx);
- mContent.setGridSize(0, 0);
- mContent.getShortcutsAndWidgets().setMotionEventSplittingEnabled(false);
- mContent.setInvertIfRtl(true);
mFolderName = (FolderEditText) findViewById(R.id.folder_name);
mFolderName.setFolder(this);
mFolderName.setOnFocusChangeListener(this);
- // We find out how tall the text view wants to be (it is set to wrap_content), so that
- // we can allocate the appropriate amount of space for it.
- int measureSpec = MeasureSpec.UNSPECIFIED;
- mFolderName.measure(measureSpec, measureSpec);
- mFolderNameHeight = mFolderName.getMeasuredHeight();
-
// We disable action mode for now since it messes up the view on phones
mFolderName.setCustomSelectionActionModeCallback(mActionModeCallback);
mFolderName.setOnEditorActionListener(this);
mFolderName.setSelectAllOnFocus(true);
mFolderName.setInputType(mFolderName.getInputType() |
InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS | InputType.TYPE_TEXT_FLAG_CAP_WORDS);
- mAutoScrollHelper = new FolderAutoScrollHelper(mScrollView);
+
+ mFooter = findViewById(R.id.folder_footer);
+
+ // We find out how tall footer wants to be (it is set to wrap_content), so that
+ // we can allocate the appropriate amount of space for it.
+ int measureSpec = MeasureSpec.UNSPECIFIED;
+ mFooter.measure(measureSpec, measureSpec);
+ mFooterHeight = mFooter.getMeasuredHeight();
}
private ActionMode.Callback mActionModeCallback = new ActionMode.Callback() {
@@ -240,7 +243,10 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
public boolean onLongClick(View v) {
// Return if global dragging is not enabled
if (!mLauncher.isDraggingEnabled()) return true;
+ return beginDrag(v, false);
+ }
+ private boolean beginDrag(View v, boolean accessible) {
Object tag = v.getTag();
if (tag instanceof ShortcutInfo) {
ShortcutInfo item = (ShortcutInfo) tag;
@@ -248,14 +254,13 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
return false;
}
- mLauncher.getWorkspace().beginDragShared(v, this);
+ mLauncher.getWorkspace().beginDragShared(v, new Point(), this, accessible);
mCurrentDragInfo = item;
- mEmptyCell[0] = item.cellX;
- mEmptyCell[1] = item.cellY;
+ mEmptyCellRank = item.rank;
mCurrentDragView = v;
- mContent.removeView(mCurrentDragView);
+ mContent.removeItem(mCurrentDragView);
mInfo.remove(mCurrentDragInfo);
mDragInProgress = true;
mItemAddedBackToSelfViaIcon = false;
@@ -263,6 +268,23 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
return true;
}
+ @Override
+ public void startDrag(CellInfo cellInfo, boolean accessible) {
+ beginDrag(cellInfo.cell, accessible);
+ }
+
+ @Override
+ public void enableAccessibleDrag(boolean enable) {
+ mLauncher.getSearchBar().enableAccessibleDrag(enable);
+ for (int i = 0; i < mContent.getChildCount(); i++) {
+ mContent.getPageAt(i).enableAccessibleDrag(enable, CellLayout.FOLDER_ACCESSIBILITY_DRAG);
+ }
+
+ mFooter.setImportantForAccessibility(enable ? IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS :
+ IMPORTANT_FOR_ACCESSIBILITY_AUTO);
+ mLauncher.getWorkspace().setAddNewPageOnDrag(!enable);
+ }
+
public boolean isEditingName() {
return mIsEditingName;
}
@@ -309,13 +331,10 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
return mFolderName;
}
- public CellLayout getContent() {
- return mContent;
- }
-
/**
* We need to handle touch events to prevent them from falling through to the workspace below.
*/
+ @SuppressLint("ClickableViewAccessibility")
@Override
public boolean onTouchEvent(MotionEvent ev) {
return true;
@@ -325,7 +344,7 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
mDragController = dragController;
}
- void setFolderIcon(FolderIcon icon) {
+ public void setFolderIcon(FolderIcon icon) {
mFolderIcon = icon;
}
@@ -338,64 +357,16 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
/**
* @return the FolderInfo object associated with this folder
*/
- FolderInfo getInfo() {
+ public FolderInfo getInfo() {
return mInfo;
}
- private class GridComparator implements Comparator<ShortcutInfo> {
- int mNumCols;
- public GridComparator(int numCols) {
- mNumCols = numCols;
- }
-
- @Override
- public int compare(ShortcutInfo lhs, ShortcutInfo rhs) {
- int lhIndex = lhs.cellY * mNumCols + lhs.cellX;
- int rhIndex = rhs.cellY * mNumCols + rhs.cellX;
- return (lhIndex - rhIndex);
- }
- }
-
- private void placeInReadingOrder(ArrayList<ShortcutInfo> items) {
- int maxX = 0;
- int count = items.size();
- for (int i = 0; i < count; i++) {
- ShortcutInfo item = items.get(i);
- if (item.cellX > maxX) {
- maxX = item.cellX;
- }
- }
-
- GridComparator gridComparator = new GridComparator(maxX + 1);
- Collections.sort(items, gridComparator);
- final int countX = mContent.getCountX();
- for (int i = 0; i < count; i++) {
- int x = i % countX;
- int y = i / countX;
- ShortcutInfo item = items.get(i);
- item.cellX = x;
- item.cellY = y;
- }
- }
-
void bind(FolderInfo info) {
mInfo = info;
ArrayList<ShortcutInfo> children = info.contents;
- ArrayList<ShortcutInfo> overflow = new ArrayList<ShortcutInfo>();
- setupContentForNumItems(children.size());
- placeInReadingOrder(children);
- int count = 0;
- for (int i = 0; i < children.size(); i++) {
- ShortcutInfo child = (ShortcutInfo) children.get(i);
- if (createAndAddShortcut(child) == null) {
- overflow.add(child);
- } else {
- count++;
- }
- }
+ Collections.sort(children, ITEM_POS_COMPARATOR);
- // We rearrange the items in case there are any empty gaps
- setupContentForNumItems(count);
+ ArrayList<ShortcutInfo> overflow = mContent.bindItems(children);
// If our folder has too many items we prune them from the list. This is an issue
// when upgrading from the old Folders implementation which could contain an unlimited
@@ -405,6 +376,14 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
LauncherModel.deleteItemFromDatabase(mLauncher, item);
}
+ DragLayer.LayoutParams lp = (DragLayer.LayoutParams) getLayoutParams();
+ if (lp == null) {
+ lp = new DragLayer.LayoutParams(0, 0);
+ lp.customPosition = true;
+ setLayoutParams(lp);
+ }
+ centerAboutIcon();
+
mItemsInvalidated = true;
updateTextViewFocus();
mInfo.addListener(this);
@@ -414,7 +393,6 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
} else {
mFolderName.setText("");
}
- updateItemLocationsInDatabase();
// In case any children didn't come across during loading, clean up the folder accordingly
mFolderIcon.post(new Runnable() {
@@ -433,8 +411,9 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
*
* @return A new UserFolder.
*/
- static Folder fromXml(Context context) {
- return (Folder) LayoutInflater.from(context).inflate(R.layout.user_folder, null);
+ @SuppressLint("InflateParams")
+ static Folder fromXml(Launcher launcher) {
+ return (Folder) launcher.getLayoutInflater().inflate(R.layout.user_folder, null);
}
/**
@@ -459,6 +438,12 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
public void animateOpen() {
if (!(getParent() instanceof DragLayer)) return;
+ mContent.completePendingPageChanges();
+ if (!mDragInProgress) {
+ // Open on the first page.
+ mContent.snapToPageImmediately(0);
+ }
+
Animator openFolderAnim = null;
final Runnable onCompleteRunnable;
if (!Utilities.isLmpOrAbove()) {
@@ -484,6 +469,7 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
prepareReveal();
centerAboutIcon();
+ AnimatorSet anim = LauncherAnimUtils.createAnimatorSet();
int width = getPaddingLeft() + getPaddingRight() + mContent.getDesiredWidth();
int height = getFolderHeight();
@@ -494,32 +480,32 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
PropertyValuesHolder tx = PropertyValuesHolder.ofFloat("translationX", transX, 0);
PropertyValuesHolder ty = PropertyValuesHolder.ofFloat("translationY", transY, 0);
+ Animator drift = ObjectAnimator.ofPropertyValuesHolder(this, tx, ty);
+ drift.setDuration(mMaterialExpandDuration);
+ drift.setStartDelay(mMaterialExpandStagger);
+ drift.setInterpolator(new LogDecelerateInterpolator(100, 0));
+
int rx = (int) Math.max(Math.max(width - getPivotX(), 0), getPivotX());
int ry = (int) Math.max(Math.max(height - getPivotY(), 0), getPivotY());
- float radius = (float) Math.sqrt(rx * rx + ry * ry);
- AnimatorSet anim = LauncherAnimUtils.createAnimatorSet();
- Animator reveal = LauncherAnimUtils.createCircularReveal(this, (int) getPivotX(),
+ float radius = (float) Math.hypot(rx, ry);
+
+ Animator reveal = UiThreadCircularReveal.createCircularReveal(this, (int) getPivotX(),
(int) getPivotY(), 0, radius);
reveal.setDuration(mMaterialExpandDuration);
reveal.setInterpolator(new LogDecelerateInterpolator(100, 0));
- mContent.setAlpha(0f);
- Animator iconsAlpha = LauncherAnimUtils.ofFloat(mContent, "alpha", 0f, 1f);
+ mContentWrapper.setAlpha(0f);
+ Animator iconsAlpha = ObjectAnimator.ofFloat(mContentWrapper, "alpha", 0f, 1f);
iconsAlpha.setDuration(mMaterialExpandDuration);
iconsAlpha.setStartDelay(mMaterialExpandStagger);
iconsAlpha.setInterpolator(new AccelerateInterpolator(1.5f));
- mFolderName.setAlpha(0f);
- Animator textAlpha = LauncherAnimUtils.ofFloat(mFolderName, "alpha", 0f, 1f);
+ mFooter.setAlpha(0f);
+ Animator textAlpha = ObjectAnimator.ofFloat(mFooter, "alpha", 0f, 1f);
textAlpha.setDuration(mMaterialExpandDuration);
textAlpha.setStartDelay(mMaterialExpandStagger);
textAlpha.setInterpolator(new AccelerateInterpolator(1.5f));
- Animator drift = LauncherAnimUtils.ofPropertyValuesHolder(this, tx, ty);
- drift.setDuration(mMaterialExpandDuration);
- drift.setStartDelay(mMaterialExpandStagger);
- drift.setInterpolator(new LogDecelerateInterpolator(60, 0));
-
anim.play(drift);
anim.play(iconsAlpha);
anim.play(textAlpha);
@@ -527,11 +513,13 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
openFolderAnim = anim;
- mContent.setLayerType(LAYER_TYPE_HARDWARE, null);
+ mContentWrapper.setLayerType(LAYER_TYPE_HARDWARE, null);
+ mFooter.setLayerType(LAYER_TYPE_HARDWARE, null);
onCompleteRunnable = new Runnable() {
@Override
public void run() {
- mContent.setLayerType(LAYER_TYPE_NONE, null);
+ mContentWrapper.setLayerType(LAYER_TYPE_NONE, null);
+ mContentWrapper.setLayerType(LAYER_TYPE_NONE, null);
}
};
}
@@ -539,8 +527,7 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
@Override
public void onAnimationStart(Animator animation) {
sendCustomAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED,
- String.format(getContext().getString(R.string.folder_opened),
- mContent.getCountX(), mContent.getCountY()));
+ mContent.getAccessibilityDescription());
mState = STATE_ANIMATING;
}
@Override
@@ -551,30 +538,79 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
onCompleteRunnable.run();
}
- setFocusOnFirstChild();
+ mContent.setFocusOnFirstChild();
}
});
+
+ // Footer animation
+ if (mContent.getPageCount() > 1 && !mInfo.hasOption(FolderInfo.FLAG_MULTI_PAGE_ANIMATION)) {
+ int footerWidth = mContent.getDesiredWidth()
+ - mFooter.getPaddingLeft() - mFooter.getPaddingRight();
+
+ float textWidth = mFolderName.getPaint().measureText(mFolderName.getText().toString());
+ float translation = (footerWidth - textWidth) / 2;
+ mFolderName.setTranslationX(mContent.mIsRtl ? -translation : translation);
+ mContent.setMarkerScale(0);
+
+ // Do not update the flag if we are in drag mode. The flag will be updated, when we
+ // actually drop the icon.
+ final boolean updateAnimationFlag = !mDragInProgress;
+ openFolderAnim.addListener(new AnimatorListenerAdapter() {
+
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ mFolderName.animate().setDuration(FOLDER_NAME_ANIMATION_DURATION)
+ .translationX(0)
+ .setInterpolator(Utilities.isLmpOrAbove() ?
+ AnimationUtils.loadInterpolator(mLauncher,
+ android.R.interpolator.fast_out_slow_in)
+ : new LogDecelerateInterpolator(100, 0));
+ mContent.animateMarkers();
+
+ if (updateAnimationFlag) {
+ mInfo.setOption(FolderInfo.FLAG_MULTI_PAGE_ANIMATION, true, mLauncher);
+ }
+ }
+ });
+ } else {
+ mFolderName.setTranslationX(0);
+ mContent.setMarkerScale(1);
+ }
+
openFolderAnim.start();
// Make sure the folder picks up the last drag move even if the finger doesn't move.
if (mDragController.isDragging()) {
mDragController.forceTouchMove();
}
+
+ FolderPagedView pages = (FolderPagedView) mContent;
+ pages.verifyVisibleHighResIcons(pages.getNextPage());
}
public void beginExternalDrag(ShortcutInfo item) {
- setupContentForNumItems(getItemCount() + 1);
- findAndSetEmptyCells(item);
-
mCurrentDragInfo = item;
- mEmptyCell[0] = item.cellX;
- mEmptyCell[1] = item.cellY;
+ mEmptyCellRank = mContent.allocateRankForNewItem(item);
mIsExternalDrag = true;
-
mDragInProgress = true;
+
+ // Since this folder opened by another controller, it might not get onDrop or
+ // onDropComplete. Perform cleanup once drag-n-drop ends.
+ mDragController.addDragListener(this);
+ }
+
+ @Override
+ public void onDragStart(DragSource source, Object info, int dragAction) { }
+
+ @Override
+ public void onDragEnd() {
+ if (mIsExternalDrag && mDragInProgress) {
+ completeDragExit();
+ }
+ mDragController.removeDragListener(this);
}
- private void sendCustomAccessibilityEvent(int type, String text) {
+ @Thunk void sendCustomAccessibilityEvent(int type, String text) {
AccessibilityManager accessibilityManager = (AccessibilityManager)
getContext().getSystemService(Context.ACCESSIBILITY_SERVICE);
if (accessibilityManager.isEnabled()) {
@@ -585,13 +621,6 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
}
}
- private void setFocusOnFirstChild() {
- View firstChild = mContent.getChildAt(0, 0);
- if (firstChild != null) {
- firstChild.requestFocus();
- }
- }
-
public void animateClosed() {
if (!(getParent() instanceof DragLayer)) return;
PropertyValuesHolder alpha = PropertyValuesHolder.ofFloat("alpha", 0);
@@ -627,174 +656,90 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
!isFull());
}
- protected boolean findAndSetEmptyCells(ShortcutInfo item) {
- int[] emptyCell = new int[2];
- if (mContent.findCellForSpan(emptyCell, item.spanX, item.spanY)) {
- item.cellX = emptyCell[0];
- item.cellY = emptyCell[1];
- return true;
- } else {
- return false;
- }
- }
-
- protected View createAndAddShortcut(ShortcutInfo item) {
- final BubbleTextView textView =
- (BubbleTextView) mInflater.inflate(R.layout.folder_application, this, false);
- textView.applyFromShortcutInfo(item, mIconCache, false);
-
- textView.setOnClickListener(this);
- textView.setOnLongClickListener(this);
- textView.setOnFocusChangeListener(mFocusIndicatorHandler);
-
- // We need to check here to verify that the given item's location isn't already occupied
- // by another item.
- if (mContent.getChildAt(item.cellX, item.cellY) != null || item.cellX < 0 || item.cellY < 0
- || item.cellX >= mContent.getCountX() || item.cellY >= mContent.getCountY()) {
- // This shouldn't happen, log it.
- Log.e(TAG, "Folder order not properly persisted during bind");
- if (!findAndSetEmptyCells(item)) {
- return null;
- }
- }
-
- CellLayout.LayoutParams lp =
- new CellLayout.LayoutParams(item.cellX, item.cellY, item.spanX, item.spanY);
- boolean insert = false;
- textView.setOnKeyListener(new FolderKeyEventListener());
- mContent.addViewToCellLayout(textView, insert ? 0 : -1, (int)item.id, lp, true);
- return textView;
- }
-
public void onDragEnter(DragObject d) {
- mPreviousTargetCell[0] = -1;
- mPreviousTargetCell[1] = -1;
+ mPrevTargetRank = -1;
mOnExitAlarm.cancelAlarm();
+ // Get the area offset such that the folder only closes if half the drag icon width
+ // is outside the folder area
+ mScrollAreaOffset = d.dragView.getDragRegionWidth() / 2 - d.xOffset;
}
OnAlarmListener mReorderAlarmListener = new OnAlarmListener() {
public void onAlarm(Alarm alarm) {
- realTimeReorder(mEmptyCell, mTargetCell);
+ mContent.realTimeReorder(mEmptyCellRank, mTargetRank);
+ mEmptyCellRank = mTargetRank;
}
};
- boolean readingOrderGreaterThan(int[] v1, int[] v2) {
- if (v1[1] > v2[1] || (v1[1] == v2[1] && v1[0] > v2[0])) {
- return true;
- } else {
- return false;
- }
+ @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
+ public boolean isLayoutRtl() {
+ return (getLayoutDirection() == LAYOUT_DIRECTION_RTL);
}
- private void realTimeReorder(int[] empty, int[] target) {
- boolean wrap;
- int startX;
- int endX;
- int startY;
- int delay = 0;
- float delayAmount = 30;
- if (readingOrderGreaterThan(target, empty)) {
- wrap = empty[0] >= mContent.getCountX() - 1;
- startY = wrap ? empty[1] + 1 : empty[1];
- for (int y = startY; y <= target[1]; y++) {
- startX = y == empty[1] ? empty[0] + 1 : 0;
- endX = y < target[1] ? mContent.getCountX() - 1 : target[0];
- for (int x = startX; x <= endX; x++) {
- View v = mContent.getChildAt(x,y);
- if (mContent.animateChildToPosition(v, empty[0], empty[1],
- REORDER_ANIMATION_DURATION, delay, true, true)) {
- empty[0] = x;
- empty[1] = y;
- delay += delayAmount;
- delayAmount *= 0.9;
- }
- }
- }
- } else {
- wrap = empty[0] == 0;
- startY = wrap ? empty[1] - 1 : empty[1];
- for (int y = startY; y >= target[1]; y--) {
- startX = y == empty[1] ? empty[0] - 1 : mContent.getCountX() - 1;
- endX = y > target[1] ? 0 : target[0];
- for (int x = startX; x >= endX; x--) {
- View v = mContent.getChildAt(x,y);
- if (mContent.animateChildToPosition(v, empty[0], empty[1],
- REORDER_ANIMATION_DURATION, delay, true, true)) {
- empty[0] = x;
- empty[1] = y;
- delay += delayAmount;
- delayAmount *= 0.9;
- }
- }
- }
- }
+ @Override
+ public void onDragOver(DragObject d) {
+ onDragOver(d, REORDER_DELAY);
}
- public boolean isLayoutRtl() {
- return (getLayoutDirection() == LAYOUT_DIRECTION_RTL);
+ private int getTargetRank(DragObject d, float[] recycle) {
+ recycle = d.getVisualCenter(recycle);
+ return mContent.findNearestArea(
+ (int) recycle[0] - getPaddingLeft(), (int) recycle[1] - getPaddingTop());
}
- public void onDragOver(DragObject d) {
- final DragView dragView = d.dragView;
- final int scrollOffset = mScrollView.getScrollY();
- final float[] r = getDragViewVisualCenter(d.x, d.y, d.xOffset, d.yOffset, dragView, null);
- r[0] -= getPaddingLeft();
- r[1] -= getPaddingTop();
-
- final long downTime = SystemClock.uptimeMillis();
- final MotionEvent translatedEv = MotionEvent.obtain(
- downTime, downTime, MotionEvent.ACTION_MOVE, d.x, d.y, 0);
-
- if (!mAutoScrollHelper.isEnabled()) {
- mAutoScrollHelper.setEnabled(true);
+ @Thunk void onDragOver(DragObject d, int reorderDelay) {
+ if (mScrollPauseAlarm.alarmPending()) {
+ return;
}
+ final float[] r = new float[2];
+ mTargetRank = getTargetRank(d, r);
- final boolean handled = mAutoScrollHelper.onTouch(this, translatedEv);
- translatedEv.recycle();
-
- if (handled) {
+ if (mTargetRank != mPrevTargetRank) {
mReorderAlarm.cancelAlarm();
+ mReorderAlarm.setOnAlarmListener(mReorderAlarmListener);
+ mReorderAlarm.setAlarm(REORDER_DELAY);
+ mPrevTargetRank = mTargetRank;
+ }
+
+ float x = r[0];
+ int currentPage = mContent.getNextPage();
+
+ float cellOverlap = mContent.getCurrentCellLayout().getCellWidth()
+ * ICON_OVERSCROLL_WIDTH_FACTOR;
+ boolean isOutsideLeftEdge = x < cellOverlap;
+ boolean isOutsideRightEdge = x > (getWidth() - cellOverlap);
+
+ if (currentPage > 0 && (mContent.mIsRtl ? isOutsideRightEdge : isOutsideLeftEdge)) {
+ showScrollHint(DragController.SCROLL_LEFT, d);
+ } else if (currentPage < (mContent.getPageCount() - 1)
+ && (mContent.mIsRtl ? isOutsideLeftEdge : isOutsideRightEdge)) {
+ showScrollHint(DragController.SCROLL_RIGHT, d);
} else {
- mTargetCell = mContent.findNearestArea(
- (int) r[0], (int) r[1] + scrollOffset, 1, 1, mTargetCell);
- if (isLayoutRtl()) {
- mTargetCell[0] = mContent.getCountX() - mTargetCell[0] - 1;
- }
- if (mTargetCell[0] != mPreviousTargetCell[0]
- || mTargetCell[1] != mPreviousTargetCell[1]) {
- mReorderAlarm.cancelAlarm();
- mReorderAlarm.setOnAlarmListener(mReorderAlarmListener);
- mReorderAlarm.setAlarm(REORDER_DELAY);
- mPreviousTargetCell[0] = mTargetCell[0];
- mPreviousTargetCell[1] = mTargetCell[1];
+ mOnScrollHintAlarm.cancelAlarm();
+ if (mScrollHintDir != DragController.SCROLL_NONE) {
+ mContent.clearScrollHint();
+ mScrollHintDir = DragController.SCROLL_NONE;
}
}
}
- // This is used to compute the visual center of the dragView. The idea is that
- // the visual center represents the user's interpretation of where the item is, and hence
- // is the appropriate point to use when determining drop location.
- private float[] getDragViewVisualCenter(int x, int y, int xOffset, int yOffset,
- DragView dragView, float[] recycle) {
- float res[];
- if (recycle == null) {
- res = new float[2];
- } else {
- res = recycle;
+ private void showScrollHint(int direction, DragObject d) {
+ // Show scroll hint on the right
+ if (mScrollHintDir != direction) {
+ mContent.showScrollHint(direction);
+ mScrollHintDir = direction;
}
- // These represent the visual top and left of drag view if a dragRect was provided.
- // If a dragRect was not provided, then they correspond to the actual view left and
- // top, as the dragRect is in that case taken to be the entire dragView.
- // R.dimen.dragViewOffsetY.
- int left = x - xOffset;
- int top = y - yOffset;
+ // Set alarm for when the hint is complete
+ if (!mOnScrollHintAlarm.alarmPending() || mCurrentScrollDir != direction) {
+ mCurrentScrollDir = direction;
+ mOnScrollHintAlarm.cancelAlarm();
+ mOnScrollHintAlarm.setOnAlarmListener(new OnScrollHintListener(d));
+ mOnScrollHintAlarm.setAlarm(SCROLL_HINT_DURATION);
- // In order to find the visual center, we shift by half the dragRect
- res[0] = left + dragView.getDragRegion().width() / 2;
- res[1] = top + dragView.getDragRegion().height() / 2;
-
- return res;
+ mReorderAlarm.cancelAlarm();
+ mTargetRank = mEmptyCellRank;
+ }
}
OnAlarmListener mOnExitAlarmListener = new OnAlarmListener() {
@@ -804,17 +749,25 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
};
public void completeDragExit() {
- mLauncher.closeFolder();
+ if (mInfo.opened) {
+ mLauncher.closeFolder();
+ mRearrangeOnClose = true;
+ } else if (mState == STATE_ANIMATING) {
+ mRearrangeOnClose = true;
+ } else {
+ rearrangeChildren();
+ clearDragInfo();
+ }
+ }
+
+ private void clearDragInfo() {
mCurrentDragInfo = null;
mCurrentDragView = null;
mSuppressOnAdd = false;
- mRearrangeOnClose = true;
mIsExternalDrag = false;
}
public void onDragExit(DragObject d) {
- // Exiting folder; stop the auto scroller.
- mAutoScrollHelper.setEnabled(false);
// We only close the folder if this is a true drag exit, ie. not because
// a drop has occurred above the folder.
if (!d.dragComplete) {
@@ -822,6 +775,25 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
mOnExitAlarm.setAlarm(ON_EXIT_CLOSE_DELAY);
}
mReorderAlarm.cancelAlarm();
+
+ mOnScrollHintAlarm.cancelAlarm();
+ mScrollPauseAlarm.cancelAlarm();
+ if (mScrollHintDir != DragController.SCROLL_NONE) {
+ mContent.clearScrollHint();
+ mScrollHintDir = DragController.SCROLL_NONE;
+ }
+ }
+
+ /**
+ * When performing an accessibility drop, onDrop is sent immediately after onDragEnter. So we
+ * need to complete all transient states based on timers.
+ */
+ @Override
+ public void prepareAccessibilityDrop() {
+ if (mReorderAlarm.alarmPending()) {
+ mReorderAlarm.cancelAlarm();
+ mReorderAlarmListener.onAlarm(mReorderAlarm);
+ }
}
public void onDropCompleted(final View target, final DragObject d,
@@ -846,9 +818,18 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
replaceFolderWithFinalItem();
}
} else {
- setupContentForNumItems(getItemCount());
// The drag failed, we need to return the item to the folder
+ ShortcutInfo info = (ShortcutInfo) d.dragInfo;
+ View icon = (mCurrentDragView != null && mCurrentDragView.getTag() == info)
+ ? mCurrentDragView : mContent.createNewView(info);
+ ArrayList<View> views = getItemsInReadingOrder();
+ views.add(info.rank, icon);
+ mContent.arrangeChildren(views, views.size());
+ mItemsInvalidated = true;
+
+ mSuppressOnAdd = true;
mFolderIcon.onDrop(d);
+ mSuppressOnAdd = false;
}
if (target != this) {
@@ -857,6 +838,7 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
if (!successfulDrop) {
mSuppressFolderDeletion = true;
}
+ mScrollPauseAlarm.cancelAlarm();
completeDragExit();
}
}
@@ -871,12 +853,22 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
// Reordering may have occured, and we need to save the new item locations. We do this once
// at the end to prevent unnecessary database operations.
updateItemLocationsInDatabaseBatch();
+
+ // Use the item count to check for multi-page as the folder UI may not have
+ // been refreshed yet.
+ if (getItemCount() <= mContent.itemsPerPage()) {
+ // Show the animation, next time something is added to the folder.
+ mInfo.setOption(FolderInfo.FLAG_MULTI_PAGE_ANIMATION, false, mLauncher);
+ }
+
}
+ @Override
public void deferCompleteDropAfterUninstallActivity() {
mDeferDropAfterUninstall = true;
}
+ @Override
public void onUninstallActivityReturned(boolean success) {
mDeferDropAfterUninstall = false;
mUninstallSuccessful = success;
@@ -905,7 +897,8 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
return true;
}
- public void onFlingToDelete(DragObject d, int x, int y, PointF vec) {
+ @Override
+ public void onFlingToDelete(DragObject d, PointF vec) {
// Do nothing
}
@@ -914,22 +907,13 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
// Do nothing
}
- private void updateItemLocationsInDatabase() {
- ArrayList<View> list = getItemsInReadingOrder();
- for (int i = 0; i < list.size(); i++) {
- View v = list.get(i);
- ItemInfo info = (ItemInfo) v.getTag();
- LauncherModel.moveItemInDatabase(mLauncher, info, mInfo.id, 0,
- info.cellX, info.cellY);
- }
- }
-
private void updateItemLocationsInDatabaseBatch() {
ArrayList<View> list = getItemsInReadingOrder();
ArrayList<ItemInfo> items = new ArrayList<ItemInfo>();
for (int i = 0; i < list.size(); i++) {
View v = list.get(i);
ItemInfo info = (ItemInfo) v.getTag();
+ info.rank = i;
items.add(info);
}
@@ -942,7 +926,7 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
View v = list.get(i);
ItemInfo info = (ItemInfo) v.getTag();
LauncherModel.addItemToDatabase(mLauncher, info, mInfo.id, 0,
- info.cellX, info.cellY, false);
+ info.cellX, info.cellY);
}
}
@@ -956,37 +940,8 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
return true;
}
- private void setupContentDimensions(int count) {
- ArrayList<View> list = getItemsInReadingOrder();
-
- int countX = mContent.getCountX();
- int countY = mContent.getCountY();
- boolean done = false;
-
- while (!done) {
- int oldCountX = countX;
- int oldCountY = countY;
- if (countX * countY < count) {
- // Current grid is too small, expand it
- if ((countX <= countY || countY == mMaxCountY) && countX < mMaxCountX) {
- countX++;
- } else if (countY < mMaxCountY) {
- countY++;
- }
- if (countY == 0) countY++;
- } else if ((countY - 1) * countX >= count && countY >= countX) {
- countY = Math.max(0, countY - 1);
- } else if ((countX - 1) * countY >= count) {
- countX = Math.max(0, countX - 1);
- }
- done = countX == oldCountX && countY == oldCountY;
- }
- mContent.setGridSize(countX, countY);
- arrangeChildren(list);
- }
-
public boolean isFull() {
- return getItemCount() >= mMaxNumItems;
+ return mContent.isFull();
}
private void centerAboutIcon() {
@@ -996,41 +951,30 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
int width = getPaddingLeft() + getPaddingRight() + mContent.getDesiredWidth();
int height = getFolderHeight();
- float scale = parent.getDescendantRectRelativeToSelf(mFolderIcon, mTempRect);
+ float scale = parent.getDescendantRectRelativeToSelf(mFolderIcon, sTempRect);
- LauncherAppState app = LauncherAppState.getInstance();
- DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
+ DeviceProfile grid = mLauncher.getDeviceProfile();
- int centerX = (int) (mTempRect.left + mTempRect.width() * scale / 2);
- int centerY = (int) (mTempRect.top + mTempRect.height() * scale / 2);
+ int centerX = (int) (sTempRect.left + sTempRect.width() * scale / 2);
+ int centerY = (int) (sTempRect.top + sTempRect.height() * scale / 2);
int centeredLeft = centerX - width / 2;
int centeredTop = centerY - height / 2;
- int currentPage = mLauncher.getWorkspace().getNextPage();
- // In case the workspace is scrolling, we need to use the final scroll to compute
- // the folders bounds.
- mLauncher.getWorkspace().setFinalScrollForPageChange(currentPage);
- // We first fetch the currently visible CellLayoutChildren
- CellLayout currentLayout = (CellLayout) mLauncher.getWorkspace().getChildAt(currentPage);
- ShortcutAndWidgetContainer boundingLayout = currentLayout.getShortcutsAndWidgets();
- Rect bounds = new Rect();
- parent.getDescendantRectRelativeToSelf(boundingLayout, bounds);
- // We reset the workspaces scroll
- mLauncher.getWorkspace().resetFinalScrollForPageChange(currentPage);
-
- // We need to bound the folder to the currently visible CellLayoutChildren
- int left = Math.min(Math.max(bounds.left, centeredLeft),
- bounds.left + bounds.width() - width);
- int top = Math.min(Math.max(bounds.top, centeredTop),
- bounds.top + bounds.height() - height);
- if (grid.isPhone() && (grid.availableWidthPx - width) < grid.iconSizePx) {
+
+ // We need to bound the folder to the currently visible workspace area
+ mLauncher.getWorkspace().getPageAreaRelativeToDragLayer(sTempRect);
+ int left = Math.min(Math.max(sTempRect.left, centeredLeft),
+ sTempRect.left + sTempRect.width() - width);
+ int top = Math.min(Math.max(sTempRect.top, centeredTop),
+ sTempRect.top + sTempRect.height() - height);
+ if (grid.isPhone && (grid.availableWidthPx - width) < grid.iconSizePx) {
// Center the folder if it is full (on phones only)
left = (grid.availableWidthPx - width) / 2;
- } else if (width >= bounds.width()) {
+ } else if (width >= sTempRect.width()) {
// If the folder doesn't fit within the bounds, center it about the desired bounds
- left = bounds.left + (bounds.width() - width) / 2;
+ left = sTempRect.left + (sTempRect.width() - width) / 2;
}
- if (height >= bounds.height()) {
- top = bounds.top + (bounds.height() - height) / 2;
+ if (height >= sTempRect.height()) {
+ top = sTempRect.top + (sTempRect.height() - height) / 2;
}
int folderPivotX = width / 2 + (centeredLeft - left);
@@ -1055,26 +999,12 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
return mFolderIconPivotY;
}
- private void setupContentForNumItems(int count) {
- setupContentDimensions(count);
-
- DragLayer.LayoutParams lp = (DragLayer.LayoutParams) getLayoutParams();
- if (lp == null) {
- lp = new DragLayer.LayoutParams(0, 0);
- lp.customPosition = true;
- setLayoutParams(lp);
- }
- centerAboutIcon();
- }
-
private int getContentAreaHeight() {
- LauncherAppState app = LauncherAppState.getInstance();
- DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
- Rect workspacePadding = grid.getWorkspacePadding(grid.isLandscape ?
- CellLayout.LANDSCAPE : CellLayout.PORTRAIT);
+ DeviceProfile grid = mLauncher.getDeviceProfile();
+ Rect workspacePadding = grid.getWorkspacePadding(mContent.mIsRtl);
int maxContentAreaHeight = grid.availableHeightPx -
workspacePadding.top - workspacePadding.bottom -
- mFolderNameHeight;
+ mFooterHeight;
int height = Math.min(maxContentAreaHeight,
mContent.getDesiredHeight());
return Math.max(height, MIN_CONTENT_DIMEN);
@@ -1085,67 +1015,67 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
}
private int getFolderHeight() {
- int height = getPaddingTop() + getPaddingBottom()
- + getContentAreaHeight() + mFolderNameHeight;
- return height;
+ return getFolderHeight(getContentAreaHeight());
+ }
+
+ private int getFolderHeight(int contentAreaHeight) {
+ return getPaddingTop() + getPaddingBottom() + contentAreaHeight + mFooterHeight;
}
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- int width = getPaddingLeft() + getPaddingRight() + mContent.getDesiredWidth();
- int height = getFolderHeight();
- int contentAreaWidthSpec = MeasureSpec.makeMeasureSpec(getContentAreaWidth(),
- MeasureSpec.EXACTLY);
- int contentAreaHeightSpec = MeasureSpec.makeMeasureSpec(getContentAreaHeight(),
- MeasureSpec.EXACTLY);
-
- if (LauncherAppState.isDisableAllApps()) {
- // Don't cap the height of the content to allow scrolling.
- mContent.setFixedSize(getContentAreaWidth(), mContent.getDesiredHeight());
- } else {
- mContent.setFixedSize(getContentAreaWidth(), getContentAreaHeight());
+ int contentWidth = getContentAreaWidth();
+ int contentHeight = getContentAreaHeight();
+
+ int contentAreaWidthSpec = MeasureSpec.makeMeasureSpec(contentWidth, MeasureSpec.EXACTLY);
+ int contentAreaHeightSpec = MeasureSpec.makeMeasureSpec(contentHeight, MeasureSpec.EXACTLY);
+
+ mContent.setFixedSize(contentWidth, contentHeight);
+ mContentWrapper.measure(contentAreaWidthSpec, contentAreaHeightSpec);
+
+ if (mContent.getChildCount() > 0) {
+ int cellIconGap = (mContent.getPageAt(0).getCellWidth()
+ - mLauncher.getDeviceProfile().iconSizePx) / 2;
+ mFooter.setPadding(mContent.getPaddingLeft() + cellIconGap,
+ mFooter.getPaddingTop(),
+ mContent.getPaddingRight() + cellIconGap,
+ mFooter.getPaddingBottom());
}
+ mFooter.measure(contentAreaWidthSpec,
+ MeasureSpec.makeMeasureSpec(mFooterHeight, MeasureSpec.EXACTLY));
- mScrollView.measure(contentAreaWidthSpec, contentAreaHeightSpec);
- mFolderName.measure(contentAreaWidthSpec,
- MeasureSpec.makeMeasureSpec(mFolderNameHeight, MeasureSpec.EXACTLY));
- setMeasuredDimension(width, height);
+ int folderWidth = getPaddingLeft() + getPaddingRight() + contentWidth;
+ int folderHeight = getFolderHeight(contentHeight);
+ setMeasuredDimension(folderWidth, folderHeight);
}
- private void arrangeChildren(ArrayList<View> list) {
- int[] vacant = new int[2];
- if (list == null) {
- list = getItemsInReadingOrder();
- }
- mContent.removeAllViews();
+ /**
+ * Rearranges the children based on their rank.
+ */
+ public void rearrangeChildren() {
+ rearrangeChildren(-1);
+ }
- for (int i = 0; i < list.size(); i++) {
- View v = list.get(i);
- mContent.getVacantCell(vacant, 1, 1);
- CellLayout.LayoutParams lp = (CellLayout.LayoutParams) v.getLayoutParams();
- lp.cellX = vacant[0];
- lp.cellY = vacant[1];
- ItemInfo info = (ItemInfo) v.getTag();
- if (info.cellX != vacant[0] || info.cellY != vacant[1]) {
- info.cellX = vacant[0];
- info.cellY = vacant[1];
- LauncherModel.addOrMoveItemInDatabase(mLauncher, info, mInfo.id, 0,
- info.cellX, info.cellY);
- }
- boolean insert = false;
- mContent.addViewToCellLayout(v, insert ? 0 : -1, (int)info.id, lp, true);
- }
+ /**
+ * Rearranges the children based on their rank.
+ * @param itemCount if greater than the total children count, empty spaces are left at the end,
+ * otherwise it is ignored.
+ */
+ public void rearrangeChildren(int itemCount) {
+ ArrayList<View> views = getItemsInReadingOrder();
+ mContent.arrangeChildren(views, Math.max(itemCount, views.size()));
mItemsInvalidated = true;
}
- public int getItemCount() {
- return mContent.getShortcutsAndWidgets().getChildCount();
+ // TODO remove this once GSA code fix is submitted
+ public ViewGroup getContent() {
+ return (ViewGroup) mContent;
}
- public View getItemAt(int index) {
- return mContent.getShortcutsAndWidgets().getChildAt(index);
+ public int getItemCount() {
+ return mContent.getItemCount();
}
- private void onCloseComplete() {
+ @Thunk void onCloseComplete() {
DragLayer parent = (DragLayer) getParent();
if (parent != null) {
parent.removeView(this);
@@ -1155,7 +1085,7 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
mFolderIcon.requestFocus();
if (mRearrangeOnClose) {
- setupContentForNumItems(getItemCount());
+ rearrangeChildren();
mRearrangeOnClose = false;
}
if (getItemCount() <= 1) {
@@ -1166,9 +1096,10 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
}
}
mSuppressFolderDeletion = false;
+ clearDragInfo();
}
- private void replaceFolderWithFinalItem() {
+ @Thunk void replaceFolderWithFinalItem() {
// Add the last remaining child to the workspace in place of the folder
Runnable onCompleteRunnable = new Runnable() {
@Override
@@ -1179,8 +1110,7 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
// 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(R.layout.application, cellLayout,
- finalItem);
+ child = mLauncher.createShortcut(cellLayout, finalItem);
LauncherModel.addOrMoveItemInDatabase(mLauncher, finalItem, mInfo.container,
mInfo.screenId, mInfo.cellX, mInfo.cellY);
}
@@ -1205,7 +1135,7 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
}
}
};
- View finalChild = getItemAt(0);
+ View finalChild = mContent.getLastItem();
if (finalChild != null) {
mFolderIcon.performDestroyAnimation(finalChild, onCompleteRunnable);
} else {
@@ -1220,9 +1150,8 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
// This method keeps track of the last item in the folder for the purposes
// of keyboard focus
- private void updateTextViewFocus() {
- View lastChild = getItemAt(getItemCount() - 1);
- getItemAt(getItemCount() - 1);
+ public void updateTextViewFocus() {
+ View lastChild = mContent.getLastItem();
if (lastChild != null) {
mFolderName.setNextFocusDownId(lastChild.getId());
mFolderName.setNextFocusRightId(lastChild.getId());
@@ -1247,12 +1176,24 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
};
}
+ // If the icon was dropped while the page was being scrolled, we need to compute
+ // the target location again such that the icon is placed of the final page.
+ if (!mContent.rankOnCurrentPage(mEmptyCellRank)) {
+ // Reorder again.
+ mTargetRank = getTargetRank(d, null);
+
+ // Rearrange items immediately.
+ mReorderAlarmListener.onAlarm(mReorderAlarm);
+
+ mOnScrollHintAlarm.cancelAlarm();
+ mScrollPauseAlarm.cancelAlarm();
+ }
+ mContent.completePendingPageChanges();
+
View currentDragView;
ShortcutInfo si = mCurrentDragInfo;
if (mIsExternalDrag) {
- si.cellX = mEmptyCell[0];
- si.cellY = mEmptyCell[1];
-
+ currentDragView = mContent.createAndAddViewForRank(si, mEmptyCellRank);
// Actually move the item in the database if it was an external drag. Call this
// before creating the view, so that ShortcutInfo is updated appropriately.
LauncherModel.addOrMoveItemInDatabase(
@@ -1263,14 +1204,9 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
updateItemLocationsInDatabaseBatch();
}
mIsExternalDrag = false;
-
- currentDragView = createAndAddShortcut(si);
} else {
currentDragView = mCurrentDragView;
- CellLayout.LayoutParams lp = (CellLayout.LayoutParams) currentDragView.getLayoutParams();
- si.cellX = lp.cellX = mEmptyCell[0];
- si.cellX = lp.cellY = mEmptyCell[1];
- mContent.addViewToCellLayout(currentDragView, -1, (int) si.id, lp, true);
+ mContent.addViewForRank(currentDragView, si, mEmptyCellRank);
}
if (d.dragView.hasDrawn()) {
@@ -1289,7 +1225,7 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
currentDragView.setVisibility(VISIBLE);
}
mItemsInvalidated = true;
- setupContentDimensions(getItemCount());
+ rearrangeChildren();
// Temporarily suppress the listener, as we did all the work already here.
mSuppressOnAdd = true;
@@ -1297,6 +1233,12 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
mSuppressOnAdd = false;
// Clear the drag info, as it is no longer being dragged.
mCurrentDragInfo = null;
+ mDragInProgress = false;
+
+ if (mContent.getPageCount() > 1) {
+ // The animation has already been shown while opening the folder.
+ mInfo.setOption(FolderInfo.FLAG_MULTI_PAGE_ANIMATION, true, mLauncher);
+ }
}
// This is used so the item doesn't immediately appear in the folder when added. In one case
@@ -1311,17 +1253,13 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
v.setVisibility(VISIBLE);
}
+ @Override
public void onAdd(ShortcutInfo item) {
- mItemsInvalidated = true;
// If the item was dropped onto this open folder, we have done the work associated
// with adding the item to the folder, as indicated by mSuppressOnAdd being set
if (mSuppressOnAdd) return;
- if (!findAndSetEmptyCells(item)) {
- // The current layout is full, can we expand it?
- setupContentForNumItems(getItemCount() + 1);
- findAndSetEmptyCells(item);
- }
- createAndAddShortcut(item);
+ mContent.createAndAddViewForRank(item, mContent.allocateRankForNewItem(item));
+ mItemsInvalidated = true;
LauncherModel.addOrMoveItemInDatabase(
mLauncher, item, mInfo.id, 0, item.cellX, item.cellY);
}
@@ -1332,27 +1270,25 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
// the work associated with removing the item, so we don't have to do anything here.
if (item == mCurrentDragInfo) return;
View v = getViewForInfo(item);
- mContent.removeView(v);
+ mContent.removeItem(v);
if (mState == STATE_ANIMATING) {
mRearrangeOnClose = true;
} else {
- setupContentForNumItems(getItemCount());
+ rearrangeChildren();
}
if (getItemCount() <= 1) {
replaceFolderWithFinalItem();
}
}
- private View getViewForInfo(ShortcutInfo item) {
- for (int j = 0; j < mContent.getCountY(); j++) {
- for (int i = 0; i < mContent.getCountX(); i++) {
- View v = mContent.getChildAt(i, j);
- if (v.getTag() == item) {
- return v;
- }
+ private View getViewForInfo(final ShortcutInfo item) {
+ return mContent.iterateOverItems(new ItemOperator() {
+
+ @Override
+ public boolean evaluate(ItemInfo info, View view, View parent) {
+ return info == item;
}
- }
- return null;
+ });
}
public void onItemsChanged() {
@@ -1365,14 +1301,14 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
public ArrayList<View> getItemsInReadingOrder() {
if (mItemsInvalidated) {
mItemsInReadingOrder.clear();
- for (int j = 0; j < mContent.getCountY(); j++) {
- for (int i = 0; i < mContent.getCountX(); i++) {
- View v = mContent.getChildAt(i, j);
- if (v != null) {
- mItemsInReadingOrder.add(v);
- }
+ mContent.iterateOverItems(new ItemOperator() {
+
+ @Override
+ public boolean evaluate(ItemInfo info, View view, View parent) {
+ mItemsInReadingOrder.add(view);
+ return false;
}
- }
+ });
mItemsInvalidated = false;
}
return mItemsInReadingOrder;
@@ -1391,5 +1327,79 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
@Override
public void getHitRectRelativeToDragLayer(Rect outRect) {
getHitRect(outRect);
+ outRect.left -= mScrollAreaOffset;
+ outRect.right += mScrollAreaOffset;
}
+
+ @Override
+ public void fillInLaunchSourceData(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);
+ sourceData.putInt(Stats.SOURCE_EXTRA_SUB_CONTAINER_PAGE, mContent.getCurrentPage());
+ }
+
+ private class OnScrollHintListener implements OnAlarmListener {
+
+ private final DragObject mDragObject;
+
+ OnScrollHintListener(DragObject object) {
+ mDragObject = object;
+ }
+
+ /**
+ * Scroll hint has been shown long enough. Now scroll to appropriate page.
+ */
+ @Override
+ public void onAlarm(Alarm alarm) {
+ if (mCurrentScrollDir == DragController.SCROLL_LEFT) {
+ mContent.scrollLeft();
+ mScrollHintDir = DragController.SCROLL_NONE;
+ } else if (mCurrentScrollDir == DragController.SCROLL_RIGHT) {
+ mContent.scrollRight();
+ mScrollHintDir = DragController.SCROLL_NONE;
+ } else {
+ // This should not happen
+ return;
+ }
+ mCurrentScrollDir = DragController.SCROLL_NONE;
+
+ // Pause drag event until the scrolling is finished
+ mScrollPauseAlarm.setOnAlarmListener(new OnScrollFinishedListener(mDragObject));
+ mScrollPauseAlarm.setAlarm(DragController.RESCROLL_DELAY);
+ }
+ }
+
+ private class OnScrollFinishedListener implements OnAlarmListener {
+
+ private final DragObject mDragObject;
+
+ OnScrollFinishedListener(DragObject object) {
+ mDragObject = object;
+ }
+
+ /**
+ * Page scroll is complete.
+ */
+ @Override
+ public void onAlarm(Alarm alarm) {
+ // Reorder immediately on page change.
+ onDragOver(mDragObject, 1);
+ }
+ }
+
+ // Compares item position based on rank and position giving priority to the rank.
+ private static final Comparator<ItemInfo> ITEM_POS_COMPARATOR = new Comparator<ItemInfo>() {
+
+ @Override
+ public int compare(ItemInfo lhs, ItemInfo rhs) {
+ if (lhs.rank != rhs.rank) {
+ return lhs.rank - rhs.rank;
+ } else if (lhs.cellY != rhs.cellY) {
+ return lhs.cellY - rhs.cellY;
+ } else {
+ return lhs.cellX - rhs.cellX;
+ }
+ }
+ };
}
diff --git a/src/com/android/launcher3/FolderAutoScrollHelper.java b/src/com/android/launcher3/FolderAutoScrollHelper.java
deleted file mode 100644
index 40e888464..000000000
--- a/src/com/android/launcher3/FolderAutoScrollHelper.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * 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.
- */
-
-package com.android.launcher3;
-
-import android.support.v4.widget.AutoScrollHelper;
-import android.widget.ScrollView;
-
-/**
- * An implementation of {@link AutoScrollHelper} that knows how to scroll
- * through a {@link Folder}.
- */
-public class FolderAutoScrollHelper extends AutoScrollHelper {
- private static final float MAX_SCROLL_VELOCITY = 1500f;
-
- private final ScrollView mTarget;
-
- public FolderAutoScrollHelper(ScrollView target) {
- super(target);
-
- mTarget = target;
-
- setActivationDelay(0);
- setEdgeType(EDGE_TYPE_INSIDE_EXTEND);
- setExclusive(true);
- setMaximumVelocity(MAX_SCROLL_VELOCITY, MAX_SCROLL_VELOCITY);
- setRampDownDuration(0);
- setRampUpDuration(0);
- }
-
- @Override
- public void scrollTargetBy(int deltaX, int deltaY) {
- mTarget.scrollBy(deltaX, deltaY);
- }
-
- @Override
- public boolean canTargetScrollHorizontally(int direction) {
- // List do not scroll horizontally.
- return false;
- }
-
- @Override
- public boolean canTargetScrollVertically(int direction) {
- return mTarget.canScrollVertically(direction);
- }
-} \ No newline at end of file
diff --git a/src/com/android/launcher3/FolderIcon.java b/src/com/android/launcher3/FolderIcon.java
index a359f1180..8d534d2fe 100644
--- a/src/com/android/launcher3/FolderIcon.java
+++ b/src/com/android/launcher3/FolderIcon.java
@@ -43,6 +43,7 @@ import android.widget.TextView;
import com.android.launcher3.DropTarget.DragObject;
import com.android.launcher3.FolderInfo.FolderListener;
+import com.android.launcher3.util.Thunk;
import java.util.ArrayList;
@@ -50,15 +51,16 @@ import java.util.ArrayList;
* An icon that can appear on in the workspace representing an {@link UserFolder}.
*/
public class FolderIcon extends FrameLayout implements FolderListener {
- private Launcher mLauncher;
- private Folder mFolder;
+ @Thunk Launcher mLauncher;
+ @Thunk Folder mFolder;
private FolderInfo mInfo;
- private static boolean sStaticValuesDirty = true;
+ @Thunk static boolean sStaticValuesDirty = true;
private CheckLongPressHelper mLongPressHelper;
+ private StylusEventHelper mStylusEventHelper;
// The number of icons to display in the
- private static final int NUM_ITEMS_IN_PREVIEW = 3;
+ public static final int NUM_ITEMS_IN_PREVIEW = 3;
private static final int CONSUMPTION_ANIMATION_DURATION = 100;
private static final int DROP_IN_ANIMATION_DURATION = 400;
private static final int INITIAL_ITEM_ANIMATION_DURATION = 350;
@@ -88,8 +90,8 @@ public class FolderIcon extends FrameLayout implements FolderListener {
public static Drawable sSharedFolderLeaveBehind = null;
- private ImageView mPreviewBackground;
- private BubbleTextView mFolderName;
+ @Thunk ImageView mPreviewBackground;
+ @Thunk BubbleTextView mFolderName;
FolderRingAnimator mFolderRingAnimator = null;
@@ -109,11 +111,11 @@ public class FolderIcon extends FrameLayout implements FolderListener {
private float mSlop;
private PreviewItemDrawingParams mParams = new PreviewItemDrawingParams(0, 0, 0, 0);
- private PreviewItemDrawingParams mAnimParams = new PreviewItemDrawingParams(0, 0, 0, 0);
- private ArrayList<ShortcutInfo> mHiddenItems = new ArrayList<ShortcutInfo>();
+ @Thunk PreviewItemDrawingParams mAnimParams = new PreviewItemDrawingParams(0, 0, 0, 0);
+ @Thunk ArrayList<ShortcutInfo> mHiddenItems = new ArrayList<ShortcutInfo>();
private Alarm mOpenAlarm = new Alarm();
- private ItemInfo mDragInfo;
+ @Thunk ItemInfo mDragInfo;
public FolderIcon(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -127,6 +129,8 @@ public class FolderIcon extends FrameLayout implements FolderListener {
private void init() {
mLongPressHelper = new CheckLongPressHelper(this);
+ mStylusEventHelper = new StylusEventHelper(this);
+ setAccessibilityDelegate(LauncherAppState.getInstance().getAccessibilityDelegate());
}
public boolean isDropEnabled() {
@@ -145,8 +149,8 @@ public class FolderIcon extends FrameLayout implements FolderListener {
"INITIAL_ITEM_ANIMATION_DURATION, as sequencing of adding first two items " +
"is dependent on this");
}
- LauncherAppState app = LauncherAppState.getInstance();
- DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
+
+ DeviceProfile grid = launcher.getDeviceProfile();
FolderIcon icon = (FolderIcon) LayoutInflater.from(launcher).inflate(resId, group, false);
icon.setClipToPadding(false);
@@ -191,7 +195,7 @@ public class FolderIcon extends FrameLayout implements FolderListener {
public static class FolderRingAnimator {
public int mCellX;
public int mCellY;
- private CellLayout mCellLayout;
+ @Thunk CellLayout mCellLayout;
public float mOuterRingSize;
public float mInnerRingSize;
public FolderIcon mFolderIcon = null;
@@ -215,12 +219,11 @@ public class FolderIcon extends FrameLayout implements FolderListener {
+ Thread.currentThread());
}
- LauncherAppState app = LauncherAppState.getInstance();
- DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
+ DeviceProfile grid = launcher.getDeviceProfile();
sPreviewSize = grid.folderIconSizePx;
sPreviewPadding = res.getDimensionPixelSize(R.dimen.folder_preview_padding);
- sSharedOuterRingDrawable = res.getDrawable(R.drawable.portal_ring_outer_holo);
- sSharedInnerRingDrawable = res.getDrawable(R.drawable.portal_ring_inner_nolip_holo);
+ sSharedOuterRingDrawable = res.getDrawable(R.drawable.portal_ring_outer);
+ sSharedInnerRingDrawable = res.getDrawable(R.drawable.portal_ring_inner_nolip);
sSharedFolderLeaveBehind = res.getDrawable(R.drawable.portal_ring_rest);
sStaticValuesDirty = false;
}
@@ -488,8 +491,7 @@ public class FolderIcon extends FrameLayout implements FolderListener {
private void computePreviewDrawingParams(int drawableSize, int totalSize) {
if (mIntrinsicIconSize != drawableSize || mTotalWidth != totalSize) {
- LauncherAppState app = LauncherAppState.getInstance();
- DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
+ DeviceProfile grid = mLauncher.getDeviceProfile();
mIntrinsicIconSize = drawableSize;
mTotalWidth = totalSize;
@@ -643,9 +645,10 @@ public class FolderIcon extends FrameLayout implements FolderListener {
final Runnable onCompleteRunnable) {
final PreviewItemDrawingParams finalParams = computePreviewItemDrawingParams(0, null);
- final float scale0 = 1.0f;
- final float transX0 = (mAvailableSpaceInPreview - d.getIntrinsicWidth()) / 2;
- final float transY0 = (mAvailableSpaceInPreview - d.getIntrinsicHeight()) / 2 + getPaddingTop();
+ float iconSize = mLauncher.getDeviceProfile().iconSizePx;
+ final float scale0 = iconSize / d.getIntrinsicWidth() ;
+ final float transX0 = (mAvailableSpaceInPreview - iconSize) / 2;
+ final float transY0 = (mAvailableSpaceInPreview - iconSize) / 2 + getPaddingTop();
mAnimParams.drawable = d;
ValueAnimator va = LauncherAnimUtils.ofFloat(this, 0f, 1.0f);
@@ -708,7 +711,7 @@ public class FolderIcon extends FrameLayout implements FolderListener {
}
public void onTitleChanged(CharSequence title) {
- mFolderName.setText(title.toString());
+ mFolderName.setText(title);
setContentDescription(String.format(getContext().getString(R.string.folder_name_format),
title));
}
@@ -719,6 +722,12 @@ public class FolderIcon extends FrameLayout implements FolderListener {
// isPressed() on an ACTION_UP
boolean result = super.onTouchEvent(event);
+ // Check for a stylus button press, if it occurs cancel any long press checks.
+ if (mStylusEventHelper.checkAndPerformStylusEvent(event)) {
+ mLongPressHelper.cancelLongPress();
+ return true;
+ }
+
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mLongPressHelper.postCheckForLongPress();
diff --git a/src/com/android/launcher3/FolderInfo.java b/src/com/android/launcher3/FolderInfo.java
index 85a792f4b..aea21c95b 100644
--- a/src/com/android/launcher3/FolderInfo.java
+++ b/src/com/android/launcher3/FolderInfo.java
@@ -29,19 +29,38 @@ import java.util.Arrays;
*/
public class FolderInfo extends ItemInfo {
+ public static final int NO_FLAGS = 0x00000000;
+
+ /**
+ * The folder is locked in sorted mode
+ */
+ public static final int FLAG_ITEMS_SORTED = 0x00000001;
+
+ /**
+ * It is a work folder
+ */
+ public static final int FLAG_WORK_FOLDER = 0x00000002;
+
+ /**
+ * The multi-page animation has run for this folder
+ */
+ public static final int FLAG_MULTI_PAGE_ANIMATION = 0x00000004;
+
/**
* Whether this folder has been opened
*/
boolean opened;
+ public int options;
+
/**
* The apps and shortcuts
*/
- ArrayList<ShortcutInfo> contents = new ArrayList<ShortcutInfo>();
+ public ArrayList<ShortcutInfo> contents = new ArrayList<ShortcutInfo>();
ArrayList<FolderListener> listeners = new ArrayList<FolderListener>();
- FolderInfo() {
+ public FolderInfo() {
itemType = LauncherSettings.Favorites.ITEM_TYPE_FOLDER;
user = UserHandleCompat.myUserHandle();
}
@@ -83,6 +102,8 @@ public class FolderInfo extends ItemInfo {
void onAddToDatabase(Context context, ContentValues values) {
super.onAddToDatabase(context, values);
values.put(LauncherSettings.Favorites.TITLE, title.toString());
+ values.put(LauncherSettings.Favorites.OPTIONS, options);
+
}
void addListener(FolderListener listener) {
@@ -121,4 +142,25 @@ public class FolderInfo extends ItemInfo {
+ " cellX=" + cellX + " cellY=" + cellY + " spanX=" + spanX
+ " spanY=" + spanY + " dropPos=" + Arrays.toString(dropPos) + ")";
}
+
+ public boolean hasOption(int optionFlag) {
+ return (options & optionFlag) != 0;
+ }
+
+ /**
+ * @param option flag to set or clear
+ * @param isEnabled whether to set or clear the flag
+ * @param context if not null, save changes to the db.
+ */
+ public void setOption(int option, boolean isEnabled, Context context) {
+ int oldOptions = options;
+ if (isEnabled) {
+ options |= option;
+ } else {
+ options &= ~option;
+ }
+ if (context != null && oldOptions != options) {
+ LauncherModel.updateItemInDatabase(context, this);
+ }
+ }
}
diff --git a/src/com/android/launcher3/FolderPagedView.java b/src/com/android/launcher3/FolderPagedView.java
new file mode 100644
index 000000000..f2ec1b68c
--- /dev/null
+++ b/src/com/android/launcher3/FolderPagedView.java
@@ -0,0 +1,678 @@
+/**
+ * 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;
+
+import android.annotation.SuppressLint;
+import android.content.Context;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.Gravity;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.animation.DecelerateInterpolator;
+import android.view.animation.Interpolator;
+import android.view.animation.OvershootInterpolator;
+
+import com.android.launcher3.FocusHelper.PagedFolderKeyEventListener;
+import com.android.launcher3.PageIndicator.PageMarkerResources;
+import com.android.launcher3.Workspace.ItemOperator;
+import com.android.launcher3.util.Thunk;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+public class FolderPagedView extends PagedView {
+
+ private static final String TAG = "FolderPagedView";
+
+ private static final boolean ALLOW_FOLDER_SCROLL = true;
+
+ private static final int REORDER_ANIMATION_DURATION = 230;
+ private static final int START_VIEW_REORDER_DELAY = 30;
+ private static final float VIEW_REORDER_DELAY_FACTOR = 0.9f;
+
+ private static final int PAGE_INDICATOR_ANIMATION_START_DELAY = 300;
+ private static final int PAGE_INDICATOR_ANIMATION_STAGGERED_DELAY = 150;
+ private static final int PAGE_INDICATOR_ANIMATION_DURATION = 400;
+
+ // This value approximately overshoots to 1.5 times the original size.
+ private static final float PAGE_INDICATOR_OVERSHOOT_TENSION = 4.9f;
+
+ /**
+ * Fraction of the width to scroll when showing the next page hint.
+ */
+ private static final float SCROLL_HINT_FRACTION = 0.07f;
+
+ private static final int[] sTempPosArray = new int[2];
+
+ public final boolean mIsRtl;
+
+ private final LayoutInflater mInflater;
+ private final IconCache mIconCache;
+
+ @Thunk final HashMap<View, Runnable> mPendingAnimations = new HashMap<>();
+
+ private final int mMaxCountX;
+ private final int mMaxCountY;
+ private final int mMaxItemsPerPage;
+
+ private int mAllocatedContentSize;
+ private int mGridCountX;
+ private int mGridCountY;
+
+ private Folder mFolder;
+ private FocusIndicatorView mFocusIndicatorView;
+ private PagedFolderKeyEventListener mKeyListener;
+
+ private PageIndicator mPageIndicator;
+
+ public FolderPagedView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ LauncherAppState app = LauncherAppState.getInstance();
+
+ InvariantDeviceProfile profile = app.getInvariantDeviceProfile();
+ mMaxCountX = profile.numFolderColumns;
+ mMaxCountY = profile.numFolderRows;
+
+ mMaxItemsPerPage = mMaxCountX * mMaxCountY;
+
+ mInflater = LayoutInflater.from(context);
+ mIconCache = app.getIconCache();
+
+ mIsRtl = Utilities.isRtl(getResources());
+ setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
+
+ setEdgeGlowColor(getResources().getColor(R.color.folder_edge_effect_color));
+ }
+
+ public void setFolder(Folder folder) {
+ mFolder = folder;
+ mFocusIndicatorView = (FocusIndicatorView) folder.findViewById(R.id.focus_indicator);
+ mKeyListener = new PagedFolderKeyEventListener(folder);
+ mPageIndicator = (PageIndicator) folder.findViewById(R.id.folder_page_indicator);
+ }
+
+ /**
+ * Sets up the grid size such that {@param count} items can fit in the grid.
+ * The grid size is calculated such that countY <= countX and countX = ceil(sqrt(count)) while
+ * maintaining the restrictions of {@link #mMaxCountX} &amp; {@link #mMaxCountY}.
+ */
+ private void setupContentDimensions(int count) {
+ mAllocatedContentSize = count;
+ boolean done;
+ if (count >= mMaxItemsPerPage) {
+ mGridCountX = mMaxCountX;
+ mGridCountY = mMaxCountY;
+ done = true;
+ } else {
+ done = false;
+ }
+
+ while (!done) {
+ int oldCountX = mGridCountX;
+ int oldCountY = mGridCountY;
+ if (mGridCountX * mGridCountY < count) {
+ // Current grid is too small, expand it
+ if ((mGridCountX <= mGridCountY || mGridCountY == mMaxCountY) && mGridCountX < mMaxCountX) {
+ mGridCountX++;
+ } else if (mGridCountY < mMaxCountY) {
+ mGridCountY++;
+ }
+ if (mGridCountY == 0) mGridCountY++;
+ } else if ((mGridCountY - 1) * mGridCountX >= count && mGridCountY >= mGridCountX) {
+ mGridCountY = Math.max(0, mGridCountY - 1);
+ } else if ((mGridCountX - 1) * mGridCountY >= count) {
+ mGridCountX = Math.max(0, mGridCountX - 1);
+ }
+ done = mGridCountX == oldCountX && mGridCountY == oldCountY;
+ }
+
+ // Update grid size
+ for (int i = getPageCount() - 1; i >= 0; i--) {
+ getPageAt(i).setGridSize(mGridCountX, mGridCountY);
+ }
+ }
+
+ /**
+ * Binds items to the layout.
+ * @return list of items that could not be bound, probably because we hit the max size limit.
+ */
+ public ArrayList<ShortcutInfo> bindItems(ArrayList<ShortcutInfo> items) {
+ ArrayList<View> icons = new ArrayList<View>();
+ ArrayList<ShortcutInfo> extra = new ArrayList<ShortcutInfo>();
+
+ for (ShortcutInfo item : items) {
+ if (!ALLOW_FOLDER_SCROLL && icons.size() >= mMaxItemsPerPage) {
+ extra.add(item);
+ } else {
+ icons.add(createNewView(item));
+ }
+ }
+ arrangeChildren(icons, icons.size(), false);
+ return extra;
+ }
+
+ /**
+ * Create space for a new item at the end, and returns the rank for that item.
+ * Also sets the current page to the last page.
+ */
+ public int allocateRankForNewItem(ShortcutInfo info) {
+ int rank = getItemCount();
+ ArrayList<View> views = new ArrayList<View>(mFolder.getItemsInReadingOrder());
+ views.add(rank, null);
+ arrangeChildren(views, views.size(), false);
+ setCurrentPage(rank / mMaxItemsPerPage);
+ return rank;
+ }
+
+ public View createAndAddViewForRank(ShortcutInfo item, int rank) {
+ View icon = createNewView(item);
+ addViewForRank(icon, item, rank);
+ return icon;
+ }
+
+ /**
+ * Adds the {@param view} to the layout based on {@param rank} and updated the position
+ * related attributes. It assumes that {@param item} is already attached to the view.
+ */
+ public void addViewForRank(View view, ShortcutInfo item, int rank) {
+ int pagePos = rank % mMaxItemsPerPage;
+ int pageNo = rank / mMaxItemsPerPage;
+
+ item.rank = rank;
+ item.cellX = pagePos % mGridCountX;
+ item.cellY = pagePos / mGridCountX;
+
+ CellLayout.LayoutParams lp = (CellLayout.LayoutParams) view.getLayoutParams();
+ lp.cellX = item.cellX;
+ lp.cellY = item.cellY;
+ getPageAt(pageNo).addViewToCellLayout(
+ view, -1, mFolder.mLauncher.getViewIdForItem(item), lp, true);
+ }
+
+ @SuppressLint("InflateParams")
+ public View createNewView(ShortcutInfo item) {
+ final BubbleTextView textView = (BubbleTextView) mInflater.inflate(
+ R.layout.folder_application, null, false);
+ textView.applyFromShortcutInfo(item, mIconCache);
+ textView.setOnClickListener(mFolder);
+ textView.setOnLongClickListener(mFolder);
+ textView.setOnFocusChangeListener(mFocusIndicatorView);
+ textView.setOnKeyListener(mKeyListener);
+
+ textView.setLayoutParams(new CellLayout.LayoutParams(
+ item.cellX, item.cellY, item.spanX, item.spanY));
+ return textView;
+ }
+
+ @Override
+ public CellLayout getPageAt(int index) {
+ return (CellLayout) getChildAt(index);
+ }
+
+ public void removeCellLayoutView(View view) {
+ for (int i = getChildCount() - 1; i >= 0; i --) {
+ getPageAt(i).removeView(view);
+ }
+ }
+
+ public CellLayout getCurrentCellLayout() {
+ return getPageAt(getNextPage());
+ }
+
+ private CellLayout createAndAddNewPage() {
+ DeviceProfile grid = ((Launcher) getContext()).getDeviceProfile();
+ CellLayout page = new CellLayout(getContext());
+ page.setCellDimensions(grid.folderCellWidthPx, grid.folderCellHeightPx);
+ page.getShortcutsAndWidgets().setMotionEventSplittingEnabled(false);
+ page.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_NO);
+ page.setInvertIfRtl(true);
+ page.setGridSize(mGridCountX, mGridCountY);
+
+ addView(page, -1, generateDefaultLayoutParams());
+ return page;
+ }
+
+ @Override
+ protected int getChildGap() {
+ return getPaddingLeft() + getPaddingRight();
+ }
+
+ public void setFixedSize(int width, int height) {
+ width -= (getPaddingLeft() + getPaddingRight());
+ height -= (getPaddingTop() + getPaddingBottom());
+ for (int i = getChildCount() - 1; i >= 0; i --) {
+ ((CellLayout) getChildAt(i)).setFixedSize(width, height);
+ }
+ }
+
+ public void removeItem(View v) {
+ for (int i = getChildCount() - 1; i >= 0; i --) {
+ getPageAt(i).removeView(v);
+ }
+ }
+
+ /**
+ * Updates position and rank of all the children in the view.
+ * It essentially removes all views from all the pages and then adds them again in appropriate
+ * page.
+ *
+ * @param list the ordered list of children.
+ * @param itemCount if greater than the total children count, empty spaces are left
+ * at the end, otherwise it is ignored.
+ *
+ */
+ public void arrangeChildren(ArrayList<View> list, int itemCount) {
+ arrangeChildren(list, itemCount, true);
+ }
+
+ @SuppressLint("RtlHardcoded")
+ private void arrangeChildren(ArrayList<View> list, int itemCount, boolean saveChanges) {
+ ArrayList<CellLayout> pages = new ArrayList<CellLayout>();
+ for (int i = 0; i < getChildCount(); i++) {
+ CellLayout page = (CellLayout) getChildAt(i);
+ page.removeAllViews();
+ pages.add(page);
+ }
+ setupContentDimensions(itemCount);
+
+ Iterator<CellLayout> pageItr = pages.iterator();
+ CellLayout currentPage = null;
+
+ int position = 0;
+ int newX, newY, rank;
+
+ rank = 0;
+ for (int i = 0; i < itemCount; i++) {
+ View v = list.size() > i ? list.get(i) : null;
+ if (currentPage == null || position >= mMaxItemsPerPage) {
+ // Next page
+ if (pageItr.hasNext()) {
+ currentPage = pageItr.next();
+ } else {
+ currentPage = createAndAddNewPage();
+ }
+ position = 0;
+ }
+
+ if (v != null) {
+ CellLayout.LayoutParams lp = (CellLayout.LayoutParams) v.getLayoutParams();
+ newX = position % mGridCountX;
+ newY = position / mGridCountX;
+ ItemInfo info = (ItemInfo) v.getTag();
+ if (info.cellX != newX || info.cellY != newY || info.rank != rank) {
+ info.cellX = newX;
+ info.cellY = newY;
+ info.rank = rank;
+ if (saveChanges) {
+ LauncherModel.addOrMoveItemInDatabase(getContext(), info,
+ mFolder.mInfo.id, 0, info.cellX, info.cellY);
+ }
+ }
+ lp.cellX = info.cellX;
+ lp.cellY = info.cellY;
+ currentPage.addViewToCellLayout(
+ v, -1, mFolder.mLauncher.getViewIdForItem(info), lp, true);
+ }
+
+ rank ++;
+ position++;
+ }
+
+ // Remove extra views.
+ boolean removed = false;
+ while (pageItr.hasNext()) {
+ removeView(pageItr.next());
+ removed = true;
+ }
+ if (removed) {
+ setCurrentPage(0);
+ }
+
+ setEnableOverscroll(getPageCount() > 1);
+
+ // Update footer
+ mPageIndicator.setVisibility(getPageCount() > 1 ? View.VISIBLE : View.GONE);
+ // Set the gravity as LEFT or RIGHT instead of START, as START depends on the actual text.
+ mFolder.mFolderName.setGravity(getPageCount() > 1 ?
+ (mIsRtl ? Gravity.RIGHT : Gravity.LEFT) : Gravity.CENTER_HORIZONTAL);
+ }
+
+ public int getDesiredWidth() {
+ return getPageCount() > 0 ?
+ (getPageAt(0).getDesiredWidth() + getPaddingLeft() + getPaddingRight()) : 0;
+ }
+
+ public int getDesiredHeight() {
+ return getPageCount() > 0 ?
+ (getPageAt(0).getDesiredHeight() + getPaddingTop() + getPaddingBottom()) : 0;
+ }
+
+ public int getItemCount() {
+ int lastPageIndex = getChildCount() - 1;
+ if (lastPageIndex < 0) {
+ // If there are no pages, nothing has yet been added to the folder.
+ return 0;
+ }
+ return getPageAt(lastPageIndex).getShortcutsAndWidgets().getChildCount()
+ + lastPageIndex * mMaxItemsPerPage;
+ }
+
+ /**
+ * @return the rank of the cell nearest to the provided pixel position.
+ */
+ public int findNearestArea(int pixelX, int pixelY) {
+ int pageIndex = getNextPage();
+ CellLayout page = getPageAt(pageIndex);
+ page.findNearestArea(pixelX, pixelY, 1, 1, sTempPosArray);
+ if (mFolder.isLayoutRtl()) {
+ sTempPosArray[0] = page.getCountX() - sTempPosArray[0] - 1;
+ }
+ return Math.min(mAllocatedContentSize - 1,
+ pageIndex * mMaxItemsPerPage + sTempPosArray[1] * mGridCountX + sTempPosArray[0]);
+ }
+
+ @Override
+ protected PageMarkerResources getPageIndicatorMarker(int pageIndex) {
+ return new PageMarkerResources(R.drawable.ic_pageindicator_current_folder,
+ R.drawable.ic_pageindicator_default_folder);
+ }
+
+ public boolean isFull() {
+ return !ALLOW_FOLDER_SCROLL && getItemCount() >= mMaxItemsPerPage;
+ }
+
+ public View getLastItem() {
+ if (getChildCount() < 1) {
+ return null;
+ }
+ ShortcutAndWidgetContainer lastContainer = getCurrentCellLayout().getShortcutsAndWidgets();
+ int lastRank = lastContainer.getChildCount() - 1;
+ if (mGridCountX > 0) {
+ return lastContainer.getChildAt(lastRank % mGridCountX, lastRank / mGridCountX);
+ } else {
+ return lastContainer.getChildAt(lastRank);
+ }
+ }
+
+ /**
+ * Iterates over all its items in a reading order.
+ * @return the view for which the operator returned true.
+ */
+ public View iterateOverItems(ItemOperator op) {
+ for (int k = 0 ; k < getChildCount(); k++) {
+ CellLayout page = getPageAt(k);
+ for (int j = 0; j < page.getCountY(); j++) {
+ for (int i = 0; i < page.getCountX(); i++) {
+ View v = page.getChildAt(i, j);
+ if ((v != null) && op.evaluate((ItemInfo) v.getTag(), v, this)) {
+ return v;
+ }
+ }
+ }
+ }
+ return null;
+ }
+
+ public String getAccessibilityDescription() {
+ return String.format(getContext().getString(R.string.folder_opened),
+ mGridCountX, mGridCountY);
+ }
+
+ /**
+ * Sets the focus on the first visible child.
+ */
+ public void setFocusOnFirstChild() {
+ View firstChild = getCurrentCellLayout().getChildAt(0, 0);
+ if (firstChild != null) {
+ firstChild.requestFocus();
+ }
+ }
+
+ @Override
+ protected void notifyPageSwitchListener() {
+ super.notifyPageSwitchListener();
+ if (mFolder != null) {
+ mFolder.updateTextViewFocus();
+ }
+ }
+
+ /**
+ * Scrolls the current view by a fraction
+ */
+ public void showScrollHint(int direction) {
+ float fraction = (direction == DragController.SCROLL_LEFT) ^ mIsRtl
+ ? -SCROLL_HINT_FRACTION : SCROLL_HINT_FRACTION;
+ int hint = (int) (fraction * getWidth());
+ int scroll = getScrollForPage(getNextPage()) + hint;
+ int delta = scroll - getScrollX();
+ if (delta != 0) {
+ mScroller.setInterpolator(new DecelerateInterpolator());
+ mScroller.startScroll(getScrollX(), 0, delta, 0, Folder.SCROLL_HINT_DURATION);
+ invalidate();
+ }
+ }
+
+ public void clearScrollHint() {
+ if (getScrollX() != getScrollForPage(getNextPage())) {
+ snapToPage(getNextPage());
+ }
+ }
+
+ /**
+ * Finish animation all the views which are animating across pages
+ */
+ public void completePendingPageChanges() {
+ if (!mPendingAnimations.isEmpty()) {
+ HashMap<View, Runnable> pendingViews = new HashMap<>(mPendingAnimations);
+ for (Map.Entry<View, Runnable> e : pendingViews.entrySet()) {
+ e.getKey().animate().cancel();
+ e.getValue().run();
+ }
+ }
+ }
+
+ public boolean rankOnCurrentPage(int rank) {
+ int p = rank / mMaxItemsPerPage;
+ return p == getNextPage();
+ }
+
+ @Override
+ protected void onPageBeginMoving() {
+ super.onPageBeginMoving();
+ getVisiblePages(sTempPosArray);
+ for (int i = sTempPosArray[0]; i <= sTempPosArray[1]; i++) {
+ verifyVisibleHighResIcons(i);
+ }
+ }
+
+ /**
+ * Ensures that all the icons on the given page are of high-res
+ */
+ public void verifyVisibleHighResIcons(int pageNo) {
+ CellLayout page = getPageAt(pageNo);
+ if (page != null) {
+ ShortcutAndWidgetContainer parent = page.getShortcutsAndWidgets();
+ for (int i = parent.getChildCount() - 1; i >= 0; i--) {
+ ((BubbleTextView) parent.getChildAt(i)).verifyHighRes();
+ }
+ }
+ }
+
+ public int getAllocatedContentSize() {
+ return mAllocatedContentSize;
+ }
+
+ /**
+ * Reorders the items such that the {@param empty} spot moves to {@param target}
+ */
+ public void realTimeReorder(int empty, int target) {
+ completePendingPageChanges();
+ int delay = 0;
+ float delayAmount = START_VIEW_REORDER_DELAY;
+
+ // Animation only happens on the current page.
+ int pageToAnimate = getNextPage();
+
+ int pageT = target / mMaxItemsPerPage;
+ int pagePosT = target % mMaxItemsPerPage;
+
+ if (pageT != pageToAnimate) {
+ Log.e(TAG, "Cannot animate when the target cell is invisible");
+ }
+ int pagePosE = empty % mMaxItemsPerPage;
+ int pageE = empty / mMaxItemsPerPage;
+
+ int startPos, endPos;
+ int moveStart, moveEnd;
+ int direction;
+
+ if (target == empty) {
+ // No animation
+ return;
+ } else if (target > empty) {
+ // Items will move backwards to make room for the empty cell.
+ direction = 1;
+
+ // If empty cell is in a different page, move them instantly.
+ if (pageE < pageToAnimate) {
+ moveStart = empty;
+ // Instantly move the first item in the current page.
+ moveEnd = pageToAnimate * mMaxItemsPerPage;
+ // Animate the 2nd item in the current page, as the first item was already moved to
+ // the last page.
+ startPos = 0;
+ } else {
+ moveStart = moveEnd = -1;
+ startPos = pagePosE;
+ }
+
+ endPos = pagePosT;
+ } else {
+ // The items will move forward.
+ direction = -1;
+
+ if (pageE > pageToAnimate) {
+ // Move the items immediately.
+ moveStart = empty;
+ // Instantly move the last item in the current page.
+ moveEnd = (pageToAnimate + 1) * mMaxItemsPerPage - 1;
+
+ // Animations start with the second last item in the page
+ startPos = mMaxItemsPerPage - 1;
+ } else {
+ moveStart = moveEnd = -1;
+ startPos = pagePosE;
+ }
+
+ endPos = pagePosT;
+ }
+
+ // Instant moving views.
+ while (moveStart != moveEnd) {
+ int rankToMove = moveStart + direction;
+ int p = rankToMove / mMaxItemsPerPage;
+ int pagePos = rankToMove % mMaxItemsPerPage;
+ int x = pagePos % mGridCountX;
+ int y = pagePos / mGridCountX;
+
+ final CellLayout page = getPageAt(p);
+ final View v = page.getChildAt(x, y);
+ if (v != null) {
+ if (pageToAnimate != p) {
+ page.removeView(v);
+ addViewForRank(v, (ShortcutInfo) v.getTag(), moveStart);
+ } else {
+ // Do a fake animation before removing it.
+ final int newRank = moveStart;
+ final float oldTranslateX = v.getTranslationX();
+
+ Runnable endAction = new Runnable() {
+
+ @Override
+ public void run() {
+ mPendingAnimations.remove(v);
+ v.setTranslationX(oldTranslateX);
+ ((CellLayout) v.getParent().getParent()).removeView(v);
+ addViewForRank(v, (ShortcutInfo) v.getTag(), newRank);
+ }
+ };
+ v.animate()
+ .translationXBy((direction > 0 ^ mIsRtl) ? -v.getWidth() : v.getWidth())
+ .setDuration(REORDER_ANIMATION_DURATION)
+ .setStartDelay(0)
+ .withEndAction(endAction);
+ mPendingAnimations.put(v, endAction);
+ }
+ }
+ moveStart = rankToMove;
+ }
+
+ if ((endPos - startPos) * direction <= 0) {
+ // No animation
+ return;
+ }
+
+ CellLayout page = getPageAt(pageToAnimate);
+ for (int i = startPos; i != endPos; i += direction) {
+ int nextPos = i + direction;
+ View v = page.getChildAt(nextPos % mGridCountX, nextPos / mGridCountX);
+ if (v != null) {
+ ((ItemInfo) v.getTag()).rank -= direction;
+ }
+ if (page.animateChildToPosition(v, i % mGridCountX, i / mGridCountX,
+ REORDER_ANIMATION_DURATION, delay, true, true)) {
+ delay += delayAmount;
+ delayAmount *= VIEW_REORDER_DELAY_FACTOR;
+ }
+ }
+ }
+
+ public void setMarkerScale(float scale) {
+ int count = mPageIndicator.getChildCount();
+ for (int i = 0; i < count; i++) {
+ View marker = mPageIndicator.getChildAt(i);
+ marker.animate().cancel();
+ marker.setScaleX(scale);
+ marker.setScaleY(scale);
+ }
+ }
+
+ public void animateMarkers() {
+ int count = mPageIndicator.getChildCount();
+ Interpolator interpolator = new OvershootInterpolator(PAGE_INDICATOR_OVERSHOOT_TENSION);
+ for (int i = 0; i < count; i++) {
+ mPageIndicator.getChildAt(i).animate().scaleX(1).scaleY(1)
+ .setInterpolator(interpolator)
+ .setDuration(PAGE_INDICATOR_ANIMATION_DURATION)
+ .setStartDelay(PAGE_INDICATOR_ANIMATION_STAGGERED_DELAY * i
+ + PAGE_INDICATOR_ANIMATION_START_DELAY);
+ }
+ }
+
+ public int itemsPerPage() {
+ return mMaxItemsPerPage;
+ }
+
+ @Override
+ protected void getEdgeVerticalPostion(int[] pos) {
+ pos[0] = 0;
+ pos[1] = getViewportHeight();
+ }
+}
diff --git a/src/com/android/launcher3/HolographicOutlineHelper.java b/src/com/android/launcher3/HolographicOutlineHelper.java
index b1e0e68a4..5ff85d664 100644
--- a/src/com/android/launcher3/HolographicOutlineHelper.java
+++ b/src/com/android/launcher3/HolographicOutlineHelper.java
@@ -17,6 +17,7 @@
package com.android.launcher3;
import android.content.Context;
+import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BlurMaskFilter;
import android.graphics.Canvas;
@@ -25,11 +26,16 @@ import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
-import android.graphics.Region.Op;
+import android.graphics.drawable.Drawable;
+import android.util.SparseArray;
+/**
+ * Utility class to generate shadow and outline effect, which are used for click feedback
+ * and drag-n-drop respectively.
+ */
public class HolographicOutlineHelper {
- private static final Rect sTempRect = new Rect();
+ private static HolographicOutlineHelper sInstance;
private final Canvas mCanvas = new Canvas();
private final Paint mDrawPaint = new Paint();
@@ -40,26 +46,23 @@ public class HolographicOutlineHelper {
private final BlurMaskFilter mThinOuterBlurMaskFilter;
private final BlurMaskFilter mMediumInnerBlurMaskFilter;
- private final BlurMaskFilter mShaowBlurMaskFilter;
- private final int mShadowOffset;
-
- /**
- * Padding used when creating shadow bitmap;
- */
- final int shadowBitmapPadding;
+ private final BlurMaskFilter mShadowBlurMaskFilter;
- static HolographicOutlineHelper INSTANCE;
+ // We have 4 different icon sizes: homescreen, hotseat, folder & all-apps
+ private final SparseArray<Bitmap> mBitmapCache = new SparseArray<>(4);
private HolographicOutlineHelper(Context context) {
- final float scale = LauncherAppState.getInstance().getScreenDensity();
+ Resources res = context.getResources();
+
+ float mediumBlur = res.getDimension(R.dimen.blur_size_medium_outline);
+ mMediumOuterBlurMaskFilter = new BlurMaskFilter(mediumBlur, BlurMaskFilter.Blur.OUTER);
+ mMediumInnerBlurMaskFilter = new BlurMaskFilter(mediumBlur, BlurMaskFilter.Blur.NORMAL);
- mMediumOuterBlurMaskFilter = new BlurMaskFilter(scale * 2.0f, BlurMaskFilter.Blur.OUTER);
- mThinOuterBlurMaskFilter = new BlurMaskFilter(scale * 1.0f, BlurMaskFilter.Blur.OUTER);
- mMediumInnerBlurMaskFilter = new BlurMaskFilter(scale * 2.0f, BlurMaskFilter.Blur.NORMAL);
+ mThinOuterBlurMaskFilter = new BlurMaskFilter(
+ res.getDimension(R.dimen.blur_size_thin_outline), BlurMaskFilter.Blur.OUTER);
- mShaowBlurMaskFilter = new BlurMaskFilter(scale * 4.0f, BlurMaskFilter.Blur.NORMAL);
- mShadowOffset = (int) (scale * 2.0f);
- shadowBitmapPadding = (int) (scale * 4.0f);
+ mShadowBlurMaskFilter = new BlurMaskFilter(
+ res.getDimension(R.dimen.blur_size_click_shadow), BlurMaskFilter.Blur.NORMAL);
mDrawPaint.setFilterBitmap(true);
mDrawPaint.setAntiAlias(true);
@@ -71,10 +74,10 @@ public class HolographicOutlineHelper {
}
public static HolographicOutlineHelper obtain(Context context) {
- if (INSTANCE == null) {
- INSTANCE = new HolographicOutlineHelper(context);
+ if (sInstance == null) {
+ sInstance = new HolographicOutlineHelper(context);
}
- return INSTANCE;
+ return sInstance;
}
/**
@@ -153,51 +156,34 @@ public class HolographicOutlineHelper {
}
Bitmap createMediumDropShadow(BubbleTextView view) {
- final Bitmap result = Bitmap.createBitmap(
- view.getWidth() + shadowBitmapPadding + shadowBitmapPadding,
- view.getHeight() + shadowBitmapPadding + shadowBitmapPadding + mShadowOffset,
- Bitmap.Config.ARGB_8888);
-
- mCanvas.setBitmap(result);
-
- final Rect clipRect = sTempRect;
- view.getDrawingRect(sTempRect);
- // adjust the clip rect so that we don't include the text label
- clipRect.bottom = view.getExtendedPaddingTop() - (int) BubbleTextView.PADDING_V
- + view.getLayout().getLineTop(0);
-
- // Draw the View into the bitmap.
- // The translate of scrollX and scrollY is necessary when drawing TextViews, because
- // they set scrollX and scrollY to large values to achieve centered text
- mCanvas.save();
- mCanvas.scale(view.getScaleX(), view.getScaleY(),
- view.getWidth() / 2 + shadowBitmapPadding,
- view.getHeight() / 2 + shadowBitmapPadding);
- mCanvas.translate(-view.getScrollX() + shadowBitmapPadding,
- -view.getScrollY() + shadowBitmapPadding);
- mCanvas.clipRect(clipRect, Op.REPLACE);
- view.draw(mCanvas);
- mCanvas.restore();
-
- int[] blurOffst = new int[2];
- mBlurPaint.setMaskFilter(mShaowBlurMaskFilter);
- Bitmap blurBitmap = result.extractAlpha(mBlurPaint, blurOffst);
-
- mCanvas.save();
- mCanvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
- mCanvas.translate(blurOffst[0], blurOffst[1]);
-
- mDrawPaint.setColor(Color.BLACK);
- mDrawPaint.setAlpha(30);
- mCanvas.drawBitmap(blurBitmap, 0, 0, mDrawPaint);
+ Drawable icon = view.getIcon();
+ if (icon == null) {
+ return null;
+ }
+ Rect rect = icon.getBounds();
+
+ int bitmapWidth = (int) (rect.width() * view.getScaleX());
+ int bitmapHeight = (int) (rect.height() * view.getScaleY());
+
+ int key = (bitmapWidth << 16) | bitmapHeight;
+ Bitmap cache = mBitmapCache.get(key);
+ if (cache == null) {
+ cache = Bitmap.createBitmap(bitmapWidth, bitmapHeight, Bitmap.Config.ARGB_8888);
+ mCanvas.setBitmap(cache);
+ mBitmapCache.put(key, cache);
+ } else {
+ mCanvas.setBitmap(cache);
+ mCanvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
+ }
- mDrawPaint.setAlpha(60);
- mCanvas.drawBitmap(blurBitmap, 0, mShadowOffset, mDrawPaint);
+ mCanvas.save(Canvas.MATRIX_SAVE_FLAG);
+ mCanvas.scale(view.getScaleX(), view.getScaleY());
+ mCanvas.translate(-rect.left, -rect.top);
+ icon.draw(mCanvas);
mCanvas.restore();
-
mCanvas.setBitmap(null);
- blurBitmap.recycle();
- return result;
+ mBlurPaint.setMaskFilter(mShadowBlurMaskFilter);
+ return cache.extractAlpha(mBlurPaint, null);
}
}
diff --git a/src/com/android/launcher3/Hotseat.java b/src/com/android/launcher3/Hotseat.java
index b08272f36..17fdeb1dc 100644
--- a/src/com/android/launcher3/Hotseat.java
+++ b/src/com/android/launcher3/Hotseat.java
@@ -16,24 +16,19 @@
package com.android.launcher3;
-import android.content.ComponentName;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
-import android.graphics.Rect;
import android.graphics.drawable.Drawable;
+import android.os.Bundle;
import android.util.AttributeSet;
-import android.util.Log;
import android.view.LayoutInflater;
import android.view.MotionEvent;
-import android.view.View;
import android.widget.FrameLayout;
import android.widget.TextView;
-import java.util.ArrayList;
-
-public class Hotseat extends FrameLayout {
- private static final String TAG = "Hotseat";
+public class Hotseat extends FrameLayout
+ implements Stats.LaunchSourceProvider{
private CellLayout mContent;
@@ -41,8 +36,7 @@ public class Hotseat extends FrameLayout {
private int mAllAppsButtonRank;
- private boolean mTransposeLayoutWithOrientation;
- private boolean mIsLandscape;
+ private final boolean mHasVerticalHotseat;
public Hotseat(Context context) {
this(context, null);
@@ -54,16 +48,8 @@ public class Hotseat extends FrameLayout {
public Hotseat(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
-
- Resources r = context.getResources();
- mTransposeLayoutWithOrientation =
- r.getBoolean(R.bool.hotseat_transpose_layout_with_orientation);
- mIsLandscape = context.getResources().getConfiguration().orientation ==
- Configuration.ORIENTATION_LANDSCAPE;
- }
-
- public void setup(Launcher launcher) {
- mLauncher = launcher;
+ mLauncher = (Launcher) context;
+ mHasVerticalHotseat = mLauncher.getDeviceProfile().isVerticalBarLayout();
}
CellLayout getLayout() {
@@ -71,6 +57,13 @@ public class Hotseat extends FrameLayout {
}
/**
+ * Returns whether there are other icons than the all apps button in the hotseat.
+ */
+ public boolean hasIcons() {
+ return mContent.getShortcutsAndWidgets().getChildCount() > 1;
+ }
+
+ /**
* Registers the specified listener on the cell layout of the hotseat.
*/
@Override
@@ -78,60 +71,35 @@ public class Hotseat extends FrameLayout {
mContent.setOnLongClickListener(l);
}
- private boolean hasVerticalHotseat() {
- return (mIsLandscape && mTransposeLayoutWithOrientation);
- }
-
/* Get the orientation invariant order of the item in the hotseat for persistence. */
int getOrderInHotseat(int x, int y) {
- return hasVerticalHotseat() ? (mContent.getCountY() - y - 1) : x;
+ return mHasVerticalHotseat ? (mContent.getCountY() - y - 1) : x;
}
+
/* Get the orientation specific coordinates given an invariant order in the hotseat. */
int getCellXFromOrder(int rank) {
- return hasVerticalHotseat() ? 0 : rank;
+ return mHasVerticalHotseat ? 0 : rank;
}
+
int getCellYFromOrder(int rank) {
- return hasVerticalHotseat() ? (mContent.getCountY() - (rank + 1)) : 0;
- }
- public boolean isAllAppsButtonRank(int rank) {
- if (LauncherAppState.isDisableAllApps()) {
- return false;
- } else {
- return rank == mAllAppsButtonRank;
- }
+ return mHasVerticalHotseat ? (mContent.getCountY() - (rank + 1)) : 0;
}
- /** This returns the coordinates of an app in a given cell, relative to the DragLayer */
- Rect getCellCoordinates(int cellX, int cellY) {
- Rect coords = new Rect();
- mContent.cellToRect(cellX, cellY, 1, 1, coords);
- int[] hotseatInParent = new int[2];
- Utilities.getDescendantCoordRelativeToParent(this, mLauncher.getDragLayer(),
- hotseatInParent, false);
- coords.offset(hotseatInParent[0], hotseatInParent[1]);
-
- // Center the icon
- int cWidth = mContent.getShortcutsAndWidgets().getCellContentWidth();
- int cHeight = mContent.getShortcutsAndWidgets().getCellContentHeight();
- int cellPaddingX = (int) Math.max(0, ((coords.width() - cWidth) / 2f));
- int cellPaddingY = (int) Math.max(0, ((coords.height() - cHeight) / 2f));
- coords.offset(cellPaddingX, cellPaddingY);
-
- return coords;
+ public boolean isAllAppsButtonRank(int rank) {
+ return rank == mAllAppsButtonRank;
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
- LauncherAppState app = LauncherAppState.getInstance();
- DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
+ DeviceProfile grid = mLauncher.getDeviceProfile();
- mAllAppsButtonRank = grid.hotseatAllAppsRank;
+ mAllAppsButtonRank = grid.inv.hotseatAllAppsRank;
mContent = (CellLayout) findViewById(R.id.layout);
- if (grid.isLandscape && !grid.isLargeTablet()) {
- mContent.setGridSize(1, (int) grid.numHotseatIcons);
+ if (grid.isLandscape && !grid.isLargeTablet) {
+ mContent.setGridSize(1, (int) grid.inv.numHotseatIcons);
} else {
- mContent.setGridSize((int) grid.numHotseatIcons, 1);
+ mContent.setGridSize((int) grid.inv.numHotseatIcons, 1);
}
mContent.setIsHotseat(true);
@@ -141,35 +109,34 @@ public class Hotseat extends FrameLayout {
void resetLayout() {
mContent.removeAllViewsInLayout();
- if (!LauncherAppState.isDisableAllApps()) {
- // Add the Apps button
- Context context = getContext();
-
- LayoutInflater inflater = LayoutInflater.from(context);
- TextView allAppsButton = (TextView)
- inflater.inflate(R.layout.all_apps_button, mContent, false);
- Drawable d = context.getResources().getDrawable(R.drawable.all_apps_button_icon);
-
- Utilities.resizeIconDrawable(d);
- allAppsButton.setCompoundDrawables(null, d, null, null);
-
- allAppsButton.setContentDescription(context.getString(R.string.all_apps_button_label));
- allAppsButton.setOnKeyListener(new HotseatIconKeyEventListener());
- if (mLauncher != null) {
- allAppsButton.setOnTouchListener(mLauncher.getHapticFeedbackTouchListener());
- mLauncher.setAllAppsButton(allAppsButton);
- allAppsButton.setOnClickListener(mLauncher);
- allAppsButton.setOnFocusChangeListener(mLauncher.mFocusHandler);
- }
-
- // Note: We do this to ensure that the hotseat is always laid out in the orientation of
- // the hotseat in order regardless of which orientation they were added
- int x = getCellXFromOrder(mAllAppsButtonRank);
- int y = getCellYFromOrder(mAllAppsButtonRank);
- CellLayout.LayoutParams lp = new CellLayout.LayoutParams(x,y,1,1);
- lp.canReorder = false;
- mContent.addViewToCellLayout(allAppsButton, -1, allAppsButton.getId(), lp, true);
+ // Add the Apps button
+ Context context = getContext();
+
+ LayoutInflater inflater = LayoutInflater.from(context);
+ TextView allAppsButton = (TextView)
+ inflater.inflate(R.layout.all_apps_button, mContent, false);
+ Drawable d = context.getResources().getDrawable(R.drawable.all_apps_button_icon);
+
+ mLauncher.resizeIconDrawable(d);
+ allAppsButton.setCompoundDrawables(null, d, null, null);
+
+ allAppsButton.setContentDescription(context.getString(R.string.all_apps_button_label));
+ allAppsButton.setOnKeyListener(new HotseatIconKeyEventListener());
+ if (mLauncher != null) {
+ mLauncher.setAllAppsButton(allAppsButton);
+ allAppsButton.setOnTouchListener(mLauncher.getHapticFeedbackTouchListener());
+ allAppsButton.setOnClickListener(mLauncher);
+ allAppsButton.setOnLongClickListener(mLauncher);
+ allAppsButton.setOnFocusChangeListener(mLauncher.mFocusHandler);
}
+
+ // Note: We do this to ensure that the hotseat is always laid out in the orientation of
+ // the hotseat in order regardless of which orientation they were added
+ int x = getCellXFromOrder(mAllAppsButtonRank);
+ int y = getCellYFromOrder(mAllAppsButtonRank);
+ CellLayout.LayoutParams lp = new CellLayout.LayoutParams(x,y,1,1);
+ lp.canReorder = false;
+ mContent.addViewToCellLayout(allAppsButton, -1, allAppsButton.getId(), lp, true);
}
@Override
@@ -182,54 +149,8 @@ public class Hotseat extends FrameLayout {
return false;
}
- void addAllAppsFolder(IconCache iconCache,
- ArrayList<AppInfo> allApps, ArrayList<ComponentName> onWorkspace,
- Launcher launcher, Workspace workspace) {
- if (LauncherAppState.isDisableAllApps()) {
- FolderInfo fi = new FolderInfo();
-
- fi.cellX = getCellXFromOrder(mAllAppsButtonRank);
- fi.cellY = getCellYFromOrder(mAllAppsButtonRank);
- fi.spanX = 1;
- fi.spanY = 1;
- fi.container = LauncherSettings.Favorites.CONTAINER_HOTSEAT;
- fi.screenId = mAllAppsButtonRank;
- fi.itemType = LauncherSettings.Favorites.ITEM_TYPE_FOLDER;
- fi.title = "More Apps";
- LauncherModel.addItemToDatabase(launcher, fi, fi.container, fi.screenId, fi.cellX,
- fi.cellY, false);
- FolderIcon folder = FolderIcon.fromXml(R.layout.folder_icon, launcher,
- getLayout(), fi, iconCache);
- workspace.addInScreen(folder, fi.container, fi.screenId, fi.cellX, fi.cellY,
- fi.spanX, fi.spanY);
-
- for (AppInfo info: allApps) {
- ComponentName cn = info.intent.getComponent();
- if (!onWorkspace.contains(cn)) {
- Log.d(TAG, "Adding to 'more apps': " + info.intent);
- ShortcutInfo si = info.makeShortcut();
- fi.add(si);
- }
- }
- }
- }
-
- void addAppsToAllAppsFolder(ArrayList<AppInfo> apps) {
- if (LauncherAppState.isDisableAllApps()) {
- View v = mContent.getChildAt(getCellXFromOrder(mAllAppsButtonRank), getCellYFromOrder(mAllAppsButtonRank));
- FolderIcon fi = null;
-
- if (v instanceof FolderIcon) {
- fi = (FolderIcon) v;
- } else {
- return;
- }
-
- FolderInfo info = fi.getFolderInfo();
- for (AppInfo a: apps) {
- ShortcutInfo si = a.makeShortcut();
- info.add(si);
- }
- }
+ @Override
+ public void fillInLaunchSourceData(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 5a0875b30..916418f18 100644
--- a/src/com/android/launcher3/IconCache.java
+++ b/src/com/android/launcher3/IconCache.java
@@ -16,19 +16,28 @@
package com.android.launcher3;
-import android.app.ActivityManager;
import android.content.ComponentName;
+import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.Resources;
+import android.database.Cursor;
+import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteOpenHelper;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.Rect;
import android.graphics.drawable.Drawable;
+import android.os.Handler;
+import android.os.SystemClock;
import android.text.TextUtils;
import android.util.Log;
@@ -36,17 +45,17 @@ import com.android.launcher3.compat.LauncherActivityInfoCompat;
import com.android.launcher3.compat.LauncherAppsCompat;
import com.android.launcher3.compat.UserHandleCompat;
import com.android.launcher3.compat.UserManagerCompat;
+import com.android.launcher3.model.PackageItemInfo;
+import com.android.launcher3.util.ComponentKey;
+import com.android.launcher3.util.Thunk;
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
+import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
-import java.util.Iterator;
-import java.util.Map.Entry;
+import java.util.List;
+import java.util.Locale;
+import java.util.Set;
+import java.util.Stack;
/**
* Cache of application icons. Icons can be made from any thread.
@@ -56,66 +65,71 @@ public class IconCache {
private static final String TAG = "Launcher.IconCache";
private static final int INITIAL_ICON_CACHE_CAPACITY = 50;
- private static final String RESOURCE_FILE_PREFIX = "icon_";
// Empty class name is used for storing package default entry.
private static final String EMPTY_CLASS_NAME = ".";
private static final boolean DEBUG = false;
- private static class CacheEntry {
- public Bitmap icon;
- public CharSequence title;
- public CharSequence contentDescription;
- }
-
- private static class CacheKey {
- public ComponentName componentName;
- public UserHandleCompat user;
+ private static final int LOW_RES_SCALE_FACTOR = 5;
- CacheKey(ComponentName componentName, UserHandleCompat user) {
- this.componentName = componentName;
- this.user = user;
- }
+ @Thunk static final Object ICON_UPDATE_TOKEN = new Object();
- @Override
- public int hashCode() {
- return componentName.hashCode() + user.hashCode();
- }
-
- @Override
- public boolean equals(Object o) {
- CacheKey other = (CacheKey) o;
- return other.componentName.equals(componentName) && other.user.equals(user);
- }
+ @Thunk static class CacheEntry {
+ public Bitmap icon;
+ public CharSequence title = "";
+ public CharSequence contentDescription = "";
+ public boolean isLowResIcon;
}
- private final HashMap<UserHandleCompat, Bitmap> mDefaultIcons =
- new HashMap<UserHandleCompat, Bitmap>();
+ private final HashMap<UserHandleCompat, Bitmap> mDefaultIcons = new HashMap<>();
+ @Thunk final MainThreadExecutor mMainThreadExecutor = new MainThreadExecutor();
+
private final Context mContext;
private final PackageManager mPackageManager;
- private final UserManagerCompat mUserManager;
+ @Thunk final UserManagerCompat mUserManager;
private final LauncherAppsCompat mLauncherApps;
- private final HashMap<CacheKey, CacheEntry> mCache =
- new HashMap<CacheKey, CacheEntry>(INITIAL_ICON_CACHE_CAPACITY);
- private int mIconDpi;
-
- public IconCache(Context context) {
- ActivityManager activityManager =
- (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
-
+ private final HashMap<ComponentKey, CacheEntry> mCache =
+ new HashMap<ComponentKey, CacheEntry>(INITIAL_ICON_CACHE_CAPACITY);
+ private final int mIconDpi;
+ @Thunk final IconDB mIconDb;
+
+ @Thunk final Handler mWorkerHandler;
+
+ // The background color used for activity icons. Since these icons are displayed in all-apps
+ // and folders, this would be same as the light quantum panel background. This color
+ // is used to convert icons to RGB_565.
+ private final int mActivityBgColor;
+ // The background color used for package icons. These are displayed in widget tray, which
+ // has a dark quantum panel background.
+ private final int mPackageBgColor;
+ private final BitmapFactory.Options mLowResOptions;
+
+ private String mSystemState;
+ private Bitmap mLowResBitmap;
+ private Canvas mLowResCanvas;
+ private Paint mLowResPaint;
+
+ public IconCache(Context context, InvariantDeviceProfile inv) {
mContext = context;
mPackageManager = context.getPackageManager();
mUserManager = UserManagerCompat.getInstance(mContext);
mLauncherApps = LauncherAppsCompat.getInstance(mContext);
- mIconDpi = activityManager.getLauncherLargeIconDensity();
-
- // need to set mIconDpi before getting default icon
- UserHandleCompat myUser = UserHandleCompat.myUserHandle();
- mDefaultIcons.put(myUser, makeDefaultIcon(myUser));
+ mIconDpi = inv.fillResIconDpi;
+ mIconDb = new IconDB(context);
+
+ mWorkerHandler = new Handler(LauncherModel.getWorkerLooper());
+
+ mActivityBgColor = context.getResources().getColor(R.color.quantum_panel_bg_color);
+ mPackageBgColor = context.getResources().getColor(R.color.quantum_panel_bg_color_dark);
+ mLowResOptions = new BitmapFactory.Options();
+ // Always prefer RGB_565 config for low res. If the bitmap has transparency, it will
+ // automatically be loaded as ALPHA_8888.
+ mLowResOptions.inPreferredConfig = Bitmap.Config.RGB_565;
+ updateSystemStateString();
}
- public Drawable getFullResDefaultActivityIcon() {
+ private Drawable getFullResDefaultActivityIcon() {
return getFullResIcon(Resources.getSystem(), android.R.mipmap.sym_def_app_icon);
}
@@ -145,10 +159,6 @@ public class IconCache {
return getFullResDefaultActivityIcon();
}
- public int getFullResIconDpi() {
- return mIconDpi;
- }
-
public Drawable getFullResIcon(ActivityInfo info) {
Resources resources;
try {
@@ -184,59 +194,269 @@ public class IconCache {
* Remove any records for the supplied ComponentName.
*/
public synchronized void remove(ComponentName componentName, UserHandleCompat user) {
- mCache.remove(new CacheKey(componentName, user));
+ mCache.remove(new ComponentKey(componentName, user));
}
/**
- * Remove any records for the supplied package name.
+ * Remove any records for the supplied package name from memory.
*/
- public synchronized void remove(String packageName, UserHandleCompat user) {
- HashSet<CacheKey> forDeletion = new HashSet<CacheKey>();
- for (CacheKey key: mCache.keySet()) {
+ private void removeFromMemCacheLocked(String packageName, UserHandleCompat user) {
+ HashSet<ComponentKey> forDeletion = new HashSet<ComponentKey>();
+ for (ComponentKey key: mCache.keySet()) {
if (key.componentName.getPackageName().equals(packageName)
&& key.user.equals(user)) {
forDeletion.add(key);
}
}
- for (CacheKey condemned: forDeletion) {
+ for (ComponentKey condemned: forDeletion) {
mCache.remove(condemned);
}
}
/**
- * Empty out the cache.
+ * Updates the entries related to the given package in memory and persistent DB.
*/
- public synchronized void flush() {
- mCache.clear();
+ public synchronized void updateIconsForPkg(String packageName, UserHandleCompat user) {
+ removeIconsForPkg(packageName, user);
+ try {
+ PackageInfo info = mPackageManager.getPackageInfo(packageName,
+ PackageManager.GET_UNINSTALLED_PACKAGES);
+ long userSerial = mUserManager.getSerialNumberForUser(user);
+ for (LauncherActivityInfoCompat app : mLauncherApps.getActivityList(packageName, user)) {
+ addIconToDBAndMemCache(app, info, userSerial);
+ }
+ } catch (NameNotFoundException e) {
+ Log.d(TAG, "Package not found", e);
+ return;
+ }
}
/**
- * Empty out the cache that aren't of the correct grid size
+ * Removes the entries related to the given package in memory and persistent DB.
*/
- public synchronized void flushInvalidIcons(DeviceProfile grid) {
- Iterator<Entry<CacheKey, CacheEntry>> it = mCache.entrySet().iterator();
- while (it.hasNext()) {
- final CacheEntry e = it.next().getValue();
- if ((e.icon != null) && (e.icon.getWidth() < grid.iconSizePx
- || e.icon.getHeight() < grid.iconSizePx)) {
- it.remove();
+ public synchronized void removeIconsForPkg(String packageName, UserHandleCompat user) {
+ removeFromMemCacheLocked(packageName, user);
+ long userSerial = mUserManager.getSerialNumberForUser(user);
+ mIconDb.getWritableDatabase().delete(IconDB.TABLE_NAME,
+ IconDB.COLUMN_COMPONENT + " LIKE ? AND " + IconDB.COLUMN_USER + " = ?",
+ new String[] {packageName + "/%", Long.toString(userSerial)});
+ }
+
+ public void updateDbIcons(Set<String> ignorePackagesForMainUser) {
+ // Remove all active icon update tasks.
+ mWorkerHandler.removeCallbacksAndMessages(ICON_UPDATE_TOKEN);
+
+ updateSystemStateString();
+ for (UserHandleCompat user : mUserManager.getUserProfiles()) {
+ // Query for the set of apps
+ final List<LauncherActivityInfoCompat> apps = mLauncherApps.getActivityList(null, user);
+ // Fail if we don't have any apps
+ // TODO: Fix this. Only fail for the current user.
+ if (apps == null || apps.isEmpty()) {
+ return;
}
+
+ // Update icon cache. This happens in segments and {@link #onPackageIconsUpdated}
+ // is called by the icon cache when the job is complete.
+ updateDBIcons(user, apps, UserHandleCompat.myUserHandle().equals(user)
+ ? ignorePackagesForMainUser : Collections.<String>emptySet());
}
}
/**
- * Fill in "application" with the icon and label for "info."
+ * Updates the persistent DB, such that only entries corresponding to {@param apps} remain in
+ * the DB and are updated.
+ * @return The set of packages for which icons have updated.
+ */
+ private void updateDBIcons(UserHandleCompat user, List<LauncherActivityInfoCompat> apps,
+ Set<String> ignorePackages) {
+ long userSerial = mUserManager.getSerialNumberForUser(user);
+ PackageManager pm = mContext.getPackageManager();
+ HashMap<String, PackageInfo> pkgInfoMap = new HashMap<String, PackageInfo>();
+ for (PackageInfo info : pm.getInstalledPackages(PackageManager.GET_UNINSTALLED_PACKAGES)) {
+ pkgInfoMap.put(info.packageName, info);
+ }
+
+ HashMap<ComponentName, LauncherActivityInfoCompat> componentMap = new HashMap<>();
+ for (LauncherActivityInfoCompat app : apps) {
+ 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())) {
+ 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);
+ }
+ }
+ c.close();
+ if (!itemsToRemove.isEmpty()) {
+ mIconDb.getWritableDatabase().delete(IconDB.TABLE_NAME,
+ Utilities.createDbSelectionQuery(IconDB.COLUMN_ROWID, itemsToRemove),
+ null);
+ }
+
+ // Insert remaining apps.
+ if (!componentMap.isEmpty() || !appsToUpdate.isEmpty()) {
+ Stack<LauncherActivityInfoCompat> appsToAdd = new Stack<>();
+ appsToAdd.addAll(componentMap.values());
+ new SerializedIconUpdateTask(userSerial, pkgInfoMap,
+ appsToAdd, appsToUpdate).scheduleNext();
+ }
+ }
+
+ @Thunk void addIconToDBAndMemCache(LauncherActivityInfoCompat app, PackageInfo info,
+ long userSerial) {
+ // Reuse the existing entry if it already exists in the DB. This ensures that we do not
+ // create bitmap if it was already created during loader.
+ ContentValues values = updateCacheAndGetContentValues(app, false);
+ addIconToDB(values, app.getComponentName(), info, userSerial);
+ }
+
+ /**
+ * Updates {@param values} to contain versoning information and adds it to the DB.
+ * @param values {@link ContentValues} containing icon & title
*/
- public synchronized void getTitleAndIcon(AppInfo application, LauncherActivityInfoCompat info,
- HashMap<Object, CharSequence> labelCache) {
- CacheEntry entry = cacheLocked(application.componentName, info, labelCache,
- info.getUser(), false);
+ private void addIconToDB(ContentValues values, ComponentName key,
+ PackageInfo info, long userSerial) {
+ values.put(IconDB.COLUMN_COMPONENT, key.flattenToString());
+ 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);
+ }
+
+ @Thunk ContentValues updateCacheAndGetContentValues(LauncherActivityInfoCompat app,
+ boolean replaceExisting) {
+ final ComponentKey key = new ComponentKey(app.getComponentName(), app.getUser());
+ CacheEntry entry = null;
+ if (!replaceExisting) {
+ entry = mCache.get(key);
+ // We can't reuse the entry if the high-res icon is not present.
+ if (entry == null || entry.isLowResIcon || entry.icon == null) {
+ entry = null;
+ }
+ }
+ if (entry == null) {
+ entry = new CacheEntry();
+ entry.icon = Utilities.createIconBitmap(app.getBadgedIcon(mIconDpi), mContext);
+ }
+ entry.title = app.getLabel();
+ entry.contentDescription = mUserManager.getBadgedLabelForUser(entry.title, app.getUser());
+ mCache.put(new ComponentKey(app.getComponentName(), app.getUser()), entry);
+
+ return newContentValues(entry.icon, entry.title.toString(), mActivityBgColor);
+ }
+
+ /**
+ * Fetches high-res icon for the provided ItemInfo and updates the caller when done.
+ * @return a request ID that can be used to cancel the request.
+ */
+ public IconLoadRequest updateIconInBackground(final BubbleTextView caller, final ItemInfo info) {
+ Runnable request = new Runnable() {
+
+ @Override
+ public void run() {
+ if (info instanceof AppInfo) {
+ getTitleAndIcon((AppInfo) info, null, false);
+ } else if (info instanceof ShortcutInfo) {
+ ShortcutInfo st = (ShortcutInfo) info;
+ getTitleAndIcon(st,
+ st.promisedIntent != null ? st.promisedIntent : st.intent,
+ st.user, false);
+ } else if (info instanceof PackageItemInfo) {
+ PackageItemInfo pti = (PackageItemInfo) info;
+ getTitleAndIconForApp(pti.packageName, pti.user, false, pti);
+ }
+ mMainThreadExecutor.execute(new Runnable() {
+
+ @Override
+ public void run() {
+ caller.reapplyItemInfo(info);
+ }
+ });
+ }
+ };
+ mWorkerHandler.post(request);
+ return new IconLoadRequest(request, mWorkerHandler);
+ }
- application.title = entry.title;
- application.iconBitmap = entry.icon;
+ private Bitmap getNonNullIcon(CacheEntry entry, UserHandleCompat user) {
+ return entry.icon == null ? getDefaultIcon(user) : entry.icon;
+ }
+
+ /**
+ * Fill in "application" with the icon and label for "info."
+ */
+ public synchronized void getTitleAndIcon(AppInfo application,
+ LauncherActivityInfoCompat info, boolean useLowResIcon) {
+ UserHandleCompat user = info == null ? application.user : info.getUser();
+ CacheEntry entry = cacheLocked(application.componentName, info, user,
+ false, useLowResIcon);
+ application.title = Utilities.trim(entry.title);
+ application.iconBitmap = getNonNullIcon(entry, user);
application.contentDescription = entry.contentDescription;
+ application.usingLowResIcon = entry.isLowResIcon;
}
+ /**
+ * Updates {@param application} only if a valid entry is found.
+ */
+ public synchronized void updateTitleAndIcon(AppInfo application) {
+ CacheEntry entry = cacheLocked(application.componentName, null, application.user,
+ false, application.usingLowResIcon);
+ if (entry.icon != null && !isDefaultIcon(entry.icon, application.user)) {
+ application.title = Utilities.trim(entry.title);
+ application.iconBitmap = entry.icon;
+ application.contentDescription = entry.contentDescription;
+ application.usingLowResIcon = entry.isLowResIcon;
+ }
+ }
+
+ /**
+ * Returns a high res icon for the given intent and user
+ */
public synchronized Bitmap getIcon(Intent intent, UserHandleCompat user) {
ComponentName component = intent.getComponent();
// null info means not installed, but if we have a component from the intent then
@@ -246,15 +466,16 @@ public class IconCache {
}
LauncherActivityInfoCompat launcherActInfo = mLauncherApps.resolveActivity(intent, user);
- CacheEntry entry = cacheLocked(component, launcherActInfo, null, user, true);
+ CacheEntry entry = cacheLocked(component, launcherActInfo, user, true, false /* useLowRes */);
return entry.icon;
}
/**
- * Fill in "shortcutInfo" with the icon and label for "info."
+ * Fill in {@param shortcutInfo} with the icon and label for {@param intent}. If the
+ * corresponding activity is not found, it reverts to the package icon.
*/
public synchronized void getTitleAndIcon(ShortcutInfo shortcutInfo, Intent intent,
- UserHandleCompat user, boolean usePkgIcon) {
+ UserHandleCompat user, boolean useLowResIcon) {
ComponentName component = intent.getComponent();
// null info means not installed, but if we have a component from the intent then
// we should still look in the cache for restored app icons.
@@ -262,17 +483,38 @@ public class IconCache {
shortcutInfo.setIcon(getDefaultIcon(user));
shortcutInfo.title = "";
shortcutInfo.usingFallbackIcon = true;
+ shortcutInfo.usingLowResIcon = false;
} else {
- LauncherActivityInfoCompat launcherActInfo =
- mLauncherApps.resolveActivity(intent, user);
- CacheEntry entry = cacheLocked(component, launcherActInfo, null, user, usePkgIcon);
-
- shortcutInfo.setIcon(entry.icon);
- shortcutInfo.title = entry.title;
- shortcutInfo.usingFallbackIcon = isDefaultIcon(entry.icon, user);
+ LauncherActivityInfoCompat info = mLauncherApps.resolveActivity(intent, user);
+ getTitleAndIcon(shortcutInfo, component, info, user, true, useLowResIcon);
}
}
+ /**
+ * Fill in {@param shortcutInfo} with the icon and label for {@param info}
+ */
+ public synchronized void getTitleAndIcon(
+ ShortcutInfo shortcutInfo, ComponentName component, LauncherActivityInfoCompat info,
+ UserHandleCompat user, boolean usePkgIcon, boolean useLowResIcon) {
+ CacheEntry entry = cacheLocked(component, info, user, usePkgIcon, useLowResIcon);
+ shortcutInfo.setIcon(getNonNullIcon(entry, user));
+ shortcutInfo.title = Utilities.trim(entry.title);
+ shortcutInfo.usingFallbackIcon = isDefaultIcon(entry.icon, user);
+ shortcutInfo.usingLowResIcon = entry.isLowResIcon;
+ }
+
+ /**
+ * Fill in {@param appInfo} with the icon and label for {@param packageName}
+ */
+ public synchronized void getTitleAndIconForApp(
+ String packageName, UserHandleCompat user, boolean useLowResIcon,
+ PackageItemInfo infoOut) {
+ CacheEntry entry = getEntryForPackageLocked(packageName, user, useLowResIcon);
+ infoOut.iconBitmap = getNonNullIcon(entry, user);
+ infoOut.title = Utilities.trim(entry.title);
+ infoOut.usingLowResIcon = entry.isLowResIcon;
+ infoOut.contentDescription = entry.contentDescription;
+ }
public synchronized Bitmap getDefaultIcon(UserHandleCompat user) {
if (!mDefaultIcons.containsKey(user)) {
@@ -281,16 +523,6 @@ public class IconCache {
return mDefaultIcons.get(user);
}
- public synchronized Bitmap getIcon(ComponentName component, LauncherActivityInfoCompat info,
- HashMap<Object, CharSequence> labelCache) {
- if (info == null || component == null) {
- return null;
- }
-
- CacheEntry entry = cacheLocked(component, info, labelCache, info.getUser(), false);
- return entry.icon;
- }
-
public boolean isDefaultIcon(Bitmap icon, UserHandleCompat user) {
return mDefaultIcons.get(user) == icon;
}
@@ -300,44 +532,27 @@ public class IconCache {
* This method is not thread safe, it must be called from a synchronized method.
*/
private CacheEntry cacheLocked(ComponentName componentName, LauncherActivityInfoCompat info,
- HashMap<Object, CharSequence> labelCache, UserHandleCompat user, boolean usePackageIcon) {
- CacheKey cacheKey = new CacheKey(componentName, user);
+ UserHandleCompat user, boolean usePackageIcon, boolean useLowResIcon) {
+ ComponentKey cacheKey = new ComponentKey(componentName, user);
CacheEntry entry = mCache.get(cacheKey);
- if (entry == null) {
+ if (entry == null || (entry.isLowResIcon && !useLowResIcon)) {
entry = new CacheEntry();
-
mCache.put(cacheKey, entry);
- if (info != null) {
- ComponentName labelKey = info.getComponentName();
- if (labelCache != null && labelCache.containsKey(labelKey)) {
- entry.title = labelCache.get(labelKey).toString();
- } else {
- entry.title = info.getLabel().toString();
- if (labelCache != null) {
- labelCache.put(labelKey, entry.title);
- }
- }
-
- entry.contentDescription = mUserManager.getBadgedLabelForUser(entry.title, user);
- entry.icon = Utilities.createIconBitmap(
- info.getBadgedIcon(mIconDpi), mContext);
- } else {
- entry.title = "";
- Bitmap preloaded = getPreloadedIcon(componentName, user);
- if (preloaded != null) {
- if (DEBUG) Log.d(TAG, "using preloaded icon for " +
- componentName.toShortString());
- entry.icon = preloaded;
+ // Check the DB first.
+ if (!getEntryFromDB(componentName, user, entry, useLowResIcon)) {
+ if (info != null) {
+ entry.icon = Utilities.createIconBitmap(info.getBadgedIcon(mIconDpi), mContext);
} else {
if (usePackageIcon) {
- CacheEntry packageEntry = getEntryForPackage(
- componentName.getPackageName(), user);
+ CacheEntry packageEntry = getEntryForPackageLocked(
+ componentName.getPackageName(), user, false);
if (packageEntry != null) {
if (DEBUG) Log.d(TAG, "using package default icon for " +
componentName.toShortString());
entry.icon = packageEntry.icon;
entry.title = packageEntry.title;
+ entry.contentDescription = packageEntry.contentDescription;
}
}
if (entry.icon == null) {
@@ -347,6 +562,11 @@ public class IconCache {
}
}
}
+
+ if (TextUtils.isEmpty(entry.title) && info != null) {
+ entry.title = info.getLabel();
+ entry.contentDescription = mUserManager.getBadgedLabelForUser(entry.title, user);
+ }
}
return entry;
}
@@ -357,9 +577,9 @@ public class IconCache {
*/
public synchronized void cachePackageInstallInfo(String packageName, UserHandleCompat user,
Bitmap icon, CharSequence title) {
- remove(packageName, user);
+ removeFromMemCacheLocked(packageName, user);
- CacheEntry entry = getEntryForPackage(packageName, user);
+ CacheEntry entry = getEntryForPackageLocked(packageName, user, false);
if (!TextUtils.isEmpty(title)) {
entry.title = title;
}
@@ -371,56 +591,68 @@ public class IconCache {
/**
* Gets an entry for the package, which can be used as a fallback entry for various components.
* This method is not thread safe, it must be called from a synchronized method.
+ *
*/
- private CacheEntry getEntryForPackage(String packageName, UserHandleCompat user) {
- ComponentName cn = new ComponentName(packageName, EMPTY_CLASS_NAME);;
- CacheKey cacheKey = new CacheKey(cn, user);
+ private CacheEntry getEntryForPackageLocked(String packageName, UserHandleCompat user,
+ boolean useLowResIcon) {
+ ComponentName cn = new ComponentName(packageName, packageName + EMPTY_CLASS_NAME);
+ ComponentKey cacheKey = new ComponentKey(cn, user);
CacheEntry entry = mCache.get(cacheKey);
- if (entry == null) {
+
+ if (entry == null || (entry.isLowResIcon && !useLowResIcon)) {
entry = new CacheEntry();
- entry.title = "";
- mCache.put(cacheKey, entry);
+ boolean entryUpdated = true;
- try {
- ApplicationInfo info = mPackageManager.getApplicationInfo(packageName, 0);
- entry.title = info.loadLabel(mPackageManager);
- entry.icon = Utilities.createIconBitmap(info.loadIcon(mPackageManager), mContext);
- } catch (NameNotFoundException e) {
- if (DEBUG) Log.d(TAG, "Application not installed " + packageName);
+ // Check the DB first.
+ if (!getEntryFromDB(cn, user, entry, useLowResIcon)) {
+ try {
+ PackageInfo info = mPackageManager.getPackageInfo(packageName, 0);
+ ApplicationInfo appInfo = info.applicationInfo;
+ if (appInfo == null) {
+ throw new NameNotFoundException("ApplicationInfo is null");
+ }
+ Drawable drawable = mUserManager.getBadgedDrawableForUser(
+ appInfo.loadIcon(mPackageManager), user);
+ entry.icon = Utilities.createIconBitmap(drawable, mContext);
+ entry.title = appInfo.loadLabel(mPackageManager);
+ entry.contentDescription = mUserManager.getBadgedLabelForUser(entry.title, user);
+ entry.isLowResIcon = false;
+
+ // Add the icon in the DB here, since these do not get written during
+ // package updates.
+ ContentValues values =
+ newContentValues(entry.icon, entry.title.toString(), mPackageBgColor);
+ addIconToDB(values, cn, info, mUserManager.getSerialNumberForUser(user));
+
+ } catch (NameNotFoundException e) {
+ if (DEBUG) Log.d(TAG, "Application not installed " + packageName);
+ entryUpdated = false;
+ }
}
- if (entry.icon == null) {
- entry.icon = getPreloadedIcon(cn, user);
+ // Only add a filled-out entry to the cache
+ if (entryUpdated) {
+ mCache.put(cacheKey, entry);
}
}
return entry;
}
- public synchronized HashMap<ComponentName,Bitmap> getAllIcons() {
- HashMap<ComponentName,Bitmap> set = new HashMap<ComponentName,Bitmap>();
- for (CacheKey ck : mCache.keySet()) {
- final CacheEntry e = mCache.get(ck);
- set.put(ck.componentName, e.icon);
- }
- return set;
- }
-
/**
* Pre-load an icon into the persistent cache.
*
* <P>Queries for a component that does not exist in the package manager
* will be answered by the persistent cache.
*
- * @param context application context
* @param componentName the icon should be returned for this component
* @param icon the icon to be persisted
* @param dpi the native density of the icon
*/
- public static void preloadIcon(Context context, ComponentName componentName, Bitmap icon,
- int dpi) {
+ public void preloadIcon(ComponentName componentName, Bitmap icon, int dpi, String label,
+ long userSerial) {
// TODO rescale to the correct native DPI
try {
- PackageManager packageManager = context.getPackageManager();
+ PackageManager packageManager = mContext.getPackageManager();
packageManager.getActivityIcon(componentName);
// component is present on the system already, do nothing
return;
@@ -428,100 +660,208 @@ public class IconCache {
// pass
}
- final String key = componentName.flattenToString();
- FileOutputStream resourceFile = null;
+ ContentValues values = newContentValues(icon, 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);
+ }
+
+ private boolean getEntryFromDB(ComponentName component, UserHandleCompat user,
+ CacheEntry entry, boolean lowRes) {
+ Cursor c = mIconDb.getReadableDatabase().query(IconDB.TABLE_NAME,
+ new String[] {lowRes ? IconDB.COLUMN_ICON_LOW_RES : IconDB.COLUMN_ICON,
+ IconDB.COLUMN_LABEL},
+ IconDB.COLUMN_COMPONENT + " = ? AND " + IconDB.COLUMN_USER + " = ?",
+ new String[] {component.flattenToString(),
+ Long.toString(mUserManager.getSerialNumberForUser(user))},
+ null, null, null);
try {
- resourceFile = context.openFileOutput(getResourceFilename(componentName),
- Context.MODE_PRIVATE);
- ByteArrayOutputStream os = new ByteArrayOutputStream();
- if (icon.compress(android.graphics.Bitmap.CompressFormat.PNG, 75, os)) {
- byte[] buffer = os.toByteArray();
- resourceFile.write(buffer, 0, buffer.length);
- } else {
- Log.w(TAG, "failed to encode cache for " + key);
- return;
- }
- } catch (FileNotFoundException e) {
- Log.w(TAG, "failed to pre-load cache for " + key, e);
- } catch (IOException e) {
- Log.w(TAG, "failed to pre-load cache for " + key, e);
- } finally {
- if (resourceFile != null) {
- try {
- resourceFile.close();
- } catch (IOException e) {
- Log.d(TAG, "failed to save restored icon for: " + key, e);
+ if (c.moveToNext()) {
+ entry.icon = loadIconNoResize(c, 0, lowRes ? mLowResOptions : null);
+ entry.isLowResIcon = lowRes;
+ entry.title = c.getString(1);
+ if (entry.title == null) {
+ entry.title = "";
+ entry.contentDescription = "";
+ } else {
+ entry.contentDescription = mUserManager.getBadgedLabelForUser(entry.title, user);
}
+ return true;
}
+ } finally {
+ c.close();
+ }
+ return false;
+ }
+
+ public static class IconLoadRequest {
+ private final Runnable mRunnable;
+ private final Handler mHandler;
+
+ IconLoadRequest(Runnable runnable, Handler handler) {
+ mRunnable = runnable;
+ mHandler = handler;
+ }
+
+ public void cancel() {
+ mHandler.removeCallbacks(mRunnable);
}
}
/**
- * Read a pre-loaded icon from the persistent icon cache.
- *
- * @param componentName the component that should own the icon
- * @returns a bitmap if one is cached, or null.
+ * A runnable that updates invalid icons and adds missing icons in the DB for the provided
+ * LauncherActivityInfoCompat list. Items are updated/added one at a time, so that the
+ * worker thread doesn't get blocked.
*/
- private Bitmap getPreloadedIcon(ComponentName componentName, UserHandleCompat user) {
- final String key = componentName.flattenToShortString();
-
- // We don't keep icons for other profiles in persistent cache.
- if (!user.equals(UserHandleCompat.myUserHandle())) {
- return null;
+ @Thunk class SerializedIconUpdateTask implements Runnable {
+ private final long mUserSerial;
+ private final HashMap<String, PackageInfo> mPkgInfoMap;
+ private final Stack<LauncherActivityInfoCompat> mAppsToAdd;
+ private final Stack<LauncherActivityInfoCompat> mAppsToUpdate;
+ private final HashSet<String> mUpdatedPackages = new HashSet<String>();
+
+ @Thunk SerializedIconUpdateTask(long userSerial, HashMap<String, PackageInfo> pkgInfoMap,
+ Stack<LauncherActivityInfoCompat> appsToAdd,
+ Stack<LauncherActivityInfoCompat> appsToUpdate) {
+ mUserSerial = userSerial;
+ mPkgInfoMap = pkgInfoMap;
+ mAppsToAdd = appsToAdd;
+ mAppsToUpdate = appsToUpdate;
}
- if (DEBUG) Log.v(TAG, "looking for pre-load icon for " + key);
- Bitmap icon = null;
- FileInputStream resourceFile = null;
- try {
- resourceFile = mContext.openFileInput(getResourceFilename(componentName));
- byte[] buffer = new byte[1024];
- ByteArrayOutputStream bytes = new ByteArrayOutputStream();
- int bytesRead = 0;
- while(bytesRead >= 0) {
- bytes.write(buffer, 0, bytesRead);
- bytesRead = resourceFile.read(buffer, 0, buffer.length);
+ @Override
+ public void run() {
+ if (!mAppsToUpdate.isEmpty()) {
+ LauncherActivityInfoCompat app = mAppsToUpdate.pop();
+ String cn = app.getComponentName().flattenToString();
+ ContentValues values = updateCacheAndGetContentValues(app, true);
+ mIconDb.getWritableDatabase().update(IconDB.TABLE_NAME, values,
+ IconDB.COLUMN_COMPONENT + " = ? AND " + IconDB.COLUMN_USER + " = ?",
+ new String[] {cn, Long.toString(mUserSerial)});
+ mUpdatedPackages.add(app.getComponentName().getPackageName());
+
+ if (mAppsToUpdate.isEmpty() && !mUpdatedPackages.isEmpty()) {
+ // No more app to update. Notify model.
+ LauncherAppState.getInstance().getModel().onPackageIconsUpdated(
+ mUpdatedPackages, mUserManager.getUserForSerialNumber(mUserSerial));
+ }
+
+ // Let it run one more time.
+ scheduleNext();
+ } else if (!mAppsToAdd.isEmpty()) {
+ LauncherActivityInfoCompat app = mAppsToAdd.pop();
+ PackageInfo info = mPkgInfoMap.get(app.getComponentName().getPackageName());
+ if (info != null) {
+ synchronized (IconCache.this) {
+ addIconToDBAndMemCache(app, info, mUserSerial);
+ }
+ }
+
+ if (!mAppsToAdd.isEmpty()) {
+ scheduleNext();
+ }
}
- if (DEBUG) Log.d(TAG, "read " + bytes.size());
- icon = BitmapFactory.decodeByteArray(bytes.toByteArray(), 0, bytes.size());
- if (icon == null) {
- Log.w(TAG, "failed to decode pre-load icon for " + key);
+ }
+
+ public void scheduleNext() {
+ mWorkerHandler.postAtTime(this, ICON_UPDATE_TOKEN, SystemClock.uptimeMillis() + 1);
+ }
+ }
+
+ private void updateSystemStateString() {
+ mSystemState = Locale.getDefault().toString();
+ }
+
+ private static final class IconDB extends SQLiteOpenHelper {
+ private final static int DB_VERSION = 6;
+
+ private final static String TABLE_NAME = "icons";
+ private final static String COLUMN_ROWID = "rowid";
+ private final static String COLUMN_COMPONENT = "componentName";
+ private final static String COLUMN_USER = "profileId";
+ private final static String COLUMN_LAST_UPDATED = "lastUpdated";
+ private final static String COLUMN_VERSION = "version";
+ private final static String COLUMN_ICON = "icon";
+ private final static String COLUMN_ICON_LOW_RES = "icon_low_res";
+ private final static String COLUMN_LABEL = "label";
+ private final static String COLUMN_SYSTEM_STATE = "system_state";
+
+ public IconDB(Context context) {
+ super(context, LauncherFiles.APP_ICONS_DB, null, DB_VERSION);
+ }
+
+ @Override
+ public void onCreate(SQLiteDatabase db) {
+ db.execSQL("CREATE TABLE IF NOT EXISTS " + TABLE_NAME + " (" +
+ COLUMN_COMPONENT + " TEXT NOT NULL, " +
+ COLUMN_USER + " INTEGER NOT NULL, " +
+ COLUMN_LAST_UPDATED + " INTEGER NOT NULL DEFAULT 0, " +
+ COLUMN_VERSION + " INTEGER NOT NULL DEFAULT 0, " +
+ COLUMN_ICON + " BLOB, " +
+ COLUMN_ICON_LOW_RES + " BLOB, " +
+ COLUMN_LABEL + " TEXT, " +
+ COLUMN_SYSTEM_STATE + " TEXT, " +
+ "PRIMARY KEY (" + COLUMN_COMPONENT + ", " + COLUMN_USER + ") " +
+ ");");
+ }
+
+ @Override
+ public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
+ if (oldVersion != newVersion) {
+ clearDB(db);
}
- } catch (FileNotFoundException e) {
- if (DEBUG) Log.d(TAG, "there is no restored icon for: " + key);
- } catch (IOException e) {
- Log.w(TAG, "failed to read pre-load icon for: " + key, e);
- } finally {
- if(resourceFile != null) {
- try {
- resourceFile.close();
- } catch (IOException e) {
- Log.d(TAG, "failed to manage pre-load icon file: " + key, e);
- }
+ }
+
+ @Override
+ public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {
+ if (oldVersion != newVersion) {
+ clearDB(db);
}
}
- return icon;
+ private void clearDB(SQLiteDatabase db) {
+ db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME);
+ onCreate(db);
+ }
}
- /**
- * Remove a pre-loaded icon from the persistent icon cache.
- *
- * @param componentName the component that should own the icon
- */
- public void deletePreloadedIcon(ComponentName componentName, UserHandleCompat user) {
- // We don't keep icons for other profiles in persistent cache.
- if (!user.equals(UserHandleCompat.myUserHandle()) || componentName == null) {
- return;
+ private ContentValues newContentValues(Bitmap icon, String label, int lowResBackgroundColor) {
+ ContentValues values = new ContentValues();
+ values.put(IconDB.COLUMN_ICON, Utilities.flattenBitmap(icon));
+
+ values.put(IconDB.COLUMN_LABEL, label);
+ values.put(IconDB.COLUMN_SYSTEM_STATE, mSystemState);
+
+ if (lowResBackgroundColor == Color.TRANSPARENT) {
+ values.put(IconDB.COLUMN_ICON_LOW_RES, Utilities.flattenBitmap(
+ Bitmap.createScaledBitmap(icon,
+ icon.getWidth() / LOW_RES_SCALE_FACTOR,
+ icon.getHeight() / LOW_RES_SCALE_FACTOR, true)));
+ } else {
+ synchronized (this) {
+ if (mLowResBitmap == null) {
+ mLowResBitmap = Bitmap.createBitmap(icon.getWidth() / LOW_RES_SCALE_FACTOR,
+ icon.getHeight() / LOW_RES_SCALE_FACTOR, Bitmap.Config.RGB_565);
+ mLowResCanvas = new Canvas(mLowResBitmap);
+ mLowResPaint = new Paint(Paint.FILTER_BITMAP_FLAG | Paint.ANTI_ALIAS_FLAG);
+ }
+ mLowResCanvas.drawColor(lowResBackgroundColor);
+ mLowResCanvas.drawBitmap(icon, new Rect(0, 0, icon.getWidth(), icon.getHeight()),
+ new Rect(0, 0, mLowResBitmap.getWidth(), mLowResBitmap.getHeight()),
+ mLowResPaint);
+ values.put(IconDB.COLUMN_ICON_LOW_RES, Utilities.flattenBitmap(mLowResBitmap));
+ }
}
- remove(componentName, user);
- boolean success = mContext.deleteFile(getResourceFilename(componentName));
- if (DEBUG && success) Log.d(TAG, "removed pre-loaded icon from persistent cache");
+ return values;
}
- private static String getResourceFilename(ComponentName component) {
- String resourceName = component.flattenToShortString();
- String filename = resourceName.replace(File.separatorChar, '_');
- return RESOURCE_FILE_PREFIX + filename;
+ private static Bitmap loadIconNoResize(Cursor c, int iconIndex, BitmapFactory.Options options) {
+ byte[] data = c.getBlob(iconIndex);
+ try {
+ return BitmapFactory.decodeByteArray(data, 0, data.length, options);
+ } catch (Exception e) {
+ return null;
+ }
}
}
diff --git a/src/com/android/launcher3/InfoDropTarget.java b/src/com/android/launcher3/InfoDropTarget.java
index 7e55af228..d93cdcc1b 100644
--- a/src/com/android/launcher3/InfoDropTarget.java
+++ b/src/com/android/launcher3/InfoDropTarget.java
@@ -18,21 +18,12 @@ package com.android.launcher3;
import android.content.ComponentName;
import android.content.Context;
-import android.content.res.ColorStateList;
-import android.content.res.Configuration;
-import android.content.res.Resources;
-import android.graphics.drawable.TransitionDrawable;
import android.util.AttributeSet;
-import android.view.View;
-import android.view.ViewGroup;
import com.android.launcher3.compat.UserHandleCompat;
public class InfoDropTarget extends ButtonDropTarget {
- private ColorStateList mOriginalTextColor;
- private TransitionDrawable mDrawable;
-
public InfoDropTarget(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
@@ -44,96 +35,44 @@ public class InfoDropTarget extends ButtonDropTarget {
@Override
protected void onFinishInflate() {
super.onFinishInflate();
-
- mOriginalTextColor = getTextColors();
-
// Get the hover color
- Resources r = getResources();
- mHoverColor = r.getColor(R.color.info_target_hover_tint);
- mDrawable = (TransitionDrawable) getCurrentDrawable();
-
- if (mDrawable == null) {
- // TODO: investigate why this is ever happening. Presently only on one known device.
- mDrawable = (TransitionDrawable) r.getDrawable(R.drawable.info_target_selector);
- setCompoundDrawablesRelativeWithIntrinsicBounds(mDrawable, null, null, null);
- }
+ mHoverColor = getResources().getColor(R.color.info_target_hover_tint);
- if (null != mDrawable) {
- mDrawable.setCrossFadeEnabled(true);
- }
-
- // Remove the text in the Phone UI in landscape
- int orientation = getResources().getConfiguration().orientation;
- if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
- if (!LauncherAppState.getInstance().isScreenLarge()) {
- setText("");
- }
- }
+ setDrawable(R.drawable.ic_info_launcher);
}
- @Override
- public boolean acceptDrop(DragObject d) {
- // acceptDrop is called just before onDrop. We do the work here, rather than
- // in onDrop, because it allows us to reject the drop (by returning false)
- // so that the object being dragged isn't removed from the drag source.
+ public static void startDetailsActivityForInfo(Object info, Launcher launcher) {
ComponentName componentName = null;
- if (d.dragInfo instanceof AppInfo) {
- componentName = ((AppInfo) d.dragInfo).componentName;
- } else if (d.dragInfo instanceof ShortcutInfo) {
- componentName = ((ShortcutInfo) d.dragInfo).intent.getComponent();
- } else if (d.dragInfo instanceof PendingAddItemInfo) {
- componentName = ((PendingAddItemInfo) d.dragInfo).componentName;
+ if (info instanceof AppInfo) {
+ componentName = ((AppInfo) info).componentName;
+ } else if (info instanceof ShortcutInfo) {
+ componentName = ((ShortcutInfo) info).intent.getComponent();
+ } else if (info instanceof PendingAddItemInfo) {
+ componentName = ((PendingAddItemInfo) info).componentName;
}
final UserHandleCompat user;
- if (d.dragInfo instanceof ItemInfo) {
- user = ((ItemInfo) d.dragInfo).user;
+ if (info instanceof ItemInfo) {
+ user = ((ItemInfo) info).user;
} else {
user = UserHandleCompat.myUserHandle();
}
if (componentName != null) {
- mLauncher.startApplicationDetailsActivity(componentName, user);
- }
-
- // There is no post-drop animation, so clean up the DragView now
- d.deferDragViewCleanupPostAnimation = false;
- return false;
- }
-
- @Override
- public void onDragStart(DragSource source, Object info, int dragAction) {
- boolean isVisible = true;
-
- // Hide this button unless we are dragging something from AllApps
- if (!source.supportsAppInfoDropTarget()) {
- isVisible = false;
+ launcher.startApplicationDetailsActivity(componentName, user);
}
-
- mActive = isVisible;
- mDrawable.resetTransition();
- setTextColor(mOriginalTextColor);
- ((ViewGroup) getParent()).setVisibility(isVisible ? View.VISIBLE : View.GONE);
}
@Override
- public void onDragEnd() {
- super.onDragEnd();
- mActive = false;
+ protected boolean supportsDrop(DragSource source, Object info) {
+ return source.supportsAppInfoDropTarget() && supportsDrop(getContext(), info);
}
- public void onDragEnter(DragObject d) {
- super.onDragEnter(d);
-
- mDrawable.startTransition(mTransitionDuration);
- setTextColor(mHoverColor);
+ public static boolean supportsDrop(Context context, Object info) {
+ return info instanceof AppInfo || info instanceof PendingAddItemInfo;
}
- public void onDragExit(DragObject d) {
- super.onDragExit(d);
-
- if (!d.dragComplete) {
- mDrawable.resetTransition();
- setTextColor(mOriginalTextColor);
- }
+ @Override
+ void completeDrop(DragObject d) {
+ startDetailsActivityForInfo(d.dragInfo, mLauncher);
}
}
diff --git a/src/com/android/launcher3/Insettable.java b/src/com/android/launcher3/Insettable.java
index 1d2356c65..3b8ef2f93 100644
--- a/src/com/android/launcher3/Insettable.java
+++ b/src/com/android/launcher3/Insettable.java
@@ -18,6 +18,10 @@ package com.android.launcher3;
import android.graphics.Rect;
+/**
+ * Allows the implementing {@link View} to not draw underneath system bars.
+ * e.g., notification bar on top and home key area on the bottom.
+ */
public interface Insettable {
void setInsets(Rect insets);
diff --git a/src/com/android/launcher3/InstallShortcutReceiver.java b/src/com/android/launcher3/InstallShortcutReceiver.java
index 1ab308558..3fc8fc0a9 100644
--- a/src/com/android/launcher3/InstallShortcutReceiver.java
+++ b/src/com/android/launcher3/InstallShortcutReceiver.java
@@ -22,6 +22,7 @@ import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.text.TextUtils;
@@ -32,6 +33,7 @@ import com.android.launcher3.compat.LauncherActivityInfoCompat;
import com.android.launcher3.compat.LauncherAppsCompat;
import com.android.launcher3.compat.UserHandleCompat;
import com.android.launcher3.compat.UserManagerCompat;
+import com.android.launcher3.util.Thunk;
import org.json.JSONException;
import org.json.JSONObject;
@@ -144,12 +146,26 @@ public class InstallShortcutReceiver extends BroadcastReceiver {
return;
}
- if (DBG) Log.d(TAG, "Got INSTALL_SHORTCUT: " + data.toUri(0));
PendingInstallShortcutInfo info = new PendingInstallShortcutInfo(data, context);
+ if (info.launchIntent == null || info.label == null) {
+ if (DBG) Log.e(TAG, "Invalid install shortcut intent");
+ return;
+ }
+ info = convertToLauncherActivityIfPossible(info);
queuePendingShortcutInfo(info, context);
}
+ public static ShortcutInfo fromShortcutIntent(Context context, Intent data) {
+ 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();
+ }
+
static void queueInstallShortcut(LauncherActivityInfoCompat info, Context context) {
queuePendingShortcutInfo(new PendingInstallShortcutInfo(info, context), context);
}
@@ -186,11 +202,6 @@ public class InstallShortcutReceiver extends BroadcastReceiver {
final PendingInstallShortcutInfo pendingInfo = iter.next();
final Intent intent = pendingInfo.launchIntent;
- if (LauncherAppState.isDisableAllApps() && !isValidShortcutLaunchIntent(intent)) {
- if (DBG) Log.d(TAG, "Ignoring shortcut with launchIntent:" + intent);
- continue;
- }
-
// If the intent specifies a package, make sure the package exists
String packageName = pendingInfo.getTargetPackage();
if (!TextUtils.isEmpty(packageName)) {
@@ -201,56 +212,28 @@ public class InstallShortcutReceiver extends BroadcastReceiver {
}
}
- final boolean exists = LauncherModel.shortcutExists(context, pendingInfo.label,
- intent, pendingInfo.user);
- if (!exists) {
- // Generate a shortcut info to add into the model
- addShortcuts.add(pendingInfo.getShortcutInfo());
- }
+ // Generate a shortcut info to add into the model
+ addShortcuts.add(pendingInfo.getShortcutInfo());
}
// Add the new apps to the model and bind them
if (!addShortcuts.isEmpty()) {
LauncherAppState app = LauncherAppState.getInstance();
- app.getModel().addAndBindAddedWorkspaceApps(context, addShortcuts);
+ app.getModel().addAndBindAddedWorkspaceItems(context, addShortcuts);
}
}
}
/**
- * Returns true if the intent is a valid launch intent for a shortcut.
- * This is used to identify shortcuts which are different from the ones exposed by the
- * applications' manifest file.
- *
- * When DISABLE_ALL_APPS is true, shortcuts exposed via the app's manifest should never be
- * duplicated or removed(unless the app is un-installed).
- *
- * @param launchIntent The intent that will be launched when the shortcut is clicked.
- */
- static boolean isValidShortcutLaunchIntent(Intent launchIntent) {
- if (launchIntent != null
- && Intent.ACTION_MAIN.equals(launchIntent.getAction())
- && launchIntent.getComponent() != null
- && launchIntent.getCategories() != null
- && launchIntent.getCategories().size() == 1
- && launchIntent.hasCategory(Intent.CATEGORY_LAUNCHER)
- && launchIntent.getExtras() == null
- && TextUtils.isEmpty(launchIntent.getDataString())) {
- return false;
- }
- return true;
- }
-
- /**
* Ensures that we have a valid, non-null name. If the provided name is null, we will return
* the application name instead.
*/
- private static CharSequence ensureValidName(Context context, Intent intent, CharSequence name) {
+ @Thunk static CharSequence ensureValidName(Context context, Intent intent, CharSequence name) {
if (name == null) {
try {
PackageManager pm = context.getPackageManager();
ActivityInfo info = pm.getActivityInfo(intent.getComponent(), 0);
- name = info.loadLabel(pm).toString();
+ name = info.loadLabel(pm);
} catch (PackageManager.NameNotFoundException nnfe) {
return "";
}
@@ -335,7 +318,7 @@ public class InstallShortcutReceiver extends BroadcastReceiver {
.key(LAUNCH_INTENT_KEY).value(launchIntent.toUri(0))
.key(NAME_KEY).value(name);
if (icon != null) {
- byte[] iconByteArray = ItemInfo.flattenBitmap(icon);
+ byte[] iconByteArray = Utilities.flattenBitmap(icon);
json = json.key(ICON_KEY).value(
Base64.encodeToString(
iconByteArray, 0, iconByteArray.length, Base64.DEFAULT));
@@ -354,16 +337,7 @@ public class InstallShortcutReceiver extends BroadcastReceiver {
public ShortcutInfo getShortcutInfo() {
if (activityInfo != null) {
- final ShortcutInfo info = new ShortcutInfo();
- info.user = user;
- info.title = label;
- info.contentDescription = label;
- info.customIcon = false;
- info.intent = launchIntent;
- info.itemType = LauncherSettings.Favorites.ITEM_TYPE_APPLICATION;
- info.flags = AppInfo.initFlags(activityInfo);
- info.firstInstallTime = activityInfo.getFirstInstallTime();
- return info;
+ return ShortcutInfo.fromActivityInfo(activityInfo, mContext);
} else {
return LauncherAppState.getInstance().getModel().infoFromShortcutIntent(mContext, data);
}
@@ -377,6 +351,10 @@ public class InstallShortcutReceiver extends BroadcastReceiver {
}
return packageName;
}
+
+ public boolean isLuncherActivity() {
+ return activityInfo != null;
+ }
}
private static PendingInstallShortcutInfo decode(String encoded, Context context) {
@@ -424,4 +402,34 @@ public class InstallShortcutReceiver extends BroadcastReceiver {
}
return null;
}
+
+ /**
+ * Tries to create a new PendingInstallShortcutInfo which represents the same target,
+ * but is an app target and not a shortcut.
+ * @return the newly created info or the original one.
+ */
+ private static PendingInstallShortcutInfo convertToLauncherActivityIfPossible(
+ PendingInstallShortcutInfo original) {
+ if (original.isLuncherActivity()) {
+ // Already an activity target
+ return original;
+ }
+ if (!Utilities.isLauncherAppTarget(original.launchIntent)
+ || !original.user.equals(UserHandleCompat.myUserHandle())) {
+ // We can only convert shortcuts which point to a main activity in the current user.
+ return original;
+ }
+
+ PackageManager pm = original.mContext.getPackageManager();
+ ResolveInfo info = pm.resolveActivity(original.launchIntent, 0);
+
+ if (info == null) {
+ return original;
+ }
+
+ // Ignore any conflicts in the label name, as that can change based on locale.
+ LauncherActivityInfoCompat launcherInfo = LauncherActivityInfoCompat
+ .fromResolveInfo(info, original.mContext);
+ return new PendingInstallShortcutInfo(launcherInfo, original.mContext);
+ }
}
diff --git a/src/com/android/launcher3/InterruptibleInOutAnimator.java b/src/com/android/launcher3/InterruptibleInOutAnimator.java
index 2898b347d..29df38bae 100644
--- a/src/com/android/launcher3/InterruptibleInOutAnimator.java
+++ b/src/com/android/launcher3/InterruptibleInOutAnimator.java
@@ -21,6 +21,8 @@ import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.view.View;
+import com.android.launcher3.util.Thunk;
+
/**
* A convenience class for two-way animations, e.g. a fadeIn/fadeOut animation.
* With a regular ValueAnimator, if you call reverse to show the 'out' animation, you'll get
@@ -43,7 +45,7 @@ public class InterruptibleInOutAnimator {
private static final int OUT = 2;
// TODO: This isn't really necessary, but is here to help diagnose a bug in the drag viz
- private int mDirection = STOPPED;
+ @Thunk int mDirection = STOPPED;
public InterruptibleInOutAnimator(View view, long duration, float fromValue, float toValue) {
mAnimator = LauncherAnimUtils.ofFloat(view, fromValue, toValue).setDuration(duration);
diff --git a/src/com/android/launcher3/InvariantDeviceProfile.java b/src/com/android/launcher3/InvariantDeviceProfile.java
new file mode 100644
index 000000000..ae204c40c
--- /dev/null
+++ b/src/com/android/launcher3/InvariantDeviceProfile.java
@@ -0,0 +1,303 @@
+/*
+ * 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;
+
+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;
+
+import com.android.launcher3.util.Thunk;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+
+public class InvariantDeviceProfile {
+
+ // This is a static that we use for the default icon size on a 4/5-inch phone
+ private static float DEFAULT_ICON_SIZE_DP = 60;
+
+ private static final float ICON_SIZE_DEFINED_IN_APP_DP = 48;
+
+ // Constants that affects the interpolation curve between statically defined device profile
+ // buckets.
+ private static float KNEARESTNEIGHBOR = 3;
+ private static float WEIGHT_POWER = 5;
+
+ // used to offset float not being able to express extremely small weights in extreme cases.
+ private static float WEIGHT_EFFICIENT = 100000f;
+
+ // Profile-defining invariant properties
+ String name;
+ float minWidthDps;
+ float minHeightDps;
+
+ /**
+ * Number of icons per row and column in the workspace.
+ */
+ public int numRows;
+ public int numColumns;
+
+ /**
+ * The minimum number of predicted apps in all apps.
+ */
+ int minAllAppsPredictionColumns;
+
+ /**
+ * Number of icons per row and column in the folder.
+ */
+ public int numFolderRows;
+ public int numFolderColumns;
+ float iconSize;
+ int iconBitmapSize;
+ int fillResIconDpi;
+ float iconTextSize;
+
+ /**
+ * Number of icons inside the hotseat area.
+ */
+ float numHotseatIcons;
+ float hotseatIconSize;
+ int defaultLayoutId;
+
+ // Derived invariant properties
+ int hotseatAllAppsRank;
+
+ DeviceProfile landscapeProfile;
+ DeviceProfile portraitProfile;
+
+ InvariantDeviceProfile() {
+ }
+
+ public InvariantDeviceProfile(InvariantDeviceProfile p) {
+ this(p.name, p.minWidthDps, p.minHeightDps, p.numRows, p.numColumns,
+ p.numFolderRows, p.numFolderColumns, p.minAllAppsPredictionColumns,
+ p.iconSize, p.iconTextSize, p.numHotseatIcons, p.hotseatIconSize,
+ p.defaultLayoutId);
+ }
+
+ InvariantDeviceProfile(String n, float w, float h, int r, int c, int fr, int fc, int maapc,
+ float is, float its, float hs, float his, int dlId) {
+ // Ensure that we have an odd number of hotseat items (since we need to place all apps)
+ if (hs % 2 == 0) {
+ throw new RuntimeException("All Device Profiles must have an odd number of hotseat spaces");
+ }
+
+ name = n;
+ minWidthDps = w;
+ minHeightDps = h;
+ numRows = r;
+ numColumns = c;
+ numFolderRows = fr;
+ numFolderColumns = fc;
+ minAllAppsPredictionColumns = maapc;
+ iconSize = is;
+ iconTextSize = its;
+ numHotseatIcons = hs;
+ hotseatIconSize = his;
+ defaultLayoutId = dlId;
+ }
+
+ @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
+ InvariantDeviceProfile(Context context) {
+ WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
+ Display display = wm.getDefaultDisplay();
+ DisplayMetrics dm = new DisplayMetrics();
+ display.getMetrics(dm);
+
+ Point smallestSize = new Point();
+ Point largestSize = new Point();
+ display.getCurrentSizeRange(smallestSize, largestSize);
+
+ // This guarantees that width < height
+ minWidthDps = Utilities.dpiFromPx(Math.min(smallestSize.x, smallestSize.y), dm);
+ minHeightDps = Utilities.dpiFromPx(Math.min(largestSize.x, largestSize.y), dm);
+
+ ArrayList<InvariantDeviceProfile> closestProfiles =
+ findClosestDeviceProfiles(minWidthDps, minHeightDps, getPredefinedDeviceProfiles());
+ InvariantDeviceProfile interpolatedDeviceProfileOut =
+ invDistWeightedInterpolate(minWidthDps, minHeightDps, closestProfiles);
+
+ InvariantDeviceProfile closestProfile = closestProfiles.get(0);
+ numRows = closestProfile.numRows;
+ numColumns = closestProfile.numColumns;
+ numHotseatIcons = closestProfile.numHotseatIcons;
+ hotseatAllAppsRank = (int) (numHotseatIcons / 2);
+ defaultLayoutId = closestProfile.defaultLayoutId;
+ numFolderRows = closestProfile.numFolderRows;
+ numFolderColumns = closestProfile.numFolderColumns;
+ minAllAppsPredictionColumns = closestProfile.minAllAppsPredictionColumns;
+
+ iconSize = interpolatedDeviceProfileOut.iconSize;
+ iconBitmapSize = Utilities.pxFromDp(iconSize, dm);
+ iconTextSize = interpolatedDeviceProfileOut.iconTextSize;
+ hotseatIconSize = interpolatedDeviceProfileOut.hotseatIconSize;
+ fillResIconDpi = getLauncherIconDensity(iconBitmapSize);
+
+ // If the partner customization apk contains any grid overrides, apply them
+ // Supported overrides: numRows, numColumns, iconSize
+ applyPartnerDeviceProfileOverrides(context, dm);
+
+ Point realSize = new Point();
+ display.getRealSize(realSize);
+ // The real size never changes. smallSide and largeSide will remain the
+ // same in any orientation.
+ int smallSide = Math.min(realSize.x, realSize.y);
+ int largeSide = Math.max(realSize.x, realSize.y);
+
+ landscapeProfile = new DeviceProfile(context, this, smallestSize, largestSize,
+ largeSide, smallSide, true /* isLandscape */);
+ portraitProfile = new DeviceProfile(context, this, smallestSize, largestSize,
+ smallSide, largeSide, false /* isLandscape */);
+ }
+
+ ArrayList<InvariantDeviceProfile> getPredefinedDeviceProfiles() {
+ ArrayList<InvariantDeviceProfile> predefinedDeviceProfiles = new ArrayList<>();
+ // 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));
+ predefinedDeviceProfiles.add(new InvariantDeviceProfile("Shorter Stubby",
+ 255, 400, 3, 3, 3, 3, 3, 48, 13, 3, 48, R.xml.default_workspace_4x4));
+ 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",
+ 255, 450, 3, 4, 3, 4, 4, 48, 13, 5, 48, R.xml.default_workspace_4x4));
+ 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("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
+ // also includes the nav bar on the side
+ predefinedDeviceProfiles.add(new InvariantDeviceProfile("Nexus 7",
+ 575, 904, 5, 6, 4, 5, 4, 72, 14.4f, 7, 60, R.xml.default_workspace_5x6));
+ // Larger tablet profiles always have system bars on the top & bottom
+ predefinedDeviceProfiles.add(new InvariantDeviceProfile("Nexus 10",
+ 727, 1207, 5, 6, 4, 5, 4, 76, 14.4f, 7, 64, 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));
+ return predefinedDeviceProfiles;
+ }
+
+ private int getLauncherIconDensity(int requiredSize) {
+ // Densities typically defined by an app.
+ int[] densityBuckets = new int[] {
+ DisplayMetrics.DENSITY_LOW,
+ DisplayMetrics.DENSITY_MEDIUM,
+ DisplayMetrics.DENSITY_TV,
+ DisplayMetrics.DENSITY_HIGH,
+ DisplayMetrics.DENSITY_XHIGH,
+ DisplayMetrics.DENSITY_XXHIGH,
+ DisplayMetrics.DENSITY_XXXHIGH
+ };
+
+ int density = DisplayMetrics.DENSITY_XXXHIGH;
+ for (int i = densityBuckets.length - 1; i >= 0; i--) {
+ float expectedSize = ICON_SIZE_DEFINED_IN_APP_DP * densityBuckets[i]
+ / DisplayMetrics.DENSITY_DEFAULT;
+ if (expectedSize >= requiredSize) {
+ density = densityBuckets[i];
+ }
+ }
+
+ return density;
+ }
+
+ /**
+ * Apply any Partner customization grid overrides.
+ *
+ * Currently we support: all apps row / column count.
+ */
+ private void applyPartnerDeviceProfileOverrides(Context context, DisplayMetrics dm) {
+ Partner p = Partner.get(context.getPackageManager());
+ if (p != null) {
+ p.applyInvariantDeviceProfileOverrides(this, dm);
+ }
+ }
+
+ @Thunk float dist(float x0, float y0, float x1, float y1) {
+ return (float) Math.hypot(x1 - x0, y1 - y0);
+ }
+
+ /**
+ * Returns the closest device profiles ordered by closeness to the specified width and height
+ */
+ // Package private visibility for testing.
+ ArrayList<InvariantDeviceProfile> findClosestDeviceProfiles(
+ final float width, final float height, ArrayList<InvariantDeviceProfile> points) {
+
+ // Sort the profiles by their closeness to the dimensions
+ 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 pointsByNearness;
+ }
+
+ // Package private visibility for testing.
+ InvariantDeviceProfile invDistWeightedInterpolate(float width, float height,
+ ArrayList<InvariantDeviceProfile> points) {
+ float weights = 0;
+
+ InvariantDeviceProfile p = points.get(0);
+ if (dist(width, height, p.minWidthDps, p.minHeightDps) == 0) {
+ return p;
+ }
+
+ InvariantDeviceProfile out = new InvariantDeviceProfile();
+ for (int i = 0; i < points.size() && i < KNEARESTNEIGHBOR; ++i) {
+ p = new InvariantDeviceProfile(points.get(i));
+ float w = weight(width, height, p.minWidthDps, p.minHeightDps, WEIGHT_POWER);
+ weights += w;
+ out.add(p.multiply(w));
+ }
+ return out.multiply(1.0f/weights);
+ }
+
+ private void add(InvariantDeviceProfile p) {
+ iconSize += p.iconSize;
+ iconTextSize += p.iconTextSize;
+ hotseatIconSize += p.hotseatIconSize;
+ }
+
+ private InvariantDeviceProfile multiply(float w) {
+ iconSize *= w;
+ iconTextSize *= w;
+ hotseatIconSize *= w;
+ return this;
+ }
+
+ private float weight(float x0, float y0, float x1, float y1, float pow) {
+ float d = dist(x0, y0, x1, y1);
+ if (Float.compare(d, 0f) == 0) {
+ return Float.POSITIVE_INFINITY;
+ }
+ return (float) (WEIGHT_EFFICIENT / Math.pow(d, pow));
+ }
+} \ No newline at end of file
diff --git a/src/com/android/launcher3/ItemInfo.java b/src/com/android/launcher3/ItemInfo.java
index 09b77f756..f7e0ea488 100644
--- a/src/com/android/launcher3/ItemInfo.java
+++ b/src/com/android/launcher3/ItemInfo.java
@@ -20,13 +20,10 @@ import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
-import android.util.Log;
import com.android.launcher3.compat.UserHandleCompat;
import com.android.launcher3.compat.UserManagerCompat;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
import java.util.Arrays;
/**
@@ -39,7 +36,7 @@ public class ItemInfo {
*/
static final String EXTRA_PROFILE = "profile";
- static final int NO_ID = -1;
+ public static final int NO_ID = -1;
/**
* The id in the settings database for this item
@@ -85,7 +82,7 @@ public class ItemInfo {
/**
* Indicates the Y cell span.
*/
- int spanY = 1;
+ public int spanY = 1;
/**
* Indicates the minimum X cell span.
@@ -98,6 +95,11 @@ public class ItemInfo {
public int minSpanY = 1;
/**
+ * Indicates the position in an ordered list.
+ */
+ public int rank = 0;
+
+ /**
* Indicates that this item needs to be updated in the db
*/
public boolean requiresDbUpdate = false;
@@ -105,21 +107,21 @@ public class ItemInfo {
/**
* Title of the item
*/
- CharSequence title;
+ public CharSequence title;
/**
* Content description of the item.
*/
- CharSequence contentDescription;
+ public CharSequence contentDescription;
/**
* The position of the item in a drag-and-drop operation.
*/
- int[] dropPos = null;
+ public int[] dropPos = null;
- UserHandleCompat user;
+ public UserHandleCompat user;
- ItemInfo() {
+ public ItemInfo() {
user = UserHandleCompat.myUserHandle();
}
@@ -135,6 +137,7 @@ public class ItemInfo {
cellY = info.cellY;
spanX = info.spanX;
spanY = info.spanY;
+ rank = info.rank;
screenId = info.screenId;
itemType = info.itemType;
container = info.container;
@@ -161,6 +164,7 @@ public class ItemInfo {
values.put(LauncherSettings.Favorites.CELLY, cellY);
values.put(LauncherSettings.Favorites.SPANX, spanX);
values.put(LauncherSettings.Favorites.SPANY, spanY);
+ values.put(LauncherSettings.Favorites.RANK, rank);
long serialNumber = UserManagerCompat.getInstance(context).getSerialNumberForUser(user);
values.put(LauncherSettings.Favorites.PROFILE_ID, serialNumber);
@@ -170,30 +174,9 @@ public class ItemInfo {
}
}
- void updateValuesWithCoordinates(ContentValues values, int cellX, int cellY) {
- values.put(LauncherSettings.Favorites.CELLX, cellX);
- values.put(LauncherSettings.Favorites.CELLY, cellY);
- }
-
- static byte[] flattenBitmap(Bitmap bitmap) {
- // Try go guesstimate how much space the icon will take when serialized
- // to avoid unnecessary allocations/copies during the write.
- int size = bitmap.getWidth() * bitmap.getHeight() * 4;
- ByteArrayOutputStream out = new ByteArrayOutputStream(size);
- try {
- bitmap.compress(Bitmap.CompressFormat.PNG, 100, out);
- out.flush();
- out.close();
- return out.toByteArray();
- } catch (IOException e) {
- Log.w("Favorite", "Could not write icon");
- return null;
- }
- }
-
static void writeBitmap(ContentValues values, Bitmap bitmap) {
if (bitmap != null) {
- byte[] data = flattenBitmap(bitmap);
+ byte[] data = Utilities.flattenBitmap(bitmap);
values.put(LauncherSettings.Favorites.ICON, data);
}
}
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index ac46fd33d..6648b6e74 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -1,4 +1,3 @@
-
/*
* Copyright (C) 2008 The Android Open Source Project
*
@@ -22,8 +21,8 @@ import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.animation.PropertyValuesHolder;
-import android.animation.TimeInterpolator;
import android.animation.ValueAnimator;
+import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.app.Activity;
import android.app.ActivityManager;
@@ -37,25 +36,24 @@ import android.content.ActivityNotFoundException;
import android.content.BroadcastReceiver;
import android.content.ComponentCallbacks2;
import android.content.ComponentName;
-import android.content.ContentResolver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.IntentSender;
import android.content.SharedPreferences;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.Configuration;
-import android.content.res.Resources;
-import android.database.ContentObserver;
import android.database.sqlite.SQLiteDatabase;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.PorterDuff;
import android.graphics.Rect;
+import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.AsyncTask;
@@ -66,6 +64,7 @@ import android.os.Handler;
import android.os.Message;
import android.os.StrictMode;
import android.os.SystemClock;
+import android.os.UserHandle;
import android.text.Selection;
import android.text.SpannableStringBuilder;
import android.text.TextUtils;
@@ -82,40 +81,41 @@ import android.view.Surface;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnLongClickListener;
-import android.view.ViewAnimationUtils;
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.AccelerateInterpolator;
-import android.view.animation.DecelerateInterpolator;
+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;
import com.android.launcher3.DropTarget.DragObject;
import com.android.launcher3.PagedView.PageSwitchListener;
+import com.android.launcher3.allapps.AllAppsContainerView;
import com.android.launcher3.compat.AppWidgetManagerCompat;
import com.android.launcher3.compat.LauncherActivityInfoCompat;
import com.android.launcher3.compat.LauncherAppsCompat;
-import com.android.launcher3.compat.PackageInstallerCompat;
-import com.android.launcher3.compat.PackageInstallerCompat.PackageInstallInfo;
import com.android.launcher3.compat.UserHandleCompat;
import com.android.launcher3.compat.UserManagerCompat;
+import com.android.launcher3.model.WidgetsModel;
+import com.android.launcher3.util.ComponentKey;
+import com.android.launcher3.util.LongArrayMap;
+import com.android.launcher3.util.Thunk;
+import com.android.launcher3.widget.PendingAddWidgetInfo;
+import com.android.launcher3.widget.WidgetHostViewLoader;
+import com.android.launcher3.widget.WidgetsContainerView;
-import java.io.DataInputStream;
-import java.io.DataOutputStream;
import java.io.File;
import java.io.FileDescriptor;
-import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
-import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.text.DateFormat;
@@ -132,12 +132,13 @@ import java.util.concurrent.atomic.AtomicInteger;
*/
public class Launcher extends Activity
implements View.OnClickListener, OnLongClickListener, LauncherModel.Callbacks,
- View.OnTouchListener, PageSwitchListener, LauncherProviderChangeListener {
+ View.OnTouchListener, PageSwitchListener, LauncherProviderChangeListener,
+ LauncherStateTransitionAnimation.Callbacks {
static final String TAG = "Launcher";
static final boolean LOGD = false;
static final boolean PROFILE_STARTUP = false;
- static final boolean DEBUG_WIDGETS = false;
+ static final boolean DEBUG_WIDGETS = true;
static final boolean DEBUG_STRICT_MODE = false;
static final boolean DEBUG_RESUME_TIME = false;
static final boolean DEBUG_DUMP_LOG = false;
@@ -146,28 +147,29 @@ public class Launcher extends Activity
private static final int REQUEST_CREATE_SHORTCUT = 1;
private static final int REQUEST_CREATE_APPWIDGET = 5;
- private static final int REQUEST_PICK_SHORTCUT = 7;
private static final int REQUEST_PICK_APPWIDGET = 9;
private static final int REQUEST_PICK_WALLPAPER = 10;
private static final int REQUEST_BIND_APPWIDGET = 11;
private static final int REQUEST_RECONFIGURE_APPWIDGET = 12;
+ private static final int WORKSPACE_BACKGROUND_GRADIENT = 0;
+ private static final int WORKSPACE_BACKGROUND_TRANSPARENT = 1;
+ private static final int WORKSPACE_BACKGROUND_BLACK = 2;
+
+ private static final float BOUNCE_ANIMATION_TENSION = 1.3f;
+
/**
* IntentStarter uses request codes starting with this. This must be greater than all activity
* request codes used internally.
*/
protected static final int REQUEST_LAST = 100;
- static final String EXTRA_SHORTCUT_DUPLICATE = "duplicate";
-
static final int SCREEN_COUNT = 5;
- static final int DEFAULT_SCREEN = 2;
// To turn on these properties, type
// adb shell setprop log.tag.PROPERTY_NAME [VERBOSE | SUPPRESS]
static final String DUMP_STATE_PROPERTY = "launcher_dump_state";
- static final String DISABLE_ALL_APPS_PROPERTY = "launcher_noallapps";
// The Intent extra that defines whether to ignore the launch animation
static final String INTENT_EXTRA_IGNORE_LAUNCH_ANIMATION =
@@ -185,10 +187,6 @@ public class Launcher extends Activity
private static final String RUNTIME_STATE_PENDING_ADD_CELL_X = "launcher.add_cell_x";
// Type: int
private static final String RUNTIME_STATE_PENDING_ADD_CELL_Y = "launcher.add_cell_y";
- // Type: boolean
- private static final String RUNTIME_STATE_PENDING_FOLDER_RENAME = "launcher.rename_folder";
- // Type: long
- private static final String RUNTIME_STATE_PENDING_FOLDER_RENAME_ID = "launcher.rename_folder_id";
// Type: int
private static final String RUNTIME_STATE_PENDING_ADD_SPAN_X = "launcher.add_span_x";
// Type: int
@@ -216,9 +214,10 @@ public class Launcher extends Activity
public static final String USER_HAS_MIGRATED = "launcher.user_migrated_from_old_data";
/** The different states that Launcher can be in. */
- private enum State { NONE, WORKSPACE, APPS_CUSTOMIZE, APPS_CUSTOMIZE_SPRING_LOADED };
- private State mState = State.WORKSPACE;
- private AnimatorSet mStateAnimation;
+ enum State { NONE, WORKSPACE, APPS, APPS_SPRING_LOADED, WIDGETS, WIDGETS_SPRING_LOADED }
+
+ @Thunk State mState = State.WORKSPACE;
+ @Thunk LauncherStateTransitionAnimation mStateTransitionAnimation;
private boolean mIsSafeModeEnabled;
@@ -231,50 +230,50 @@ public class Launcher extends Activity
private static final int ON_ACTIVITY_RESULT_ANIMATION_DELAY = 500;
private static final int ACTIVITY_START_DELAY = 1000;
- private static final Object sLock = new Object();
- private static int sScreen = DEFAULT_SCREEN;
-
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;
- private static int NEW_APPS_ANIMATION_DELAY = 500;
- private static final int SINGLE_FRAME_DELAY = 16;
+ @Thunk static int NEW_APPS_ANIMATION_DELAY = 500;
private final BroadcastReceiver mCloseSystemDialogsReceiver
= new CloseSystemDialogsIntentReceiver();
- private final ContentObserver mWidgetObserver = new AppWidgetResetObserver();
private LayoutInflater mInflater;
- private Workspace mWorkspace;
+ @Thunk Workspace mWorkspace;
private View mLauncherView;
private View mPageIndicators;
- private DragLayer mDragLayer;
+ @Thunk DragLayer mDragLayer;
private DragController mDragController;
private View mWeightWatcher;
private AppWidgetManagerCompat mAppWidgetManager;
private LauncherAppWidgetHost mAppWidgetHost;
- private ItemInfo mPendingAddInfo = new ItemInfo();
- private AppWidgetProviderInfo mPendingAddWidgetInfo;
+ @Thunk ItemInfo mPendingAddInfo = new ItemInfo();
+ private LauncherAppWidgetProviderInfo mPendingAddWidgetInfo;
private int mPendingAddWidgetId = -1;
private int[] mTmpAddItemCellCoordinates = new int[2];
- private FolderInfo mFolderInfo;
-
- private Hotseat mHotseat;
+ @Thunk Hotseat mHotseat;
private ViewGroup mOverviewPanel;
private View mAllAppsButton;
+ private View mWidgetsButton;
private SearchDropTargetBar mSearchDropTargetBar;
- private AppsCustomizeTabHost mAppsCustomizeTabHost;
- private AppsCustomizePagedView mAppsCustomizeContent;
+
+ // Main container view for the all apps screen.
+ @Thunk AllAppsContainerView mAppsView;
+
+ // Main container view and the model for the widget tray screen.
+ @Thunk WidgetsContainerView mWidgetsView;
+ @Thunk WidgetsModel mWidgetsModel;
+
private boolean mAutoAdvanceRunning = false;
private AppWidgetHostView mQsb;
@@ -286,7 +285,7 @@ public class Launcher extends Activity
private SpannableStringBuilder mDefaultKeySsb = null;
- private boolean mWorkspaceLoading = true;
+ @Thunk boolean mWorkspaceLoading = true;
private boolean mPaused = true;
private boolean mRestoring;
@@ -300,14 +299,12 @@ public class Launcher extends Activity
private LauncherModel mModel;
private IconCache mIconCache;
- private boolean mUserPresent = true;
+ @Thunk boolean mUserPresent = true;
private boolean mVisible = false;
private boolean mHasFocus = false;
private boolean mAttached = false;
- private static LocaleConfiguration sLocaleConfiguration = null;
-
- private static HashMap<Long, FolderInfo> sFolders = new HashMap<Long, FolderInfo>();
+ private static LongArrayMap<FolderInfo> sFolders = new LongArrayMap<>();
private View.OnTouchListener mHapticFeedbackTouchListener;
@@ -317,14 +314,14 @@ public class Launcher extends Activity
private final int mAdvanceStagger = 250;
private long mAutoAdvanceSentTime;
private long mAutoAdvanceTimeLeft = -1;
- private HashMap<View, AppWidgetProviderInfo> mWidgetsToAdvance =
+ @Thunk HashMap<View, AppWidgetProviderInfo> mWidgetsToAdvance =
new HashMap<View, AppWidgetProviderInfo>();
// Determines how long to wait after a rotation before restoring the screen orientation to
// match the sensor state.
private final int mRestoreScreenOrientationDelay = 500;
- private Drawable mWorkspaceBackgroundDrawable;
+ @Thunk Drawable mWorkspaceBackgroundDrawable;
private final ArrayList<Integer> mSynchronouslyBoundPages = new ArrayList<Integer>();
private static final boolean DISABLE_SYNCHRONOUS_BINDING_CURRENT_PAGE = false;
@@ -340,18 +337,43 @@ public class Launcher extends Activity
// it from the context.
private SharedPreferences mSharedPrefs;
- private static ArrayList<ComponentName> mIntentsOnWorkspaceFromUpgradePath = null;
-
// Holds the page that we need to animate to, and the icon views that we need to animate up
// when we scroll to that page on resume.
- private ImageView mFolderIconImageView;
+ @Thunk ImageView mFolderIconImageView;
private Bitmap mFolderIconBitmap;
private Canvas mFolderIconCanvas;
private Rect mRectForFolderAnimation = new Rect();
+ private DeviceProfile mDeviceProfile;
+
+ // This is set to the view that launched the activity that navigated the user away from
+ // launcher. Since there is no callback for when the activity has finished launching, enable
+ // the press state and keep this reference to reset the press state when we return to launcher.
private BubbleTextView mWaitingForResume;
- private Runnable mBuildLayersRunnable = new Runnable() {
+ 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());
+ }
+ }
+
+ // TODO: remove this field and call method directly when Launcher3 can depend on M APIs
+ private static Method sClipRevealMethod = null;
+ static {
+ Class<?> activityOptionsClass = ActivityOptions.class;
+ try {
+ sClipRevealMethod = activityOptionsClass.getDeclaredMethod("makeClipRevealAnimation",
+ View.class, int.class, int.class, int.class, int.class);
+ } catch (Exception e) {
+ // Earlier version
+ }
+ }
+
+ @Thunk Runnable mBuildLayersRunnable = new Runnable() {
public void run() {
if (mWorkspace != null) {
mWorkspace.buildPageHardwareLayers();
@@ -361,7 +383,7 @@ public class Launcher extends Activity
private static PendingAddArguments sPendingAddItem;
- private static class PendingAddArguments {
+ @Thunk static class PendingAddArguments {
int requestCode;
Intent intent;
long container;
@@ -372,8 +394,23 @@ public class Launcher extends Activity
}
private Stats mStats;
-
FocusIndicatorView mFocusHandler;
+ private boolean mRotationEnabled = false;
+
+ @Thunk void setOrientation() {
+ if (mRotationEnabled) {
+ unlockScreenOrientation(true);
+ } else {
+ setRequestedOrientation(
+ ActivityInfo.SCREEN_ORIENTATION_NOSENSOR);
+ }
+ }
+
+ private Runnable mUpdateOrientationRunnable = new Runnable() {
+ public void run() {
+ setOrientation();
+ }
+ };
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -400,20 +437,22 @@ public class Launcher extends Activity
LauncherAppState.setApplicationContext(getApplicationContext());
LauncherAppState app = LauncherAppState.getInstance();
- LauncherAppState.getLauncherProvider().setLauncherProviderChangeListener(this);
- // Lazy-initialize the dynamic grid
- DeviceProfile grid = app.initDynamicGrid(this);
+ // Load configuration-specific DeviceProfile
+ mDeviceProfile = getResources().getConfiguration().orientation
+ == Configuration.ORIENTATION_LANDSCAPE ?
+ app.getInvariantDeviceProfile().landscapeProfile
+ : app.getInvariantDeviceProfile().portraitProfile;
- // the LauncherApplication should call this, but in case of Instrumentation it might not be present yet
mSharedPrefs = getSharedPreferences(LauncherAppState.getSharedPreferencesKey(),
Context.MODE_PRIVATE);
mIsSafeModeEnabled = getPackageManager().isSafeMode();
mModel = app.setLauncher(this);
mIconCache = app.getIconCache();
- mIconCache.flushInvalidIcons(grid);
+
mDragController = new DragController(this);
mInflater = getLayoutInflater();
+ mStateTransitionAnimation = new LauncherStateTransitionAnimation(this, this);
mStats = new Stats(this);
@@ -432,13 +471,10 @@ public class Launcher extends Activity
Environment.getExternalStorageDirectory() + "/launcher");
}
- checkForLocaleChange();
setContentView(R.layout.launcher);
setupViews();
- grid.layout(this);
-
- registerContentObservers();
+ mDeviceProfile.layout(this);
lockAllApps();
@@ -453,11 +489,11 @@ public class Launcher extends Activity
if (DISABLE_SYNCHRONOUS_BINDING_CURRENT_PAGE) {
// If the user leaves launcher, then we should just load items asynchronously when
// they return.
- mModel.startLoader(true, PagedView.INVALID_RESTORE_PAGE);
+ mModel.startLoader(PagedView.INVALID_RESTORE_PAGE);
} else {
// We only load the page synchronously if the user rotates (or triggers a
// configuration change) while launcher is in the foreground
- mModel.startLoader(true, mWorkspace.getRestorePage());
+ mModel.startLoader(mWorkspace.getRestorePage());
}
}
@@ -468,8 +504,16 @@ public class Launcher extends Activity
IntentFilter filter = new IntentFilter(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
registerReceiver(mCloseSystemDialogsReceiver, filter);
- // On large interfaces, we want the screen to auto-rotate based on the current orientation
- unlockScreenOrientation(true);
+ mRotationEnabled = Utilities.isRotationAllowedForDevice(getApplicationContext());
+ // In case we are on a device with locked rotation, we should look at preferences to check
+ // if the user has specifically allowed rotation.
+ if (!mRotationEnabled) {
+ mRotationEnabled = Utilities.isAllowRotationPrefEnabled(getApplicationContext(), false);
+ }
+
+ // On large interfaces, or on devices that a user has specifically enabled screen rotation,
+ // we want the screen to auto-rotate based on the current orientation
+ setOrientation();
if (mLauncherCallbacks != null) {
mLauncherCallbacks.onCreate(savedInstanceState);
@@ -490,6 +534,16 @@ public class Launcher extends Activity
}
}
+ @Override
+ public void onSettingsChanged(String settings, boolean value) {
+ if (Utilities.ALLOW_ROTATION_PREFERENCE_KEY.equals(settings)) {
+ mRotationEnabled = value;
+ if (!waitUntilResume(mUpdateOrientationRunnable, true)) {
+ mUpdateOrientationRunnable.run();
+ }
+ }
+ }
+
private LauncherCallbacks mLauncherCallbacks;
public void onPostCreate(Bundle savedInstanceState) {
@@ -501,6 +555,47 @@ public class Launcher extends Activity
public boolean setLauncherCallbacks(LauncherCallbacks callbacks) {
mLauncherCallbacks = callbacks;
+ mLauncherCallbacks.setLauncherSearchCallback(new Launcher.LauncherSearchCallbacks() {
+ private boolean mWorkspaceImportanceStored = false;
+ private boolean mHotseatImportanceStored = false;
+ private int mWorkspaceImportanceForAccessibility =
+ View.IMPORTANT_FOR_ACCESSIBILITY_AUTO;
+ private int mHotseatImportanceForAccessibility = View.IMPORTANT_FOR_ACCESSIBILITY_AUTO;
+
+ @Override
+ public void onSearchOverlayOpened() {
+ if (mWorkspaceImportanceStored || mHotseatImportanceStored) {
+ return;
+ }
+ // The underlying workspace and hotseat are temporarily suppressed by the search
+ // overlay. So they sholudn't be accessible.
+ if (mWorkspace != null) {
+ mWorkspaceImportanceForAccessibility =
+ mWorkspace.getImportantForAccessibility();
+ mWorkspace.setImportantForAccessibility(
+ View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS);
+ mWorkspaceImportanceStored = true;
+ }
+ if (mHotseat != null) {
+ mHotseatImportanceForAccessibility = mHotseat.getImportantForAccessibility();
+ mHotseat.setImportantForAccessibility(
+ View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS);
+ mHotseatImportanceStored = true;
+ }
+ }
+
+ @Override
+ public void onSearchOverlayClosed() {
+ if (mWorkspaceImportanceStored && mWorkspace != null) {
+ mWorkspace.setImportantForAccessibility(mWorkspaceImportanceForAccessibility);
+ }
+ if (mHotseatImportanceStored && mHotseat != null) {
+ mHotseat.setImportantForAccessibility(mHotseatImportanceForAccessibility);
+ }
+ mWorkspaceImportanceStored = false;
+ mHotseatImportanceStored = false;
+ }
+ });
return true;
}
@@ -511,6 +606,14 @@ public class Launcher extends Activity
}
}
+ /**
+ * Updates the bounds of all the overlays to match the new fixed bounds.
+ */
+ public void updateOverlayBounds(Rect newBounds) {
+ mAppsView.setSearchBarBounds(newBounds);
+ mWidgetsView.setSearchBarBounds(newBounds);
+ }
+
/** To be overridden by subclasses to hint to Launcher that we have custom content */
protected boolean hasCustomContentToLeft() {
if (mLauncherCallbacks != null) {
@@ -549,108 +652,6 @@ public class Launcher extends Activity
}
}
- private void checkForLocaleChange() {
- if (sLocaleConfiguration == null) {
- new AsyncTask<Void, Void, LocaleConfiguration>() {
- @Override
- protected LocaleConfiguration doInBackground(Void... unused) {
- LocaleConfiguration localeConfiguration = new LocaleConfiguration();
- readConfiguration(Launcher.this, localeConfiguration);
- return localeConfiguration;
- }
-
- @Override
- protected void onPostExecute(LocaleConfiguration result) {
- sLocaleConfiguration = result;
- checkForLocaleChange(); // recursive, but now with a locale configuration
- }
- }.execute();
- return;
- }
-
- final Configuration configuration = getResources().getConfiguration();
-
- final String previousLocale = sLocaleConfiguration.locale;
- final String locale = configuration.locale.toString();
-
- final int previousMcc = sLocaleConfiguration.mcc;
- final int mcc = configuration.mcc;
-
- final int previousMnc = sLocaleConfiguration.mnc;
- final int mnc = configuration.mnc;
-
- boolean localeChanged = !locale.equals(previousLocale) || mcc != previousMcc || mnc != previousMnc;
-
- if (localeChanged) {
- sLocaleConfiguration.locale = locale;
- sLocaleConfiguration.mcc = mcc;
- sLocaleConfiguration.mnc = mnc;
-
- mIconCache.flush();
-
- final LocaleConfiguration localeConfiguration = sLocaleConfiguration;
- new AsyncTask<Void, Void, Void>() {
- public Void doInBackground(Void ... args) {
- writeConfiguration(Launcher.this, localeConfiguration);
- return null;
- }
- }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void) null);
- }
- }
-
- private static class LocaleConfiguration {
- public String locale;
- public int mcc = -1;
- public int mnc = -1;
- }
-
- private static void readConfiguration(Context context, LocaleConfiguration configuration) {
- DataInputStream in = null;
- try {
- in = new DataInputStream(context.openFileInput(LauncherFiles.LAUNCHER_PREFERENCES));
- configuration.locale = in.readUTF();
- configuration.mcc = in.readInt();
- configuration.mnc = in.readInt();
- } catch (FileNotFoundException e) {
- // Ignore
- } catch (IOException e) {
- // Ignore
- } finally {
- if (in != null) {
- try {
- in.close();
- } catch (IOException e) {
- // Ignore
- }
- }
- }
- }
-
- private static void writeConfiguration(Context context, LocaleConfiguration configuration) {
- DataOutputStream out = null;
- try {
- out = new DataOutputStream(context.openFileOutput(
- LauncherFiles.LAUNCHER_PREFERENCES, MODE_PRIVATE));
- out.writeUTF(configuration.locale);
- out.writeInt(configuration.mcc);
- out.writeInt(configuration.mnc);
- out.flush();
- } catch (FileNotFoundException e) {
- // Ignore
- } catch (IOException e) {
- //noinspection ResultOfMethodCallIgnored
- context.getFileStreamPath(LauncherFiles.LAUNCHER_PREFERENCES).delete();
- } finally {
- if (out != null) {
- try {
- out.close();
- } catch (IOException e) {
- // Ignore
- }
- }
- }
- }
-
public Stats getStats() {
return mStats;
}
@@ -659,24 +660,13 @@ public class Launcher extends Activity
return mInflater;
}
- boolean isDraggingEnabled() {
+ public boolean isDraggingEnabled() {
// We prevent dragging when we are loading the workspace as it is possible to pick up a view
// that is subsequently removed from the workspace in startBinding().
return !mModel.isLoadingWorkspace();
}
- static int getScreen() {
- synchronized (sLock) {
- return sScreen;
- }
- }
-
- static void setScreen(int screen) {
- synchronized (sLock) {
- sScreen = screen;
- }
- }
-
+ @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
public static int generateViewId() {
if (Build.VERSION.SDK_INT >= 17) {
return View.generateViewId();
@@ -766,7 +756,7 @@ public class Launcher extends Activity
return;
} else if (requestCode == REQUEST_PICK_WALLPAPER) {
if (resultCode == RESULT_OK && mWorkspace.isInOverviewMode()) {
- mWorkspace.exitOverviewMode(false);
+ showWorkspace(false);
}
return;
}
@@ -882,6 +872,15 @@ public class Launcher extends Activity
}
}
+ /** @Override for MNC */
+ public void onRequestPermissionsResult(int requestCode, String[] permissions,
+ int[] grantResults) {
+ if (mLauncherCallbacks != null) {
+ mLauncherCallbacks.onRequestPermissionsResult(requestCode, permissions,
+ grantResults);
+ }
+ }
+
private PendingAddArguments preparePendingAddArgs(int requestCode, Intent data, int
appWidgetId, ItemInfo info) {
PendingAddArguments args = new PendingAddArguments();
@@ -914,7 +913,7 @@ public class Launcher extends Activity
}
}
- private void completeTwoStageWidgetDrop(final int resultCode, final int appWidgetId) {
+ @Thunk void completeTwoStageWidgetDrop(final int resultCode, final int appWidgetId) {
CellLayout cellLayout =
(CellLayout) mWorkspace.getScreenWithId(mPendingAddInfo.screenId);
Runnable onCompleteRunnable = null;
@@ -986,18 +985,26 @@ public class Launcher extends Activity
// Restore the previous launcher state
if (mOnResumeState == State.WORKSPACE) {
showWorkspace(false);
- } else if (mOnResumeState == State.APPS_CUSTOMIZE) {
- showAllApps(false, mAppsCustomizeContent.getContentType(), false);
+ } else if (mOnResumeState == State.APPS) {
+ boolean launchedFromApp = (mWaitingForResume != null);
+ // Don't update the predicted apps if the user is returning to launcher in the apps
+ // view after launching an app, as they may be depending on the UI to be static to
+ // switch to another app, otherwise, if it was
+ showAppsView(false /* animated */, false /* resetListToTop */,
+ !launchedFromApp /* updatePredictedApps */, false /* focusSearchBar */);
+ } else if (mOnResumeState == State.WIDGETS) {
+ showWidgetsView(false, false);
}
mOnResumeState = State.NONE;
- // Background was set to gradient in onPause(), restore to black if in all apps.
- setWorkspaceBackground(mState == State.WORKSPACE);
+ // Background was set to gradient in onPause(), restore to transparent if in all apps.
+ setWorkspaceBackground(mState == State.WORKSPACE ? WORKSPACE_BACKGROUND_GRADIENT
+ : WORKSPACE_BACKGROUND_TRANSPARENT);
mPaused = false;
if (mRestoring || mOnResumeNeedsLoad) {
setWorkspaceLoading(true);
- mModel.startLoader(true, PagedView.INVALID_RESTORE_PAGE);
+ mModel.startLoader(PagedView.INVALID_RESTORE_PAGE);
mRestoring = false;
mOnResumeNeedsLoad = false;
}
@@ -1009,15 +1016,9 @@ public class Launcher extends Activity
startTimeCallbacks = System.currentTimeMillis();
}
- if (mAppsCustomizeContent != null) {
- mAppsCustomizeContent.setBulkBind(true);
- }
for (int i = 0; i < mBindOnResumeCallbacks.size(); i++) {
mBindOnResumeCallbacks.get(i).run();
}
- if (mAppsCustomizeContent != null) {
- mAppsCustomizeContent.setBulkBind(false);
- }
mBindOnResumeCallbacks.clear();
if (DEBUG_RESUME_TIME) {
Log.d(TAG, "Time spent processing callbacks in onResume: " +
@@ -1043,9 +1044,7 @@ public class Launcher extends Activity
// (framework issue). On resuming, we ensure that any widgets are inflated for the current
// orientation.
getWorkspace().reinflateWidgetsIfNecessary();
-
- // Process any items that were added while Launcher was away.
- InstallShortcutReceiver.disableAndFlushInstallQueue(this);
+ reinflateQSBIfNecessary();
if (DEBUG_RESUME_TIME) {
Log.d(TAG, "Time spent in onResume: " + (System.currentTimeMillis() - startTime));
@@ -1059,10 +1058,13 @@ public class Launcher extends Activity
mWorkspace.getCustomContentCallbacks().onShow(true);
}
}
- mWorkspace.updateInteractionForState();
+ updateInteraction(Workspace.State.NORMAL, mWorkspace.getState());
mWorkspace.onResume();
- PackageInstallerCompat.getInstance(this).onResume();
+ if (!isWorkspaceLoading()) {
+ // Process any items that were added while Launcher was away.
+ InstallShortcutReceiver.disableAndFlushInstallQueue(this);
+ }
if (mLauncherCallbacks != null) {
mLauncherCallbacks.onResume();
@@ -1073,7 +1075,6 @@ public class Launcher extends Activity
protected void onPause() {
// Ensure that items added to Launcher are queued until Launcher returns
InstallShortcutReceiver.enableInstallQueue();
- PackageInstallerCompat.getInstance(this).onPause();
super.onPause();
mPaused = true;
@@ -1136,6 +1137,18 @@ public class Launcher extends Activity
public void forceExitFullImmersion();
}
+ public interface LauncherSearchCallbacks {
+ /**
+ * Called when the search overlay is shown.
+ */
+ public void onSearchOverlayOpened();
+
+ /**
+ * Called when the search overlay is dismissed.
+ */
+ public void onSearchOverlayClosed();
+ }
+
public interface LauncherOverlayCallbacks {
/**
* This method indicates whether a call to {@link #enterFullImmersion()} will succeed,
@@ -1187,11 +1200,13 @@ public class Launcher extends Activity
protected boolean hasSettings() {
if (mLauncherCallbacks != null) {
return mLauncherCallbacks.hasSettings();
+ } else {
+ // On devices with a locked orientation, we will at least have the allow rotation
+ // setting.
+ return !Utilities.isRotationAllowedForDevice(this);
}
- return false;
}
-
public void addToCustomContentPage(View customContent,
CustomContentCallbacks callbacks, String description) {
mWorkspace.addToCustomContentPage(customContent, callbacks, description);
@@ -1208,9 +1223,8 @@ public class Launcher extends Activity
if (mModel.isCurrentCallbacks(this)) {
mModel.stopLoader();
}
- if (mAppsCustomizeContent != null) {
- mAppsCustomizeContent.surrender();
- }
+ //TODO(hyunyoungs): stop the widgets loader when there is a rotation.
+
return Boolean.TRUE;
}
@@ -1296,8 +1310,8 @@ public class Launcher extends Activity
}
State state = intToState(savedState.getInt(RUNTIME_STATE, State.WORKSPACE.ordinal()));
- if (state == State.APPS_CUSTOMIZE) {
- mOnResumeState = State.APPS_CUSTOMIZE;
+ if (state == State.APPS || state == State.WIDGETS) {
+ mOnResumeState = state;
}
int currentScreen = savedState.getInt(RUNTIME_STATE_CURRENT_SCREEN,
@@ -1316,32 +1330,16 @@ public class Launcher extends Activity
mPendingAddInfo.cellY = savedState.getInt(RUNTIME_STATE_PENDING_ADD_CELL_Y);
mPendingAddInfo.spanX = savedState.getInt(RUNTIME_STATE_PENDING_ADD_SPAN_X);
mPendingAddInfo.spanY = savedState.getInt(RUNTIME_STATE_PENDING_ADD_SPAN_Y);
- mPendingAddWidgetInfo = savedState.getParcelable(RUNTIME_STATE_PENDING_ADD_WIDGET_INFO);
+ AppWidgetProviderInfo info = savedState.getParcelable(
+ RUNTIME_STATE_PENDING_ADD_WIDGET_INFO);
+ mPendingAddWidgetInfo = info == null ?
+ null : LauncherAppWidgetProviderInfo.fromProviderInfo(this, info);
+
mPendingAddWidgetId = savedState.getInt(RUNTIME_STATE_PENDING_ADD_WIDGET_ID);
setWaitingForResult(true);
mRestoring = true;
}
- boolean renameFolder = savedState.getBoolean(RUNTIME_STATE_PENDING_FOLDER_RENAME, false);
- if (renameFolder) {
- long id = savedState.getLong(RUNTIME_STATE_PENDING_FOLDER_RENAME_ID);
- mFolderInfo = mModel.getFolderById(this, sFolders, id);
- mRestoring = true;
- }
-
- // Restore the AppsCustomize tab
- if (mAppsCustomizeTabHost != null) {
- String curTab = savedState.getString("apps_customize_currentTab");
- if (curTab != null) {
- mAppsCustomizeTabHost.setContentTypeImmediate(
- mAppsCustomizeTabHost.getContentTypeForTabTag(curTab));
- mAppsCustomizeContent.loadAssociatedPages(
- mAppsCustomizeContent.getCurrentPage());
- }
-
- int currentIndex = savedState.getInt("apps_customize_currentIndex");
- mAppsCustomizeContent.restorePageForIndex(currentIndex);
- }
mItemIdToViewId = (HashMap<Integer, Integer>)
savedState.getSerializable(RUNTIME_STATE_VIEW_IDS);
}
@@ -1369,13 +1367,12 @@ public class Launcher extends Activity
// Setup the hotseat
mHotseat = (Hotseat) findViewById(R.id.hotseat);
if (mHotseat != null) {
- mHotseat.setup(this);
mHotseat.setOnLongClickListener(this);
}
mOverviewPanel = (ViewGroup) findViewById(R.id.overview_panel);
- View widgetButton = findViewById(R.id.widget_button);
- widgetButton.setOnClickListener(new OnClickListener() {
+ mWidgetsButton = findViewById(R.id.widget_button);
+ mWidgetsButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
if (!mWorkspace.isSwitchingState()) {
@@ -1383,7 +1380,7 @@ public class Launcher extends Activity
}
}
});
- widgetButton.setOnTouchListener(getHapticFeedbackTouchListener());
+ mWidgetsButton.setOnTouchListener(getHapticFeedbackTouchListener());
View wallpaperButton = findViewById(R.id.wallpaper_button);
wallpaperButton.setOnClickListener(new OnClickListener() {
@@ -1423,11 +1420,14 @@ public class Launcher extends Activity
mSearchDropTargetBar = (SearchDropTargetBar)
mDragLayer.findViewById(R.id.search_drop_target_bar);
- // Setup AppsCustomize
- mAppsCustomizeTabHost = (AppsCustomizeTabHost) findViewById(R.id.apps_customize_pane);
- mAppsCustomizeContent = (AppsCustomizePagedView)
- mAppsCustomizeTabHost.findViewById(R.id.apps_customize_pane_content);
- mAppsCustomizeContent.setup(this, dragController);
+ // Setup Apps and Widgets
+ mAppsView = (AllAppsContainerView) findViewById(R.id.apps_view);
+ mWidgetsView = (WidgetsContainerView) findViewById(R.id.widgets_view);
+ if (mLauncherCallbacks != null && mLauncherCallbacks.getAllAppsSearchBarController() != null) {
+ mAppsView.setSearchBarController(mLauncherCallbacks.getAllAppsSearchBarController());
+ } else {
+ mAppsView.setSearchBarController(mAppsView.newDefaultAppSearchController());
+ }
// Setup the drag controller (drop targets have to be added in reverse order in priority)
dragController.setDragScoller(mWorkspace);
@@ -1436,7 +1436,7 @@ public class Launcher extends Activity
dragController.addDropTarget(mWorkspace);
if (mSearchDropTargetBar != null) {
mSearchDropTargetBar.setup(this, dragController);
- mSearchDropTargetBar.setQsbSearchBar(getQsbBar());
+ mSearchDropTargetBar.setQsbSearchBar(getOrCreateQsbBar());
}
if (getResources().getBoolean(R.bool.debug_memory_enabled)) {
@@ -1466,30 +1466,32 @@ public class Launcher extends Activity
return mAllAppsButton;
}
+ public View getWidgetsButton() {
+ return mWidgetsButton;
+ }
+
/**
* Creates a view representing a shortcut.
*
* @param info The data structure describing the shortcut.
- *
- * @return A View inflated from R.layout.application.
*/
View createShortcut(ShortcutInfo info) {
- return createShortcut(R.layout.application,
- (ViewGroup) mWorkspace.getChildAt(mWorkspace.getCurrentPage()), info);
+ return createShortcut((ViewGroup) mWorkspace.getChildAt(mWorkspace.getCurrentPage()), info);
}
/**
* Creates a view representing a shortcut inflated from the specified resource.
*
- * @param layoutResId The id of the XML layout used to create the shortcut.
* @param parent The group the shortcut belongs to.
* @param info The data structure describing the shortcut.
*
* @return A View inflated from layoutResId.
*/
- View createShortcut(int layoutResId, ViewGroup parent, ShortcutInfo info) {
- BubbleTextView favorite = (BubbleTextView) mInflater.inflate(layoutResId, parent, false);
- favorite.applyFromShortcutInfo(info, mIconCache, true);
+ public View createShortcut(ViewGroup parent, ShortcutInfo info) {
+ BubbleTextView favorite = (BubbleTextView) mInflater.inflate(R.layout.app_icon,
+ parent, false);
+ favorite.applyFromShortcutInfo(info, mIconCache);
+ favorite.setCompoundDrawablePadding(mDeviceProfile.iconDrawablePaddingPx);
favorite.setOnClickListener(this);
favorite.setOnFocusChangeListener(mFocusHandler);
return favorite;
@@ -1499,7 +1501,6 @@ public class Launcher extends Activity
* Add a shortcut to the workspace.
*
* @param data The intent describing the shortcut.
- * @param cellInfo The position on screen where to create the shortcut.
*/
private void completeAddShortcut(Intent data, long container, long screenId, int cellX,
int cellY) {
@@ -1507,14 +1508,13 @@ public class Launcher extends Activity
int[] touchXY = mPendingAddInfo.dropPos;
CellLayout layout = getCellLayout(container, screenId);
- boolean foundCellSpan = false;
-
- ShortcutInfo info = mModel.infoFromShortcutIntent(this, data);
+ ShortcutInfo info = InstallShortcutReceiver.fromShortcutIntent(this, data);
if (info == null) {
return;
}
final View view = createShortcut(info);
+ boolean foundCellSpan = false;
// First we check if we already know the exact location where we want to add this item.
if (cellX >= 0 && cellY >= 0) {
cellXY[0] = cellX;
@@ -1545,7 +1545,7 @@ public class Launcher extends Activity
return;
}
- LauncherModel.addItemToDatabase(this, info, container, screenId, cellXY[0], cellXY[1], false);
+ LauncherModel.addItemToDatabase(this, info, container, screenId, cellXY[0], cellXY[1]);
if (!mRestoring) {
mWorkspace.addInScreen(view, container, screenId, cellXY[0], cellXY[1], 1, 1,
@@ -1553,119 +1553,67 @@ public class Launcher extends Activity
}
}
- static int[] getSpanForWidget(Context context, ComponentName component, int minWidth,
- int minHeight) {
- Rect padding = AppWidgetHostView.getDefaultPaddingForWidget(context, component, null);
+ private int[] getSpanForWidget(ComponentName component, int minWidth, int minHeight) {
+ Rect padding = AppWidgetHostView.getDefaultPaddingForWidget(this, component, null);
// We want to account for the extra amount of padding that we are adding to the widget
// to ensure that it gets the full amount of space that it has requested
int requiredWidth = minWidth + padding.left + padding.right;
int requiredHeight = minHeight + padding.top + padding.bottom;
- return CellLayout.rectToCell(requiredWidth, requiredHeight, null);
- }
-
- static int[] getSpanForWidget(Context context, AppWidgetProviderInfo info) {
- return getSpanForWidget(context, info.provider, info.minWidth, info.minHeight);
- }
-
- static int[] getMinSpanForWidget(Context context, AppWidgetProviderInfo info) {
- return getSpanForWidget(context, info.provider, info.minResizeWidth, info.minResizeHeight);
+ return CellLayout.rectToCell(this, requiredWidth, requiredHeight, null);
}
- static int[] getSpanForWidget(Context context, PendingAddWidgetInfo info) {
- return getSpanForWidget(context, info.componentName, info.minWidth, info.minHeight);
+ public int[] getSpanForWidget(AppWidgetProviderInfo info) {
+ return getSpanForWidget(info.provider, info.minWidth, info.minHeight);
}
- static int[] getMinSpanForWidget(Context context, PendingAddWidgetInfo info) {
- return getSpanForWidget(context, info.componentName, info.minResizeWidth,
- info.minResizeHeight);
+ public int[] getMinSpanForWidget(AppWidgetProviderInfo info) {
+ return getSpanForWidget(info.provider, info.minResizeWidth, info.minResizeHeight);
}
/**
* Add a widget to the workspace.
*
* @param appWidgetId The app widget id
- * @param cellInfo The position on screen where to create the widget.
*/
- private void completeAddAppWidget(final int appWidgetId, long container, long screenId,
- AppWidgetHostView hostView, AppWidgetProviderInfo appWidgetInfo) {
- if (appWidgetInfo == null) {
- appWidgetInfo = mAppWidgetManager.getAppWidgetInfo(appWidgetId);
- }
+ @Thunk void completeAddAppWidget(int appWidgetId, long container, long screenId,
+ AppWidgetHostView hostView, LauncherAppWidgetProviderInfo appWidgetInfo) {
- // Calculate the grid spans needed to fit this widget
- CellLayout layout = getCellLayout(container, screenId);
-
- int[] minSpanXY = getMinSpanForWidget(this, appWidgetInfo);
- int[] spanXY = getSpanForWidget(this, appWidgetInfo);
-
- // Try finding open space on Launcher screen
- // We have saved the position to which the widget was dragged-- this really only matters
- // if we are placing widgets on a "spring-loaded" screen
- int[] cellXY = mTmpAddItemCellCoordinates;
- int[] touchXY = mPendingAddInfo.dropPos;
- int[] finalSpan = new int[2];
- boolean foundCellSpan = false;
- if (mPendingAddInfo.cellX >= 0 && mPendingAddInfo.cellY >= 0) {
- cellXY[0] = mPendingAddInfo.cellX;
- cellXY[1] = mPendingAddInfo.cellY;
- spanXY[0] = mPendingAddInfo.spanX;
- spanXY[1] = mPendingAddInfo.spanY;
- foundCellSpan = true;
- } else if (touchXY != null) {
- // when dragging and dropping, just find the closest free spot
- int[] result = layout.findNearestVacantArea(
- touchXY[0], touchXY[1], minSpanXY[0], minSpanXY[1], spanXY[0],
- spanXY[1], cellXY, finalSpan);
- spanXY[0] = finalSpan[0];
- spanXY[1] = finalSpan[1];
- foundCellSpan = (result != null);
- } else {
- foundCellSpan = layout.findCellForSpan(cellXY, minSpanXY[0], minSpanXY[1]);
+ ItemInfo info = mPendingAddInfo;
+ if (appWidgetInfo == null) {
+ appWidgetInfo = LauncherAppWidgetProviderInfo.fromProviderInfo(this,
+ mAppWidgetManager.getAppWidgetInfo(appWidgetId));
}
- if (!foundCellSpan) {
- if (appWidgetId != -1) {
- // 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) {
- mAppWidgetHost.deleteAppWidgetId(appWidgetId);
- return null;
- }
- }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void) null);
- }
- showOutOfSpaceMessage(isHotseatLayout(layout));
- return;
+ if (appWidgetInfo.isCustomWidget) {
+ appWidgetId = LauncherAppWidgetInfo.CUSTOM_WIDGET_ID;
}
- // Build Launcher-specific widget info and save to database
- LauncherAppWidgetInfo launcherInfo = new LauncherAppWidgetInfo(appWidgetId,
- appWidgetInfo.provider);
- launcherInfo.spanX = spanXY[0];
- launcherInfo.spanY = spanXY[1];
- launcherInfo.minSpanX = mPendingAddInfo.minSpanX;
- launcherInfo.minSpanY = mPendingAddInfo.minSpanY;
+ LauncherAppWidgetInfo launcherInfo;
+ launcherInfo = new LauncherAppWidgetInfo(appWidgetId, appWidgetInfo.provider);
+ launcherInfo.spanX = info.spanX;
+ launcherInfo.spanY = info.spanY;
+ launcherInfo.minSpanX = info.minSpanX;
+ launcherInfo.minSpanY = info.minSpanY;
launcherInfo.user = mAppWidgetManager.getUser(appWidgetInfo);
LauncherModel.addItemToDatabase(this, launcherInfo,
- container, screenId, cellXY[0], cellXY[1], false);
+ container, screenId, info.cellX, info.cellY);
if (!mRestoring) {
if (hostView == null) {
// Perform actual inflation because we're live
- launcherInfo.hostView = mAppWidgetHost.createView(this, appWidgetId, appWidgetInfo);
- launcherInfo.hostView.setAppWidget(appWidgetId, appWidgetInfo);
+ launcherInfo.hostView = mAppWidgetHost.createView(this, appWidgetId,
+ appWidgetInfo);
} else {
// 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, cellXY[0], cellXY[1],
- launcherInfo.spanX, launcherInfo.spanY, isWorkspaceLocked());
+ mWorkspace.addInScreen(launcherInfo.hostView, container, screenId, info.cellX,
+ info.cellY, launcherInfo.spanX, launcherInfo.spanY, isWorkspaceLocked());
addWidgetToAutoAdvanceIfNeeded(launcherInfo.hostView, appWidgetInfo);
}
@@ -1679,28 +1627,26 @@ public class Launcher extends Activity
if (Intent.ACTION_SCREEN_OFF.equals(action)) {
mUserPresent = false;
mDragLayer.clearAllResizeFrames();
- updateRunning();
+ updateAutoAdvanceState();
// Reset AllApps to its initial state only if we are not in the middle of
// processing a multi-step drop
- if (mAppsCustomizeTabHost != null && mPendingAddInfo.container == ItemInfo.NO_ID) {
+ if (mAppsView != null && mWidgetsView != null &&
+ mPendingAddInfo.container == ItemInfo.NO_ID) {
showWorkspace(false);
}
} else if (Intent.ACTION_USER_PRESENT.equals(action)) {
mUserPresent = true;
- updateRunning();
+ updateAutoAdvanceState();
} else if (ENABLE_DEBUG_INTENTS && DebugIntents.DELETE_DATABASE.equals(action)) {
mModel.resetLoadedState(false, true);
- mModel.startLoader(false, PagedView.INVALID_RESTORE_PAGE,
+ mModel.startLoader(PagedView.INVALID_RESTORE_PAGE,
LauncherModel.LOADER_FLAG_CLEAR_WORKSPACE);
} else if (ENABLE_DEBUG_INTENTS && DebugIntents.MIGRATE_DATABASE.equals(action)) {
mModel.resetLoadedState(false, true);
- mModel.startLoader(false, PagedView.INVALID_RESTORE_PAGE,
+ mModel.startLoader(PagedView.INVALID_RESTORE_PAGE,
LauncherModel.LOADER_FLAG_CLEAR_WORKSPACE
| LauncherModel.LOADER_FLAG_MIGRATE_SHORTCUTS);
- } else if (LauncherAppsCompat.ACTION_MANAGED_PROFILE_ADDED.equals(action)
- || LauncherAppsCompat.ACTION_MANAGED_PROFILE_REMOVED.equals(action)) {
- getModel().forceReload();
}
}
};
@@ -1714,8 +1660,6 @@ public class Launcher extends Activity
filter.addAction(Intent.ACTION_SCREEN_OFF);
filter.addAction(Intent.ACTION_USER_PRESENT);
// For handling managed profiles
- filter.addAction(LauncherAppsCompat.ACTION_MANAGED_PROFILE_ADDED);
- filter.addAction(LauncherAppsCompat.ACTION_MANAGED_PROFILE_REMOVED);
if (ENABLE_DEBUG_INTENTS) {
filter.addAction(DebugIntents.DELETE_DATABASE);
filter.addAction(DebugIntents.MIGRATE_DATABASE);
@@ -1731,40 +1675,19 @@ public class Launcher extends Activity
* Sets up transparent navigation and status bars in LMP.
* This method is a no-op for other platform versions.
*/
- @TargetApi(19)
+ @TargetApi(Build.VERSION_CODES.LOLLIPOP)
private void setupTransparentSystemBarsForLmp() {
- // TODO(sansid): use the APIs directly when compiling against L sdk.
- // Currently we use reflection to access the flags and the API to set the transparency
- // on the System bars.
if (Utilities.isLmpOrAbove()) {
- try {
- getWindow().getAttributes().systemUiVisibility |=
- (View.SYSTEM_UI_FLAG_LAYOUT_STABLE
- | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
- | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);
- getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS
- | WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
- Field drawsSysBackgroundsField = WindowManager.LayoutParams.class.getField(
- "FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS");
- getWindow().addFlags(drawsSysBackgroundsField.getInt(null));
-
- Method setStatusBarColorMethod =
- Window.class.getDeclaredMethod("setStatusBarColor", int.class);
- Method setNavigationBarColorMethod =
- Window.class.getDeclaredMethod("setNavigationBarColor", int.class);
- setStatusBarColorMethod.invoke(getWindow(), Color.TRANSPARENT);
- setNavigationBarColorMethod.invoke(getWindow(), Color.TRANSPARENT);
- } catch (NoSuchFieldException e) {
- Log.w(TAG, "NoSuchFieldException while setting up transparent bars");
- } catch (NoSuchMethodException ex) {
- Log.w(TAG, "NoSuchMethodException while setting up transparent bars");
- } catch (IllegalAccessException e) {
- Log.w(TAG, "IllegalAccessException while setting up transparent bars");
- } catch (IllegalArgumentException e) {
- Log.w(TAG, "IllegalArgumentException while setting up transparent bars");
- } catch (InvocationTargetException e) {
- Log.w(TAG, "InvocationTargetException while setting up transparent bars");
- } finally {}
+ 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);
}
}
@@ -1777,17 +1700,16 @@ public class Launcher extends Activity
unregisterReceiver(mReceiver);
mAttached = false;
}
- updateRunning();
+ updateAutoAdvanceState();
}
public void onWindowVisibilityChanged(int visibility) {
mVisible = visibility == View.VISIBLE;
- updateRunning();
+ updateAutoAdvanceState();
// The following code used to be in onResume, but it turns out onResume is called when
// you're in All Apps and click home to go to the workspace. onWindowVisibilityChanged
// is a more appropriate event to handle
if (mVisible) {
- mAppsCustomizeTabHost.onWindowVisible();
if (!mWorkspaceLoading) {
final ViewTreeObserver observer = mWorkspace.getViewTreeObserver();
// We want to let Launcher draw itself at least once before we force it to build
@@ -1822,14 +1744,14 @@ public class Launcher extends Activity
}
}
- private void sendAdvanceMessage(long delay) {
+ @Thunk void sendAdvanceMessage(long delay) {
mHandler.removeMessages(ADVANCE_MSG);
Message msg = mHandler.obtainMessage(ADVANCE_MSG);
mHandler.sendMessageDelayed(msg, delay);
mAutoAdvanceSentTime = System.currentTimeMillis();
}
- private void updateRunning() {
+ @Thunk void updateAutoAdvanceState() {
boolean autoAdvanceRunning = mVisible && mUserPresent && !mWidgetsToAdvance.isEmpty();
if (autoAdvanceRunning != mAutoAdvanceRunning) {
mAutoAdvanceRunning = autoAdvanceRunning;
@@ -1847,16 +1769,17 @@ public class Launcher extends Activity
}
}
- private final Handler mHandler = new Handler() {
+ @Thunk final Handler mHandler = new Handler(new Handler.Callback() {
+
@Override
- public void handleMessage(Message msg) {
+ public boolean handleMessage(Message msg) {
if (msg.what == ADVANCE_MSG) {
int i = 0;
for (View key: mWidgetsToAdvance.keySet()) {
final View v = key.findViewById(mWidgetsToAdvance.get(key).autoAdvanceViewId);
final int delay = mAdvanceStagger * i;
if (v instanceof Advanceable) {
- postDelayed(new Runnable() {
+ mHandler.postDelayed(new Runnable() {
public void run() {
((Advanceable) v).advance();
}
@@ -1866,8 +1789,9 @@ public class Launcher extends Activity
}
sendAdvanceMessage(mAdvanceInterval);
}
+ return true;
}
- };
+ });
void addWidgetToAutoAdvanceIfNeeded(View hostView, AppWidgetProviderInfo appWidgetInfo) {
if (appWidgetInfo == null || appWidgetInfo.autoAdvanceViewId == -1) return;
@@ -1875,14 +1799,14 @@ public class Launcher extends Activity
if (v instanceof Advanceable) {
mWidgetsToAdvance.put(hostView, appWidgetInfo);
((Advanceable) v).fyiWillBeAdvancedByHostKThx();
- updateRunning();
+ updateAutoAdvanceState();
}
}
void removeWidgetToAutoAdvance(View hostView) {
if (mWidgetsToAdvance.containsKey(hostView)) {
mWidgetsToAdvance.remove(hostView);
- updateRunning();
+ updateAutoAdvanceState();
}
}
@@ -1891,7 +1815,7 @@ public class Launcher extends Activity
launcherInfo.hostView = null;
}
- void showOutOfSpaceMessage(boolean isHotseatLayout) {
+ 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();
}
@@ -1900,6 +1824,14 @@ public class Launcher extends Activity
return mDragLayer;
}
+ public AllAppsContainerView getAppsView() {
+ return mAppsView;
+ }
+
+ public WidgetsContainerView getWidgetsView() {
+ return mWidgetsView;
+ }
+
public Workspace getWorkspace() {
return mWorkspace;
}
@@ -1928,6 +1860,10 @@ public class Launcher extends Activity
return mSharedPrefs;
}
+ public DeviceProfile getDeviceProfile() {
+ return mDeviceProfile;
+ }
+
public void closeSystemDialogs() {
getWindow().closeAllPanels();
@@ -1985,9 +1921,14 @@ public class Launcher extends Activity
imm.hideSoftInputFromWindow(v.getWindowToken(), 0);
}
- // Reset the apps customize page
- if (!alreadyOnHome && mAppsCustomizeTabHost != null) {
- mAppsCustomizeTabHost.reset();
+ // Reset the apps view
+ if (!alreadyOnHome && mAppsView != null) {
+ mAppsView.scrollToTop();
+ }
+
+ // Reset the widgets view
+ if (!alreadyOnHome && mWidgetsView != null) {
+ mWidgetsView.scrollToTop();
}
if (mLauncherCallbacks != null) {
@@ -2037,21 +1978,8 @@ public class Launcher extends Activity
outState.putInt(RUNTIME_STATE_PENDING_ADD_WIDGET_ID, mPendingAddWidgetId);
}
- if (mFolderInfo != null && mWaitingForResult) {
- outState.putBoolean(RUNTIME_STATE_PENDING_FOLDER_RENAME, true);
- outState.putLong(RUNTIME_STATE_PENDING_FOLDER_RENAME_ID, mFolderInfo.id);
- }
-
- // Save the current AppsCustomize tab
- if (mAppsCustomizeTabHost != null) {
- AppsCustomizePagedView.ContentType type = mAppsCustomizeContent.getContentType();
- String currentTabTag = mAppsCustomizeTabHost.getTabTagForContentType(type);
- if (currentTabTag != null) {
- outState.putString("apps_customize_currentTab", currentTabTag);
- }
- int currentIndex = mAppsCustomizeContent.getSaveInstanceStateIndex();
- outState.putInt("apps_customize_currentIndex", currentIndex);
- }
+ // Save the current widgets tray?
+ // TODO(hyunyoungs)
outState.putSerializable(RUNTIME_STATE_VIEW_IDS, mItemIdToViewId);
if (mLauncherCallbacks != null) {
@@ -2089,13 +2017,6 @@ public class Launcher extends Activity
TextKeyListener.getInstance().release();
- // Disconnect any of the callbacks and drawables associated with ItemInfos on the workspace
- // to prevent leaking Launcher activities on orientation change.
- if (mModel != null) {
- mModel.unbindItemInfosAndClearQueuedBindRunnables();
- }
-
- getContentResolver().unregisterContentObserver(mWidgetObserver);
unregisterReceiver(mCloseSystemDialogsReceiver);
mDragLayer.clearAllResizeFrames();
@@ -2117,10 +2038,26 @@ public class Launcher extends Activity
@Override
public void startActivityForResult(Intent intent, int requestCode) {
+ onStartForResult(requestCode);
+ super.startActivityForResult(intent, requestCode);
+ }
+
+ @Override
+ public void startIntentSenderForResult (IntentSender intent, int requestCode,
+ Intent fillInIntent, int flagsMask, int flagsValues, int extraFlags, Bundle options) {
+ onStartForResult(requestCode);
+ try {
+ super.startIntentSenderForResult(intent, requestCode,
+ fillInIntent, flagsMask, flagsValues, extraFlags, options);
+ } catch (IntentSender.SendIntentException e) {
+ throw new ActivityNotFoundException();
+ }
+ }
+
+ private void onStartForResult(int requestCode) {
if (requestCode >= 0) {
setWaitingForResult(true);
}
- super.startActivityForResult(intent, requestCode);
}
/**
@@ -2131,8 +2068,6 @@ public class Launcher extends Activity
public void startSearch(String initialQuery, boolean selectInitialQuery,
Bundle appSearchData, boolean globalSearch) {
- showWorkspace(true);
-
if (initialQuery == null) {
// Use any text typed in the launcher as the initial query
initialQuery = getTypedText();
@@ -2151,6 +2086,9 @@ public class Launcher extends Activity
if (clearTextImmediately) {
clearTypedText();
}
+
+ // We need to show the workspace after starting the search
+ showWorkspace(true);
}
/**
@@ -2284,14 +2222,14 @@ public class Launcher extends Activity
mPendingAddInfo.dropPos = null;
}
- void addAppWidgetImpl(final int appWidgetId, final ItemInfo info,
- final AppWidgetHostView boundWidget, final AppWidgetProviderInfo appWidgetInfo) {
+ void addAppWidgetImpl(final int appWidgetId, final ItemInfo info, final
+ AppWidgetHostView boundWidget, final LauncherAppWidgetProviderInfo appWidgetInfo) {
addAppWidgetImpl(appWidgetId, info, boundWidget, appWidgetInfo, 0);
}
void addAppWidgetImpl(final int appWidgetId, final ItemInfo info,
- final AppWidgetHostView boundWidget, final AppWidgetProviderInfo appWidgetInfo, int
- delay) {
+ final AppWidgetHostView boundWidget, final LauncherAppWidgetProviderInfo appWidgetInfo,
+ int delay) {
if (appWidgetInfo.configure != null) {
mPendingAddWidgetInfo = appWidgetInfo;
mPendingAddWidgetId = appWidgetId;
@@ -2321,20 +2259,39 @@ public class Launcher extends Activity
closeFolder();
mWorkspace.moveToCustomContentScreen(animate);
}
+
+ public void addPendingItem(PendingAddItemInfo info, long container, long screenId,
+ int[] cell, int spanX, int spanY) {
+ switch (info.itemType) {
+ case LauncherSettings.Favorites.ITEM_TYPE_CUSTOM_APPWIDGET:
+ case LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET:
+ int span[] = new int[2];
+ span[0] = spanX;
+ span[1] = spanY;
+ addAppWidgetFromDrop((PendingAddWidgetInfo) info,
+ container, screenId, cell, span);
+ break;
+ case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
+ processShortcutFromDrop(info.componentName, container, screenId, cell);
+ break;
+ default:
+ throw new IllegalStateException("Unknown item type: " + info.itemType);
+ }
+ }
+
/**
* Process a shortcut drop.
*
* @param componentName The name of the component
* @param screenId The ID of the screen where it should be added
* @param cell The cell it should be added to, optional
- * @param position The location on the screen where it was dropped, optional
*/
- void processShortcutFromDrop(ComponentName componentName, long container, long screenId,
- int[] cell, int[] loc) {
+ private void processShortcutFromDrop(ComponentName componentName, long container, long screenId,
+ int[] cell) {
resetAddInfo();
mPendingAddInfo.container = container;
mPendingAddInfo.screenId = screenId;
- mPendingAddInfo.dropPos = loc;
+ mPendingAddInfo.dropPos = null;
if (cell != null) {
mPendingAddInfo.cellX = cell[0];
@@ -2343,7 +2300,7 @@ public class Launcher extends Activity
Intent createShortcutIntent = new Intent(Intent.ACTION_CREATE_SHORTCUT);
createShortcutIntent.setComponent(componentName);
- processShortcut(createShortcutIntent);
+ Utilities.startActivityForResultSafely(this, createShortcutIntent, REQUEST_CREATE_SHORTCUT);
}
/**
@@ -2352,14 +2309,13 @@ public class Launcher extends Activity
* @param info The PendingAppWidgetInfo of the widget being added.
* @param screenId The ID of the screen where it should be added
* @param cell The cell it should be added to, optional
- * @param position The location on the screen where it was dropped, optional
*/
- void addAppWidgetFromDrop(PendingAddWidgetInfo info, long container, long screenId,
- int[] cell, int[] span, int[] loc) {
+ private void addAppWidgetFromDrop(PendingAddWidgetInfo info, long container, long screenId,
+ int[] cell, int[] span) {
resetAddInfo();
mPendingAddInfo.container = info.container = container;
mPendingAddInfo.screenId = info.screenId = screenId;
- mPendingAddInfo.dropPos = loc;
+ mPendingAddInfo.dropPos = null;
mPendingAddInfo.minSpanX = info.minSpanX;
mPendingAddInfo.minSpanY = info.minSpanY;
@@ -2377,6 +2333,9 @@ public class Launcher extends Activity
if (hostView != null) {
appWidgetId = hostView.getAppWidgetId();
addAppWidgetImpl(appWidgetId, info, hostView, info.info);
+
+ // Clear the boundWidget so that it doesn't get destroyed.
+ info.boundWidget = null;
} else {
// In this case, we either need to start an activity to get permission to bind
// the widget, or we need to start an activity to configure the widget, or both.
@@ -2401,22 +2360,14 @@ public class Launcher extends Activity
}
}
- void processShortcut(Intent intent) {
- Utilities.startActivityForResultSafely(this, intent, REQUEST_CREATE_SHORTCUT);
- }
-
- void processWallpaper(Intent intent) {
- startActivityForResult(intent, REQUEST_PICK_WALLPAPER);
- }
-
FolderIcon addFolder(CellLayout layout, long container, final long screenId, int cellX,
int cellY) {
final FolderInfo folderInfo = new FolderInfo();
folderInfo.title = getText(R.string.folder_name);
// Update the model
- LauncherModel.addItemToDatabase(Launcher.this, folderInfo, container, screenId, cellX, cellY,
- false);
+ LauncherModel.addItemToDatabase(Launcher.this, folderInfo, container, screenId,
+ cellX, cellY);
sFolders.put(folderInfo.id, folderInfo);
// Create the view
@@ -2434,23 +2385,6 @@ public class Launcher extends Activity
sFolders.remove(folder.id);
}
- protected ComponentName getWallpaperPickerComponent() {
- if (mLauncherCallbacks != null) {
- return mLauncherCallbacks.getWallpaperPickerComponent();
- }
- return new ComponentName(getPackageName(), LauncherWallpaperPickerActivity.class.getName());
- }
-
- /**
- * Registers various content observers. The current implementation registers
- * only a favorites observer to keep track of the favorites applications.
- */
- private void registerContentObservers() {
- ContentResolver resolver = getContentResolver();
- resolver.registerContentObserver(LauncherProvider.CONTENT_APPWIDGET_RESET_URI,
- true, mWidgetObserver);
- }
-
@Override
public boolean dispatchKeyEvent(KeyEvent event) {
if (event.getAction() == KeyEvent.ACTION_DOWN) {
@@ -2480,15 +2414,17 @@ public class Launcher extends Activity
return;
}
- if (isAllAppsVisible()) {
- if (mAppsCustomizeContent.getContentType() ==
- AppsCustomizePagedView.ContentType.Applications) {
- showWorkspace(true);
- } else {
- showOverviewMode(true);
- }
+ if (mDragController.isDragging()) {
+ mDragController.cancelDrag();
+ return;
+ }
+
+ if (isAppsViewVisible()) {
+ showWorkspace(true);
+ } else if (isWidgetsViewVisible()) {
+ showOverviewMode(true);
} else if (mWorkspace.isInOverviewMode()) {
- mWorkspace.exitOverviewMode(true);
+ showWorkspace(true);
} else if (mWorkspace.getOpenFolder() != null) {
Folder openFolder = mWorkspace.getOpenFolder();
if (openFolder.isEditingName()) {
@@ -2505,9 +2441,10 @@ public class Launcher extends Activity
}
/**
- * Re-listen when widgets are reset.
+ * Re-listen when widget host is reset.
*/
- private void onAppWidgetReset() {
+ @Override
+ public void onAppWidgetHostReset() {
if (mAppWidgetHost != null) {
mAppWidgetHost.startListening();
}
@@ -2531,14 +2468,14 @@ public class Launcher extends Activity
if (v instanceof Workspace) {
if (mWorkspace.isInOverviewMode()) {
- mWorkspace.exitOverviewMode(true);
+ showWorkspace(true);
}
return;
}
if (v instanceof CellLayout) {
if (mWorkspace.isInOverviewMode()) {
- mWorkspace.exitOverviewMode(mWorkspace.indexOfChild(v), true);
+ showWorkspace(mWorkspace.indexOfChild(v), true);
}
}
@@ -2560,13 +2497,7 @@ public class Launcher extends Activity
}
}
- public void onClickPagedViewIcon(View v) {
- startAppShortcutOrInfoActivity(v);
- if (mLauncherCallbacks != null) {
- mLauncherCallbacks.onClickPagedViewIcon(v);
- }
- }
-
+ @SuppressLint("ClickableViewAccessibility")
public boolean onTouch(View v, MotionEvent event) {
return false;
}
@@ -2585,7 +2516,8 @@ public class Launcher extends Activity
int widgetId = info.appWidgetId;
AppWidgetProviderInfo appWidgetInfo = mAppWidgetManager.getAppWidgetInfo(widgetId);
if (appWidgetInfo != null) {
- mPendingAddWidgetInfo = appWidgetInfo;
+ mPendingAddWidgetInfo = LauncherAppWidgetProviderInfo.fromProviderInfo(
+ this, appWidgetInfo);
mPendingAddInfo.copyFrom(info);
mPendingAddWidgetId = widgetId;
@@ -2616,13 +2548,17 @@ public class Launcher extends Activity
*/
protected void onClickAllAppsButton(View v) {
if (LOGD) Log.d(TAG, "onClickAllAppsButton");
- if (isAllAppsVisible()) {
- showWorkspace(true);
- } else {
- showAllApps(true, AppsCustomizePagedView.ContentType.Applications, false);
+ if (!isAppsViewVisible()) {
+ showAppsView(true /* animated */, false /* resetListToTop */,
+ true /* updatePredictedApps */, false /* focusSearchBar */);
}
- if (mLauncherCallbacks != null) {
- mLauncherCallbacks.onClickAllAppsButton(v);
+ }
+
+ protected void onLongClickAllAppsButton(View v) {
+ if (LOGD) Log.d(TAG, "onLongClickAllAppsButton");
+ if (!isAppsViewVisible()) {
+ showAppsView(true /* animated */, false /* resetListToTop */,
+ true /* updatePredictedApps */, true /* focusSearchBar */);
}
}
@@ -2704,7 +2640,7 @@ public class Launcher extends Activity
}
}
- private void startAppShortcutOrInfoActivity(View v) {
+ @Thunk void startAppShortcutOrInfoActivity(View v) {
Object tag = v.getTag();
final ShortcutInfo shortcut;
final Intent intent;
@@ -2724,7 +2660,7 @@ public class Launcher extends Activity
}
boolean success = startActivitySafely(v, intent, tag);
- mStats.recordLaunch(intent, shortcut);
+ mStats.recordLaunch(v, intent, shortcut);
if (success && v instanceof BubbleTextView) {
mWaitingForResume = (BubbleTextView) v;
@@ -2790,7 +2726,7 @@ public class Launcher extends Activity
if (mIsSafeModeEnabled) {
Toast.makeText(this, R.string.safemode_widget_error, Toast.LENGTH_SHORT).show();
} else {
- showAllApps(true, AppsCustomizePagedView.ContentType.Widgets, true);
+ showWidgetsView(true /* animated */, true /* resetPageToZero */);
if (mLauncherCallbacks != null) {
mLauncherCallbacks.onClickAddWidgetButton(view);
}
@@ -2803,9 +2739,8 @@ public class Launcher extends Activity
*/
protected void onClickWallpaperPicker(View v) {
if (LOGD) Log.d(TAG, "onClickWallpaperPicker");
- final Intent pickWallpaper = new Intent(Intent.ACTION_SET_WALLPAPER);
- pickWallpaper.setComponent(getWallpaperPickerComponent());
- startActivityForResult(pickWallpaper, REQUEST_PICK_WALLPAPER);
+ startActivityForResult(new Intent(Intent.ACTION_SET_WALLPAPER).setPackage(getPackageName()),
+ REQUEST_PICK_WALLPAPER);
if (mLauncherCallbacks != null) {
mLauncherCallbacks.onClickWallpaperPicker(v);
@@ -2820,22 +2755,15 @@ public class Launcher extends Activity
if (LOGD) Log.d(TAG, "onClickSettingsButton");
if (mLauncherCallbacks != null) {
mLauncherCallbacks.onClickSettingsButton(v);
+ } else {
+ startActivity(new Intent(this, SettingsActivity.class));
}
}
- public void onTouchDownAllAppsButton(View v) {
- // Provide the same haptic feedback that the system offers for virtual keys.
- v.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY);
- }
-
- public void performHapticFeedbackOnTouchDown(View v) {
- // Provide the same haptic feedback that the system offers for virtual keys.
- v.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY);
- }
-
public View.OnTouchListener getHapticFeedbackTouchListener() {
if (mHapticFeedbackTouchListener == null) {
mHapticFeedbackTouchListener = new View.OnTouchListener() {
+ @SuppressLint("ClickableViewAccessibility")
@Override
public boolean onTouch(View v, MotionEvent event) {
if ((event.getAction() & MotionEvent.ACTION_MASK) == MotionEvent.ACTION_DOWN) {
@@ -2885,6 +2813,19 @@ public class Launcher extends Activity
}
}
+ /** Updates the interaction state. */
+ public void updateInteraction(Workspace.State fromState, Workspace.State toState) {
+ // Only update the interacting state if we are transitioning to/from a view with an
+ // overlay
+ boolean fromStateWithOverlay = fromState != Workspace.State.NORMAL;
+ boolean toStateWithOverlay = toState != Workspace.State.NORMAL;
+ if (toStateWithOverlay) {
+ onInteractionBegin();
+ } else if (fromStateWithOverlay) {
+ onInteractionEnd();
+ }
+ }
+
void startApplicationDetailsActivity(ComponentName componentName, UserHandleCompat user) {
try {
LauncherAppsCompat launcherApps = LauncherAppsCompat.getInstance(this);
@@ -2922,7 +2863,7 @@ public class Launcher extends Activity
}
}
- boolean startActivity(View v, Intent intent, Object tag) {
+ private boolean startActivity(View v, Intent intent, Object tag) {
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
try {
// Only launch using the new animation if the shortcut has not opted out (this is a
@@ -2940,10 +2881,45 @@ public class Launcher extends Activity
Bundle optsBundle = null;
if (useLaunchAnimation) {
- ActivityOptions opts = Utilities.isLmpOrAbove() ?
- ActivityOptions.makeCustomAnimation(this, R.anim.task_open_enter, R.anim.no_anim) :
- ActivityOptions.makeScaleUpAnimation(v, 0, 0, v.getMeasuredWidth(), v.getMeasuredHeight());
- optsBundle = opts.toBundle();
+ ActivityOptions opts = null;
+ if (sClipRevealMethod != null) {
+ // TODO: call method directly when Launcher3 can depend on M APIs
+ int left = 0, top = 0;
+ int width = v.getMeasuredWidth(), height = v.getMeasuredHeight();
+ if (v instanceof TextView) {
+ // Launch from center of icon, not entire view
+ Drawable icon = Workspace.getTextViewIcon((TextView) v);
+ if (icon != null) {
+ Rect bounds = icon.getBounds();
+ left = (width - bounds.width()) / 2;
+ top = v.getPaddingTop();
+ width = bounds.width();
+ height = bounds.height();
+ }
+ }
+ try {
+ opts = (ActivityOptions) sClipRevealMethod.invoke(null, v,
+ left, top, width, height);
+ } catch (IllegalAccessException e) {
+ Log.d(TAG, "Could not call makeClipRevealAnimation: " + e);
+ sClipRevealMethod = null;
+ } catch (InvocationTargetException e) {
+ Log.d(TAG, "Could not call makeClipRevealAnimation: " + e);
+ sClipRevealMethod = null;
+ }
+ }
+ if (opts == null && !Utilities.isLmpOrAbove()) {
+ // Below L, we use a scale up animation
+ opts = ActivityOptions.makeScaleUpAnimation(v, 0, 0,
+ v.getMeasuredWidth(), v.getMeasuredHeight());
+ } else if (opts == null && Utilities.isLmpMR1()) {
+ // On L devices, we use the device default slide-up transition.
+ // On L MR1 devices, we a custom version of the slide-up transition which
+ // doesn't have the delay present in the device default.
+ opts = ActivityOptions.makeCustomAnimation(this,
+ R.anim.task_open_enter, R.anim.no_anim);
+ }
+ optsBundle = opts != null ? opts.toBundle() : null;
}
if (user == null || user.equals(UserHandleCompat.myUserHandle())) {
@@ -2965,7 +2941,7 @@ public class Launcher extends Activity
return false;
}
- boolean startActivitySafely(View v, Intent intent, Object tag) {
+ @Thunk boolean startActivitySafely(View v, Intent intent, Object tag) {
boolean success = false;
if (mIsSafeModeEnabled && !Utilities.isSystemApp(this, intent)) {
Toast.makeText(this, R.string.safemode_shortcut_error, Toast.LENGTH_SHORT).show();
@@ -3095,10 +3071,19 @@ public class Launcher extends Activity
*/
public void openFolder(FolderIcon folderIcon) {
Folder folder = folderIcon.getFolder();
+ Folder openFolder = mWorkspace != null ? mWorkspace.getOpenFolder() : null;
+ if (openFolder != null && openFolder != folder) {
+ // Close any open folder before opening a folder.
+ closeFolder();
+ }
+
FolderInfo info = folder.mInfo;
info.opened = true;
+ // While the folder is open, the position of the icon cannot change.
+ ((CellLayout.LayoutParams) folderIcon.getLayoutParams()).canReorder = false;
+
// Just verify that the folder hasn't already been added to the DragLayer.
// There was a one-off crash where the folder had a parent already.
if (folder.getParent() == null) {
@@ -3127,13 +3112,16 @@ public class Launcher extends Activity
}
}
- void closeFolder(Folder folder) {
+ public void closeFolder(Folder folder) {
folder.getInfo().opened = false;
ViewGroup parent = (ViewGroup) folder.getParent().getParent();
if (parent != null) {
FolderIcon fi = (FolderIcon) mWorkspace.getViewForTag(folder.mInfo);
shrinkAndFadeInFolderIcon(fi);
+ if (fi != null) {
+ ((CellLayout.LayoutParams) fi.getLayoutParams()).canReorder = true;
+ }
}
folder.animateClosed();
@@ -3147,9 +3135,15 @@ public class Launcher extends Activity
if (isWorkspaceLocked()) return false;
if (mState != State.WORKSPACE) return false;
+ if (v == mAllAppsButton) {
+ onLongClickAllAppsButton(v);
+ return true;
+ }
+
if (v instanceof Workspace) {
if (!mWorkspace.isInOverviewMode()) {
- if (mWorkspace.enterOverviewMode()) {
+ if (!mWorkspace.isTouchActive()) {
+ showOverviewMode(true);
mWorkspace.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS,
HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING);
return true;
@@ -3165,7 +3159,7 @@ public class Launcher extends Activity
View itemUnderLongClick = null;
if (v.getTag() instanceof ItemInfo) {
ItemInfo info = (ItemInfo) v.getTag();
- longClickCellInfo = new CellLayout.CellInfo(v, info);;
+ longClickCellInfo = new CellLayout.CellInfo(v, info);
itemUnderLongClick = longClickCellInfo.cell;
resetAddInfo();
}
@@ -3173,8 +3167,7 @@ public class Launcher extends Activity
// The hotseat touch handling does not go through Workspace, and we always allow long press
// on hotseat items.
final boolean inHotseat = isHotseatLayout(v);
- boolean allowLongPress = inHotseat || mWorkspace.allowLongPress();
- if (allowLongPress && !mDragController.isDragging()) {
+ if (!mDragController.isDragging()) {
if (itemUnderLongClick == null) {
// User long pressed on empty space
mWorkspace.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS,
@@ -3182,7 +3175,7 @@ public class Launcher extends Activity
if (mWorkspace.isInOverviewMode()) {
mWorkspace.startReordering(v);
} else {
- mWorkspace.enterOverviewMode();
+ showOverviewMode(true);
}
} else {
final boolean isAllAppsButton = inHotseat && isAllAppsButtonRank(
@@ -3206,7 +3199,7 @@ public class Launcher extends Activity
/**
* Returns the CellLayout of the specified container at the specified screen.
*/
- CellLayout getCellLayout(long container, long screenId) {
+ public CellLayout getCellLayout(long container, long screenId) {
if (container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) {
if (mHotseat != null) {
return mHotseat.getLayout();
@@ -3214,17 +3207,36 @@ public class Launcher extends Activity
return null;
}
} else {
- return (CellLayout) mWorkspace.getScreenWithId(screenId);
+ return mWorkspace.getScreenWithId(screenId);
}
}
+ /**
+ * For overridden classes.
+ */
public boolean isAllAppsVisible() {
- return (mState == State.APPS_CUSTOMIZE) || (mOnResumeState == State.APPS_CUSTOMIZE);
+ return isAppsViewVisible();
+ }
+
+ public boolean isAppsViewVisible() {
+ return (mState == State.APPS) || (mOnResumeState == State.APPS);
+ }
+
+ public boolean isWidgetsViewVisible() {
+ return (mState == State.WIDGETS) || (mOnResumeState == State.WIDGETS);
}
- private void setWorkspaceBackground(boolean workspace) {
- mLauncherView.setBackground(workspace ?
- mWorkspaceBackgroundDrawable : null);
+ private void setWorkspaceBackground(int background) {
+ switch (background) {
+ case WORKSPACE_BACKGROUND_TRANSPARENT:
+ getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
+ break;
+ case WORKSPACE_BACKGROUND_BLACK:
+ getWindow().setBackgroundDrawable(null);
+ break;
+ default:
+ getWindow().setBackgroundDrawable(mWorkspaceBackgroundDrawable);
+ }
}
protected void changeWallpaperVisiblity(boolean visible) {
@@ -3234,577 +3246,7 @@ public class Launcher extends Activity
if (wpflags != curflags) {
getWindow().setFlags(wpflags, WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER);
}
- setWorkspaceBackground(visible);
- }
-
- private void dispatchOnLauncherTransitionPrepare(View v, boolean animated, boolean toWorkspace) {
- if (v instanceof LauncherTransitionable) {
- ((LauncherTransitionable) v).onLauncherTransitionPrepare(this, animated, toWorkspace);
- }
- }
-
- private void dispatchOnLauncherTransitionStart(View v, boolean animated, boolean toWorkspace) {
- if (v instanceof LauncherTransitionable) {
- ((LauncherTransitionable) v).onLauncherTransitionStart(this, animated, toWorkspace);
- }
-
- // Update the workspace transition step as well
- dispatchOnLauncherTransitionStep(v, 0f);
- }
-
- private void dispatchOnLauncherTransitionStep(View v, float t) {
- if (v instanceof LauncherTransitionable) {
- ((LauncherTransitionable) v).onLauncherTransitionStep(this, t);
- }
- }
-
- private void dispatchOnLauncherTransitionEnd(View v, boolean animated, boolean toWorkspace) {
- if (v instanceof LauncherTransitionable) {
- ((LauncherTransitionable) v).onLauncherTransitionEnd(this, animated, toWorkspace);
- }
-
- // Update the workspace transition step as well
- dispatchOnLauncherTransitionStep(v, 1f);
- }
-
- /**
- * Things to test when changing the following seven functions.
- * - Home from workspace
- * - from center screen
- * - from other screens
- * - Home from all apps
- * - from center screen
- * - from other screens
- * - Back from all apps
- * - from center screen
- * - from other screens
- * - Launch app from workspace and quit
- * - with back
- * - with home
- * - Launch app from all apps and quit
- * - with back
- * - with home
- * - Go to a screen that's not the default, then all
- * apps, and launch and app, and go back
- * - with back
- * -with home
- * - On workspace, long press power and go back
- * - with back
- * - with home
- * - On all apps, long press power and go back
- * - with back
- * - with home
- * - On workspace, power off
- * - On all apps, power off
- * - Launch an app and turn off the screen while in that app
- * - Go back with home key
- * - Go back with back key TODO: make this not go to workspace
- * - From all apps
- * - From workspace
- * - Enter and exit car mode (becuase it causes an extra configuration changed)
- * - From all apps
- * - From the center workspace
- * - From another workspace
- */
-
- /**
- * Zoom the camera out from the workspace to reveal 'toView'.
- * Assumes that the view to show is anchored at either the very top or very bottom
- * of the screen.
- */
- private void showAppsCustomizeHelper(final boolean animated, final boolean springLoaded) {
- AppsCustomizePagedView.ContentType contentType = mAppsCustomizeContent.getContentType();
- showAppsCustomizeHelper(animated, springLoaded, contentType);
- }
-
- private void showAppsCustomizeHelper(final boolean animated, final boolean springLoaded,
- final AppsCustomizePagedView.ContentType contentType) {
- if (mStateAnimation != null) {
- mStateAnimation.setDuration(0);
- mStateAnimation.cancel();
- mStateAnimation = null;
- }
-
- boolean material = Utilities.isLmpOrAbove();
-
- final Resources res = getResources();
-
- final int duration = res.getInteger(R.integer.config_appsCustomizeZoomInTime);
- final int fadeDuration = res.getInteger(R.integer.config_appsCustomizeFadeInTime);
- final int revealDuration = res.getInteger(R.integer.config_appsCustomizeRevealTime);
- final int itemsAlphaStagger =
- res.getInteger(R.integer.config_appsCustomizeItemsAlphaStagger);
-
- final float scale = (float) res.getInteger(R.integer.config_appsCustomizeZoomScaleFactor);
- final View fromView = mWorkspace;
- final AppsCustomizeTabHost toView = mAppsCustomizeTabHost;
-
- final ArrayList<View> layerViews = new ArrayList<View>();
-
- Workspace.State workspaceState = contentType == AppsCustomizePagedView.ContentType.Widgets ?
- Workspace.State.OVERVIEW_HIDDEN : Workspace.State.NORMAL_HIDDEN;
- Animator workspaceAnim =
- mWorkspace.getChangeStateAnimation(workspaceState, animated, layerViews);
- if (!LauncherAppState.isDisableAllApps()
- || contentType == AppsCustomizePagedView.ContentType.Widgets) {
- // Set the content type for the all apps/widgets space
- mAppsCustomizeTabHost.setContentTypeImmediate(contentType);
- }
-
- // If for some reason our views aren't initialized, don't animate
- boolean initialized = getAllAppsButton() != null;
-
- if (animated && initialized) {
- mStateAnimation = LauncherAnimUtils.createAnimatorSet();
- final AppsCustomizePagedView content = (AppsCustomizePagedView)
- toView.findViewById(R.id.apps_customize_pane_content);
-
- final View page = content.getPageAt(content.getCurrentPage());
- final View revealView = toView.findViewById(R.id.fake_page);
-
- final boolean isWidgetTray = contentType == AppsCustomizePagedView.ContentType.Widgets;
- if (isWidgetTray) {
- revealView.setBackground(res.getDrawable(R.drawable.quantum_panel_dark));
- } else {
- revealView.setBackground(res.getDrawable(R.drawable.quantum_panel));
- }
-
- // Hide the real page background, and swap in the fake one
- content.setPageBackgroundsVisible(false);
- revealView.setVisibility(View.VISIBLE);
- // We need to hide this view as the animation start will be posted.
- revealView.setAlpha(0);
-
- int width = revealView.getMeasuredWidth();
- int height = revealView.getMeasuredHeight();
- float revealRadius = (float) Math.sqrt((width * width) / 4 + (height * height) / 4);
-
- revealView.setTranslationY(0);
- revealView.setTranslationX(0);
-
- // Get the y delta between the center of the page and the center of the all apps button
- int[] allAppsToPanelDelta = Utilities.getCenterDeltaInScreenSpace(revealView,
- getAllAppsButton(), null);
-
- float alpha = 0;
- float xDrift = 0;
- float yDrift = 0;
- if (material) {
- alpha = isWidgetTray ? 0.3f : 1f;
- yDrift = isWidgetTray ? height / 2 : allAppsToPanelDelta[1];
- xDrift = isWidgetTray ? 0 : allAppsToPanelDelta[0];
- } else {
- yDrift = 2 * height / 3;
- xDrift = 0;
- }
- final float initAlpha = alpha;
-
- revealView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
- layerViews.add(revealView);
- PropertyValuesHolder panelAlpha = PropertyValuesHolder.ofFloat("alpha", initAlpha, 1f);
- PropertyValuesHolder panelDriftY =
- PropertyValuesHolder.ofFloat("translationY", yDrift, 0);
- PropertyValuesHolder panelDriftX =
- PropertyValuesHolder.ofFloat("translationX", xDrift, 0);
-
- ObjectAnimator panelAlphaAndDrift = ObjectAnimator.ofPropertyValuesHolder(revealView,
- panelAlpha, panelDriftY, panelDriftX);
-
- panelAlphaAndDrift.setDuration(revealDuration);
- panelAlphaAndDrift.setInterpolator(new LogDecelerateInterpolator(100, 0));
-
- mStateAnimation.play(panelAlphaAndDrift);
-
- if (page != null) {
- page.setVisibility(View.VISIBLE);
- page.setLayerType(View.LAYER_TYPE_HARDWARE, null);
- layerViews.add(page);
-
- ObjectAnimator pageDrift = ObjectAnimator.ofFloat(page, "translationY", yDrift, 0);
- page.setTranslationY(yDrift);
- pageDrift.setDuration(revealDuration);
- pageDrift.setInterpolator(new LogDecelerateInterpolator(100, 0));
- pageDrift.setStartDelay(itemsAlphaStagger);
- mStateAnimation.play(pageDrift);
-
- page.setAlpha(0f);
- ObjectAnimator itemsAlpha = ObjectAnimator.ofFloat(page, "alpha", 0f, 1f);
- itemsAlpha.setDuration(revealDuration);
- itemsAlpha.setInterpolator(new AccelerateInterpolator(1.5f));
- itemsAlpha.setStartDelay(itemsAlphaStagger);
- mStateAnimation.play(itemsAlpha);
- }
-
- View pageIndicators = toView.findViewById(R.id.apps_customize_page_indicator);
- pageIndicators.setAlpha(0.01f);
- ObjectAnimator indicatorsAlpha =
- ObjectAnimator.ofFloat(pageIndicators, "alpha", 1f);
- indicatorsAlpha.setDuration(revealDuration);
- mStateAnimation.play(indicatorsAlpha);
-
- if (material) {
- final View allApps = getAllAppsButton();
- int allAppsButtonSize = LauncherAppState.getInstance().
- getDynamicGrid().getDeviceProfile().allAppsButtonVisualSize;
- float startRadius = isWidgetTray ? 0 : allAppsButtonSize / 2;
- Animator reveal = ViewAnimationUtils.createCircularReveal(revealView, width / 2,
- height / 2, startRadius, revealRadius);
- reveal.setDuration(revealDuration);
- reveal.setInterpolator(new LogDecelerateInterpolator(100, 0));
-
- reveal.addListener(new AnimatorListenerAdapter() {
- public void onAnimationStart(Animator animation) {
- if (!isWidgetTray) {
- allApps.setVisibility(View.INVISIBLE);
- }
- }
- public void onAnimationEnd(Animator animation) {
- if (!isWidgetTray) {
- allApps.setVisibility(View.VISIBLE);
- }
- }
- });
- mStateAnimation.play(reveal);
- }
-
- mStateAnimation.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- dispatchOnLauncherTransitionEnd(fromView, animated, false);
- dispatchOnLauncherTransitionEnd(toView, animated, false);
-
- revealView.setVisibility(View.INVISIBLE);
- revealView.setLayerType(View.LAYER_TYPE_NONE, null);
- if (page != null) {
- page.setLayerType(View.LAYER_TYPE_NONE, null);
- }
- content.setPageBackgroundsVisible(true);
-
- // Hide the search bar
- if (mSearchDropTargetBar != null) {
- mSearchDropTargetBar.hideSearchBar(false);
- }
-
- // This can hold unnecessary references to views.
- mStateAnimation = null;
- }
-
- });
-
- if (workspaceAnim != null) {
- mStateAnimation.play(workspaceAnim);
- }
-
- dispatchOnLauncherTransitionPrepare(fromView, animated, false);
- dispatchOnLauncherTransitionPrepare(toView, animated, false);
- final AnimatorSet stateAnimation = mStateAnimation;
- final Runnable startAnimRunnable = new Runnable() {
- public void run() {
- // Check that mStateAnimation hasn't changed while
- // we waited for a layout/draw pass
- if (mStateAnimation != stateAnimation)
- return;
- dispatchOnLauncherTransitionStart(fromView, animated, false);
- dispatchOnLauncherTransitionStart(toView, animated, false);
-
- revealView.setAlpha(initAlpha);
- if (Utilities.isLmpOrAbove()) {
- for (int i = 0; i < layerViews.size(); i++) {
- View v = layerViews.get(i);
- if (v != null) {
- if (Utilities.isViewAttachedToWindow(v)) v.buildLayer();
- }
- }
- }
- mStateAnimation.start();
- }
- };
- toView.bringToFront();
- toView.setVisibility(View.VISIBLE);
- toView.post(startAnimRunnable);
- } else {
- toView.setTranslationX(0.0f);
- toView.setTranslationY(0.0f);
- toView.setScaleX(1.0f);
- toView.setScaleY(1.0f);
- toView.setVisibility(View.VISIBLE);
- toView.bringToFront();
-
- if (!springLoaded && !LauncherAppState.getInstance().isScreenLarge()) {
- // Hide the search bar
- if (mSearchDropTargetBar != null) {
- mSearchDropTargetBar.hideSearchBar(false);
- }
- }
- dispatchOnLauncherTransitionPrepare(fromView, animated, false);
- dispatchOnLauncherTransitionStart(fromView, animated, false);
- dispatchOnLauncherTransitionEnd(fromView, animated, false);
- dispatchOnLauncherTransitionPrepare(toView, animated, false);
- dispatchOnLauncherTransitionStart(toView, animated, false);
- dispatchOnLauncherTransitionEnd(toView, animated, false);
- }
- }
-
- /**
- * Zoom the camera back into the workspace, hiding 'fromView'.
- * This is the opposite of showAppsCustomizeHelper.
- * @param animated If true, the transition will be animated.
- */
- private void hideAppsCustomizeHelper(Workspace.State toState, final boolean animated,
- final boolean springLoaded, final Runnable onCompleteRunnable) {
-
- if (mStateAnimation != null) {
- mStateAnimation.setDuration(0);
- mStateAnimation.cancel();
- mStateAnimation = null;
- }
-
- boolean material = Utilities.isLmpOrAbove();
- Resources res = getResources();
-
- final int duration = res.getInteger(R.integer.config_appsCustomizeZoomOutTime);
- final int fadeOutDuration = res.getInteger(R.integer.config_appsCustomizeFadeOutTime);
- final int revealDuration = res.getInteger(R.integer.config_appsCustomizeConcealTime);
- final int itemsAlphaStagger =
- res.getInteger(R.integer.config_appsCustomizeItemsAlphaStagger);
-
- final float scaleFactor = (float)
- res.getInteger(R.integer.config_appsCustomizeZoomScaleFactor);
- final View fromView = mAppsCustomizeTabHost;
- final View toView = mWorkspace;
- Animator workspaceAnim = null;
- final ArrayList<View> layerViews = new ArrayList<View>();
-
- if (toState == Workspace.State.NORMAL) {
- workspaceAnim = mWorkspace.getChangeStateAnimation(
- toState, animated, layerViews);
- } else if (toState == Workspace.State.SPRING_LOADED ||
- toState == Workspace.State.OVERVIEW) {
- workspaceAnim = mWorkspace.getChangeStateAnimation(
- toState, animated, layerViews);
- }
-
- // If for some reason our views aren't initialized, don't animate
- boolean initialized = getAllAppsButton() != null;
-
- if (animated && initialized) {
- mStateAnimation = LauncherAnimUtils.createAnimatorSet();
- if (workspaceAnim != null) {
- mStateAnimation.play(workspaceAnim);
- }
-
- final AppsCustomizePagedView content = (AppsCustomizePagedView)
- fromView.findViewById(R.id.apps_customize_pane_content);
-
- final View page = content.getPageAt(content.getNextPage());
-
- // We need to hide side pages of the Apps / Widget tray to avoid some ugly edge cases
- int count = content.getChildCount();
- for (int i = 0; i < count; i++) {
- View child = content.getChildAt(i);
- if (child != page) {
- child.setVisibility(View.INVISIBLE);
- }
- }
- final View revealView = fromView.findViewById(R.id.fake_page);
-
- // 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.
- if (fromView.getVisibility() == View.VISIBLE) {
- AppsCustomizePagedView.ContentType contentType = content.getContentType();
- final boolean isWidgetTray =
- contentType == AppsCustomizePagedView.ContentType.Widgets;
-
- if (isWidgetTray) {
- revealView.setBackground(res.getDrawable(R.drawable.quantum_panel_dark));
- } else {
- revealView.setBackground(res.getDrawable(R.drawable.quantum_panel));
- }
-
- int width = revealView.getMeasuredWidth();
- int height = revealView.getMeasuredHeight();
- float revealRadius = (float) Math.sqrt((width * width) / 4 + (height * height) / 4);
-
- // Hide the real page background, and swap in the fake one
- revealView.setVisibility(View.VISIBLE);
- content.setPageBackgroundsVisible(false);
-
- final View allAppsButton = getAllAppsButton();
- revealView.setTranslationY(0);
- int[] allAppsToPanelDelta = Utilities.getCenterDeltaInScreenSpace(revealView,
- allAppsButton, null);
-
- float xDrift = 0;
- float yDrift = 0;
- if (material) {
- yDrift = isWidgetTray ? height / 2 : allAppsToPanelDelta[1];
- xDrift = isWidgetTray ? 0 : allAppsToPanelDelta[0];
- } else {
- yDrift = 2 * height / 3;
- xDrift = 0;
- }
-
- revealView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
- TimeInterpolator decelerateInterpolator = material ?
- new LogDecelerateInterpolator(100, 0) :
- new DecelerateInterpolator(1f);
-
- // The vertical motion of the apps panel should be delayed by one frame
- // from the conceal animation in order to give the right feel. We correpsondingly
- // shorten the duration so that the slide and conceal end at the same time.
- ObjectAnimator panelDriftY = LauncherAnimUtils.ofFloat(revealView, "translationY",
- 0, yDrift);
- panelDriftY.setDuration(revealDuration - SINGLE_FRAME_DELAY);
- panelDriftY.setStartDelay(itemsAlphaStagger + SINGLE_FRAME_DELAY);
- panelDriftY.setInterpolator(decelerateInterpolator);
- mStateAnimation.play(panelDriftY);
-
- ObjectAnimator panelDriftX = LauncherAnimUtils.ofFloat(revealView, "translationX",
- 0, xDrift);
- panelDriftX.setDuration(revealDuration - SINGLE_FRAME_DELAY);
- panelDriftX.setStartDelay(itemsAlphaStagger + SINGLE_FRAME_DELAY);
- panelDriftX.setInterpolator(decelerateInterpolator);
- mStateAnimation.play(panelDriftX);
-
- if (isWidgetTray || !material) {
- float finalAlpha = material ? 0.4f : 0f;
- revealView.setAlpha(1f);
- ObjectAnimator panelAlpha = LauncherAnimUtils.ofFloat(revealView, "alpha",
- 1f, finalAlpha);
- panelAlpha.setDuration(material ? revealDuration : 150);
- panelAlpha.setInterpolator(decelerateInterpolator);
- panelAlpha.setStartDelay(material ? 0 : itemsAlphaStagger + SINGLE_FRAME_DELAY);
- mStateAnimation.play(panelAlpha);
- }
-
- if (page != null) {
- page.setLayerType(View.LAYER_TYPE_HARDWARE, null);
-
- ObjectAnimator pageDrift = LauncherAnimUtils.ofFloat(page, "translationY",
- 0, yDrift);
- page.setTranslationY(0);
- pageDrift.setDuration(revealDuration - SINGLE_FRAME_DELAY);
- pageDrift.setInterpolator(decelerateInterpolator);
- pageDrift.setStartDelay(itemsAlphaStagger + SINGLE_FRAME_DELAY);
- mStateAnimation.play(pageDrift);
-
- page.setAlpha(1f);
- ObjectAnimator itemsAlpha = LauncherAnimUtils.ofFloat(page, "alpha", 1f, 0f);
- itemsAlpha.setDuration(100);
- itemsAlpha.setInterpolator(decelerateInterpolator);
- mStateAnimation.play(itemsAlpha);
- }
-
- View pageIndicators = fromView.findViewById(R.id.apps_customize_page_indicator);
- pageIndicators.setAlpha(1f);
- ObjectAnimator indicatorsAlpha =
- LauncherAnimUtils.ofFloat(pageIndicators, "alpha", 0f);
- indicatorsAlpha.setDuration(revealDuration);
- indicatorsAlpha.setInterpolator(new DecelerateInterpolator(1.5f));
- mStateAnimation.play(indicatorsAlpha);
-
- width = revealView.getMeasuredWidth();
-
- if (material) {
- if (!isWidgetTray) {
- allAppsButton.setVisibility(View.INVISIBLE);
- }
- int allAppsButtonSize = LauncherAppState.getInstance().
- getDynamicGrid().getDeviceProfile().allAppsButtonVisualSize;
- float finalRadius = isWidgetTray ? 0 : allAppsButtonSize / 2;
- Animator reveal =
- LauncherAnimUtils.createCircularReveal(revealView, width / 2,
- height / 2, revealRadius, finalRadius);
- reveal.setInterpolator(new LogDecelerateInterpolator(100, 0));
- reveal.setDuration(revealDuration);
- reveal.setStartDelay(itemsAlphaStagger);
-
- reveal.addListener(new AnimatorListenerAdapter() {
- public void onAnimationEnd(Animator animation) {
- revealView.setVisibility(View.INVISIBLE);
- if (!isWidgetTray) {
- allAppsButton.setVisibility(View.VISIBLE);
- }
- }
- });
-
- mStateAnimation.play(reveal);
- }
-
- dispatchOnLauncherTransitionPrepare(fromView, animated, true);
- dispatchOnLauncherTransitionPrepare(toView, animated, true);
- mAppsCustomizeContent.stopScrolling();
- }
-
- mStateAnimation.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- fromView.setVisibility(View.GONE);
- dispatchOnLauncherTransitionEnd(fromView, animated, true);
- dispatchOnLauncherTransitionEnd(toView, animated, true);
- if (onCompleteRunnable != null) {
- onCompleteRunnable.run();
- }
-
- revealView.setLayerType(View.LAYER_TYPE_NONE, null);
- if (page != null) {
- page.setLayerType(View.LAYER_TYPE_NONE, null);
- }
- content.setPageBackgroundsVisible(true);
- // Unhide side pages
- int count = content.getChildCount();
- for (int i = 0; i < count; i++) {
- View child = content.getChildAt(i);
- child.setVisibility(View.VISIBLE);
- }
-
- // Reset page transforms
- if (page != null) {
- page.setTranslationX(0);
- page.setTranslationY(0);
- page.setAlpha(1);
- }
- content.setCurrentPage(content.getNextPage());
-
- mAppsCustomizeContent.updateCurrentPageScroll();
-
- // This can hold unnecessary references to views.
- mStateAnimation = null;
- }
- });
-
- final AnimatorSet stateAnimation = mStateAnimation;
- final Runnable startAnimRunnable = new Runnable() {
- public void run() {
- // Check that mStateAnimation hasn't changed while
- // we waited for a layout/draw pass
- if (mStateAnimation != stateAnimation)
- return;
- dispatchOnLauncherTransitionStart(fromView, animated, false);
- dispatchOnLauncherTransitionStart(toView, animated, false);
-
- if (Utilities.isLmpOrAbove()) {
- for (int i = 0; i < layerViews.size(); i++) {
- View v = layerViews.get(i);
- if (v != null) {
- if (Utilities.isViewAttachedToWindow(v)) v.buildLayer();
- }
- }
- }
- mStateAnimation.start();
- }
- };
- fromView.post(startAnimRunnable);
- } else {
- fromView.setVisibility(View.GONE);
- dispatchOnLauncherTransitionPrepare(fromView, animated, true);
- dispatchOnLauncherTransitionStart(fromView, animated, true);
- dispatchOnLauncherTransitionEnd(fromView, animated, true);
- dispatchOnLauncherTransitionPrepare(toView, animated, true);
- dispatchOnLauncherTransitionStart(toView, animated, true);
- dispatchOnLauncherTransitionEnd(toView, animated, true);
- }
+ setWorkspaceBackground(visible ? WORKSPACE_BACKGROUND_GRADIENT : WORKSPACE_BACKGROUND_BLACK);
}
@Override
@@ -3816,25 +3258,42 @@ public class Launcher extends Activity
SQLiteDatabase.releaseMemory();
// This clears all widget bitmaps from the widget tray
- if (mAppsCustomizeTabHost != null) {
- mAppsCustomizeTabHost.trimMemory();
- }
+ // TODO(hyunyoungs)
+ }
+ if (mLauncherCallbacks != null) {
+ mLauncherCallbacks.onTrimMemory(level);
}
}
- protected void showWorkspace(boolean animated) {
- showWorkspace(animated, null);
+ @Override
+ public void onStateTransitionHideSearchBar() {
+ // Hide the search bar
+ if (mSearchDropTargetBar != null) {
+ mSearchDropTargetBar.hideSearchBar(false /* animated */);
+ }
}
- protected void showWorkspace() {
- showWorkspace(true);
+ public void showWorkspace(boolean animated) {
+ showWorkspace(WorkspaceStateTransitionAnimation.SCROLL_TO_CURRENT_PAGE, animated, null);
+ }
+
+ public void showWorkspace(boolean animated, Runnable onCompleteRunnable) {
+ showWorkspace(WorkspaceStateTransitionAnimation.SCROLL_TO_CURRENT_PAGE, animated,
+ onCompleteRunnable);
+ }
+
+ protected void showWorkspace(int snapToPage, boolean animated) {
+ showWorkspace(snapToPage, animated, null);
}
- void showWorkspace(boolean animated, Runnable onCompleteRunnable) {
- if (mState != State.WORKSPACE || mWorkspace.getState() != Workspace.State.NORMAL) {
+ void showWorkspace(int snapToPage, boolean animated, Runnable onCompleteRunnable) {
+ boolean changed = mState != State.WORKSPACE ||
+ mWorkspace.getState() != Workspace.State.NORMAL;
+ if (changed) {
boolean wasInSpringLoadedMode = (mState != State.WORKSPACE);
mWorkspace.setVisibility(View.VISIBLE);
- hideAppsCustomizeHelper(Workspace.State.NORMAL, animated, false, onCompleteRunnable);
+ mStateTransitionAnimation.startAnimationToWorkspace(mState, Workspace.State.NORMAL,
+ snapToPage, animated, onCompleteRunnable);
// Show the search bar (only animate if we were showing the drop target bar in spring
// loaded mode)
@@ -3853,73 +3312,131 @@ public class Launcher extends Activity
// Resume the auto-advance of widgets
mUserPresent = true;
- updateRunning();
+ updateAutoAdvanceState();
- // Send an accessibility event to announce the context change
- getWindow().getDecorView()
- .sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
-
- onWorkspaceShown(animated);
+ if (changed) {
+ // Send an accessibility event to announce the context change
+ getWindow().getDecorView()
+ .sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
+ }
}
void showOverviewMode(boolean animated) {
mWorkspace.setVisibility(View.VISIBLE);
- hideAppsCustomizeHelper(Workspace.State.OVERVIEW, animated, false, null);
+ mStateTransitionAnimation.startAnimationToWorkspace(mState, Workspace.State.OVERVIEW,
+ WorkspaceStateTransitionAnimation.SCROLL_TO_CURRENT_PAGE, animated,
+ null /* onCompleteRunnable */);
mState = State.WORKSPACE;
- onWorkspaceShown(animated);
}
- public void onWorkspaceShown(boolean animated) {
+ /**
+ * Shows the apps view.
+ */
+ void showAppsView(boolean animated, boolean resetListToTop, boolean updatePredictedApps,
+ boolean focusSearchBar) {
+ if (resetListToTop) {
+ mAppsView.scrollToTop();
+ }
+ if (updatePredictedApps) {
+ tryAndUpdatePredictedApps();
+ }
+ showAppsOrWidgets(State.APPS, animated, focusSearchBar);
}
- void showAllApps(boolean animated, AppsCustomizePagedView.ContentType contentType,
- boolean resetPageToZero) {
- if (mState != State.WORKSPACE) return;
-
+ /**
+ * Shows the widgets view.
+ */
+ void showWidgetsView(boolean animated, boolean resetPageToZero) {
+ if (LOGD) Log.d(TAG, "showWidgetsView:" + animated + " resetPageToZero:" + resetPageToZero);
if (resetPageToZero) {
- mAppsCustomizeTabHost.reset();
+ mWidgetsView.scrollToTop();
}
- showAppsCustomizeHelper(animated, false, contentType);
- mAppsCustomizeTabHost.post(new Runnable() {
+ showAppsOrWidgets(State.WIDGETS, animated, false);
+
+ mWidgetsView.post(new Runnable() {
@Override
public void run() {
- // We post this in-case the all apps view isn't yet constructed.
- mAppsCustomizeTabHost.requestFocus();
+ mWidgetsView.requestFocus();
}
});
+ }
+
+ /**
+ * Sets up the transition to show the apps/widgets view.
+ *
+ * @return whether the current from and to state allowed this operation
+ */
+ // TODO: calling method should use the return value so that when {@code false} is returned
+ // the workspace transition doesn't fall into invalid state.
+ private boolean showAppsOrWidgets(State toState, boolean animated, boolean focusSearchBar) {
+ if (mState != State.WORKSPACE && mState != State.APPS_SPRING_LOADED &&
+ mState != State.WIDGETS_SPRING_LOADED) {
+ return false;
+ }
+ if (toState != State.APPS && toState != State.WIDGETS) {
+ return false;
+ }
+
+ if (toState == State.APPS) {
+ mStateTransitionAnimation.startAnimationToAllApps(animated, focusSearchBar);
+ } else {
+ mStateTransitionAnimation.startAnimationToWidgets(animated);
+ }
// Change the state *after* we've called all the transition code
- mState = State.APPS_CUSTOMIZE;
+ mState = toState;
// Pause the auto-advance of widgets until we are out of AllApps
mUserPresent = false;
- updateRunning();
+ updateAutoAdvanceState();
closeFolder();
// Send an accessibility event to announce the context change
getWindow().getDecorView()
.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
+ return true;
}
- void enterSpringLoadedDragMode() {
- if (isAllAppsVisible()) {
- hideAppsCustomizeHelper(Workspace.State.SPRING_LOADED, true, true, null);
- mState = State.APPS_CUSTOMIZE_SPRING_LOADED;
+ /**
+ * Updates the workspace and interaction state on state change, and return the animation to this
+ * new state.
+ */
+ public Animator startWorkspaceStateChangeAnimation(Workspace.State toState, int toPage,
+ boolean animated, boolean hasOverlaySearchBar, HashMap<View, Integer> layerViews) {
+ Workspace.State fromState = mWorkspace.getState();
+ Animator anim = mWorkspace.setStateWithAnimation(toState, toPage, animated,
+ hasOverlaySearchBar, layerViews);
+ updateInteraction(fromState, toState);
+ return anim;
+ }
+
+ public void enterSpringLoadedDragMode() {
+ if (LOGD) Log.d(TAG, String.format("enterSpringLoadedDragMode [mState=%s", mState.name()));
+ if (mState == State.WORKSPACE || mState == State.APPS_SPRING_LOADED ||
+ mState == State.WIDGETS_SPRING_LOADED) {
+ return;
}
+
+ mStateTransitionAnimation.startAnimationToWorkspace(mState, Workspace.State.SPRING_LOADED,
+ WorkspaceStateTransitionAnimation.SCROLL_TO_CURRENT_PAGE, true /* animated */,
+ null /* onCompleteRunnable */);
+ mState = isAppsViewVisible() ? State.APPS_SPRING_LOADED : State.WIDGETS_SPRING_LOADED;
}
- void exitSpringLoadedDragModeDelayed(final boolean successfulDrop, int delay,
+ public void exitSpringLoadedDragModeDelayed(final boolean successfulDrop, int delay,
final Runnable onCompleteRunnable) {
- if (mState != State.APPS_CUSTOMIZE_SPRING_LOADED) return;
+ if (mState != State.APPS_SPRING_LOADED && mState != State.WIDGETS_SPRING_LOADED) return;
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
if (successfulDrop) {
+ // TODO(hyunyoungs): verify if this hack is still needed, if not, delete.
+ //
// Before we show workspace, hide all apps again because
// exitSpringLoadedDragMode made it visible. This is a bit hacky; we should
// clean up our state transition functions
- mAppsCustomizeTabHost.setVisibility(View.GONE);
+ mWidgetsView.setVisibility(View.GONE);
showWorkspace(true, onCompleteRunnable);
} else {
exitSpringLoadedDragMode();
@@ -3929,13 +3446,25 @@ public class Launcher extends Activity
}
void exitSpringLoadedDragMode() {
- if (mState == State.APPS_CUSTOMIZE_SPRING_LOADED) {
- final boolean animated = true;
- final boolean springLoaded = true;
- showAppsCustomizeHelper(animated, springLoaded);
- mState = State.APPS_CUSTOMIZE;
+ if (mState == State.APPS_SPRING_LOADED) {
+ showAppsView(true /* animated */, false /* resetListToTop */,
+ false /* updatePredictedApps */, false /* focusSearchBar */);
+ } else if (mState == State.WIDGETS_SPRING_LOADED) {
+ showWidgetsView(true, false);
+ }
+ }
+
+ /**
+ * Updates the set of predicted apps if it hasn't been updated since the last time Launcher was
+ * resumed.
+ */
+ private void tryAndUpdatePredictedApps() {
+ if (mLauncherCallbacks != null) {
+ List<ComponentKey> apps = mLauncherCallbacks.getPredictedApps();
+ if (apps != null) {
+ mAppsView.setPredictedApps(apps);
+ }
}
- // Otherwise, we are not in spring loaded mode, so don't do anything.
}
void lockAllApps() {
@@ -3950,7 +3479,7 @@ public class Launcher extends Activity
// NO-OP
}
- public View getQsbBar() {
+ public View getOrCreateQsbBar() {
if (mLauncherCallbacks != null && mLauncherCallbacks.providesSearch()) {
return mLauncherCallbacks.getQsbBar();
}
@@ -3994,24 +3523,39 @@ public class Launcher extends Activity
.commit();
}
+ mAppWidgetHost.setQsbWidgetId(widgetId);
if (widgetId != -1) {
mQsb = mAppWidgetHost.createView(this, widgetId, searchProvider);
mQsb.updateAppWidgetOptions(opts);
mQsb.setPadding(0, 0, 0, 0);
mSearchDropTargetBar.addView(mQsb);
+ mSearchDropTargetBar.setQsbSearchBar(mQsb);
}
}
return mQsb;
}
+ private void reinflateQSBIfNecessary() {
+ if (mQsb instanceof LauncherAppWidgetHostView &&
+ ((LauncherAppWidgetHostView) mQsb).isReinflateRequired()) {
+ mSearchDropTargetBar.removeView(mQsb);
+ mQsb = null;
+ mSearchDropTargetBar.setQsbSearchBar(getOrCreateQsbBar());
+ }
+ }
+
@Override
public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
final boolean result = super.dispatchPopulateAccessibilityEvent(event);
final List<CharSequence> text = event.getText();
text.clear();
// Populate event with a fake title based on the current state.
- if (mState == State.APPS_CUSTOMIZE) {
- text.add(mAppsCustomizeTabHost.getContentTag());
+ if (mState == State.APPS) {
+ text.add(getString(R.string.all_apps_button_label));
+ } else if (mState == State.WIDGETS) {
+ text.add(getString(R.string.widget_button_text));
+ } else if (mWorkspace != null) {
+ text.add(mWorkspace.getCurrentPageDescription());
} else {
text.add(getString(R.string.all_apps_home_button_label));
}
@@ -4021,7 +3565,7 @@ public class Launcher extends Activity
/**
* Receives notifications when system dialogs are to be closed.
*/
- private class CloseSystemDialogsIntentReceiver extends BroadcastReceiver {
+ @Thunk class CloseSystemDialogsIntentReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
closeSystemDialogs();
@@ -4029,36 +3573,21 @@ public class Launcher extends Activity
}
/**
- * Receives notifications whenever the appwidgets are reset.
- */
- private class AppWidgetResetObserver extends ContentObserver {
- public AppWidgetResetObserver() {
- super(new Handler());
- }
-
- @Override
- public void onChange(boolean selfChange) {
- onAppWidgetReset();
- }
- }
-
- /**
* If the activity is currently paused, signal that we need to run the passed Runnable
* in onResume.
*
* This needs to be called from incoming places where resources might have been loaded
- * while we are paused. That is becaues the Configuration might be wrong
- * when we're not running, and if it comes back to what it was when we
- * were paused, we are not restarted.
+ * while the activity is paused. That is because the Configuration (e.g., rotation) might be
+ * wrong when we're not running, and if the activity comes back to what the configuration was
+ * when we were paused, activity is not restarted.
*
* Implementation of the method from LauncherModel.Callbacks.
*
- * @return true if we are currently paused. The caller might be able to
- * skip some work in that case since we will come back again.
+ * @return {@code true} if we are currently paused. The caller might be able to skip some work
*/
- private boolean waitUntilResume(Runnable run, boolean deletePreviousRunnables) {
+ @Thunk boolean waitUntilResume(Runnable run, boolean deletePreviousRunnables) {
if (mPaused) {
- Log.i(TAG, "Deferring update until onResume");
+ if (LOGD) Log.d(TAG, "Deferring update until onResume");
if (deletePreviousRunnables) {
while (mBindOnResumeCallbacks.remove(run)) {
}
@@ -4094,7 +3623,7 @@ public class Launcher extends Activity
*/
public boolean setLoadOnResume() {
if (mPaused) {
- Log.i(TAG, "setLoadOnResume");
+ if (LOGD) Log.d(TAG, "setLoadOnResume");
mOnResumeNeedsLoad = true;
return true;
} else {
@@ -4155,10 +3684,6 @@ public class Launcher extends Activity
@Override
public void bindAddScreens(ArrayList<Long> orderedScreenIds) {
- // Log to disk
- Launcher.addDumpLog(TAG, "11683562 - bindAddScreens()", true);
- Launcher.addDumpLog(TAG, "11683562 - orderedScreenIds: " +
- TextUtils.join(", ", orderedScreenIds), true);
int count = orderedScreenIds.size();
for (int i = 0; i < count; i++) {
mWorkspace.insertNewWorkspaceScreenBeforeEmptyScreen(orderedScreenIds.get(i));
@@ -4221,9 +3746,8 @@ public class Launcher extends Activity
// Remove the extra empty screen
mWorkspace.removeExtraEmptyScreen(false, false);
- if (!LauncherAppState.isDisableAllApps() &&
- addedApps != null && mAppsCustomizeContent != null) {
- mAppsCustomizeContent.addApps(addedApps);
+ if (addedApps != null && mAppsView != null) {
+ mAppsView.addApps(addedApps);
}
}
@@ -4339,7 +3863,7 @@ public class Launcher extends Activity
/**
* Implementation of the method from LauncherModel.Callbacks.
*/
- public void bindFolders(final HashMap<Long, FolderInfo> folders) {
+ public void bindFolders(final LongArrayMap<FolderInfo> folders) {
Runnable r = new Runnable() {
public void run() {
bindFolders(folders);
@@ -4348,8 +3872,7 @@ public class Launcher extends Activity
if (waitUntilResume(r)) {
return;
}
- sFolders.clear();
- sFolders.putAll(folders);
+ sFolders = folders.clone();
}
/**
@@ -4373,12 +3896,12 @@ public class Launcher extends Activity
}
final Workspace workspace = mWorkspace;
- AppWidgetProviderInfo appWidgetInfo;
+ LauncherAppWidgetProviderInfo appWidgetInfo =
+ LauncherModel.getProviderInfo(this, item.providerName, item.user);
+
if (!mIsSafeModeEnabled
&& ((item.restoreStatus & LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY) == 0)
&& ((item.restoreStatus & LauncherAppWidgetInfo.FLAG_ID_NOT_VALID) != 0)) {
-
- appWidgetInfo = mModel.findAppWidgetProviderInfoWithComponent(this, item.providerName);
if (appWidgetInfo == null) {
if (DEBUG_WIDGETS) {
Log.d(TAG, "Removing restored widget: id=" + item.appWidgetId
@@ -4391,13 +3914,13 @@ public class Launcher extends Activity
// Note: This assumes that the id remap broadcast is received before this step.
// If that is not the case, the id remap will be ignored and user may see the
// click to setup view.
- PendingAddWidgetInfo pendingInfo = new PendingAddWidgetInfo(appWidgetInfo, null, null);
+ PendingAddWidgetInfo pendingInfo = new PendingAddWidgetInfo(this, appWidgetInfo, null);
pendingInfo.spanX = item.spanX;
pendingInfo.spanY = item.spanY;
pendingInfo.minSpanX = item.minSpanX;
pendingInfo.minSpanY = item.minSpanY;
- Bundle options =
- AppsCustomizePagedView.getDefaultOptionsForWidget(this, pendingInfo);
+ Bundle options = null;
+ WidgetHostViewLoader.getDefaultOptionsForWidget(this, pendingInfo);
int newWidgetId = mAppWidgetHost.allocateAppWidgetId();
boolean success = mAppWidgetManager.bindAppWidgetIdIfAllowed(
@@ -4428,9 +3951,9 @@ public class Launcher extends Activity
if (!mIsSafeModeEnabled && item.restoreStatus == LauncherAppWidgetInfo.RESTORE_COMPLETED) {
final int appWidgetId = item.appWidgetId;
- appWidgetInfo = mAppWidgetManager.getAppWidgetInfo(appWidgetId);
if (DEBUG_WIDGETS) {
- Log.d(TAG, "bindAppWidget: id=" + item.appWidgetId + " belongs to component " + appWidgetInfo.provider);
+ Log.d(TAG, "bindAppWidget: id=" + item.appWidgetId + " belongs to component "
+ + appWidgetInfo.provider);
}
item.hostView = mAppWidgetHost.createView(this, appWidgetId, appWidgetInfo);
@@ -4449,7 +3972,9 @@ public class Launcher extends Activity
workspace.addInScreen(item.hostView, item.container, item.screenId, item.cellX,
item.cellY, item.spanX, item.spanY, false);
- addWidgetToAutoAdvanceIfNeeded(item.hostView, appWidgetInfo);
+ if (!item.isCustomWidget()) {
+ addWidgetToAutoAdvanceIfNeeded(item.hostView, appWidgetInfo);
+ }
workspace.requestLayout();
@@ -4488,10 +4013,10 @@ public class Launcher extends Activity
*
* Implementation of the method from LauncherModel.Callbacks.
*/
- public void finishBindingItems(final boolean upgradePath) {
+ public void finishBindingItems() {
Runnable r = new Runnable() {
public void run() {
- finishBindingItems(upgradePath);
+ finishBindingItems();
}
};
if (waitUntilResume(r)) {
@@ -4526,14 +4051,10 @@ public class Launcher extends Activity
sPendingAddItem = null;
}
- if (upgradePath) {
- mWorkspace.getUniqueComponents(true, null);
- mIntentsOnWorkspaceFromUpgradePath = mWorkspace.getUniqueComponents(true, null);
- }
- PackageInstallerCompat.getInstance(this).onFinishBind();
+ InstallShortcutReceiver.disableAndFlushInstallQueue(this);
if (mLauncherCallbacks != null) {
- mLauncherCallbacks.finishBindingItems(upgradePath);
+ mLauncherCallbacks.finishBindingItems(false);
}
}
@@ -4568,18 +4089,16 @@ public class Launcher extends Activity
PropertyValuesHolder.ofFloat("scaleY", 1f));
bounceAnim.setDuration(InstallShortcutReceiver.NEW_SHORTCUT_BOUNCE_DURATION);
bounceAnim.setStartDelay(i * InstallShortcutReceiver.NEW_SHORTCUT_STAGGER_DELAY);
- bounceAnim.setInterpolator(new SmoothPagedView.OvershootInterpolator());
+ bounceAnim.setInterpolator(new OvershootInterpolator(BOUNCE_ANIMATION_TENSION));
return bounceAnim;
}
public boolean useVerticalBarLayout() {
- return LauncherAppState.getInstance().getDynamicGrid().
- getDeviceProfile().isVerticalBarLayout();
+ return mDeviceProfile.isVerticalBarLayout();
}
protected Rect getSearchBarBounds() {
- return LauncherAppState.getInstance().getDynamicGrid().
- getDeviceProfile().getSearchBarBounds();
+ return mDeviceProfile.getSearchBarBounds(Utilities.isRtl(getResources()));
}
public void bindSearchablesChanged() {
@@ -4590,33 +4109,34 @@ public class Launcher extends Activity
mSearchDropTargetBar.removeView(mQsb);
mQsb = null;
}
- mSearchDropTargetBar.setQsbSearchBar(getQsbBar());
+ mSearchDropTargetBar.setQsbSearchBar(getOrCreateQsbBar());
}
/**
+ * A runnable that we can dequeue and re-enqueue when all applications are bound (to prevent
+ * multiple calls to bind the same list.)
+ */
+ @Thunk ArrayList<AppInfo> mTmpAppsList;
+ private Runnable mBindAllApplicationsRunnable = new Runnable() {
+ public void run() {
+ bindAllApplications(mTmpAppsList);
+ mTmpAppsList = null;
+ }
+ };
+
+ /**
* Add the icons for all apps.
*
* Implementation of the method from LauncherModel.Callbacks.
*/
public void bindAllApplications(final ArrayList<AppInfo> apps) {
- if (LauncherAppState.isDisableAllApps()) {
- if (mIntentsOnWorkspaceFromUpgradePath != null) {
- if (LauncherModel.UPGRADE_USE_MORE_APPS_FOLDER) {
- getHotseat().addAllAppsFolder(mIconCache, apps,
- mIntentsOnWorkspaceFromUpgradePath, Launcher.this, mWorkspace);
- }
- mIntentsOnWorkspaceFromUpgradePath = null;
- }
- if (mAppsCustomizeContent != null) {
- mAppsCustomizeContent.onPackagesUpdated(
- LauncherModel.getSortedWidgetsAndShortcuts(this));
- }
- } else {
- if (mAppsCustomizeContent != null) {
- mAppsCustomizeContent.setApps(apps);
- mAppsCustomizeContent.onPackagesUpdated(
- LauncherModel.getSortedWidgetsAndShortcuts(this));
- }
+ if (waitUntilResume(mBindAllApplicationsRunnable, true)) {
+ mTmpAppsList = apps;
+ return;
+ }
+
+ if (mAppsView != null) {
+ mAppsView.setApps(apps);
}
if (mLauncherCallbacks != null) {
mLauncherCallbacks.bindAllApplications(apps);
@@ -4638,9 +4158,8 @@ public class Launcher extends Activity
return;
}
- if (!LauncherAppState.isDisableAllApps() &&
- mAppsCustomizeContent != null) {
- mAppsCustomizeContent.updateApps(apps);
+ if (mAppsView != null) {
+ mAppsView.updateApps(apps);
}
}
@@ -4695,22 +4214,17 @@ public class Launcher extends Activity
* Implementation of the method from LauncherModel.Callbacks.
*/
@Override
- public void updatePackageState(ArrayList<PackageInstallInfo> installInfo) {
- if (mWorkspace != null) {
- mWorkspace.updatePackageState(installInfo);
+ public void bindRestoreItemsChange(final HashSet<ItemInfo> updates) {
+ Runnable r = new Runnable() {
+ public void run() {
+ bindRestoreItemsChange(updates);
+ }
+ };
+ if (waitUntilResume(r)) {
+ return;
}
- }
- /**
- * Update the label and icon of all the icons in a package
- *
- * Implementation of the method from LauncherModel.Callbacks.
- */
- @Override
- public void updatePackageBadge(String packageName) {
- if (mWorkspace != null) {
- mWorkspace.updatePackageBadge(packageName, UserHandleCompat.myUserHandle());
- }
+ mWorkspace.updateRestoreItems(updates);
}
/**
@@ -4754,31 +4268,27 @@ public class Launcher extends Activity
}
// Update AllApps
- if (!LauncherAppState.isDisableAllApps() &&
- mAppsCustomizeContent != null) {
- mAppsCustomizeContent.removeApps(appInfos);
+ if (mAppsView != null) {
+ mAppsView.removeApps(appInfos);
}
}
- /**
- * A number of packages were updated.
- */
- private ArrayList<Object> mWidgetsAndShortcuts;
private Runnable mBindPackagesUpdatedRunnable = new Runnable() {
public void run() {
- bindPackagesUpdated(mWidgetsAndShortcuts);
- mWidgetsAndShortcuts = null;
+ bindAllPackages(mWidgetsModel);
}
};
- public void bindPackagesUpdated(final ArrayList<Object> widgetsAndShortcuts) {
+
+ @Override
+ public void bindAllPackages(final WidgetsModel model) {
if (waitUntilResume(mBindPackagesUpdatedRunnable, true)) {
- mWidgetsAndShortcuts = widgetsAndShortcuts;
+ mWidgetsModel = model;
return;
}
- // Update the widgets pane
- if (mAppsCustomizeContent != null) {
- mAppsCustomizeContent.onPackagesUpdated(widgetsAndShortcuts);
+ if (mWidgetsView != null && model != null) {
+ mWidgetsView.addWidgets(model);
+ mWidgetsModel = null;
}
}
@@ -4815,13 +4325,18 @@ public class Launcher extends Activity
}
public void lockScreenOrientation() {
- if (Utilities.isRotationEnabled(this)) {
- setRequestedOrientation(mapConfigurationOriActivityInfoOri(getResources()
- .getConfiguration().orientation));
+ if (mRotationEnabled) {
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR2) {
+ setRequestedOrientation(mapConfigurationOriActivityInfoOri(getResources()
+ .getConfiguration().orientation));
+ } else {
+ setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LOCKED);
+ }
}
}
+
public void unlockScreenOrientation(boolean immediate) {
- if (Utilities.isRotationEnabled(this)) {
+ if (mRotationEnabled) {
if (immediate) {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
} else {
@@ -4984,7 +4499,7 @@ public class Launcher extends Activity
editor.apply();
}
- private void showFirstRunClings() {
+ @Thunk void showFirstRunClings() {
// The two first run cling paths are mutually exclusive, if the launcher is preinstalled
// on the device, then we always show the first run cling experience (or if there is no
// launcher2). Otherwise, we prompt the user upon started for migration
@@ -5012,42 +4527,54 @@ public class Launcher extends Activity
if (mSearchDropTargetBar != null) mSearchDropTargetBar.hideSearchBar(false);
}
+ // TODO: These method should be a part of LauncherSearchCallback
+ @TargetApi(Build.VERSION_CODES.LOLLIPOP)
public ItemInfo createAppDragInfo(Intent appLaunchIntent) {
- // Called from search suggestion, not supported in other profiles.
- final UserHandleCompat myUser = UserHandleCompat.myUserHandle();
+ // Called from search suggestion
+ UserHandleCompat user = null;
+ if (Utilities.isLmpOrAbove()) {
+ UserHandle userHandle = appLaunchIntent.getParcelableExtra(Intent.EXTRA_USER);
+ if (userHandle != null) {
+ user = UserHandleCompat.fromUser(userHandle);
+ }
+ }
+ return createAppDragInfo(appLaunchIntent, user);
+ }
+
+ // TODO: This method should be a part of LauncherSearchCallback
+ public ItemInfo createAppDragInfo(Intent intent, UserHandleCompat user) {
+ if (user == null) {
+ user = UserHandleCompat.myUserHandle();
+ }
+
+ // Called from search suggestion, add the profile extra to the intent to ensure that we
+ // can launch it correctly
LauncherAppsCompat launcherApps = LauncherAppsCompat.getInstance(this);
- LauncherActivityInfoCompat activityInfo = launcherApps.resolveActivity(appLaunchIntent,
- myUser);
+ LauncherActivityInfoCompat activityInfo = launcherApps.resolveActivity(intent, user);
if (activityInfo == null) {
return null;
}
- return new AppInfo(this, activityInfo, myUser, mIconCache, null);
+ return new AppInfo(this, activityInfo, user, mIconCache);
}
+ // TODO: This method should be a part of LauncherSearchCallback
public ItemInfo createShortcutDragInfo(Intent shortcutIntent, CharSequence caption,
Bitmap icon) {
- // Called from search suggestion, not supported in other profiles.
- return createShortcutDragInfo(shortcutIntent, caption, icon,
+ return new ShortcutInfo(shortcutIntent, caption, caption, icon,
UserHandleCompat.myUserHandle());
}
- public ItemInfo createShortcutDragInfo(Intent shortcutIntent, CharSequence caption,
- Bitmap icon, UserHandleCompat user) {
- UserManagerCompat userManager = UserManagerCompat.getInstance(this);
- CharSequence contentDescription = userManager.getBadgedLabelForUser(caption, user);
- return new ShortcutInfo(shortcutIntent, caption, contentDescription, icon, user);
- }
-
- protected void moveWorkspaceToDefaultScreen() {
- mWorkspace.moveToDefaultScreen(false);
- }
-
+ // TODO: This method should be a part of LauncherSearchCallback
public void startDrag(View dragView, ItemInfo dragInfo, DragSource source) {
dragView.setTag(dragInfo);
mWorkspace.onExternalDragStartedWithItem(dragView);
mWorkspace.beginExternalDragShared(dragView, source);
}
+ protected void moveWorkspaceToDefaultScreen() {
+ mWorkspace.moveToDefaultScreen(false);
+ }
+
@Override
public void onPageSwitch(View newPage, int newPageIndex) {
if (mLauncherCallbacks != null) {
@@ -5056,6 +4583,23 @@ public class Launcher extends Activity
}
/**
+ * Returns a FastBitmapDrawable with the icon, accurately sized.
+ */
+ public FastBitmapDrawable createIconDrawable(Bitmap icon) {
+ FastBitmapDrawable d = new FastBitmapDrawable(icon);
+ d.setFilterBitmap(true);
+ resizeIconDrawable(d);
+ return d;
+ }
+
+ /**
+ * Resizes an icon drawable to the correct icon size.
+ */
+ public void resizeIconDrawable(Drawable icon) {
+ icon.setBounds(0, 0, mDeviceProfile.iconSizePx, mDeviceProfile.iconSizePx);
+ }
+
+ /**
* Prints out out state for debugging.
*/
public void dumpState() {
@@ -5067,10 +4611,8 @@ public class Launcher extends Activity
Log.d(TAG, "mSavedInstanceState=" + mSavedInstanceState);
Log.d(TAG, "sFolders.size=" + sFolders.size());
mModel.dumpState();
+ // TODO(hyunyoungs): add mWidgetsView.dumpState(); or mWidgetsModel.dumpState();
- if (mAppsCustomizeContent != null) {
- mAppsCustomizeContent.dumpState();
- }
Log.d(TAG, "END launcher3 dump state");
}
@@ -5125,6 +4667,14 @@ public class Launcher extends Activity
}
}
+ public static CustomAppWidget getCustomAppWidget(String name) {
+ return sCustomAppWidgets.get(name);
+ }
+
+ public static HashMap<String, CustomAppWidget> getCustomAppWidgets() {
+ return sCustomAppWidgets;
+ }
+
public void dumpLogsToLocalData() {
if (DEBUG_DUMP_LOG) {
new AsyncTask<Void, Void, Void>() {
@@ -5173,14 +4723,6 @@ public class Launcher extends Activity
}
}
-interface LauncherTransitionable {
- View getContent();
- void onLauncherTransitionPrepare(Launcher l, boolean animated, boolean toWorkspace);
- void onLauncherTransitionStart(Launcher l, boolean animated, boolean toWorkspace);
- void onLauncherTransitionStep(Launcher l, float t);
- void onLauncherTransitionEnd(Launcher l, boolean animated, boolean toWorkspace);
-}
-
interface DebugIntents {
static final String DELETE_DATABASE = "com.android.launcher3.action.DELETE_DATABASE";
static final String MIGRATE_DATABASE = "com.android.launcher3.action.MIGRATE_DATABASE";
diff --git a/src/com/android/launcher3/LauncherAnimUtils.java b/src/com/android/launcher3/LauncherAnimUtils.java
index be295f8b3..6a248a332 100644
--- a/src/com/android/launcher3/LauncherAnimUtils.java
+++ b/src/com/android/launcher3/LauncherAnimUtils.java
@@ -21,10 +21,14 @@ import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.animation.PropertyValuesHolder;
import android.animation.ValueAnimator;
+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;
+
import java.util.HashSet;
import java.util.WeakHashMap;
@@ -128,13 +132,12 @@ public class LauncherAnimUtils {
return anim;
}
- public static Animator createCircularReveal(View view, int centerX,
+ @TargetApi(Build.VERSION_CODES.LOLLIPOP)
+ public static ValueAnimator createCircularReveal(View view, int centerX,
int centerY, float startRadius, float endRadius) {
- Animator anim = ViewAnimationUtils.createCircularReveal(view, centerX,
+ ValueAnimator anim = UiThreadCircularReveal.createCircularReveal(view, centerX,
centerY, startRadius, endRadius);
- if (anim instanceof ValueAnimator) {
- new FirstFrameAnimatorHelper((ValueAnimator) anim, view);
- }
+ new FirstFrameAnimatorHelper(anim, view);
return anim;
}
}
diff --git a/src/com/android/launcher3/LauncherAppState.java b/src/com/android/launcher3/LauncherAppState.java
index b7c45a340..0b7b1fdc4 100644
--- a/src/com/android/launcher3/LauncherAppState.java
+++ b/src/com/android/launcher3/LauncherAppState.java
@@ -16,44 +16,28 @@
package com.android.launcher3;
-import android.annotation.TargetApi;
import android.app.SearchManager;
import android.content.ComponentName;
-import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
-import android.content.res.Configuration;
-import android.content.res.Resources;
-import android.database.ContentObserver;
-import android.graphics.Point;
-import android.os.Build;
-import android.os.Handler;
-import android.util.DisplayMetrics;
import android.util.Log;
-import android.view.Display;
-import android.view.WindowManager;
+
+import com.android.launcher3.accessibility.LauncherAccessibilityDelegate;
import com.android.launcher3.compat.LauncherAppsCompat;
import com.android.launcher3.compat.PackageInstallerCompat;
-import com.android.launcher3.compat.PackageInstallerCompat.PackageInstallInfo;
-import java.lang.ref.WeakReference;
-import java.util.ArrayList;
+import com.android.launcher3.util.Thunk;
-public class LauncherAppState implements DeviceProfile.DeviceProfileCallbacks {
- private static final String TAG = "LauncherAppState";
+import java.lang.ref.WeakReference;
- private static final boolean DEBUG = false;
+public class LauncherAppState {
private final AppFilter mAppFilter;
private final BuildInfo mBuildInfo;
- private final LauncherModel mModel;
+ @Thunk final LauncherModel mModel;
private final IconCache mIconCache;
+ private final WidgetPreviewLoader mWidgetCache;
- private final boolean mIsScreenLarge;
- private final float mScreenDensity;
- private final int mLongPressTimeout = 300;
-
- private WidgetPreviewLoader.CacheDb mWidgetPreviewCacheDb;
private boolean mWallpaperChangedSinceLastCheck;
private static WeakReference<LauncherProvider> sLauncherProvider;
@@ -61,7 +45,9 @@ public class LauncherAppState implements DeviceProfile.DeviceProfileCallbacks {
private static LauncherAppState INSTANCE;
- private DynamicGrid mDynamicGrid;
+ private InvariantDeviceProfile mInvariantDeviceProfile;
+
+ private LauncherAccessibilityDelegate mAccessibilityDelegate;
public static LauncherAppState getInstance() {
if (INSTANCE == null) {
@@ -96,42 +82,26 @@ public class LauncherAppState implements DeviceProfile.DeviceProfileCallbacks {
MemoryTracker.startTrackingMe(sContext, "L");
}
- // set sIsScreenXLarge and mScreenDensity *before* creating icon cache
- mIsScreenLarge = isScreenLarge(sContext.getResources());
- mScreenDensity = sContext.getResources().getDisplayMetrics().density;
-
- recreateWidgetPreviewDb();
- mIconCache = new IconCache(sContext);
+ mInvariantDeviceProfile = new InvariantDeviceProfile(sContext);
+ mIconCache = new IconCache(sContext, mInvariantDeviceProfile);
+ mWidgetCache = new WidgetPreviewLoader(sContext, mIconCache);
mAppFilter = AppFilter.loadByName(sContext.getString(R.string.app_filter_class));
mBuildInfo = BuildInfo.loadByName(sContext.getString(R.string.build_info_class));
mModel = new LauncherModel(this, mIconCache, mAppFilter);
- final LauncherAppsCompat launcherApps = LauncherAppsCompat.getInstance(sContext);
- launcherApps.addOnAppsChangedCallback(mModel);
+
+ LauncherAppsCompat.getInstance(sContext).addOnAppsChangedCallback(mModel);
// Register intent receivers
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_LOCALE_CHANGED);
- filter.addAction(Intent.ACTION_CONFIGURATION_CHANGED);
- sContext.registerReceiver(mModel, filter);
- filter = new IntentFilter();
filter.addAction(SearchManager.INTENT_GLOBAL_SEARCH_ACTIVITY_CHANGED);
- sContext.registerReceiver(mModel, filter);
- filter = new IntentFilter();
filter.addAction(SearchManager.INTENT_ACTION_SEARCHABLES_CHANGED);
- sContext.registerReceiver(mModel, filter);
-
- // Register for changes to the favorites
- ContentResolver resolver = sContext.getContentResolver();
- resolver.registerContentObserver(LauncherSettings.Favorites.CONTENT_URI, true,
- mFavoritesObserver);
- }
+ // For handling managed profiles
+ filter.addAction(LauncherAppsCompat.ACTION_MANAGED_PROFILE_ADDED);
+ filter.addAction(LauncherAppsCompat.ACTION_MANAGED_PROFILE_REMOVED);
- public void recreateWidgetPreviewDb() {
- if (mWidgetPreviewCacheDb != null) {
- mWidgetPreviewCacheDb.close();
- }
- mWidgetPreviewCacheDb = new WidgetPreviewLoader.CacheDb(sContext);
+ sContext.registerReceiver(mModel, filter);
}
/**
@@ -142,45 +112,37 @@ public class LauncherAppState implements DeviceProfile.DeviceProfileCallbacks {
final LauncherAppsCompat launcherApps = LauncherAppsCompat.getInstance(sContext);
launcherApps.removeOnAppsChangedCallback(mModel);
PackageInstallerCompat.getInstance(sContext).onStop();
-
- ContentResolver resolver = sContext.getContentResolver();
- resolver.unregisterContentObserver(mFavoritesObserver);
}
/**
- * Receives notifications whenever the user favorites have changed.
+ * Reloads the workspace items from the DB and re-binds the workspace. This should generally
+ * not be called as DB updates are automatically followed by UI update
*/
- private final ContentObserver mFavoritesObserver = new ContentObserver(new Handler()) {
- @Override
- public void onChange(boolean selfChange) {
- // If the database has ever changed, then we really need to force a reload of the
- // workspace on the next load
- mModel.resetLoadedState(false, true);
- mModel.startLoaderFromBackground();
- }
- };
+ public void reloadWorkspace() {
+ mModel.resetLoadedState(false, true);
+ mModel.startLoaderFromBackground();
+ }
LauncherModel setLauncher(Launcher launcher) {
+ getLauncherProvider().setLauncherProviderChangeListener(launcher);
mModel.initialize(launcher);
+ mAccessibilityDelegate = ((launcher != null) && Utilities.isLmpOrAbove()) ?
+ new LauncherAccessibilityDelegate(launcher) : null;
return mModel;
}
+ public LauncherAccessibilityDelegate getAccessibilityDelegate() {
+ return mAccessibilityDelegate;
+ }
+
public IconCache getIconCache() {
return mIconCache;
}
- LauncherModel getModel() {
+ public LauncherModel getModel() {
return mModel;
}
- boolean shouldShowAppOrWidgetProvider(ComponentName componentName) {
- return mAppFilter == null || mAppFilter.shouldShowApp(componentName);
- }
-
- WidgetPreviewLoader.CacheDb getWidgetPreviewCacheDb() {
- return mWidgetPreviewCacheDb;
- }
-
static void setLauncherProvider(LauncherProvider provider) {
sLauncherProvider = new WeakReference<LauncherProvider>(provider);
}
@@ -193,71 +155,10 @@ public class LauncherAppState implements DeviceProfile.DeviceProfileCallbacks {
return LauncherFiles.SHARED_PREFERENCES_KEY;
}
- @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
- DeviceProfile initDynamicGrid(Context context) {
- mDynamicGrid = createDynamicGrid(context, mDynamicGrid);
- mDynamicGrid.getDeviceProfile().addCallback(this);
- return mDynamicGrid.getDeviceProfile();
+ public WidgetPreviewLoader getWidgetCache() {
+ return mWidgetCache;
}
-
- @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
- static DynamicGrid createDynamicGrid(Context context, DynamicGrid dynamicGrid) {
- // Determine the dynamic grid properties
- WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
- Display display = wm.getDefaultDisplay();
-
- Point realSize = new Point();
- display.getRealSize(realSize);
- DisplayMetrics dm = new DisplayMetrics();
- display.getMetrics(dm);
-
- if (dynamicGrid == null) {
- Point smallestSize = new Point();
- Point largestSize = new Point();
- display.getCurrentSizeRange(smallestSize, largestSize);
-
- dynamicGrid = new DynamicGrid(context,
- context.getResources(),
- Math.min(smallestSize.x, smallestSize.y),
- Math.min(largestSize.x, largestSize.y),
- realSize.x, realSize.y,
- dm.widthPixels, dm.heightPixels);
- }
-
- // Update the icon size
- DeviceProfile grid = dynamicGrid.getDeviceProfile();
- grid.updateFromConfiguration(context, context.getResources(),
- realSize.x, realSize.y,
- dm.widthPixels, dm.heightPixels);
- return dynamicGrid;
- }
-
- public DynamicGrid getDynamicGrid() {
- return mDynamicGrid;
- }
-
- public boolean isScreenLarge() {
- return mIsScreenLarge;
- }
-
- // Need a version that doesn't require an instance of LauncherAppState for the wallpaper picker
- public static boolean isScreenLarge(Resources res) {
- return res.getBoolean(R.bool.is_large_tablet);
- }
-
- public static boolean isScreenLandscape(Context context) {
- return context.getResources().getConfiguration().orientation ==
- Configuration.ORIENTATION_LANDSCAPE;
- }
-
- public float getScreenDensity() {
- return mScreenDensity;
- }
-
- public int getLongPressTimeout() {
- return mLongPressTimeout;
- }
-
+
public void onWallpaperChanged() {
mWallpaperChangedSinceLastCheck = true;
}
@@ -268,29 +169,11 @@ public class LauncherAppState implements DeviceProfile.DeviceProfileCallbacks {
return result;
}
- @Override
- public void onAvailableSizeChanged(DeviceProfile grid) {
- Utilities.setIconSize(grid.iconSizePx);
- }
-
- public static boolean isDisableAllApps() {
- // Returns false on non-dogfood builds.
- return getInstance().mBuildInfo.isDogfoodBuild() &&
- Utilities.isPropertyEnabled(Launcher.DISABLE_ALL_APPS_PROPERTY);
+ public InvariantDeviceProfile getInvariantDeviceProfile() {
+ return mInvariantDeviceProfile;
}
public static boolean isDogfoodBuild() {
return getInstance().mBuildInfo.isDogfoodBuild();
}
-
- public void setPackageState(ArrayList<PackageInstallInfo> installInfo) {
- mModel.setPackageState(installInfo);
- }
-
- /**
- * Updates the icons and label of all icons for the provided package name.
- */
- public void updatePackageBadge(String packageName) {
- mModel.updatePackageBadge(packageName);
- }
}
diff --git a/src/com/android/launcher3/LauncherAppWidgetHost.java b/src/com/android/launcher3/LauncherAppWidgetHost.java
index a309f268c..de7c61000 100644
--- a/src/com/android/launcher3/LauncherAppWidgetHost.java
+++ b/src/com/android/launcher3/LauncherAppWidgetHost.java
@@ -21,9 +21,12 @@ import android.appwidget.AppWidgetHostView;
import android.appwidget.AppWidgetProviderInfo;
import android.content.Context;
import android.os.TransactionTooLargeException;
+import android.view.LayoutInflater;
+import android.view.View;
import java.util.ArrayList;
+
/**
* Specific {@link AppWidgetHost} that creates our {@link LauncherAppWidgetHostView}
* which correctly captures all long-press events. This ensures that users can
@@ -33,16 +36,31 @@ public class LauncherAppWidgetHost extends AppWidgetHost {
private final ArrayList<Runnable> mProviderChangeListeners = new ArrayList<Runnable>();
- Launcher mLauncher;
+ private int mQsbWidgetId = -1;
+ private Launcher mLauncher;
public LauncherAppWidgetHost(Launcher launcher, int hostId) {
super(launcher, hostId);
mLauncher = launcher;
}
+ public void setQsbWidgetId(int widgetId) {
+ mQsbWidgetId = widgetId;
+ }
+
@Override
protected AppWidgetHostView onCreateView(Context context, int appWidgetId,
AppWidgetProviderInfo appWidget) {
+ if (appWidgetId == mQsbWidgetId) {
+ return new LauncherAppWidgetHostView(context) {
+
+ @Override
+ protected View getErrorView() {
+ // For the QSB, show an empty view instead of an error view.
+ return new View(getContext());
+ }
+ };
+ }
return new LauncherAppWidgetHostView(context);
}
@@ -77,12 +95,37 @@ public class LauncherAppWidgetHost extends AppWidgetHost {
}
protected void onProvidersChanged() {
- // Once we get the message that widget packages are updated, we need to rebind items
- // in AppsCustomize accordingly.
- mLauncher.bindPackagesUpdated(LauncherModel.getSortedWidgetsAndShortcuts(mLauncher));
+ mLauncher.getModel().loadAndBindWidgetsAndShortcuts(mLauncher, mLauncher,
+ true /* refresh */);
+ if (!mProviderChangeListeners.isEmpty()) {
+ for (Runnable callback : new ArrayList<>(mProviderChangeListeners)) {
+ callback.run();
+ }
+ }
+ }
- for (Runnable callback : mProviderChangeListeners) {
- callback.run();
+ public AppWidgetHostView createView(Context context, int appWidgetId,
+ LauncherAppWidgetProviderInfo appWidget) {
+ if (appWidget.isCustomWidget) {
+ LauncherAppWidgetHostView lahv = new LauncherAppWidgetHostView(context);
+ LayoutInflater inflater = (LayoutInflater)
+ context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+ inflater.inflate(appWidget.initialLayout, lahv);
+ lahv.setAppWidget(0, appWidget);
+ lahv.updateLastInflationOrientation();
+ return lahv;
+ } else {
+ return super.createView(context, appWidgetId, appWidget);
}
}
+
+ /**
+ * Called when the AppWidget provider for a AppWidget has been upgraded to a new apk.
+ */
+ @Override
+ protected void onProviderChanged(int appWidgetId, AppWidgetProviderInfo appWidget) {
+ LauncherAppWidgetProviderInfo info = LauncherAppWidgetProviderInfo.fromProviderInfo(
+ mLauncher, appWidget);
+ super.onProviderChanged(appWidgetId, info);
+ }
}
diff --git a/src/com/android/launcher3/LauncherAppWidgetHostView.java b/src/com/android/launcher3/LauncherAppWidgetHostView.java
index e39727b17..cf461a5b8 100644
--- a/src/com/android/launcher3/LauncherAppWidgetHostView.java
+++ b/src/com/android/launcher3/LauncherAppWidgetHostView.java
@@ -17,6 +17,7 @@
package com.android.launcher3;
import android.appwidget.AppWidgetHostView;
+import android.appwidget.AppWidgetProviderInfo;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.MotionEvent;
@@ -35,6 +36,7 @@ public class LauncherAppWidgetHostView extends AppWidgetHostView implements Touc
LayoutInflater mInflater;
private CheckLongPressHelper mLongPressHelper;
+ private StylusEventHelper mStylusEventHelper;
private Context mContext;
private int mPreviousOrientation;
private DragLayer mDragLayer;
@@ -45,8 +47,10 @@ public class LauncherAppWidgetHostView extends AppWidgetHostView implements Touc
super(context);
mContext = context;
mLongPressHelper = new CheckLongPressHelper(this);
+ mStylusEventHelper = new StylusEventHelper(this);
mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
mDragLayer = ((Launcher) context).getDragLayer();
+ setAccessibilityDelegate(LauncherAppState.getInstance().getAccessibilityDelegate());
}
@Override
@@ -54,10 +58,14 @@ public class LauncherAppWidgetHostView extends AppWidgetHostView implements Touc
return mInflater.inflate(R.layout.appwidget_error, this, false);
}
+ public void updateLastInflationOrientation() {
+ mPreviousOrientation = mContext.getResources().getConfiguration().orientation;
+ }
+
@Override
public void updateAppWidget(RemoteViews remoteViews) {
// Store the orientation in which the widget was inflated
- mPreviousOrientation = mContext.getResources().getConfiguration().orientation;
+ updateLastInflationOrientation();
super.updateAppWidget(remoteViews);
}
@@ -83,11 +91,17 @@ public class LauncherAppWidgetHostView extends AppWidgetHostView implements Touc
return true;
}
- // Watch for longpress events at this level to make sure
- // users can always pick up this widget
+ // Watch for longpress or stylus button press events at this level to
+ // make sure users can always pick up this widget
+ if (mStylusEventHelper.checkAndPerformStylusEvent(ev)) {
+ mLongPressHelper.cancelLongPress();
+ return true;
+ }
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN: {
- mLongPressHelper.postCheckForLongPress();
+ if (!mStylusEventHelper.inStylusButtonPressed()) {
+ mLongPressHelper.postCheckForLongPress();
+ }
mDragLayer.setTouchCompleteListener(this);
break;
}
@@ -137,6 +151,20 @@ public class LauncherAppWidgetHostView extends AppWidgetHostView implements Touc
}
@Override
+ public AppWidgetProviderInfo getAppWidgetInfo() {
+ AppWidgetProviderInfo info = super.getAppWidgetInfo();
+ if (info != null && !(info instanceof LauncherAppWidgetProviderInfo)) {
+ throw new IllegalStateException("Launcher widget must have"
+ + " LauncherAppWidgetProviderInfo");
+ }
+ return info;
+ }
+
+ public LauncherAppWidgetProviderInfo getLauncherAppWidgetProviderInfo() {
+ return (LauncherAppWidgetProviderInfo) getAppWidgetInfo();
+ }
+
+ @Override
public void onTouchComplete() {
if (!mLongPressHelper.hasPerformedLongPress()) {
// If a long press has been performed, we don't want to clear the record of that since
diff --git a/src/com/android/launcher3/LauncherAppWidgetInfo.java b/src/com/android/launcher3/LauncherAppWidgetInfo.java
index 5c6535a24..aad18b578 100644
--- a/src/com/android/launcher3/LauncherAppWidgetInfo.java
+++ b/src/com/android/launcher3/LauncherAppWidgetInfo.java
@@ -56,6 +56,11 @@ public class LauncherAppWidgetInfo extends ItemInfo {
static final int NO_ID = -1;
/**
+ * Indicates that this is a locally defined widget and hence has no system allocated id.
+ */
+ static final int CUSTOM_WIDGET_ID = -100;
+
+ /**
* Identifier for this widget when talking with
* {@link android.appwidget.AppWidgetManager} for updates.
*/
@@ -86,7 +91,12 @@ public class LauncherAppWidgetInfo extends ItemInfo {
AppWidgetHostView hostView = null;
LauncherAppWidgetInfo(int appWidgetId, ComponentName providerName) {
- itemType = LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET;
+ if (appWidgetId == CUSTOM_WIDGET_ID) {
+ itemType = LauncherSettings.Favorites.ITEM_TYPE_CUSTOM_APPWIDGET;
+ } else {
+ itemType = LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET;
+ }
+
this.appWidgetId = appWidgetId;
this.providerName = providerName;
@@ -99,6 +109,10 @@ public class LauncherAppWidgetInfo extends ItemInfo {
restoreStatus = RESTORE_COMPLETED;
}
+ public boolean isCustomWidget() {
+ return appWidgetId == CUSTOM_WIDGET_ID;
+ }
+
@Override
void onAddToDatabase(Context context, ContentValues values) {
super.onAddToDatabase(context, values);
diff --git a/src/com/android/launcher3/LauncherAppWidgetProviderInfo.java b/src/com/android/launcher3/LauncherAppWidgetProviderInfo.java
new file mode 100644
index 000000000..85af92f30
--- /dev/null
+++ b/src/com/android/launcher3/LauncherAppWidgetProviderInfo.java
@@ -0,0 +1,113 @@
+package com.android.launcher3;
+
+import android.annotation.TargetApi;
+import android.appwidget.AppWidgetProviderInfo;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.graphics.drawable.Drawable;
+import android.os.Build;
+import android.os.Parcel;
+
+/**
+ * This class is a thin wrapper around the framework AppWidgetProviderInfo class. This class affords
+ * a common object for describing both framework provided AppWidgets as well as custom widgets
+ * (who's implementation is owned by the launcher). This object represents a widget type / class,
+ * as opposed to a widget instance, and so should not be confused with {@link LauncherAppWidgetInfo}
+ */
+public class LauncherAppWidgetProviderInfo extends AppWidgetProviderInfo {
+
+ public boolean isCustomWidget = false;
+
+ private int mSpanX = -1;
+ private int mSpanY = -1;
+ private int mMinSpanX = -1;
+ private int mMinSpanY = -1;
+
+ public static LauncherAppWidgetProviderInfo fromProviderInfo(Context context,
+ AppWidgetProviderInfo info) {
+
+ // In lieu of a public super copy constructor, we first write the AppWidgetProviderInfo
+ // into a parcel, and then construct a new LauncherAppWidgetProvider info from the
+ // associated super parcel constructor. This allows us to copy non-public members without
+ // using reflection.
+ Parcel p = Parcel.obtain();
+ info.writeToParcel(p, 0);
+ p.setDataPosition(0);
+ LauncherAppWidgetProviderInfo lawpi = new LauncherAppWidgetProviderInfo(p);
+ p.recycle();
+ return lawpi;
+ }
+
+ public LauncherAppWidgetProviderInfo(Parcel in) {
+ super(in);
+ }
+
+ public LauncherAppWidgetProviderInfo(Context context, CustomAppWidget widget) {
+ isCustomWidget = true;
+
+ provider = new ComponentName(context, widget.getClass().getName());
+ icon = widget.getIcon();
+ label = widget.getLabel();
+ previewImage = widget.getPreviewImage();
+ initialLayout = widget.getWidgetLayout();
+ resizeMode = widget.getResizeMode();
+ }
+
+ @TargetApi(Build.VERSION_CODES.LOLLIPOP)
+ public String getLabel(PackageManager packageManager) {
+ if (isCustomWidget) {
+ return Utilities.trim(label);
+ }
+ return super.loadLabel(packageManager);
+ }
+
+ @TargetApi(Build.VERSION_CODES.LOLLIPOP)
+ public Drawable getIcon(Context context, IconCache cache) {
+ if (isCustomWidget) {
+ return cache.getFullResIcon(provider.getPackageName(), icon);
+ }
+ return super.loadIcon(context,
+ LauncherAppState.getInstance().getInvariantDeviceProfile().fillResIconDpi);
+ }
+
+ public String toString(PackageManager pm) {
+ if (isCustomWidget) {
+ return "WidgetProviderInfo(" + provider + ")";
+ }
+ return String.format("WidgetProviderInfo provider:%s package:%s short:%s label:%s",
+ provider.toString(), provider.getPackageName(), provider.getShortClassName(), getLabel(pm));
+ }
+
+ public int getSpanX(Launcher launcher) {
+ lazyLoadSpans(launcher);
+ return mSpanX;
+ }
+
+ public int getSpanY(Launcher launcher) {
+ lazyLoadSpans(launcher);
+ return mSpanY;
+ }
+
+ public int getMinSpanX(Launcher launcher) {
+ lazyLoadSpans(launcher);
+ return mMinSpanX;
+ }
+
+ public int getMinSpanY(Launcher launcher) {
+ lazyLoadSpans(launcher);
+ return mMinSpanY;
+ }
+
+ private void lazyLoadSpans(Launcher launcher) {
+ if (mSpanX < 0 || mSpanY < 0 || mMinSpanX < 0 || mMinSpanY < 0) {
+ int[] minResizeSpan = launcher.getMinSpanForWidget(this);
+ int[] span = launcher.getSpanForWidget(this);
+
+ mSpanX = span[0];
+ mSpanY = span[1];
+ mMinSpanX = minResizeSpan[0];
+ mMinSpanY = minResizeSpan[1];
+ }
+ }
+ }
diff --git a/src/com/android/launcher3/LauncherBackupAgentHelper.java b/src/com/android/launcher3/LauncherBackupAgentHelper.java
index 3868a57f1..a92a889f9 100644
--- a/src/com/android/launcher3/LauncherBackupAgentHelper.java
+++ b/src/com/android/launcher3/LauncherBackupAgentHelper.java
@@ -32,7 +32,7 @@ public class LauncherBackupAgentHelper extends BackupAgentHelper {
private static final String LAUNCHER_DATA_PREFIX = "L";
- static final boolean VERBOSE = true;
+ static final boolean VERBOSE = false;
static final boolean DEBUG = false;
private static BackupManager sBackupManager;
@@ -78,7 +78,7 @@ public class LauncherBackupAgentHelper extends BackupAgentHelper {
super.onRestore(data, appVersionCode, newState);
// If no favorite was migrated, clear the data and start fresh.
final Cursor c = getContentResolver().query(
- LauncherSettings.Favorites.CONTENT_URI_NO_NOTIFICATION, null, null, null, null);
+ LauncherSettings.Favorites.CONTENT_URI, null, null, null, null);
hasData = c.moveToNext();
c.close();
} catch (Exception e) {
@@ -90,6 +90,12 @@ public class LauncherBackupAgentHelper extends BackupAgentHelper {
if (hasData && mHelper.restoreSuccessful) {
LauncherAppState.getLauncherProvider().clearFlagEmptyDbCreated();
LauncherClings.synchonouslyMarkFirstRunClingDismissed(this);
+
+ // TODO: Update the backup set to include rank.
+ if (mHelper.restoredBackupVersion <= 3) {
+ LauncherAppState.getLauncherProvider().updateFolderItemsRank();
+ LauncherAppState.getLauncherProvider().convertShortcutsToLauncherActivities();
+ }
} else {
if (VERBOSE) Log.v(TAG, "Nothing was restored, clearing DB");
LauncherAppState.getLauncherProvider().createEmptyDB();
diff --git a/src/com/android/launcher3/LauncherBackupHelper.java b/src/com/android/launcher3/LauncherBackupHelper.java
index 437434748..8c6fedbdc 100644
--- a/src/com/android/launcher3/LauncherBackupHelper.java
+++ b/src/com/android/launcher3/LauncherBackupHelper.java
@@ -19,14 +19,16 @@ import android.app.backup.BackupDataInputStream;
import android.app.backup.BackupDataOutput;
import android.app.backup.BackupHelper;
import android.app.backup.BackupManager;
-import android.appwidget.AppWidgetManager;
-import android.appwidget.AppWidgetProviderInfo;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.ResolveInfo;
+import android.content.res.XmlResourceParser;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
@@ -49,18 +51,20 @@ import com.android.launcher3.backup.BackupProtos.Screen;
import com.android.launcher3.backup.BackupProtos.Widget;
import com.android.launcher3.compat.UserHandleCompat;
import com.android.launcher3.compat.UserManagerCompat;
+import com.android.launcher3.util.Thunk;
import com.google.protobuf.nano.InvalidProtocolBufferNanoException;
import com.google.protobuf.nano.MessageNano;
-import java.io.ByteArrayOutputStream;
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URISyntaxException;
import java.util.ArrayList;
-import java.util.HashMap;
+import java.util.Arrays;
import java.util.HashSet;
-import java.util.List;
import java.util.zip.CRC32;
/**
@@ -71,7 +75,7 @@ public class LauncherBackupHelper implements BackupHelper {
private static final boolean VERBOSE = LauncherBackupAgentHelper.VERBOSE;
private static final boolean DEBUG = LauncherBackupAgentHelper.DEBUG;
- private static final int BACKUP_VERSION = 2;
+ private static final int BACKUP_VERSION = 3;
private static final int MAX_JOURNAL_SIZE = 1000000;
// Journal key is such that it is always smaller than any dynamically generated
@@ -84,11 +88,6 @@ public class LauncherBackupHelper implements BackupHelper {
/** widgets contain previews, which are very large, dribble them out */
private static final int MAX_WIDGETS_PER_PASS = 5;
- private static final int IMAGE_COMPRESSION_QUALITY = 75;
-
- private static final Bitmap.CompressFormat IMAGE_FORMAT =
- android.graphics.Bitmap.CompressFormat.PNG;
-
private static final String[] FAVORITE_PROJECTION = {
Favorites._ID, // 0
Favorites.MODIFIED, // 1
@@ -136,24 +135,33 @@ public class LauncherBackupHelper implements BackupHelper {
private static final int SCREEN_RANK_INDEX = 2;
- private final Context mContext;
+ @Thunk final Context mContext;
private final HashSet<String> mExistingKeys;
private final ArrayList<Key> mKeys;
+ private final ItemTypeMatcher[] mItemTypeMatchers;
+ private final long mUserSerial;
- private IconCache mIconCache;
private BackupManager mBackupManager;
- private HashMap<ComponentName, AppWidgetProviderInfo> mWidgetMap;
private byte[] mBuffer = new byte[512];
private long mLastBackupRestoreTime;
+ private boolean mBackupDataWasUpdated;
+
+ private IconCache mIconCache;
+ private DeviceProfieData mDeviceProfileData;
+ private InvariantDeviceProfile mIdp;
- private DeviceProfieData mCurrentProfile;
boolean restoreSuccessful;
+ int restoredBackupVersion = 1;
public LauncherBackupHelper(Context context) {
mContext = context;
mExistingKeys = new HashSet<String>();
mKeys = new ArrayList<Key>();
restoreSuccessful = true;
+ mItemTypeMatchers = new ItemTypeMatcher[CommonAppTypeParser.SUPPORTED_TYPE_COUNT];
+
+ UserManagerCompat userManager = UserManagerCompat.getInstance(mContext);
+ mUserSerial = userManager.getSerialNumberForUser(UserHandleCompat.myUserHandle());
}
private void dataChanged() {
@@ -171,6 +179,7 @@ public class LauncherBackupHelper implements BackupHelper {
mExistingKeys.add(keyToBackupKey(key));
}
}
+ restoredBackupVersion = journal.backupVersion;
}
/**
@@ -191,10 +200,19 @@ public class LauncherBackupHelper implements BackupHelper {
Journal in = readJournal(oldState);
if (!launcherIsReady()) {
+ dataChanged();
// Perform backup later.
writeJournal(newState, in);
return;
}
+
+ if (mDeviceProfileData == null) {
+ LauncherAppState app = LauncherAppState.getInstance();
+ mIdp = app.getInvariantDeviceProfile();
+ mDeviceProfileData = initDeviceProfileData(mIdp);
+ mIconCache = app.getIconCache();
+ }
+
Log.v(TAG, "lastBackupTime = " + in.t);
mKeys.clear();
applyJournal(in);
@@ -202,7 +220,7 @@ public class LauncherBackupHelper implements BackupHelper {
// Record the time before performing backup so that entries edited while the backup
// was going on, do not get missed in next backup.
long newBackupTime = System.currentTimeMillis();
-
+ mBackupDataWasUpdated = false;
try {
backupFavorites(data);
backupScreens(data);
@@ -220,16 +238,30 @@ public class LauncherBackupHelper implements BackupHelper {
for (String deleted: mExistingKeys) {
if (VERBOSE) Log.v(TAG, "dropping deleted item " + deleted);
data.writeEntityHeader(deleted, -1);
+ mBackupDataWasUpdated = true;
}
mExistingKeys.clear();
- mLastBackupRestoreTime = newBackupTime;
+ if (!mBackupDataWasUpdated) {
+ // Check if any metadata has changed
+ mBackupDataWasUpdated = (in.profile == null)
+ || !Arrays.equals(DeviceProfieData.toByteArray(in.profile),
+ DeviceProfieData.toByteArray(mDeviceProfileData))
+ || (in.backupVersion != BACKUP_VERSION)
+ || (in.appVersion != getAppVersion());
+ }
- // We store the journal at two places.
- // 1) Storing it in newState allows us to do partial backups by comparing old state
- // 2) Storing it in backup data allows us to validate keys during restore
- Journal state = getCurrentStateJournal();
- writeRowToBackup(JOURNAL_KEY, state, data);
+ if (mBackupDataWasUpdated) {
+ mLastBackupRestoreTime = newBackupTime;
+
+ // We store the journal at two places.
+ // 1) Storing it in newState allows us to do partial backups by comparing old state
+ // 2) Storing it in backup data allows us to validate keys during restore
+ Journal state = getCurrentStateJournal();
+ writeRowToBackup(JOURNAL_KEY, state, data);
+ } else {
+ if (DEBUG) Log.d(TAG, "Nothing was written during backup");
+ }
} catch (IOException e) {
Log.e(TAG, "launcher backup has failed", e);
}
@@ -242,8 +274,7 @@ public class LauncherBackupHelper implements BackupHelper {
* to this device.
*/
private boolean isBackupCompatible(Journal oldState) {
- DeviceProfieData currentProfile = getDeviceProfieData();
-
+ DeviceProfieData currentProfile = mDeviceProfileData;
DeviceProfieData oldProfile = oldState.profile;
if (oldProfile == null || oldProfile.desktopCols == 0) {
@@ -277,6 +308,14 @@ public class LauncherBackupHelper implements BackupHelper {
return;
}
+ if (mDeviceProfileData == null) {
+ // This call does not happen on a looper thread. So LauncherAppState
+ // can't be created . Instead initialize required dependencies directly.
+ mIdp = new InvariantDeviceProfile(mContext);
+ mDeviceProfileData = initDeviceProfileData(mIdp);
+ mIconCache = new IconCache(mContext, mIdp);
+ }
+
int dataSize = data.size();
if (mBuffer.length < dataSize) {
mBuffer = new byte[dataSize];
@@ -351,7 +390,7 @@ public class LauncherBackupHelper implements BackupHelper {
journal.key = mKeys.toArray(new BackupProtos.Key[mKeys.size()]);
journal.appVersion = getAppVersion();
journal.backupVersion = BACKUP_VERSION;
- journal.profile = getDeviceProfieData();
+ journal.profile = mDeviceProfileData;
return journal;
}
@@ -364,23 +403,13 @@ public class LauncherBackupHelper implements BackupHelper {
}
}
- /**
- * @return the current device profile information.
- */
- private DeviceProfieData getDeviceProfieData() {
- if (mCurrentProfile != null) {
- return mCurrentProfile;
- }
- final Context applicationContext = mContext.getApplicationContext();
- DeviceProfile profile = LauncherAppState.createDynamicGrid(applicationContext, null)
- .getDeviceProfile();
-
- mCurrentProfile = new DeviceProfieData();
- mCurrentProfile.desktopRows = profile.numRows;
- mCurrentProfile.desktopCols = profile.numColumns;
- mCurrentProfile.hotseatCount = profile.numHotseatIcons;
- mCurrentProfile.allappsRank = profile.hotseatAllAppsRank;
- return mCurrentProfile;
+ private DeviceProfieData initDeviceProfileData(InvariantDeviceProfile profile) {
+ DeviceProfieData data = new DeviceProfieData();
+ data.desktopRows = profile.numRows;
+ data.desktopCols = profile.numColumns;
+ data.hotseatCount = profile.numHotseatIcons;
+ data.allappsRank = profile.hotseatAllAppsRank;
+ return data;
}
/**
@@ -430,7 +459,7 @@ public class LauncherBackupHelper implements BackupHelper {
ContentResolver cr = mContext.getContentResolver();
ContentValues values = unpackFavorite(buffer, dataSize);
- cr.insert(Favorites.CONTENT_URI_NO_NOTIFICATION, values);
+ cr.insert(Favorites.CONTENT_URI, values);
}
/**
@@ -491,11 +520,6 @@ public class LauncherBackupHelper implements BackupHelper {
*/
private void backupIcons(BackupDataOutput data) throws IOException {
// persist icons that haven't been persisted yet
- if (!initializeIconCache()) {
- dataChanged(); // try again later
- if (DEBUG) Log.d(TAG, "Launcher is not initialized, delaying icon backup");
- return;
- }
final ContentResolver cr = mContext.getContentResolver();
final int dpi = mContext.getResources().getDisplayMetrics().densityDpi;
final UserHandleCompat myUserHandle = UserHandleCompat.myUserHandle();
@@ -579,7 +603,8 @@ public class LauncherBackupHelper implements BackupHelper {
Log.w(TAG, "failed to unpack icon for " + key.name);
}
if (VERBOSE) Log.v(TAG, "saving restored icon as: " + key.name);
- IconCache.preloadIcon(mContext, ComponentName.unflattenFromString(key.name), icon, res.dpi);
+ mIconCache.preloadIcon(ComponentName.unflattenFromString(key.name), icon, res.dpi,
+ "" /* label */, mUserSerial);
}
/**
@@ -591,17 +616,8 @@ public class LauncherBackupHelper implements BackupHelper {
*/
private void backupWidgets(BackupDataOutput data) throws IOException {
// persist static widget info that hasn't been persisted yet
- final LauncherAppState appState = LauncherAppState.getInstanceNoCreate();
- if (appState == null || !initializeIconCache()) {
- Log.w(TAG, "Failed to get icon cache during restore");
- return;
- }
final ContentResolver cr = mContext.getContentResolver();
- final WidgetPreviewLoader previewLoader = new WidgetPreviewLoader(mContext);
- final PagedViewCellLayout widgetSpacingLayout = new PagedViewCellLayout(mContext);
final int dpi = mContext.getResources().getDisplayMetrics().densityDpi;
- final DeviceProfile profile = appState.getDynamicGrid().getDeviceProfile();
- if (DEBUG) Log.d(TAG, "cellWidthPx: " + profile.cellWidthPx);
int backupWidgetCount = 0;
String where = Favorites.ITEM_TYPE + "=" + Favorites.ITEM_TYPE_APPWIDGET + " AND "
@@ -613,8 +629,6 @@ public class LauncherBackupHelper implements BackupHelper {
while(cursor.moveToNext()) {
final long id = cursor.getLong(ID_INDEX);
final String providerName = cursor.getString(APPWIDGET_PROVIDER_INDEX);
- final int spanX = cursor.getInt(SPANX_INDEX);
- final int spanY = cursor.getInt(SPANY_INDEX);
final ComponentName provider = ComponentName.unflattenFromString(providerName);
Key key = null;
String backupKey = null;
@@ -624,7 +638,7 @@ public class LauncherBackupHelper implements BackupHelper {
} else {
Log.w(TAG, "empty intent on appwidget: " + id);
}
- if (mExistingKeys.contains(backupKey)) {
+ if (mExistingKeys.contains(backupKey) && restoredBackupVersion >= BACKUP_VERSION) {
if (DEBUG) Log.d(TAG, "already saved widget " + backupKey);
// remember that we already backed this up previously
@@ -633,9 +647,8 @@ public class LauncherBackupHelper implements BackupHelper {
if (DEBUG) Log.d(TAG, "I can count this high: " + backupWidgetCount);
if (backupWidgetCount < MAX_WIDGETS_PER_PASS) {
if (DEBUG) Log.d(TAG, "saving widget " + backupKey);
- previewLoader.setPreviewSize(spanX * profile.cellWidthPx,
- spanY * profile.cellHeightPx, widgetSpacingLayout);
- writeRowToBackup(key, packWidget(dpi, previewLoader, mIconCache, provider), data);
+ UserHandleCompat user = UserHandleCompat.myUserHandle();
+ writeRowToBackup(key, packWidget(dpi, provider, user), data);
mKeys.add(key);
backupWidgetCount ++;
} else {
@@ -671,8 +684,8 @@ public class LauncherBackupHelper implements BackupHelper {
if (icon == null) {
Log.w(TAG, "failed to unpack widget icon for " + key.name);
} else {
- IconCache.preloadIcon(mContext, ComponentName.unflattenFromString(widget.provider),
- icon, widget.icon.dpi);
+ mIconCache.preloadIcon(ComponentName.unflattenFromString(widget.provider),
+ icon, widget.icon.dpi, widget.label, mUserSerial);
}
}
@@ -738,6 +751,17 @@ public class LauncherBackupHelper implements BackupHelper {
return checksum.getValue();
}
+ /**
+ * @return true if its an hotseat item, that can be replaced during restore.
+ * TODO: Extend check for folders in hotseat.
+ */
+ private boolean isReplaceableHotseatItem(Favorite favorite) {
+ return favorite.container == Favorites.CONTAINER_HOTSEAT
+ && favorite.intent != null
+ && (favorite.itemType == Favorites.ITEM_TYPE_APPLICATION
+ || favorite.itemType == Favorites.ITEM_TYPE_SHORTCUT);
+ }
+
/** Serialize a Favorite for persistence, including a checksum wrapper. */
private Favorite packFavorite(Cursor c) {
Favorite favorite = new Favorite();
@@ -749,30 +773,16 @@ public class LauncherBackupHelper implements BackupHelper {
favorite.spanX = c.getInt(SPANX_INDEX);
favorite.spanY = c.getInt(SPANY_INDEX);
favorite.iconType = c.getInt(ICON_TYPE_INDEX);
- if (favorite.iconType == Favorites.ICON_TYPE_RESOURCE) {
- String iconPackage = c.getString(ICON_PACKAGE_INDEX);
- if (!TextUtils.isEmpty(iconPackage)) {
- favorite.iconPackage = iconPackage;
- }
- String iconResource = c.getString(ICON_RESOURCE_INDEX);
- if (!TextUtils.isEmpty(iconResource)) {
- favorite.iconResource = iconResource;
- }
- }
- if (favorite.iconType == Favorites.ICON_TYPE_BITMAP) {
- byte[] blob = c.getBlob(ICON_INDEX);
- if (blob != null && blob.length > 0) {
- favorite.icon = blob;
- }
- }
+
String title = c.getString(TITLE_INDEX);
if (!TextUtils.isEmpty(title)) {
favorite.title = title;
}
String intentDescription = c.getString(INTENT_INDEX);
+ Intent intent = null;
if (!TextUtils.isEmpty(intentDescription)) {
try {
- Intent intent = Intent.parseUri(intentDescription, 0);
+ intent = Intent.parseUri(intentDescription, 0);
intent.removeExtra(ItemInfo.EXTRA_PROFILE);
favorite.intent = intent.toUri(0);
} catch (URISyntaxException e) {
@@ -786,6 +796,47 @@ public class LauncherBackupHelper implements BackupHelper {
if (!TextUtils.isEmpty(appWidgetProvider)) {
favorite.appWidgetProvider = appWidgetProvider;
}
+ } else if (favorite.itemType == Favorites.ITEM_TYPE_SHORTCUT) {
+ if (favorite.iconType == Favorites.ICON_TYPE_RESOURCE) {
+ String iconPackage = c.getString(ICON_PACKAGE_INDEX);
+ if (!TextUtils.isEmpty(iconPackage)) {
+ favorite.iconPackage = iconPackage;
+ }
+ String iconResource = c.getString(ICON_RESOURCE_INDEX);
+ if (!TextUtils.isEmpty(iconResource)) {
+ favorite.iconResource = iconResource;
+ }
+ }
+
+ byte[] blob = c.getBlob(ICON_INDEX);
+ if (blob != null && blob.length > 0) {
+ favorite.icon = blob;
+ }
+ }
+
+ if (isReplaceableHotseatItem(favorite)) {
+ if (intent != null && intent.getComponent() != null) {
+ PackageManager pm = mContext.getPackageManager();
+ ActivityInfo activity = null;;
+ try {
+ activity = pm.getActivityInfo(intent.getComponent(), 0);
+ } catch (NameNotFoundException e) {
+ Log.e(TAG, "Target not found", e);
+ }
+ if (activity == null) {
+ return favorite;
+ }
+ for (int i = 0; i < mItemTypeMatchers.length; i++) {
+ if (mItemTypeMatchers[i] == null) {
+ mItemTypeMatchers[i] = new ItemTypeMatcher(
+ CommonAppTypeParser.getResourceForItemType(i));
+ }
+ if (mItemTypeMatchers[i].matches(activity, pm)) {
+ favorite.targetType = i;
+ break;
+ }
+ }
+ }
}
return favorite;
@@ -795,6 +846,7 @@ public class LauncherBackupHelper implements BackupHelper {
private ContentValues unpackFavorite(byte[] buffer, int dataSize)
throws IOException {
Favorite favorite = unpackProto(new Favorite(), buffer, dataSize);
+
ContentValues values = new ContentValues();
values.put(Favorites._ID, favorite.id);
values.put(Favorites.SCREEN, favorite.screen);
@@ -803,14 +855,16 @@ public class LauncherBackupHelper implements BackupHelper {
values.put(Favorites.CELLY, favorite.cellY);
values.put(Favorites.SPANX, favorite.spanX);
values.put(Favorites.SPANY, favorite.spanY);
- values.put(Favorites.ICON_TYPE, favorite.iconType);
- if (favorite.iconType == Favorites.ICON_TYPE_RESOURCE) {
- values.put(Favorites.ICON_PACKAGE, favorite.iconPackage);
- values.put(Favorites.ICON_RESOURCE, favorite.iconResource);
- }
- if (favorite.iconType == Favorites.ICON_TYPE_BITMAP) {
+
+ if (favorite.itemType == Favorites.ITEM_TYPE_SHORTCUT) {
+ values.put(Favorites.ICON_TYPE, favorite.iconType);
+ if (favorite.iconType == Favorites.ICON_TYPE_RESOURCE) {
+ values.put(Favorites.ICON_PACKAGE, favorite.iconPackage);
+ values.put(Favorites.ICON_RESOURCE, favorite.iconResource);
+ }
values.put(Favorites.ICON, favorite.icon);
}
+
if (!TextUtils.isEmpty(favorite.title)) {
values.put(Favorites.TITLE, favorite.title);
} else {
@@ -826,7 +880,7 @@ public class LauncherBackupHelper implements BackupHelper {
UserManagerCompat.getInstance(mContext).getSerialNumberForUser(myUserHandle);
values.put(LauncherSettings.Favorites.PROFILE_ID, userSerialNumber);
- DeviceProfieData currentProfile = getDeviceProfieData();
+ DeviceProfieData currentProfile = mDeviceProfileData;
if (favorite.itemType == Favorites.ITEM_TYPE_APPWIDGET) {
if (!TextUtils.isEmpty(favorite.appWidgetProvider)) {
@@ -845,8 +899,17 @@ public class LauncherBackupHelper implements BackupHelper {
throw new InvalidBackupException("Widget not in screen bounds, aborting restore");
}
} else {
- // Let LauncherModel know we've been here.
- values.put(LauncherSettings.Favorites.RESTORED, 1);
+ // Check if it is an hotseat item, that can be replaced.
+ if (isReplaceableHotseatItem(favorite)
+ && favorite.targetType != Favorite.TARGET_NONE
+ && favorite.targetType < CommonAppTypeParser.SUPPORTED_TYPE_COUNT) {
+ Log.e(TAG, "Added item type flag");
+ values.put(LauncherSettings.Favorites.RESTORED,
+ 1 | CommonAppTypeParser.encodeItemTypeToFlag(favorite.targetType));
+ } else {
+ // Let LauncherModel know we've been here.
+ values.put(LauncherSettings.Favorites.RESTORED, 1);
+ }
// Verify placement
if (favorite.container == Favorites.CONTAINER_HOTSEAT) {
@@ -889,40 +952,35 @@ public class LauncherBackupHelper implements BackupHelper {
private Resource packIcon(int dpi, Bitmap icon) {
Resource res = new Resource();
res.dpi = dpi;
- ByteArrayOutputStream os = new ByteArrayOutputStream();
- if (icon.compress(IMAGE_FORMAT, IMAGE_COMPRESSION_QUALITY, os)) {
- res.data = os.toByteArray();
- }
+ res.data = Utilities.flattenBitmap(icon);
return res;
}
/** Serialize a widget for persistence, including a checksum wrapper. */
- private Widget packWidget(int dpi, WidgetPreviewLoader previewLoader, IconCache iconCache,
- ComponentName provider) {
- final AppWidgetProviderInfo info = findAppWidgetProviderInfo(provider);
+ private Widget packWidget(int dpi, ComponentName provider, UserHandleCompat user) {
+ final LauncherAppWidgetProviderInfo info =
+ LauncherModel.getProviderInfo(mContext, provider, user);
Widget widget = new Widget();
widget.provider = provider.flattenToShortString();
widget.label = info.label;
widget.configure = info.configure != null;
if (info.icon != 0) {
widget.icon = new Resource();
- Drawable fullResIcon = iconCache.getFullResIcon(provider.getPackageName(), info.icon);
+ Drawable fullResIcon = mIconCache.getFullResIcon(provider.getPackageName(), info.icon);
Bitmap icon = Utilities.createIconBitmap(fullResIcon, mContext);
- ByteArrayOutputStream os = new ByteArrayOutputStream();
- if (icon.compress(IMAGE_FORMAT, IMAGE_COMPRESSION_QUALITY, os)) {
- widget.icon.data = os.toByteArray();
- widget.icon.dpi = dpi;
- }
- }
- if (info.previewImage != 0) {
- widget.preview = new Resource();
- Bitmap preview = previewLoader.generateWidgetPreview(info, null);
- ByteArrayOutputStream os = new ByteArrayOutputStream();
- if (preview.compress(IMAGE_FORMAT, IMAGE_COMPRESSION_QUALITY, os)) {
- widget.preview.data = os.toByteArray();
- widget.preview.dpi = dpi;
- }
+ widget.icon.data = Utilities.flattenBitmap(icon);
+ widget.icon.dpi = dpi;
}
+
+ // Calculate the spans corresponding to any one of the orientations as it should not change
+ // based on orientation.
+ int[] minSpans = CellLayout.rectToCell(
+ mIdp.portraitProfile, mContext, info.minResizeWidth, info.minResizeHeight, null);
+ widget.minSpanX = (info.resizeMode & LauncherAppWidgetProviderInfo.RESIZE_HORIZONTAL) != 0
+ ? minSpans[0] : -1;
+ widget.minSpanY = (info.resizeMode & LauncherAppWidgetProviderInfo.RESIZE_VERTICAL) != 0
+ ? minSpans[1] : -1;
+
return widget;
}
@@ -1019,6 +1077,7 @@ public class LauncherBackupHelper implements BackupHelper {
byte[] blob = writeCheckedBytes(proto);
data.writeEntityHeader(backupKey, blob.length);
data.writeEntityData(blob, blob.length);
+ mBackupDataWasUpdated = true;
if (VERBOSE) Log.v(TAG, "Writing New entry " + backupKey);
}
@@ -1067,36 +1126,6 @@ public class LauncherBackupHelper implements BackupHelper {
return wrapper.payload;
}
- private AppWidgetProviderInfo findAppWidgetProviderInfo(ComponentName component) {
- if (mWidgetMap == null) {
- List<AppWidgetProviderInfo> widgets =
- AppWidgetManager.getInstance(mContext).getInstalledProviders();
- mWidgetMap = new HashMap<ComponentName, AppWidgetProviderInfo>(widgets.size());
- for (AppWidgetProviderInfo info : widgets) {
- mWidgetMap.put(info.provider, info);
- }
- }
- return mWidgetMap.get(component);
- }
-
-
- private boolean initializeIconCache() {
- if (mIconCache != null) {
- return true;
- }
-
- final LauncherAppState appState = LauncherAppState.getInstanceNoCreate();
- if (appState == null) {
- Throwable stackTrace = new Throwable();
- stackTrace.fillInStackTrace();
- Log.w(TAG, "Failed to get app state during backup/restore", stackTrace);
- return false;
- }
- mIconCache = appState.getIconCache();
- return mIconCache != null;
- }
-
-
/**
* @return true if the launcher is in a state to support backup
*/
@@ -1109,9 +1138,8 @@ public class LauncherBackupHelper implements BackupHelper {
}
cursor.close();
- if (!initializeIconCache()) {
+ if (LauncherAppState.getInstanceNoCreate() == null) {
// launcher services are unavailable, try again later
- dataChanged();
return false;
}
@@ -1123,13 +1151,66 @@ public class LauncherBackupHelper implements BackupHelper {
.getSerialNumberForUser(UserHandleCompat.myUserHandle());
}
- private class InvalidBackupException extends IOException {
- private InvalidBackupException(Throwable cause) {
+ @Thunk class InvalidBackupException extends IOException {
+
+ private static final long serialVersionUID = 8931456637211665082L;
+
+ @Thunk InvalidBackupException(Throwable cause) {
super(cause);
}
- public InvalidBackupException(String reason) {
+ @Thunk InvalidBackupException(String reason) {
super(reason);
}
}
+
+ /**
+ * A class to check if an activity can handle one of the intents from a list of
+ * predefined intents.
+ */
+ private class ItemTypeMatcher {
+
+ private final ArrayList<Intent> mIntents;
+
+ ItemTypeMatcher(int xml_res) {
+ mIntents = xml_res == 0 ? new ArrayList<Intent>() : parseIntents(xml_res);
+ }
+
+ private ArrayList<Intent> parseIntents(int xml_res) {
+ ArrayList<Intent> intents = new ArrayList<Intent>();
+ XmlResourceParser parser = mContext.getResources().getXml(xml_res);
+ try {
+ DefaultLayoutParser.beginDocument(parser, DefaultLayoutParser.TAG_RESOLVE);
+ final int depth = parser.getDepth();
+ int type;
+ while (((type = parser.next()) != XmlPullParser.END_TAG ||
+ parser.getDepth() > depth) && type != XmlPullParser.END_DOCUMENT) {
+ if (type != XmlPullParser.START_TAG) {
+ continue;
+ } else if (DefaultLayoutParser.TAG_FAVORITE.equals(parser.getName())) {
+ final String uri = DefaultLayoutParser.getAttributeValue(
+ parser, DefaultLayoutParser.ATTR_URI);
+ intents.add(Intent.parseUri(uri, 0));
+ }
+ }
+ } catch (URISyntaxException | XmlPullParserException | IOException e) {
+ Log.e(TAG, "Unable to parse " + xml_res, e);
+ } finally {
+ parser.close();
+ }
+ return intents;
+ }
+
+ public boolean matches(ActivityInfo activity, PackageManager pm) {
+ for (Intent intent : mIntents) {
+ intent.setPackage(activity.packageName);
+ ResolveInfo info = pm.resolveActivity(intent, 0);
+ if (info != null && (info.activityInfo.name.equals(activity.name)
+ || info.activityInfo.name.equals(activity.targetActivity))) {
+ return true;
+ }
+ }
+ return false;
+ }
+ }
}
diff --git a/src/com/android/launcher3/LauncherCallbacks.java b/src/com/android/launcher3/LauncherCallbacks.java
index a1f4e0b90..6618cca78 100644
--- a/src/com/android/launcher3/LauncherCallbacks.java
+++ b/src/com/android/launcher3/LauncherCallbacks.java
@@ -7,10 +7,13 @@ import android.os.Bundle;
import android.view.Menu;
import android.view.View;
import android.view.ViewGroup;
+import com.android.launcher3.allapps.AllAppsSearchBarController;
+import com.android.launcher3.util.ComponentKey;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
+import java.util.List;
/**
* LauncherCallbacks is an interface used to extend the Launcher activity. It includes many hooks
@@ -37,11 +40,14 @@ public interface LauncherCallbacks {
public void onPostCreate(Bundle savedInstanceState);
public void onNewIntent(Intent intent);
public void onActivityResult(int requestCode, int resultCode, Intent data);
+ public void onRequestPermissionsResult(int requestCode, String[] permissions,
+ int[] grantResults);
public void onWindowFocusChanged(boolean hasFocus);
public boolean onPrepareOptionsMenu(Menu menu);
public void dump(String prefix, FileDescriptor fd, PrintWriter w, String[] args);
public void onHomeIntent();
public boolean handleBackPressed();
+ public void onTrimMemory(int level);
/*
* Extension points for providing custom behavior on certain user interactions.
@@ -52,6 +58,7 @@ public interface LauncherCallbacks {
public void bindAllApplications(ArrayList<AppInfo> apps);
public void onClickFolderIcon(View v);
public void onClickAppShortcut(View v);
+ @Deprecated
public void onClickPagedViewIcon(View v);
public void onClickWallpaperPicker(View v);
public void onClickSettingsButton(View v);
@@ -65,10 +72,12 @@ public interface LauncherCallbacks {
/*
* Extension points for replacing the search experience
*/
+ @Deprecated
public boolean forceDisableVoiceButtonProxy();
public boolean providesSearch();
public boolean startSearch(String initialQuery, boolean selectInitialQuery,
Bundle appSearchData, Rect sourceBounds);
+ @Deprecated
public void startVoice();
public boolean hasCustomContentToLeft();
public void populateCustomContentContainer();
@@ -83,9 +92,12 @@ public interface LauncherCallbacks {
public View getIntroScreen();
public boolean shouldMoveToDefaultScreenOnHomeIntent();
public boolean hasSettings();
+ @Deprecated
public ComponentName getWallpaperPickerComponent();
public boolean overrideWallpaperDimensions();
public boolean isLauncherPreinstalled();
+ public AllAppsSearchBarController getAllAppsSearchBarController();
+ public List<ComponentKey> getPredictedApps();
/**
* Returning true will immediately result in a call to {@link #setLauncherOverlayView(ViewGroup,
@@ -105,4 +117,11 @@ public interface LauncherCallbacks {
public Launcher.LauncherOverlay setLauncherOverlayView(InsettableFrameLayout container,
Launcher.LauncherOverlayCallbacks callbacks);
+ /**
+ * Sets the callbacks to allow reacting the actions of search overlays of the launcher.
+ *
+ * @param callbacks A set of callbacks to the Launcher, is actually a LauncherSearchCallback,
+ * but for implementation purposes is passed around as an object.
+ */
+ public void setLauncherSearchCallback(Object callbacks);
}
diff --git a/src/com/android/launcher3/LauncherClings.java b/src/com/android/launcher3/LauncherClings.java
index ef8e8abcf..c13752cb1 100644
--- a/src/com/android/launcher3/LauncherClings.java
+++ b/src/com/android/launcher3/LauncherClings.java
@@ -20,10 +20,12 @@ import android.accounts.Account;
import android.accounts.AccountManager;
import android.animation.ObjectAnimator;
import android.animation.PropertyValuesHolder;
+import android.annotation.TargetApi;
import android.app.ActivityManager;
import android.content.Context;
import android.content.SharedPreferences;
import android.graphics.drawable.Drawable;
+import android.os.Build;
import android.os.Bundle;
import android.os.UserManager;
import android.provider.Settings;
@@ -34,6 +36,7 @@ import android.view.View.OnLongClickListener;
import android.view.ViewGroup;
import android.view.ViewTreeObserver.OnGlobalLayoutListener;
import android.view.accessibility.AccessibilityManager;
+import com.android.launcher3.util.Thunk;
class LauncherClings implements OnClickListener {
private static final String MIGRATION_CLING_DISMISSED_KEY = "cling_gel.migration.dismissed";
@@ -49,7 +52,7 @@ class LauncherClings implements OnClickListener {
// New Secure Setting in L
private static final String SKIP_FIRST_USE_HINTS = "skip_first_use_hints";
- private Launcher mLauncher;
+ @Thunk Launcher mLauncher;
private LayoutInflater mInflater;
/** Ctor */
@@ -68,7 +71,7 @@ class LauncherClings implements OnClickListener {
// Copy the shortcuts from the old database
LauncherModel model = mLauncher.getModel();
model.resetLoadedState(false, true);
- model.startLoader(false, PagedView.INVALID_RESTORE_PAGE,
+ model.startLoader(PagedView.INVALID_RESTORE_PAGE,
LauncherModel.LOADER_FLAG_CLEAR_WORKSPACE
| LauncherModel.LOADER_FLAG_MIGRATE_SHORTCUTS);
// Set the flag to skip the folder cling
@@ -124,7 +127,7 @@ class LauncherClings implements OnClickListener {
@Override
public boolean onLongClick(View v) {
- mLauncher.getWorkspace().enterOverviewMode();
+ mLauncher.showOverviewMode(true);
dismissLongPressCling();
return true;
}
@@ -174,7 +177,7 @@ class LauncherClings implements OnClickListener {
});
}
- private void dismissLongPressCling() {
+ @Thunk void dismissLongPressCling() {
Runnable dismissCb = new Runnable() {
public void run() {
dismissCling(mLauncher.findViewById(R.id.longpress_cling), null,
@@ -185,7 +188,7 @@ class LauncherClings implements OnClickListener {
}
/** Hides the specified Cling */
- private void dismissCling(final View cling, final Runnable postAnimationCb,
+ @Thunk void dismissCling(final View cling, final Runnable postAnimationCb,
final String flag, int duration) {
// To catch cases where siblings of top-level views are made invisible, just check whether
// the cling is directly set to GONE before dismissing it.
@@ -210,6 +213,7 @@ class LauncherClings implements OnClickListener {
}
/** Returns whether the clings are enabled or should be shown */
+ @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2)
private boolean areClingsEnabled() {
if (DISABLE_CLINGS) {
return false;
diff --git a/src/com/android/launcher3/LauncherFiles.java b/src/com/android/launcher3/LauncherFiles.java
index fa053650f..c08cd0bf5 100644
--- a/src/com/android/launcher3/LauncherFiles.java
+++ b/src/com/android/launcher3/LauncherFiles.java
@@ -17,24 +17,30 @@ public class LauncherFiles {
public static final String DEFAULT_WALLPAPER_THUMBNAIL = "default_thumb2.jpg";
public static final String DEFAULT_WALLPAPER_THUMBNAIL_OLD = "default_thumb.jpg";
public static final String LAUNCHER_DB = "launcher.db";
- public static final String LAUNCHER_PREFERENCES = "launcher.preferences";
- public static final String LAUNCHES_LOG = "launches.log";
public static final String SHARED_PREFERENCES_KEY = "com.android.launcher3.prefs";
- public static final String STATS_LOG = "stats.log";
public static final String WALLPAPER_CROP_PREFERENCES_KEY =
- WallpaperCropActivity.class.getName();
+ "com.android.launcher3.WallpaperCropActivity";
+ public static final String MANAGED_USER_PREFERENCES_KEY = "com.android.launcher3.managedusers.prefs";
+
public static final String WALLPAPER_IMAGES_DB = "saved_wallpaper_images.db";
public static final String WIDGET_PREVIEWS_DB = "widgetpreviews.db";
+ public static final String APP_ICONS_DB = "app_icons.db";
public static final List<String> ALL_FILES = Collections.unmodifiableList(Arrays.asList(
DEFAULT_WALLPAPER_THUMBNAIL,
DEFAULT_WALLPAPER_THUMBNAIL_OLD,
LAUNCHER_DB,
- LAUNCHER_PREFERENCES,
- LAUNCHES_LOG,
SHARED_PREFERENCES_KEY + XML,
- STATS_LOG,
WALLPAPER_CROP_PREFERENCES_KEY + XML,
WALLPAPER_IMAGES_DB,
- WIDGET_PREVIEWS_DB));
+ WIDGET_PREVIEWS_DB,
+ MANAGED_USER_PREFERENCES_KEY,
+ APP_ICONS_DB));
+
+ // TODO: Delete these files on upgrade
+ public static final List<String> OBSOLETE_FILES = Collections.unmodifiableList(Arrays.asList(
+ "launches.log",
+ "stats.log",
+ "launcher.preferences",
+ "com.android.launcher3.compat.PackageInstallerCompatV16.queue"));
}
diff --git a/src/com/android/launcher3/LauncherModel.java b/src/com/android/launcher3/LauncherModel.java
index 954887dc3..b60477fa0 100644
--- a/src/com/android/launcher3/LauncherModel.java
+++ b/src/com/android/launcher3/LauncherModel.java
@@ -17,11 +17,9 @@
package com.android.launcher3;
import android.app.SearchManager;
-import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProviderInfo;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
-import android.content.ContentProviderClient;
import android.content.ContentProviderOperation;
import android.content.ContentResolver;
import android.content.ContentValues;
@@ -29,27 +27,25 @@ import android.content.Context;
import android.content.Intent;
import android.content.Intent.ShortcutIconResource;
import android.content.IntentFilter;
-import android.content.SharedPreferences;
-import android.content.pm.LauncherApps.Callback;
import android.content.pm.PackageManager;
import android.content.pm.ProviderInfo;
import android.content.pm.ResolveInfo;
-import android.content.res.Configuration;
-import android.content.res.Resources;
import android.database.Cursor;
import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
import android.net.Uri;
+import android.os.Build;
import android.os.Environment;
import android.os.Handler;
import android.os.HandlerThread;
+import android.os.Looper;
import android.os.Parcelable;
import android.os.Process;
-import android.os.RemoteException;
import android.os.SystemClock;
+import android.os.TransactionTooLargeException;
import android.provider.BaseColumns;
import android.text.TextUtils;
import android.util.Log;
+import android.util.LongSparseArray;
import android.util.Pair;
import com.android.launcher3.compat.AppWidgetManagerCompat;
@@ -59,11 +55,16 @@ import com.android.launcher3.compat.PackageInstallerCompat;
import com.android.launcher3.compat.PackageInstallerCompat.PackageInstallInfo;
import com.android.launcher3.compat.UserHandleCompat;
import com.android.launcher3.compat.UserManagerCompat;
+import com.android.launcher3.model.WidgetsModel;
+import com.android.launcher3.util.ComponentKey;
+import com.android.launcher3.util.CursorIconInfo;
+import com.android.launcher3.util.LongArrayMap;
+import com.android.launcher3.util.ManagedProfileHeuristic;
+import com.android.launcher3.util.Thunk;
import java.lang.ref.WeakReference;
import java.net.URISyntaxException;
import java.security.InvalidParameterException;
-import java.text.Collator;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
@@ -75,7 +76,6 @@ import java.util.Iterator;
import java.util.List;
import java.util.Map.Entry;
import java.util.Set;
-import java.util.TreeMap;
/**
* Maintains in-memory state of the Launcher. It is expected that there should be only one
@@ -87,13 +87,9 @@ public class LauncherModel extends BroadcastReceiver
static final boolean DEBUG_LOADERS = false;
private static final boolean DEBUG_RECEIVER = false;
private static final boolean REMOVE_UNRESTORED_ICONS = true;
- private static final boolean ADD_MANAGED_PROFILE_SHORTCUTS = false;
static final String TAG = "Launcher.Model";
- // true = use a "More Apps" folder for non-workspace apps on upgrade
- // false = strew non-workspace apps across the workspace on upgrade
- public static final boolean UPGRADE_USE_MORE_APPS_FOLDER = false;
public static final int LOADER_FLAG_NONE = 0;
public static final int LOADER_FLAG_CLEAR_WORKSPACE = 1 << 0;
public static final int LOADER_FLAG_MIGRATE_SHORTCUTS = 1 << 1;
@@ -101,39 +97,29 @@ public class LauncherModel extends BroadcastReceiver
private static final int ITEMS_CHUNK = 6; // batch size for the workspace icons
private static final long INVALID_SCREEN_ID = -1L;
- private final boolean mAppsCanBeOnRemoveableStorage;
+ @Thunk final boolean mAppsCanBeOnRemoveableStorage;
private final boolean mOldContentProviderExists;
- private final LauncherAppState mApp;
- private final Object mLock = new Object();
- private DeferredHandler mHandler = new DeferredHandler();
- private LoaderTask mLoaderTask;
- private boolean mIsLoaderTaskRunning;
- private volatile boolean mFlushingWorkerThread;
-
- /**
- * Maintain a set of packages per user, for which we added a shortcut on the workspace.
- */
- private static final String INSTALLED_SHORTCUTS_SET_PREFIX = "installed_shortcuts_set_for_user_";
-
- // Specific runnable types that are run on the main thread deferred handler, this allows us to
- // clear all queued binding runnables when the Launcher activity is destroyed.
- private static final int MAIN_THREAD_NORMAL_RUNNABLE = 0;
- private static final int MAIN_THREAD_BINDING_RUNNABLE = 1;
+ @Thunk final LauncherAppState mApp;
+ @Thunk final Object mLock = new Object();
+ @Thunk DeferredHandler mHandler = new DeferredHandler();
+ @Thunk LoaderTask mLoaderTask;
+ @Thunk boolean mIsLoaderTaskRunning;
+ @Thunk boolean mHasLoaderCompletedOnce;
private static final String MIGRATE_AUTHORITY = "com.android.launcher2.settings";
- private static final HandlerThread sWorkerThread = new HandlerThread("launcher-loader");
+ @Thunk static final HandlerThread sWorkerThread = new HandlerThread("launcher-loader");
static {
sWorkerThread.start();
}
- private static final Handler sWorker = new Handler(sWorkerThread.getLooper());
+ @Thunk static final Handler sWorker = new Handler(sWorkerThread.getLooper());
// We start off with everything not loaded. After that, we assume that
// our monitoring of the package manager provides all updates and we never
// need to do a requery. These are only ever touched from the loader thread.
- private boolean mWorkspaceLoaded;
- private boolean mAllAppsLoaded;
+ @Thunk boolean mWorkspaceLoaded;
+ @Thunk boolean mAllAppsLoaded;
// When we are loading pages synchronously, we can't just post the binding of items on the side
// pages as this delays the rotation process. Instead, we wait for a callback from the first
@@ -141,10 +127,18 @@ public class LauncherModel extends BroadcastReceiver
// a normal load, we also clear this set of Runnables.
static final ArrayList<Runnable> mDeferredBindRunnables = new ArrayList<Runnable>();
- private WeakReference<Callbacks> mCallbacks;
+ /**
+ * Set of runnables to be called on the background thread after the workspace binding
+ * is complete.
+ */
+ static final ArrayList<Runnable> mBindCompleteRunnables = new ArrayList<Runnable>();
+
+ @Thunk WeakReference<Callbacks> mCallbacks;
// < only access in worker thread >
AllAppsList mBgAllAppsList;
+ // Entire list of widgets.
+ WidgetsModel mBgWidgetsModel;
// The lock that must be acquired before referencing any static bg data structures. Unlike
// other locks, this one can generally be held long-term because we never expect any of these
@@ -154,7 +148,7 @@ public class LauncherModel extends BroadcastReceiver
// sBgItemsIdMap maps *all* the ItemInfos (shortcuts, folders, and widgets) created by
// LauncherModel to their ids
- static final HashMap<Long, ItemInfo> sBgItemsIdMap = new HashMap<Long, ItemInfo>();
+ static final LongArrayMap<ItemInfo> sBgItemsIdMap = new LongArrayMap<>();
// sBgWorkspaceItems is passed to bindItems, which expects a list of all folders and shortcuts
// created by LauncherModel that are directly on the home screen (however, no widgets or
@@ -166,26 +160,24 @@ public class LauncherModel extends BroadcastReceiver
new ArrayList<LauncherAppWidgetInfo>();
// sBgFolders is all FolderInfos created by LauncherModel. Passed to bindFolders()
- static final HashMap<Long, FolderInfo> sBgFolders = new HashMap<Long, FolderInfo>();
-
- // sBgDbIconCache is the set of ItemInfos that need to have their icons updated in the database
- static final HashMap<Object, byte[]> sBgDbIconCache = new HashMap<Object, byte[]>();
+ static final LongArrayMap<FolderInfo> sBgFolders = new LongArrayMap<>();
// sBgWorkspaceScreens is the ordered set of workspace screens.
static final ArrayList<Long> sBgWorkspaceScreens = new ArrayList<Long>();
+ // sBgWidgetProviders is the set of widget providers including custom internal widgets
+ public static HashMap<ComponentKey, LauncherAppWidgetProviderInfo> sBgWidgetProviders;
+
// sPendingPackages is a set of packages which could be on sdcard and are not available yet
static final HashMap<UserHandleCompat, HashSet<String>> sPendingPackages =
new HashMap<UserHandleCompat, HashSet<String>>();
// </ only access in worker thread >
- private IconCache mIconCache;
-
- protected int mPreviousConfigMcc;
+ @Thunk IconCache mIconCache;
- private final LauncherAppsCompat mLauncherApps;
- private final UserManagerCompat mUserManager;
+ @Thunk final LauncherAppsCompat mLauncherApps;
+ @Thunk final UserManagerCompat mUserManager;
public interface Callbacks {
public boolean setLoadOnResume();
@@ -195,8 +187,8 @@ public class LauncherModel extends BroadcastReceiver
boolean forceAnimateIcons);
public void bindScreens(ArrayList<Long> orderedScreenIds);
public void bindAddScreens(ArrayList<Long> orderedScreenIds);
- public void bindFolders(HashMap<Long,FolderInfo> folders);
- public void finishBindingItems(boolean upgradePath);
+ public void bindFolders(LongArrayMap<FolderInfo> folders);
+ public void finishBindingItems();
public void bindAppWidget(LauncherAppWidgetInfo info);
public void bindAllApplications(ArrayList<AppInfo> apps);
public void bindAppsAdded(ArrayList<Long> newScreens,
@@ -207,11 +199,10 @@ public class LauncherModel extends BroadcastReceiver
public void bindShortcutsChanged(ArrayList<ShortcutInfo> updated,
ArrayList<ShortcutInfo> removed, UserHandleCompat user);
public void bindWidgetsRestored(ArrayList<LauncherAppWidgetInfo> widgets);
- public void updatePackageState(ArrayList<PackageInstallInfo> installInfo);
- public void updatePackageBadge(String packageName);
+ public void bindRestoreItemsChange(HashSet<ItemInfo> updates);
public void bindComponentsRemoved(ArrayList<String> packageNames,
ArrayList<AppInfo> appInfos, UserHandleCompat user, int reason);
- public void bindPackagesUpdated(ArrayList<Object> widgetsAndShortcuts);
+ public void bindAllPackages(WidgetsModel model);
public void bindSearchablesChanged();
public boolean isAllAppsButtonRank(int rank);
public void onPageBoundSynchronously(int page);
@@ -246,21 +237,16 @@ public class LauncherModel extends BroadcastReceiver
mApp = app;
mBgAllAppsList = new AllAppsList(iconCache, appFilter);
+ mBgWidgetsModel = new WidgetsModel(context, iconCache, appFilter);
mIconCache = iconCache;
- final Resources res = context.getResources();
- Configuration config = res.getConfiguration();
- mPreviousConfigMcc = config.mcc;
mLauncherApps = LauncherAppsCompat.getInstance(context);
mUserManager = UserManagerCompat.getInstance(context);
}
/** Runs the specified runnable immediately if called from the main thread, otherwise it is
* posted on the main thread handler. */
- private void runOnMainThread(Runnable r) {
- runOnMainThread(r, 0);
- }
- private void runOnMainThread(Runnable r, int type) {
+ @Thunk void runOnMainThread(Runnable r) {
if (sWorkerThread.getThreadId() == Process.myTid()) {
// If we are on the worker thread, post onto the main handler
mHandler.post(r);
@@ -280,95 +266,127 @@ public class LauncherModel extends BroadcastReceiver
}
}
+ /**
+ * Runs the specified runnable after the loader is complete
+ */
+ @Thunk void runAfterBindCompletes(Runnable r) {
+ if (isLoadingWorkspace() || !mHasLoaderCompletedOnce) {
+ synchronized (mBindCompleteRunnables) {
+ mBindCompleteRunnables.add(r);
+ }
+ } else {
+ runOnWorkerThread(r);
+ }
+ }
+
boolean canMigrateFromOldLauncherDb(Launcher launcher) {
return mOldContentProviderExists && !launcher.isLauncherPreinstalled() ;
}
- static boolean findNextAvailableIconSpaceInScreen(ArrayList<ItemInfo> items, int[] xy,
- long screen) {
- LauncherAppState app = LauncherAppState.getInstance();
- DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
- final int xCount = (int) grid.numColumns;
- final int yCount = (int) grid.numRows;
- boolean[][] occupied = new boolean[xCount][yCount];
+ public void setPackageState(final PackageInstallInfo installInfo) {
+ Runnable updateRunnable = new Runnable() {
- int cellX, cellY, spanX, spanY;
- for (int i = 0; i < items.size(); ++i) {
- final ItemInfo item = items.get(i);
- if (item.container == LauncherSettings.Favorites.CONTAINER_DESKTOP) {
- if (item.screenId == screen) {
- cellX = item.cellX;
- cellY = item.cellY;
- spanX = item.spanX;
- spanY = item.spanY;
- for (int x = cellX; 0 <= x && x < cellX + spanX && x < xCount; x++) {
- for (int y = cellY; 0 <= y && y < cellY + spanY && y < yCount; y++) {
- occupied[x][y] = true;
- }
+ @Override
+ public void run() {
+ synchronized (sBgLock) {
+ final HashSet<ItemInfo> updates = new HashSet<>();
+
+ if (installInfo.state == PackageInstallerCompat.STATUS_INSTALLED) {
+ // Ignore install success events as they are handled by Package add events.
+ return;
}
- }
- }
- }
- return CellLayout.findVacantCell(xy, 1, 1, xCount, yCount, occupied);
- }
- static Pair<Long, int[]> findNextAvailableIconSpace(Context context, String name,
- Intent launchIntent,
- int firstScreenIndex,
- ArrayList<Long> workspaceScreens) {
- // Lock on the app so that we don't try and get the items while apps are being added
- LauncherAppState app = LauncherAppState.getInstance();
- LauncherModel model = app.getModel();
- boolean found = false;
- synchronized (app) {
- if (sWorkerThread.getThreadId() != Process.myTid()) {
- // Flush the LauncherModel worker thread, so that if we just did another
- // processInstallShortcut, we give it time for its shortcut to get added to the
- // database (getItemsInLocalCoordinates reads the database)
- model.flushWorkerThread();
- }
- final ArrayList<ItemInfo> items = LauncherModel.getItemsInLocalCoordinates(context);
+ for (ItemInfo info : sBgItemsIdMap) {
+ if (info instanceof ShortcutInfo) {
+ ShortcutInfo si = (ShortcutInfo) info;
+ ComponentName cn = si.getTargetComponent();
+ if (si.isPromise() && (cn != null)
+ && installInfo.packageName.equals(cn.getPackageName())) {
+ si.setInstallProgress(installInfo.progress);
- // Try adding to the workspace screens incrementally, starting at the default or center
- // screen and alternating between +1, -1, +2, -2, etc. (using ~ ceil(i/2f)*(-1)^(i-1))
- firstScreenIndex = Math.min(firstScreenIndex, workspaceScreens.size());
- int count = workspaceScreens.size();
- for (int screen = firstScreenIndex; screen < count && !found; screen++) {
- int[] tmpCoordinates = new int[2];
- if (findNextAvailableIconSpaceInScreen(items, tmpCoordinates,
- workspaceScreens.get(screen))) {
- // Update the Launcher db
- return new Pair<Long, int[]>(workspaceScreens.get(screen), tmpCoordinates);
- }
- }
- }
- return null;
- }
+ if (installInfo.state == PackageInstallerCompat.STATUS_FAILED) {
+ // Mark this info as broken.
+ si.status &= ~ShortcutInfo.FLAG_INSTALL_SESSION_ACTIVE;
+ }
+ updates.add(si);
+ }
+ }
+ }
- public void setPackageState(final ArrayList<PackageInstallInfo> installInfo) {
- // Process the updated package state
- Runnable r = new Runnable() {
- public void run() {
- Callbacks callbacks = getCallback();
- if (callbacks != null) {
- callbacks.updatePackageState(installInfo);
+ for (LauncherAppWidgetInfo widget : sBgAppWidgets) {
+ if (widget.providerName.getPackageName().equals(installInfo.packageName)) {
+ widget.installProgress = installInfo.progress;
+ updates.add(widget);
+ }
+ }
+
+ if (!updates.isEmpty()) {
+ // Push changes to the callback.
+ Runnable r = new Runnable() {
+ public void run() {
+ Callbacks callbacks = getCallback();
+ if (callbacks != null) {
+ callbacks.bindRestoreItemsChange(updates);
+ }
+ }
+ };
+ mHandler.post(r);
+ }
}
}
};
- mHandler.post(r);
+ runOnWorkerThread(updateRunnable);
}
- public void updatePackageBadge(final String packageName) {
- // Process the updated package badge
- Runnable r = new Runnable() {
+ /**
+ * Updates the icons and label of all pending icons for the provided package name.
+ */
+ public void updateSessionDisplayInfo(final String packageName) {
+ Runnable updateRunnable = new Runnable() {
+
+ @Override
public void run() {
- Callbacks callbacks = getCallback();
- if (callbacks != null) {
- callbacks.updatePackageBadge(packageName);
+ synchronized (sBgLock) {
+ final ArrayList<ShortcutInfo> updates = new ArrayList<>();
+ final UserHandleCompat user = UserHandleCompat.myUserHandle();
+
+ for (ItemInfo info : sBgItemsIdMap) {
+ if (info instanceof ShortcutInfo) {
+ ShortcutInfo si = (ShortcutInfo) info;
+ ComponentName cn = si.getTargetComponent();
+ if (si.isPromise() && (cn != null)
+ && packageName.equals(cn.getPackageName())) {
+ if (si.hasStatusFlag(ShortcutInfo.FLAG_AUTOINTALL_ICON)) {
+ // For auto install apps update the icon as well as label.
+ mIconCache.getTitleAndIcon(si,
+ si.promisedIntent, user,
+ si.shouldUseLowResIcon());
+ } else {
+ // Only update the icon for restored apps.
+ si.updateIcon(mIconCache);
+ }
+ updates.add(si);
+ }
+ }
+ }
+
+ if (!updates.isEmpty()) {
+ // Push changes to the callback.
+ Runnable r = new Runnable() {
+ public void run() {
+ Callbacks callbacks = getCallback();
+ if (callbacks != null) {
+ callbacks.bindShortcutsChanged(updates,
+ new ArrayList<ShortcutInfo>(), user);
+ }
+ }
+ };
+ mHandler.post(r);
+ }
}
}
};
- mHandler.post(r);
+ runOnWorkerThread(updateRunnable);
}
public void addAppsToAllApps(final Context ctx, final ArrayList<AppInfo> allAppsApps) {
@@ -397,13 +415,103 @@ public class LauncherModel extends BroadcastReceiver
runOnWorkerThread(r);
}
- public void addAndBindAddedWorkspaceApps(final Context context,
- final ArrayList<ItemInfo> workspaceApps) {
- final Callbacks callbacks = getCallback();
+ private static boolean findNextAvailableIconSpaceInScreen(ArrayList<ItemInfo> occupiedPos,
+ int[] xy, int spanX, int spanY) {
+ LauncherAppState app = LauncherAppState.getInstance();
+ InvariantDeviceProfile profile = app.getInvariantDeviceProfile();
+ final int xCount = (int) profile.numColumns;
+ final int yCount = (int) profile.numRows;
+ boolean[][] occupied = new boolean[xCount][yCount];
+ if (occupiedPos != null) {
+ for (ItemInfo r : occupiedPos) {
+ int right = r.cellX + r.spanX;
+ int bottom = r.cellY + r.spanY;
+ for (int x = r.cellX; 0 <= x && x < right && x < xCount; x++) {
+ for (int y = r.cellY; 0 <= y && y < bottom && y < yCount; y++) {
+ occupied[x][y] = true;
+ }
+ }
+ }
+ }
+ return Utilities.findVacantCell(xy, spanX, spanY, xCount, yCount, occupied);
+ }
- if (workspaceApps == null) {
- throw new RuntimeException("workspaceApps and allAppsApps must not be null");
+ /**
+ * Find a position on the screen for the given size or adds a new screen.
+ * @return screenId and the coordinates for the item.
+ */
+ @Thunk Pair<Long, int[]> findSpaceForItem(
+ Context context,
+ ArrayList<Long> workspaceScreens,
+ ArrayList<Long> addedWorkspaceScreensFinal,
+ int spanX, int spanY) {
+ LongSparseArray<ArrayList<ItemInfo>> screenItems = new LongSparseArray<>();
+
+ // Use sBgItemsIdMap as all the items are already loaded.
+ assertWorkspaceLoaded();
+ synchronized (sBgLock) {
+ for (ItemInfo info : sBgItemsIdMap) {
+ if (info.container == LauncherSettings.Favorites.CONTAINER_DESKTOP) {
+ ArrayList<ItemInfo> items = screenItems.get(info.screenId);
+ if (items == null) {
+ items = new ArrayList<>();
+ screenItems.put(info.screenId, items);
+ }
+ items.add(info);
+ }
+ }
}
+
+ // Find appropriate space for the item.
+ long screenId = 0;
+ int[] cordinates = new int[2];
+ boolean found = false;
+
+ int screenCount = workspaceScreens.size();
+ // First check the preferred screen.
+ int preferredScreenIndex = workspaceScreens.isEmpty() ? 0 : 1;
+ if (preferredScreenIndex < screenCount) {
+ screenId = workspaceScreens.get(preferredScreenIndex);
+ found = findNextAvailableIconSpaceInScreen(
+ screenItems.get(screenId), cordinates, spanX, spanY);
+ }
+
+ if (!found) {
+ // Search on any of the screens starting from the first screen.
+ for (int screen = 1; screen < screenCount; screen++) {
+ screenId = workspaceScreens.get(screen);
+ if (findNextAvailableIconSpaceInScreen(
+ screenItems.get(screenId), cordinates, spanX, spanY)) {
+ // We found a space for it
+ found = true;
+ break;
+ }
+ }
+ }
+
+ if (!found) {
+ // Still no position found. Add a new screen to the end.
+ screenId = LauncherAppState.getLauncherProvider().generateNewScreenId();
+
+ // Save the screen id for binding in the workspace
+ workspaceScreens.add(screenId);
+ addedWorkspaceScreensFinal.add(screenId);
+
+ // If we still can't find an empty space, then God help us all!!!
+ if (!findNextAvailableIconSpaceInScreen(
+ screenItems.get(screenId), cordinates, spanX, spanY)) {
+ throw new RuntimeException("Can't find space to add the item");
+ }
+ }
+ return Pair.create(screenId, cordinates);
+ }
+
+ /**
+ * Adds the provided items to the workspace.
+ */
+ public void addAndBindAddedWorkspaceItems(final Context context,
+ final ArrayList<? extends ItemInfo> workspaceApps) {
+ final Callbacks callbacks = getCallback();
if (workspaceApps.isEmpty()) {
return;
}
@@ -416,71 +524,38 @@ public class LauncherModel extends BroadcastReceiver
// Get the list of workspace screens. We need to append to this list and
// can not use sBgWorkspaceScreens because loadWorkspace() may not have been
// called.
- ArrayList<Long> workspaceScreens = new ArrayList<Long>();
- TreeMap<Integer, Long> orderedScreens = loadWorkspaceScreensDb(context);
- for (Integer i : orderedScreens.keySet()) {
- long screenId = orderedScreens.get(i);
- workspaceScreens.add(screenId);
- }
-
+ ArrayList<Long> workspaceScreens = loadWorkspaceScreensDb(context);
synchronized(sBgLock) {
- Iterator<ItemInfo> iter = workspaceApps.iterator();
- while (iter.hasNext()) {
- ItemInfo a = iter.next();
- final String name = a.title.toString();
- final Intent launchIntent = a.getIntent();
-
- // Short-circuit this logic if the icon exists somewhere on the workspace
- if (shortcutExists(context, name, launchIntent, a.user)) {
- continue;
- }
-
- // Add this icon to the db, creating a new page if necessary. If there
- // is only the empty page then we just add items to the first page.
- // Otherwise, we add them to the next pages.
- int startSearchPageIndex = workspaceScreens.isEmpty() ? 0 : 1;
- Pair<Long, int[]> coords = LauncherModel.findNextAvailableIconSpace(context,
- name, launchIntent, startSearchPageIndex, workspaceScreens);
- if (coords == null) {
- LauncherProvider lp = LauncherAppState.getLauncherProvider();
-
- // If we can't find a valid position, then just add a new screen.
- // This takes time so we need to re-queue the add until the new
- // page is added. Create as many screens as necessary to satisfy
- // the startSearchPageIndex.
- int numPagesToAdd = Math.max(1, startSearchPageIndex + 1 -
- workspaceScreens.size());
- while (numPagesToAdd > 0) {
- long screenId = lp.generateNewScreenId();
- // Save the screen id for binding in the workspace
- workspaceScreens.add(screenId);
- addedWorkspaceScreensFinal.add(screenId);
- numPagesToAdd--;
+ for (ItemInfo item : workspaceApps) {
+ if (item instanceof ShortcutInfo) {
+ // Short-circuit this logic if the icon exists somewhere on the workspace
+ if (shortcutExists(context, item.getIntent(), item.user)) {
+ continue;
}
-
- // Find the coordinate again
- coords = LauncherModel.findNextAvailableIconSpace(context,
- name, launchIntent, startSearchPageIndex, workspaceScreens);
- }
- if (coords == null) {
- throw new RuntimeException("Coordinates should not be null");
}
- ShortcutInfo shortcutInfo;
- if (a instanceof ShortcutInfo) {
- shortcutInfo = (ShortcutInfo) a;
- } else if (a instanceof AppInfo) {
- shortcutInfo = ((AppInfo) a).makeShortcut();
+ // Find appropriate space for the item.
+ Pair<Long, int[]> coords = findSpaceForItem(context,
+ workspaceScreens, addedWorkspaceScreensFinal,
+ 1, 1);
+ long screenId = coords.first;
+ int[] cordinates = coords.second;
+
+ ItemInfo itemInfo;
+ if (item instanceof ShortcutInfo || item instanceof FolderInfo) {
+ itemInfo = item;
+ } else if (item instanceof AppInfo) {
+ itemInfo = ((AppInfo) item).makeShortcut();
} else {
throw new RuntimeException("Unexpected info type");
}
// Add the shortcut to the db
- addItemToDatabase(context, shortcutInfo,
+ addItemToDatabase(context, itemInfo,
LauncherSettings.Favorites.CONTAINER_DESKTOP,
- coords.first, coords.second[0], coords.second[1], false);
+ screenId, cordinates[0], cordinates[1]);
// Save the ShortcutInfo for binding in the workspace
- addedShortcutsFinal.add(shortcutInfo);
+ addedShortcutsFinal.add(itemInfo);
}
}
@@ -516,7 +591,7 @@ public class LauncherModel extends BroadcastReceiver
runOnWorkerThread(r);
}
- public void unbindItemInfosAndClearQueuedBindRunnables() {
+ private void unbindItemInfosAndClearQueuedBindRunnables() {
if (sWorkerThread.getThreadId() == Process.myTid()) {
throw new RuntimeException("Expected unbindLauncherItemInfos() to be called from the " +
"main thread");
@@ -526,8 +601,9 @@ public class LauncherModel extends BroadcastReceiver
synchronized (mDeferredBindRunnables) {
mDeferredBindRunnables.clear();
}
- // Remove any queued bind runnables
- mHandler.cancelAllRunnablesOfType(MAIN_THREAD_BINDING_RUNNABLE);
+
+ // Remove any queued UI runnables
+ mHandler.cancelAll();
// Unbind all the workspace items
unbindWorkspaceItemsOnMainThread();
}
@@ -536,19 +612,15 @@ public class LauncherModel extends BroadcastReceiver
void unbindWorkspaceItemsOnMainThread() {
// Ensure that we don't use the same workspace items data structure on the main thread
// by making a copy of workspace items first.
- final ArrayList<ItemInfo> tmpWorkspaceItems = new ArrayList<ItemInfo>();
- final ArrayList<ItemInfo> tmpAppWidgets = new ArrayList<ItemInfo>();
+ final ArrayList<ItemInfo> tmpItems = new ArrayList<ItemInfo>();
synchronized (sBgLock) {
- tmpWorkspaceItems.addAll(sBgWorkspaceItems);
- tmpAppWidgets.addAll(sBgAppWidgets);
+ tmpItems.addAll(sBgWorkspaceItems);
+ tmpItems.addAll(sBgAppWidgets);
}
Runnable r = new Runnable() {
@Override
public void run() {
- for (ItemInfo item : tmpWorkspaceItems) {
- item.unbind();
- }
- for (ItemInfo item : tmpAppWidgets) {
+ for (ItemInfo item : tmpItems) {
item.unbind();
}
}
@@ -564,7 +636,7 @@ public class LauncherModel extends BroadcastReceiver
long screenId, int cellX, int cellY) {
if (item.container == ItemInfo.NO_ID) {
// From all apps
- addItemToDatabase(context, item, container, screenId, cellX, cellY, false);
+ addItemToDatabase(context, item, container, screenId, cellX, cellY);
} else {
// From somewhere else
moveItemInDatabase(context, item, container, screenId, cellX, cellY);
@@ -630,7 +702,7 @@ public class LauncherModel extends BroadcastReceiver
static void updateItemInDatabaseHelper(Context context, final ContentValues values,
final ItemInfo item, final String callingFunction) {
final long itemId = item.id;
- final Uri uri = LauncherSettings.Favorites.getContentUri(itemId, false);
+ final Uri uri = LauncherSettings.Favorites.getContentUri(itemId);
final ContentResolver cr = context.getContentResolver();
final StackTraceElement[] stackTrace = new Throwable().getStackTrace();
@@ -656,7 +728,7 @@ public class LauncherModel extends BroadcastReceiver
for (int i = 0; i < count; i++) {
ItemInfo item = items.get(i);
final long itemId = item.id;
- final Uri uri = LauncherSettings.Favorites.getContentUri(itemId, false);
+ final Uri uri = LauncherSettings.Favorites.getContentUri(itemId);
ContentValues values = valuesList.get(i);
ops.add(ContentProviderOperation.newUpdate(uri).withValues(values).build());
@@ -714,39 +786,10 @@ public class LauncherModel extends BroadcastReceiver
}
}
- public void flushWorkerThread() {
- mFlushingWorkerThread = true;
- Runnable waiter = new Runnable() {
- public void run() {
- synchronized (this) {
- notifyAll();
- mFlushingWorkerThread = false;
- }
- }
- };
-
- synchronized(waiter) {
- runOnWorkerThread(waiter);
- if (mLoaderTask != null) {
- synchronized(mLoaderTask) {
- mLoaderTask.notify();
- }
- }
- boolean success = false;
- while (!success) {
- try {
- waiter.wait();
- success = true;
- } catch (InterruptedException e) {
- }
- }
- }
- }
-
/**
* Move an item in the DB to a new <container, screen, cellX, cellY>
*/
- static void moveItemInDatabase(Context context, final ItemInfo item, final long container,
+ public static void moveItemInDatabase(Context context, final ItemInfo item, final long container,
final long screenId, final int cellX, final int cellY) {
item.container = container;
item.cellX = cellX;
@@ -765,6 +808,7 @@ public class LauncherModel extends BroadcastReceiver
values.put(LauncherSettings.Favorites.CONTAINER, item.container);
values.put(LauncherSettings.Favorites.CELLX, item.cellX);
values.put(LauncherSettings.Favorites.CELLY, item.cellY);
+ values.put(LauncherSettings.Favorites.RANK, item.rank);
values.put(LauncherSettings.Favorites.SCREEN, item.screenId);
updateItemInDatabaseHelper(context, values, item, "moveItemInDatabase");
@@ -798,6 +842,7 @@ public class LauncherModel extends BroadcastReceiver
values.put(LauncherSettings.Favorites.CONTAINER, item.container);
values.put(LauncherSettings.Favorites.CELLX, item.cellX);
values.put(LauncherSettings.Favorites.CELLY, item.cellY);
+ values.put(LauncherSettings.Favorites.RANK, item.rank);
values.put(LauncherSettings.Favorites.SCREEN, item.screenId);
contentValues.add(values);
@@ -829,6 +874,7 @@ public class LauncherModel extends BroadcastReceiver
values.put(LauncherSettings.Favorites.CONTAINER, item.container);
values.put(LauncherSettings.Favorites.CELLX, item.cellX);
values.put(LauncherSettings.Favorites.CELLY, item.cellY);
+ values.put(LauncherSettings.Favorites.RANK, item.rank);
values.put(LauncherSettings.Favorites.SPANX, item.spanX);
values.put(LauncherSettings.Favorites.SPANY, item.spanY);
values.put(LauncherSettings.Favorites.SCREEN, item.screenId);
@@ -839,104 +885,63 @@ public class LauncherModel extends BroadcastReceiver
/**
* Update an item to the database in a specified container.
*/
- static void updateItemInDatabase(Context context, final ItemInfo item) {
+ public static void updateItemInDatabase(Context context, final ItemInfo item) {
final ContentValues values = new ContentValues();
item.onAddToDatabase(context, values);
- item.updateValuesWithCoordinates(values, item.cellX, item.cellY);
updateItemInDatabaseHelper(context, values, item, "updateItemInDatabase");
}
+ private void assertWorkspaceLoaded() {
+ if (LauncherAppState.isDogfoodBuild() && (isLoadingWorkspace() || !mHasLoaderCompletedOnce)) {
+ throw new RuntimeException("Trying to add shortcut while loader is running");
+ }
+ }
+
/**
- * Returns true if the shortcuts already exists in the database.
- * we identify a shortcut by its title and intent.
+ * Returns true if the shortcuts already exists on the workspace. This must be called after
+ * the workspace has been loaded. We identify a shortcut by its intent.
*/
- static boolean shortcutExists(Context context, String title, Intent intent,
- UserHandleCompat user) {
- final ContentResolver cr = context.getContentResolver();
- final Intent intentWithPkg, intentWithoutPkg;
-
+ @Thunk boolean shortcutExists(Context context, Intent intent, UserHandleCompat user) {
+ assertWorkspaceLoaded();
+ final String intentWithPkg, intentWithoutPkg;
if (intent.getComponent() != null) {
// If component is not null, an intent with null package will produce
// the same result and should also be a match.
+ String packageName = intent.getComponent().getPackageName();
if (intent.getPackage() != null) {
- intentWithPkg = intent;
- intentWithoutPkg = new Intent(intent).setPackage(null);
+ intentWithPkg = intent.toUri(0);
+ intentWithoutPkg = new Intent(intent).setPackage(null).toUri(0);
} else {
- intentWithPkg = new Intent(intent).setPackage(
- intent.getComponent().getPackageName());
- intentWithoutPkg = intent;
+ intentWithPkg = new Intent(intent).setPackage(packageName).toUri(0);
+ intentWithoutPkg = intent.toUri(0);
}
} else {
- intentWithPkg = intent;
- intentWithoutPkg = intent;
- }
- String userSerial = Long.toString(UserManagerCompat.getInstance(context)
- .getSerialNumberForUser(user));
- Cursor c = cr.query(LauncherSettings.Favorites.CONTENT_URI,
- new String[] { "title", "intent", "profileId" },
- "title=? and (intent=? or intent=?) and profileId=?",
- new String[] { title, intentWithPkg.toUri(0), intentWithoutPkg.toUri(0), userSerial },
- null);
- try {
- return c.moveToFirst();
- } finally {
- c.close();
+ intentWithPkg = intent.toUri(0);
+ intentWithoutPkg = intent.toUri(0);
}
- }
- /**
- * Returns an ItemInfo array containing all the items in the LauncherModel.
- * The ItemInfo.id is not set through this function.
- */
- static ArrayList<ItemInfo> getItemsInLocalCoordinates(Context context) {
- ArrayList<ItemInfo> items = new ArrayList<ItemInfo>();
- final ContentResolver cr = context.getContentResolver();
- Cursor c = cr.query(LauncherSettings.Favorites.CONTENT_URI, new String[] {
- LauncherSettings.Favorites.ITEM_TYPE, LauncherSettings.Favorites.CONTAINER,
- LauncherSettings.Favorites.SCREEN,
- LauncherSettings.Favorites.CELLX, LauncherSettings.Favorites.CELLY,
- LauncherSettings.Favorites.SPANX, LauncherSettings.Favorites.SPANY,
- LauncherSettings.Favorites.PROFILE_ID }, null, null, null);
-
- final int itemTypeIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ITEM_TYPE);
- final int containerIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.CONTAINER);
- final int screenIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.SCREEN);
- final int cellXIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.CELLX);
- final int cellYIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.CELLY);
- final int spanXIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.SPANX);
- final int spanYIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.SPANY);
- final int profileIdIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.PROFILE_ID);
- UserManagerCompat userManager = UserManagerCompat.getInstance(context);
- try {
- while (c.moveToNext()) {
- ItemInfo item = new ItemInfo();
- item.cellX = c.getInt(cellXIndex);
- item.cellY = c.getInt(cellYIndex);
- item.spanX = Math.max(1, c.getInt(spanXIndex));
- item.spanY = Math.max(1, c.getInt(spanYIndex));
- item.container = c.getInt(containerIndex);
- item.itemType = c.getInt(itemTypeIndex);
- item.screenId = c.getInt(screenIndex);
- long serialNumber = c.getInt(profileIdIndex);
- item.user = userManager.getUserForSerialNumber(serialNumber);
- // Skip if user has been deleted.
- if (item.user != null) {
- items.add(item);
+ synchronized (sBgLock) {
+ for (ItemInfo item : sBgItemsIdMap) {
+ if (item instanceof ShortcutInfo) {
+ ShortcutInfo info = (ShortcutInfo) item;
+ Intent targetIntent = info.promisedIntent == null
+ ? info.intent : info.promisedIntent;
+ if (targetIntent != null && info.user.equals(user)) {
+ String s = targetIntent.toUri(0);
+ if (intentWithPkg.equals(s) || intentWithoutPkg.equals(s)) {
+ return true;
+ }
+ }
}
}
- } catch (Exception e) {
- items.clear();
- } finally {
- c.close();
}
-
- return items;
+ return false;
}
/**
* Find a folder in the db, creating the FolderInfo if necessary, and adding it to folderList.
*/
- FolderInfo getFolderById(Context context, HashMap<Long,FolderInfo> folderList, long id) {
+ FolderInfo getFolderById(Context context, LongArrayMap<FolderInfo> folderList, long id) {
final ContentResolver cr = context.getContentResolver();
Cursor c = cr.query(LauncherSettings.Favorites.CONTENT_URI, null,
"_id=? and (itemType=? or itemType=?)",
@@ -951,6 +956,7 @@ public class LauncherModel extends BroadcastReceiver
final int screenIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.SCREEN);
final int cellXIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.CELLX);
final int cellYIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.CELLY);
+ final int optionsIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.OPTIONS);
FolderInfo folderInfo = null;
switch (c.getInt(itemTypeIndex)) {
@@ -959,12 +965,14 @@ public class LauncherModel extends BroadcastReceiver
break;
}
+ // Do not trim the folder label, as is was set by the user.
folderInfo.title = c.getString(titleIndex);
folderInfo.id = id;
folderInfo.container = c.getInt(containerIndex);
folderInfo.screenId = c.getInt(screenIndex);
folderInfo.cellX = c.getInt(cellXIndex);
folderInfo.cellY = c.getInt(cellYIndex);
+ folderInfo.options = c.getInt(optionsIndex);
return folderInfo;
}
@@ -979,8 +987,8 @@ public class LauncherModel extends BroadcastReceiver
* Add an item to the database in a specified container. Sets the container, screen, cellX and
* cellY fields of the item. Also assigns an ID to the item.
*/
- static void addItemToDatabase(Context context, final ItemInfo item, final long container,
- final long screenId, final int cellX, final int cellY, final boolean notify) {
+ public static void addItemToDatabase(Context context, final ItemInfo item, final long container,
+ final long screenId, final int cellX, final int cellY) {
item.container = container;
item.cellX = cellX;
item.cellY = cellY;
@@ -999,13 +1007,11 @@ public class LauncherModel extends BroadcastReceiver
item.id = LauncherAppState.getLauncherProvider().generateNewItemId();
values.put(LauncherSettings.Favorites._ID, item.id);
- item.updateValuesWithCoordinates(values, item.cellX, item.cellY);
final StackTraceElement[] stackTrace = new Throwable().getStackTrace();
Runnable r = new Runnable() {
public void run() {
- cr.insert(notify ? LauncherSettings.Favorites.CONTENT_URI :
- LauncherSettings.Favorites.CONTENT_URI_NO_NOTIFICATION, values);
+ cr.insert(LauncherSettings.Favorites.CONTENT_URI, values);
// Lock on mBgLock *after* the db operation
synchronized (sBgLock) {
@@ -1056,7 +1062,7 @@ public class LauncherModel extends BroadcastReceiver
return cn.getPackageName().equals(pn) && info.user.equals(user);
}
};
- return filterItemInfos(sBgItemsIdMap.values(), filter);
+ return filterItemInfos(sBgItemsIdMap, filter);
}
/**
@@ -1072,7 +1078,7 @@ public class LauncherModel extends BroadcastReceiver
* @param context
* @param item
*/
- static void deleteItemFromDatabase(Context context, final ItemInfo item) {
+ public static void deleteItemFromDatabase(Context context, final ItemInfo item) {
ArrayList<ItemInfo> items = new ArrayList<ItemInfo>();
items.add(item);
deleteItemsFromDatabase(context, items);
@@ -1085,11 +1091,10 @@ public class LauncherModel extends BroadcastReceiver
*/
static void deleteItemsFromDatabase(Context context, final ArrayList<? extends ItemInfo> items) {
final ContentResolver cr = context.getContentResolver();
-
Runnable r = new Runnable() {
public void run() {
for (ItemInfo item : items) {
- final Uri uri = LauncherSettings.Favorites.getContentUri(item.id, false);
+ final Uri uri = LauncherSettings.Favorites.getContentUri(item.id);
cr.delete(uri, null, null);
// Lock on mBgLock *after* the db operation
@@ -1097,7 +1102,7 @@ public class LauncherModel extends BroadcastReceiver
switch (item.itemType) {
case LauncherSettings.Favorites.ITEM_TYPE_FOLDER:
sBgFolders.remove(item.id);
- for (ItemInfo info: sBgItemsIdMap.values()) {
+ for (ItemInfo info: sBgItemsIdMap) {
if (info.container == item.id) {
// We are deleting a folder which still contains items that
// think they are contained by that folder.
@@ -1117,7 +1122,6 @@ public class LauncherModel extends BroadcastReceiver
break;
}
sBgItemsIdMap.remove(item.id);
- sBgDbIconCache.remove(item);
}
}
}
@@ -1130,10 +1134,6 @@ public class LauncherModel extends BroadcastReceiver
* a list of screen ids in the order that they should appear.
*/
void updateWorkspaceScreenOrder(Context context, final ArrayList<Long> screens) {
- // Log to disk
- Launcher.addDumpLog(TAG, "11683562 - updateWorkspaceScreenOrder()", true);
- Launcher.addDumpLog(TAG, "11683562 - screens: " + TextUtils.join(", ", screens), true);
-
final ArrayList<Long> screensCopy = new ArrayList<Long>(screens);
final ContentResolver cr = context.getContentResolver();
final Uri uri = LauncherSettings.WorkspaceScreens.CONTENT_URI;
@@ -1180,27 +1180,25 @@ public class LauncherModel extends BroadcastReceiver
/**
* Remove the contents of the specified folder from the database
*/
- static void deleteFolderContentsFromDatabase(Context context, final FolderInfo info) {
+ public static void deleteFolderContentsFromDatabase(Context context, final FolderInfo info) {
final ContentResolver cr = context.getContentResolver();
Runnable r = new Runnable() {
public void run() {
- cr.delete(LauncherSettings.Favorites.getContentUri(info.id, false), null, null);
+ cr.delete(LauncherSettings.Favorites.getContentUri(info.id), null, null);
// Lock on mBgLock *after* the db operation
synchronized (sBgLock) {
sBgItemsIdMap.remove(info.id);
sBgFolders.remove(info.id);
- sBgDbIconCache.remove(info);
sBgWorkspaceItems.remove(info);
}
- cr.delete(LauncherSettings.Favorites.CONTENT_URI_NO_NOTIFICATION,
+ cr.delete(LauncherSettings.Favorites.CONTENT_URI,
LauncherSettings.Favorites.CONTAINER + "=" + info.id, null);
// Lock on mBgLock *after* the db operation
synchronized (sBgLock) {
for (ItemInfo childInfo : info.contents) {
sBgItemsIdMap.remove(childInfo.id);
- sBgDbIconCache.remove(childInfo);
}
}
}
@@ -1213,6 +1211,9 @@ public class LauncherModel extends BroadcastReceiver
*/
public void initialize(Callbacks callbacks) {
synchronized (mLock) {
+ // Disconnect any of the callbacks and drawables associated with ItemInfos on the
+ // workspace to prevent leaking Launcher activities on orientation change.
+ unbindItemInfosAndClearQueuedBindRunnables();
mCallbacks = new WeakReference<Callbacks>(callbacks);
}
}
@@ -1265,7 +1266,6 @@ public class LauncherModel extends BroadcastReceiver
PackageUpdatedTask.OP_UNAVAILABLE, packageNames,
user));
}
-
}
/**
@@ -1280,24 +1280,15 @@ public class LauncherModel extends BroadcastReceiver
if (Intent.ACTION_LOCALE_CHANGED.equals(action)) {
// If we have changed locale we need to clear out the labels in all apps/workspace.
forceReload();
- } else if (Intent.ACTION_CONFIGURATION_CHANGED.equals(action)) {
- // Check if configuration change was an mcc/mnc change which would affect app resources
- // and we would need to clear out the labels in all apps/workspace. Same handling as
- // above for ACTION_LOCALE_CHANGED
- Configuration currentConfig = context.getResources().getConfiguration();
- if (mPreviousConfigMcc != currentConfig.mcc) {
- Log.d(TAG, "Reload apps on config change. curr_mcc:"
- + currentConfig.mcc + " prevmcc:" + mPreviousConfigMcc);
- forceReload();
- }
- // Update previousConfig
- mPreviousConfigMcc = currentConfig.mcc;
} else if (SearchManager.INTENT_GLOBAL_SEARCH_ACTIVITY_CHANGED.equals(action) ||
SearchManager.INTENT_ACTION_SEARCHABLES_CHANGED.equals(action)) {
Callbacks callbacks = getCallback();
if (callbacks != null) {
callbacks.bindSearchablesChanged();
}
+ } else if (LauncherAppsCompat.ACTION_MANAGED_PROFILE_ADDED.equals(action)
+ || LauncherAppsCompat.ACTION_MANAGED_PROFILE_REMOVED.equals(action)) {
+ forceReload();
}
}
@@ -1336,38 +1327,32 @@ public class LauncherModel extends BroadcastReceiver
}
}
if (runLoader) {
- startLoader(false, PagedView.INVALID_RESTORE_PAGE);
+ startLoader(PagedView.INVALID_RESTORE_PAGE);
}
}
- // If there is already a loader task running, tell it to stop.
- // returns true if isLaunching() was true on the old task
- private boolean stopLoaderLocked() {
- boolean isLaunching = false;
+ /**
+ * If there is already a loader task running, tell it to stop.
+ */
+ private void stopLoaderLocked() {
LoaderTask oldTask = mLoaderTask;
if (oldTask != null) {
- if (oldTask.isLaunching()) {
- isLaunching = true;
- }
oldTask.stopLocked();
}
- return isLaunching;
}
public boolean isCurrentCallbacks(Callbacks callbacks) {
return (mCallbacks != null && mCallbacks.get() == callbacks);
}
- public void startLoader(boolean isLaunching, int synchronousBindPage) {
- startLoader(isLaunching, synchronousBindPage, LOADER_FLAG_NONE);
+ public void startLoader(int synchronousBindPage) {
+ startLoader(synchronousBindPage, LOADER_FLAG_NONE);
}
- public void startLoader(boolean isLaunching, int synchronousBindPage, int loadFlags) {
+ public void startLoader(int synchronousBindPage, int loadFlags) {
+ // Enable queue before starting loader. It will get disabled in Launcher#finishBindingItems
+ InstallShortcutReceiver.enableInstallQueue();
synchronized (mLock) {
- if (DEBUG_LOADERS) {
- Log.d(TAG, "startLoader isLaunching=" + isLaunching);
- }
-
// Clear any deferred bind-runnables from the synchronized load process
// We must do this before any loading/binding is scheduled below.
synchronized (mDeferredBindRunnables) {
@@ -1377,11 +1362,10 @@ public class LauncherModel extends BroadcastReceiver
// Don't bother to start the thread if we know it's not going to do anything
if (mCallbacks != null && mCallbacks.get() != null) {
// If there is already one running, tell it to stop.
- // also, don't downgrade isLaunching if we're already running
- isLaunching = isLaunching || stopLoaderLocked();
- mLoaderTask = new LoaderTask(mApp.getContext(), isLaunching, loadFlags);
+ stopLoaderLocked();
+ mLoaderTask = new LoaderTask(mApp.getContext(), loadFlags);
if (synchronousBindPage != PagedView.INVALID_RESTORE_PAGE
- && mAllAppsLoaded && mWorkspaceLoaded) {
+ && mAllAppsLoaded && mWorkspaceLoaded && !mIsLoaderTaskRunning) {
mLoaderTask.runBindSynchronousPage(synchronousBindPage);
} else {
sWorkerThread.setPriority(Thread.NORM_PRIORITY);
@@ -1401,7 +1385,17 @@ public class LauncherModel extends BroadcastReceiver
mDeferredBindRunnables.clear();
}
for (final Runnable r : deferredBindRunnables) {
- mHandler.post(r, MAIN_THREAD_BINDING_RUNNABLE);
+ mHandler.post(r);
+ }
+ }
+
+ // Run all the bind complete runnables after workspace is bound.
+ if (!mBindCompleteRunnables.isEmpty()) {
+ synchronized (mBindCompleteRunnables) {
+ for (final Runnable r : mBindCompleteRunnables) {
+ runOnWorkerThread(r);
+ }
+ mBindCompleteRunnables.clear();
}
}
}
@@ -1414,40 +1408,31 @@ public class LauncherModel extends BroadcastReceiver
}
}
- /** Loads the workspace screens db into a map of Rank -> ScreenId */
- private static TreeMap<Integer, Long> loadWorkspaceScreensDb(Context context) {
+ /**
+ * Loads the workspace screen ids in an ordered list.
+ */
+ @Thunk static ArrayList<Long> loadWorkspaceScreensDb(Context context) {
final ContentResolver contentResolver = context.getContentResolver();
final Uri screensUri = LauncherSettings.WorkspaceScreens.CONTENT_URI;
- final Cursor sc = contentResolver.query(screensUri, null, null, null, null);
- TreeMap<Integer, Long> orderedScreens = new TreeMap<Integer, Long>();
+ // Get screens ordered by rank.
+ final Cursor sc = contentResolver.query(screensUri, null, null, null,
+ LauncherSettings.WorkspaceScreens.SCREEN_RANK);
+ ArrayList<Long> screenIds = new ArrayList<Long>();
try {
- final int idIndex = sc.getColumnIndexOrThrow(
- LauncherSettings.WorkspaceScreens._ID);
- final int rankIndex = sc.getColumnIndexOrThrow(
- LauncherSettings.WorkspaceScreens.SCREEN_RANK);
+ final int idIndex = sc.getColumnIndexOrThrow(LauncherSettings.WorkspaceScreens._ID);
while (sc.moveToNext()) {
try {
- long screenId = sc.getLong(idIndex);
- int rank = sc.getInt(rankIndex);
- orderedScreens.put(rank, screenId);
+ screenIds.add(sc.getLong(idIndex));
} catch (Exception e) {
- Launcher.addDumpLog(TAG, "Desktop items loading interrupted - invalid screens: " + e, true);
+ Launcher.addDumpLog(TAG, "Desktop items loading interrupted"
+ + " - invalid screens: " + e, true);
}
}
} finally {
sc.close();
}
-
- // Log to disk
- Launcher.addDumpLog(TAG, "11683562 - loadWorkspaceScreensDb()", true);
- ArrayList<String> orderedScreensPairs= new ArrayList<String>();
- for (Integer i : orderedScreens.keySet()) {
- orderedScreensPairs.add("{ " + i + ": " + orderedScreens.get(i) + " }");
- }
- Launcher.addDumpLog(TAG, "11683562 - screens: " +
- TextUtils.join(", ", orderedScreensPairs), true);
- return orderedScreens;
+ return screenIds;
}
public boolean isAllAppsLoaded() {
@@ -1471,31 +1456,21 @@ public class LauncherModel extends BroadcastReceiver
*/
private class LoaderTask implements Runnable {
private Context mContext;
- private boolean mIsLaunching;
- private boolean mIsLoadingAndBindingWorkspace;
+ @Thunk boolean mIsLoadingAndBindingWorkspace;
private boolean mStopped;
- private boolean mLoadAndBindStepFinished;
+ @Thunk boolean mLoadAndBindStepFinished;
private int mFlags;
- private HashMap<Object, CharSequence> mLabelCache;
-
- LoaderTask(Context context, boolean isLaunching, int flags) {
+ LoaderTask(Context context, int flags) {
mContext = context;
- mIsLaunching = isLaunching;
- mLabelCache = new HashMap<Object, CharSequence>();
mFlags = flags;
}
- boolean isLaunching() {
- return mIsLaunching;
- }
-
boolean isLoadingWorkspace() {
return mIsLoadingAndBindingWorkspace;
}
- /** Returns whether this is an upgrade path */
- private boolean loadAndBindWorkspace() {
+ private void loadAndBindWorkspace() {
mIsLoadingAndBindingWorkspace = true;
// Load the workspace
@@ -1503,20 +1478,18 @@ public class LauncherModel extends BroadcastReceiver
Log.d(TAG, "loadAndBindWorkspace mWorkspaceLoaded=" + mWorkspaceLoaded);
}
- boolean isUpgradePath = false;
if (!mWorkspaceLoaded) {
- isUpgradePath = loadWorkspace();
+ loadWorkspace();
synchronized (LoaderTask.this) {
if (mStopped) {
- return isUpgradePath;
+ return;
}
mWorkspaceLoaded = true;
}
}
// Bind the workspace
- bindWorkspace(-1, isUpgradePath);
- return isUpgradePath;
+ bindWorkspace(-1);
}
private void waitForIdle() {
@@ -1538,7 +1511,7 @@ public class LauncherModel extends BroadcastReceiver
}
});
- while (!mStopped && !mLoadAndBindStepFinished && !mFlushingWorkerThread) {
+ while (!mStopped && !mLoadAndBindStepFinished) {
try {
// Just in case mFlushingWorkerThread changes but we aren't woken up,
// wait no longer than 1sec at a time
@@ -1585,72 +1558,35 @@ public class LauncherModel extends BroadcastReceiver
// Divide the set of loaded items into those that we are binding synchronously, and
// everything else that is to be bound normally (asynchronously).
- bindWorkspace(synchronousBindPage, false);
+ bindWorkspace(synchronousBindPage);
// XXX: For now, continue posting the binding of AllApps as there are other issues that
// arise from that.
onlyBindAllApps();
}
public void run() {
- boolean isUpgrade = false;
-
synchronized (mLock) {
+ if (mStopped) {
+ return;
+ }
mIsLoaderTaskRunning = true;
}
// Optimize for end-user experience: if the Launcher is up and // running with the
// All Apps interface in the foreground, load All Apps first. Otherwise, load the
// workspace first (default).
keep_running: {
- // Elevate priority when Home launches for the first time to avoid
- // starving at boot time. Staring at a blank home is not cool.
- synchronized (mLock) {
- if (DEBUG_LOADERS) Log.d(TAG, "Setting thread priority to " +
- (mIsLaunching ? "DEFAULT" : "BACKGROUND"));
- android.os.Process.setThreadPriority(mIsLaunching
- ? Process.THREAD_PRIORITY_DEFAULT : Process.THREAD_PRIORITY_BACKGROUND);
- }
if (DEBUG_LOADERS) Log.d(TAG, "step 1: loading workspace");
- isUpgrade = loadAndBindWorkspace();
+ loadAndBindWorkspace();
if (mStopped) {
break keep_running;
}
- // Whew! Hard work done. Slow us down, and wait until the UI thread has
- // settled down.
- synchronized (mLock) {
- if (mIsLaunching) {
- if (DEBUG_LOADERS) Log.d(TAG, "Setting thread priority to BACKGROUND");
- android.os.Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
- }
- }
waitForIdle();
// second step
if (DEBUG_LOADERS) Log.d(TAG, "step 2: loading all apps");
loadAndBindAllApps();
-
- // Restore the default thread priority after we are done loading items
- synchronized (mLock) {
- android.os.Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
- }
- }
-
- // Update the saved icons if necessary
- if (DEBUG_LOADERS) Log.d(TAG, "Comparing loaded icons to database icons");
- synchronized (sBgLock) {
- for (Object key : sBgDbIconCache.keySet()) {
- updateSavedIcon(mContext, (ShortcutInfo) key, sBgDbIconCache.get(key));
- }
- sBgDbIconCache.clear();
- }
-
- if (LauncherAppState.isDisableAllApps()) {
- // Ensure that all the applications that are in the system are
- // represented on the home screen.
- if (!UPGRADE_USE_MORE_APPS_FOLDER || !isUpgrade) {
- verifyApplications();
- }
}
// Clear out this reference, otherwise we end up holding it until all of the
@@ -1663,6 +1599,7 @@ public class LauncherModel extends BroadcastReceiver
mLoaderTask = null;
}
mIsLoaderTaskRunning = false;
+ mHasLoaderCompletedOnce = true;
}
}
@@ -1703,34 +1640,12 @@ public class LauncherModel extends BroadcastReceiver
}
}
- private void verifyApplications() {
- final Context context = mApp.getContext();
-
- // Cross reference all the applications in our apps list with items in the workspace
- ArrayList<ItemInfo> tmpInfos;
- ArrayList<ItemInfo> added = new ArrayList<ItemInfo>();
- synchronized (sBgLock) {
- for (AppInfo app : mBgAllAppsList.data) {
- tmpInfos = getItemInfoForComponentName(app.componentName, app.user);
- if (tmpInfos.isEmpty()) {
- // We are missing an application icon, so add this to the workspace
- added.add(app);
- // This is a rare event, so lets log it
- Log.e(TAG, "Missing Application on load: " + app);
- }
- }
- }
- if (!added.isEmpty()) {
- addAndBindAddedWorkspaceApps(context, added);
- }
- }
-
// check & update map of what's occupied; used to discard overlapping/invalid items
- private boolean checkItemPlacement(HashMap<Long, ItemInfo[][]> occupied, ItemInfo item) {
+ private boolean checkItemPlacement(LongArrayMap<ItemInfo[][]> occupied, ItemInfo item) {
LauncherAppState app = LauncherAppState.getInstance();
- DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
- final int countX = (int) grid.numColumns;
- final int countY = (int) grid.numRows;
+ InvariantDeviceProfile profile = app.getInvariantDeviceProfile();
+ final int countX = (int) profile.numColumns;
+ final int countY = (int) profile.numRows;
long containerIndex = item.screenId;
if (item.container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) {
@@ -1746,10 +1661,10 @@ public class LauncherModel extends BroadcastReceiver
final ItemInfo[][] hotseatItems =
occupied.get((long) LauncherSettings.Favorites.CONTAINER_HOTSEAT);
- if (item.screenId >= grid.numHotseatIcons) {
+ if (item.screenId >= profile.numHotseatIcons) {
Log.e(TAG, "Error loading shortcut " + item
+ " into hotseat position " + item.screenId
- + ", position out of bounds: (0 to " + (grid.numHotseatIcons - 1)
+ + ", position out of bounds: (0 to " + (profile.numHotseatIcons - 1)
+ ")");
return false;
}
@@ -1767,7 +1682,7 @@ public class LauncherModel extends BroadcastReceiver
return true;
}
} else {
- final ItemInfo[][] items = new ItemInfo[(int) grid.numHotseatIcons][1];
+ final ItemInfo[][] items = new ItemInfo[(int) profile.numHotseatIcons][1];
items[(int) item.screenId][0] = item;
occupied.put((long) LauncherSettings.Favorites.CONTAINER_HOTSEAT, items);
return true;
@@ -1822,31 +1737,25 @@ public class LauncherModel extends BroadcastReceiver
sBgAppWidgets.clear();
sBgFolders.clear();
sBgItemsIdMap.clear();
- sBgDbIconCache.clear();
sBgWorkspaceScreens.clear();
}
}
- /** Returns whether this is an upgrade path */
- private boolean loadWorkspace() {
- // Log to disk
- Launcher.addDumpLog(TAG, "11683562 - loadWorkspace()", true);
-
+ private void loadWorkspace() {
final long t = DEBUG_LOADERS ? SystemClock.uptimeMillis() : 0;
final Context context = mContext;
final ContentResolver contentResolver = context.getContentResolver();
final PackageManager manager = context.getPackageManager();
- final AppWidgetManager widgets = AppWidgetManager.getInstance(context);
final boolean isSafeMode = manager.isSafeMode();
final LauncherAppsCompat launcherApps = LauncherAppsCompat.getInstance(context);
final boolean isSdCardReady = context.registerReceiver(null,
new IntentFilter(StartupReceiver.SYSTEM_READY)) != null;
LauncherAppState app = LauncherAppState.getInstance();
- DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
- int countX = (int) grid.numColumns;
- int countY = (int) grid.numRows;
+ InvariantDeviceProfile profile = app.getInvariantDeviceProfile();
+ int countX = (int) profile.numColumns;
+ int countY = (int) profile.numRows;
if ((mFlags & LOADER_FLAG_CLEAR_WORKSPACE) != 0) {
Launcher.addDumpLog(TAG, "loadWorkspace: resetting launcher database", true);
@@ -1863,27 +1772,21 @@ public class LauncherModel extends BroadcastReceiver
LauncherAppState.getLauncherProvider().loadDefaultFavoritesIfNecessary();
}
- // This code path is for our old migration code and should no longer be exercised
- boolean loadedOldDb = false;
-
- // Log to disk
- Launcher.addDumpLog(TAG, "11683562 - loadedOldDb: " + loadedOldDb, true);
-
synchronized (sBgLock) {
clearSBgDataStructures();
- final HashSet<String> installingPkgs = PackageInstallerCompat
+ final HashMap<String, Integer> installingPkgs = PackageInstallerCompat
.getInstance(mContext).updateAndGetActiveSessionCache();
final ArrayList<Long> itemsToRemove = new ArrayList<Long>();
final ArrayList<Long> restoredRows = new ArrayList<Long>();
- final Uri contentUri = LauncherSettings.Favorites.CONTENT_URI_NO_NOTIFICATION;
+ final Uri contentUri = LauncherSettings.Favorites.CONTENT_URI;
if (DEBUG_LOADERS) Log.d(TAG, "loading model from " + contentUri);
final Cursor c = contentResolver.query(contentUri, null, null, null, null);
// +1 for the hotseat (it can be larger than the workspace)
// Load workspace in reverse order to ensure that latest items are loaded first (and
// before any earlier duplicates)
- final HashMap<Long, ItemInfo[][]> occupied = new HashMap<Long, ItemInfo[][]>();
+ final LongArrayMap<ItemInfo[][]> occupied = new LongArrayMap<>();
try {
final int idIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites._ID);
@@ -1891,13 +1794,6 @@ public class LauncherModel extends BroadcastReceiver
(LauncherSettings.Favorites.INTENT);
final int titleIndex = c.getColumnIndexOrThrow
(LauncherSettings.Favorites.TITLE);
- final int iconTypeIndex = c.getColumnIndexOrThrow(
- LauncherSettings.Favorites.ICON_TYPE);
- final int iconIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ICON);
- final int iconPackageIndex = c.getColumnIndexOrThrow(
- LauncherSettings.Favorites.ICON_PACKAGE);
- final int iconResourceIndex = c.getColumnIndexOrThrow(
- LauncherSettings.Favorites.ICON_RESOURCE);
final int containerIndex = c.getColumnIndexOrThrow(
LauncherSettings.Favorites.CONTAINER);
final int itemTypeIndex = c.getColumnIndexOrThrow(
@@ -1916,19 +1812,27 @@ public class LauncherModel extends BroadcastReceiver
(LauncherSettings.Favorites.SPANX);
final int spanYIndex = c.getColumnIndexOrThrow(
LauncherSettings.Favorites.SPANY);
+ final int rankIndex = c.getColumnIndexOrThrow(
+ LauncherSettings.Favorites.RANK);
final int restoredIndex = c.getColumnIndexOrThrow(
LauncherSettings.Favorites.RESTORED);
final int profileIdIndex = c.getColumnIndexOrThrow(
LauncherSettings.Favorites.PROFILE_ID);
- //final int uriIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.URI);
- //final int displayModeIndex = c.getColumnIndexOrThrow(
- // LauncherSettings.Favorites.DISPLAY_MODE);
+ final int optionsIndex = c.getColumnIndexOrThrow(
+ LauncherSettings.Favorites.OPTIONS);
+ final CursorIconInfo cursorIconInfo = new CursorIconInfo(c);
+
+ final LongSparseArray<UserHandleCompat> allUsers = new LongSparseArray<>();
+ for (UserHandleCompat user : mUserManager.getUserProfiles()) {
+ allUsers.put(mUserManager.getSerialNumberForUser(user), user);
+ }
ShortcutInfo info;
String intentDescription;
LauncherAppWidgetInfo appWidgetInfo;
int container;
long id;
+ long serialNumber;
Intent intent;
UserHandleCompat user;
@@ -1937,16 +1841,18 @@ public class LauncherModel extends BroadcastReceiver
int itemType = c.getInt(itemTypeIndex);
boolean restored = 0 != c.getInt(restoredIndex);
boolean allowMissingTarget = false;
+ container = c.getInt(containerIndex);
switch (itemType) {
case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION:
case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
id = c.getLong(idIndex);
intentDescription = c.getString(intentIndex);
- long serialNumber = c.getInt(profileIdIndex);
- user = mUserManager.getUserForSerialNumber(serialNumber);
+ serialNumber = c.getInt(profileIdIndex);
+ user = allUsers.get(serialNumber);
int promiseType = c.getInt(restoredIndex);
int disabledState = 0;
+ boolean itemReplaced = false;
if (user == null) {
// User has been deleted remove the item.
itemsToRemove.add(id);
@@ -1978,9 +1884,7 @@ public class LauncherModel extends BroadcastReceiver
ContentValues values = new ContentValues();
values.put(LauncherSettings.Favorites.INTENT,
intent.toUri(0));
- String where = BaseColumns._ID + "= ?";
- String[] args = {Long.toString(id)};
- contentResolver.update(contentUri, values, where, args);
+ updateItem(id, values);
}
}
@@ -2004,16 +1908,33 @@ public class LauncherModel extends BroadcastReceiver
if ((promiseType & ShortcutInfo.FLAG_RESTORE_STARTED) != 0) {
// Restore has started once.
- } else if (installingPkgs.contains(cn.getPackageName())) {
+ } else if (installingPkgs.containsKey(cn.getPackageName())) {
// App restore has started. Update the flag
promiseType |= ShortcutInfo.FLAG_RESTORE_STARTED;
ContentValues values = new ContentValues();
values.put(LauncherSettings.Favorites.RESTORED,
promiseType);
- String where = BaseColumns._ID + "= ?";
- String[] args = {Long.toString(id)};
- contentResolver.update(contentUri, values, where, args);
-
+ updateItem(id, values);
+ } else if ((promiseType & ShortcutInfo.FLAG_RESTORED_APP_TYPE) != 0) {
+ // This is a common app. Try to replace this.
+ int appType = CommonAppTypeParser.decodeItemTypeFromFlag(promiseType);
+ CommonAppTypeParser parser = new CommonAppTypeParser(id, appType, context);
+ if (parser.findDefaultApp()) {
+ // Default app found. Replace it.
+ intent = parser.parsedIntent;
+ cn = intent.getComponent();
+ ContentValues values = parser.parsedValues;
+ values.put(LauncherSettings.Favorites.RESTORED, 0);
+ updateItem(id, values);
+ restored = false;
+ itemReplaced = true;
+
+ } else if (REMOVE_UNRESTORED_ICONS) {
+ Launcher.addDumpLog(TAG,
+ "Unrestored package removed: " + cn, true);
+ itemsToRemove.add(id);
+ continue;
+ }
} else if (REMOVE_UNRESTORED_ICONS) {
Launcher.addDumpLog(TAG,
"Unrestored package removed: " + cn, true);
@@ -2059,12 +1980,26 @@ public class LauncherModel extends BroadcastReceiver
continue;
}
- if (restored) {
+ boolean useLowResIcon = container >= 0 &&
+ c.getInt(rankIndex) >= FolderIcon.NUM_ITEMS_IN_PREVIEW;
+
+ if (itemReplaced) {
+ if (user.equals(UserHandleCompat.myUserHandle())) {
+ info = getAppShortcutInfo(manager, intent, user, context, null,
+ cursorIconInfo.iconIndex, titleIndex,
+ false, useLowResIcon);
+ } else {
+ // Don't replace items for other profiles.
+ itemsToRemove.add(id);
+ continue;
+ }
+ } else if (restored) {
if (user.equals(UserHandleCompat.myUserHandle())) {
Launcher.addDumpLog(TAG,
"constructing info for partially restored package",
true);
- info = getRestoredItemInfo(c, titleIndex, intent, promiseType);
+ info = getRestoredItemInfo(c, titleIndex, intent,
+ promiseType, itemType, cursorIconInfo, context);
intent = getRestoredItemIntent(c, context, intent);
} else {
// Don't restore items for other profiles.
@@ -2073,12 +2008,11 @@ public class LauncherModel extends BroadcastReceiver
}
} else if (itemType ==
LauncherSettings.Favorites.ITEM_TYPE_APPLICATION) {
- info = getShortcutInfo(manager, intent, user, context, c,
- iconIndex, titleIndex, mLabelCache, allowMissingTarget);
+ info = getAppShortcutInfo(manager, intent, user, context, c,
+ cursorIconInfo.iconIndex, titleIndex,
+ allowMissingTarget, useLowResIcon);
} else {
- info = getShortcutInfo(c, context, iconTypeIndex,
- iconPackageIndex, iconResourceIndex, iconIndex,
- titleIndex);
+ info = getShortcutInfo(c, context, titleIndex, cursorIconInfo);
// App shortcuts that used to be automatically added to Launcher
// didn't always have the correct intent flags set, so do that
@@ -2096,14 +2030,17 @@ public class LauncherModel extends BroadcastReceiver
if (info != null) {
info.id = id;
info.intent = intent;
- container = c.getInt(containerIndex);
info.container = container;
info.screenId = c.getInt(screenIndex);
info.cellX = c.getInt(cellXIndex);
info.cellY = c.getInt(cellYIndex);
+ info.rank = c.getInt(rankIndex);
info.spanX = 1;
info.spanY = 1;
info.intent.putExtra(ItemInfo.EXTRA_PROFILE, serialNumber);
+ if (info.promisedIntent != null) {
+ info.promisedIntent.putExtra(ItemInfo.EXTRA_PROFILE, serialNumber);
+ }
info.isDisabled = disabledState;
if (isSafeMode && !Utilities.isSystemApp(context, intent)) {
info.isDisabled |= ShortcutInfo.FLAG_DISABLED_SAFEMODE;
@@ -2115,6 +2052,18 @@ public class LauncherModel extends BroadcastReceiver
break;
}
+ if (restored) {
+ ComponentName cn = info.getTargetComponent();
+ if (cn != null) {
+ Integer progress = installingPkgs.get(cn.getPackageName());
+ if (progress != null) {
+ info.setInstallProgress(progress);
+ } else {
+ info.status &= ~ShortcutInfo.FLAG_INSTALL_SESSION_ACTIVE;
+ }
+ }
+ }
+
switch (container) {
case LauncherSettings.Favorites.CONTAINER_DESKTOP:
case LauncherSettings.Favorites.CONTAINER_HOTSEAT:
@@ -2128,10 +2077,6 @@ public class LauncherModel extends BroadcastReceiver
break;
}
sBgItemsIdMap.put(info.id, info);
-
- // now that we've loaded everthing re-save it with the
- // icon in case it disappears somehow.
- queueIconToBeChecked(sBgDbIconCache, info, c, iconIndex);
} else {
throw new RuntimeException("Unexpected null ShortcutInfo");
}
@@ -2141,15 +2086,16 @@ public class LauncherModel extends BroadcastReceiver
id = c.getLong(idIndex);
FolderInfo folderInfo = findOrMakeFolder(sBgFolders, id);
+ // Do not trim the folder label, as is was set by the user.
folderInfo.title = c.getString(titleIndex);
folderInfo.id = id;
- container = c.getInt(containerIndex);
folderInfo.container = container;
folderInfo.screenId = c.getInt(screenIndex);
folderInfo.cellX = c.getInt(cellXIndex);
folderInfo.cellY = c.getInt(cellYIndex);
folderInfo.spanX = 1;
folderInfo.spanY = 1;
+ folderInfo.options = c.getInt(optionsIndex);
// check & update map of what's occupied
if (!checkItemPlacement(occupied, folderInfo)) {
@@ -2174,28 +2120,41 @@ public class LauncherModel extends BroadcastReceiver
break;
case LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET:
+ case LauncherSettings.Favorites.ITEM_TYPE_CUSTOM_APPWIDGET:
// Read all Launcher-specific widget details
+ boolean customWidget = itemType ==
+ LauncherSettings.Favorites.ITEM_TYPE_CUSTOM_APPWIDGET;
+
int appWidgetId = c.getInt(appWidgetIdIndex);
+ serialNumber = c.getLong(profileIdIndex);
String savedProvider = c.getString(appWidgetProviderIndex);
id = c.getLong(idIndex);
+ user = allUsers.get(serialNumber);
+ if (user == null) {
+ itemsToRemove.add(id);
+ continue;
+ }
+
final ComponentName component =
ComponentName.unflattenFromString(savedProvider);
final int restoreStatus = c.getInt(restoredIndex);
final boolean isIdValid = (restoreStatus &
LauncherAppWidgetInfo.FLAG_ID_NOT_VALID) == 0;
-
final boolean wasProviderReady = (restoreStatus &
LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY) == 0;
- final AppWidgetProviderInfo provider = isIdValid
- ? widgets.getAppWidgetInfo(appWidgetId)
- : findAppWidgetProviderInfoWithComponent(context, component);
+ final LauncherAppWidgetProviderInfo provider =
+ LauncherModel.getProviderInfo(context,
+ ComponentName.unflattenFromString(savedProvider),
+ user);
final boolean isProviderReady = isValidProvider(provider);
- if (!isSafeMode && wasProviderReady && !isProviderReady) {
+ if (!isSafeMode && !customWidget &&
+ wasProviderReady && !isProviderReady) {
String log = "Deleting widget that isn't installed anymore: "
+ "id=" + id + " appWidgetId=" + appWidgetId;
+
Log.e(TAG, log);
Launcher.addDumpLog(TAG, log, false);
itemsToRemove.add(id);
@@ -2203,10 +2162,6 @@ public class LauncherModel extends BroadcastReceiver
if (isProviderReady) {
appWidgetInfo = new LauncherAppWidgetInfo(appWidgetId,
provider.provider);
- int[] minSpan =
- Launcher.getMinSpanForWidget(context, provider);
- appWidgetInfo.minSpanX = minSpan[0];
- appWidgetInfo.minSpanY = minSpan[1];
int status = restoreStatus;
if (!wasProviderReady) {
@@ -2229,10 +2184,11 @@ public class LauncherModel extends BroadcastReceiver
appWidgetInfo = new LauncherAppWidgetInfo(appWidgetId,
component);
appWidgetInfo.restoreStatus = restoreStatus;
+ Integer installProgress = installingPkgs.get(component.getPackageName());
if ((restoreStatus & LauncherAppWidgetInfo.FLAG_RESTORE_STARTED) != 0) {
// Restore has started once.
- } else if (installingPkgs.contains(component.getPackageName())) {
+ } else if (installProgress != null) {
// App restore has started. Update the flag
appWidgetInfo.restoreStatus |=
LauncherAppWidgetInfo.FLAG_RESTORE_STARTED;
@@ -2242,6 +2198,9 @@ public class LauncherModel extends BroadcastReceiver
itemsToRemove.add(id);
continue;
}
+
+ appWidgetInfo.installProgress =
+ installProgress == null ? 0 : installProgress;
}
appWidgetInfo.id = id;
@@ -2250,8 +2209,8 @@ public class LauncherModel extends BroadcastReceiver
appWidgetInfo.cellY = c.getInt(cellYIndex);
appWidgetInfo.spanX = c.getInt(spanXIndex);
appWidgetInfo.spanY = c.getInt(spanYIndex);
+ appWidgetInfo.user = user;
- container = c.getInt(containerIndex);
if (container != LauncherSettings.Favorites.CONTAINER_DESKTOP &&
container != LauncherSettings.Favorites.CONTAINER_HOTSEAT) {
Log.e(TAG, "Widget found where container != " +
@@ -2259,24 +2218,26 @@ public class LauncherModel extends BroadcastReceiver
continue;
}
- appWidgetInfo.container = c.getInt(containerIndex);
+ appWidgetInfo.container = container;
// check & update map of what's occupied
if (!checkItemPlacement(occupied, appWidgetInfo)) {
itemsToRemove.add(id);
break;
}
- String providerName = appWidgetInfo.providerName.flattenToString();
- if (!providerName.equals(savedProvider) ||
- (appWidgetInfo.restoreStatus != restoreStatus)) {
- ContentValues values = new ContentValues();
- values.put(LauncherSettings.Favorites.APPWIDGET_PROVIDER,
- providerName);
- values.put(LauncherSettings.Favorites.RESTORED,
- appWidgetInfo.restoreStatus);
- String where = BaseColumns._ID + "= ?";
- String[] args = {Long.toString(id)};
- contentResolver.update(contentUri, values, where, args);
+ if (!customWidget) {
+ String providerName =
+ appWidgetInfo.providerName.flattenToString();
+ if (!providerName.equals(savedProvider) ||
+ (appWidgetInfo.restoreStatus != restoreStatus)) {
+ ContentValues values = new ContentValues();
+ values.put(
+ LauncherSettings.Favorites.APPWIDGET_PROVIDER,
+ providerName);
+ values.put(LauncherSettings.Favorites.RESTORED,
+ appWidgetInfo.restoreStatus);
+ updateItem(id, values);
+ }
}
sBgItemsIdMap.put(appWidgetInfo.id, appWidgetInfo);
sBgAppWidgets.add(appWidgetInfo);
@@ -2296,44 +2257,35 @@ public class LauncherModel extends BroadcastReceiver
// Break early if we've stopped loading
if (mStopped) {
clearSBgDataStructures();
- return false;
+ return;
}
if (itemsToRemove.size() > 0) {
- ContentProviderClient client = contentResolver.acquireContentProviderClient(
- contentUri);
// Remove dead items
- for (long id : itemsToRemove) {
- if (DEBUG_LOADERS) {
- Log.d(TAG, "Removed id = " + id);
- }
- // Don't notify content observers
- try {
- client.delete(LauncherSettings.Favorites.getContentUri(id, false),
- null, null);
- } catch (RemoteException e) {
- Log.w(TAG, "Could not remove id = " + id);
- }
+ contentResolver.delete(LauncherSettings.Favorites.CONTENT_URI,
+ Utilities.createDbSelectionQuery(
+ LauncherSettings.Favorites._ID, itemsToRemove), null);
+ if (DEBUG_LOADERS) {
+ Log.d(TAG, "Removed = " + Utilities.createDbSelectionQuery(
+ LauncherSettings.Favorites._ID, itemsToRemove));
+ }
+
+ // Remove any empty folder
+ for (long folderId : LauncherAppState.getLauncherProvider()
+ .deleteEmptyFolders()) {
+ sBgWorkspaceItems.remove(sBgFolders.get(folderId));
+ sBgFolders.remove(folderId);
+ sBgItemsIdMap.remove(folderId);
}
}
if (restoredRows.size() > 0) {
- ContentProviderClient updater = contentResolver.acquireContentProviderClient(
- contentUri);
// Update restored items that no longer require special handling
- try {
- StringBuilder selectionBuilder = new StringBuilder();
- selectionBuilder.append(LauncherSettings.Favorites._ID);
- selectionBuilder.append(" IN (");
- selectionBuilder.append(TextUtils.join(", ", restoredRows));
- selectionBuilder.append(")");
- ContentValues values = new ContentValues();
- values.put(LauncherSettings.Favorites.RESTORED, 0);
- updater.update(LauncherSettings.Favorites.CONTENT_URI_NO_NOTIFICATION,
- values, selectionBuilder.toString(), null);
- } catch (RemoteException e) {
- Log.w(TAG, "Could not update restored rows");
- }
+ ContentValues values = new ContentValues();
+ values.put(LauncherSettings.Favorites.RESTORED, 0);
+ contentResolver.update(LauncherSettings.Favorites.CONTENT_URI, values,
+ Utilities.createDbSelectionQuery(
+ LauncherSettings.Favorites._ID, restoredRows), null);
}
if (!isSdCardReady && !sPendingPackages.isEmpty()) {
@@ -2342,63 +2294,22 @@ public class LauncherModel extends BroadcastReceiver
null, sWorker);
}
- if (loadedOldDb) {
- long maxScreenId = 0;
- // If we're importing we use the old screen order.
- for (ItemInfo item: sBgItemsIdMap.values()) {
- long screenId = item.screenId;
- if (item.container == LauncherSettings.Favorites.CONTAINER_DESKTOP &&
- !sBgWorkspaceScreens.contains(screenId)) {
- sBgWorkspaceScreens.add(screenId);
- if (screenId > maxScreenId) {
- maxScreenId = screenId;
- }
- }
- }
- Collections.sort(sBgWorkspaceScreens);
- // Log to disk
- Launcher.addDumpLog(TAG, "11683562 - maxScreenId: " + maxScreenId, true);
- Launcher.addDumpLog(TAG, "11683562 - sBgWorkspaceScreens: " +
- TextUtils.join(", ", sBgWorkspaceScreens), true);
+ sBgWorkspaceScreens.addAll(loadWorkspaceScreensDb(mContext));
- LauncherAppState.getLauncherProvider().updateMaxScreenId(maxScreenId);
- updateWorkspaceScreenOrder(context, sBgWorkspaceScreens);
-
- // Update the max item id after we load an old db
- long maxItemId = 0;
- // If we're importing we use the old screen order.
- for (ItemInfo item: sBgItemsIdMap.values()) {
- maxItemId = Math.max(maxItemId, item.id);
+ // Remove any empty screens
+ ArrayList<Long> unusedScreens = new ArrayList<Long>(sBgWorkspaceScreens);
+ for (ItemInfo item: sBgItemsIdMap) {
+ long screenId = item.screenId;
+ if (item.container == LauncherSettings.Favorites.CONTAINER_DESKTOP &&
+ unusedScreens.contains(screenId)) {
+ unusedScreens.remove(screenId);
}
- LauncherAppState.getLauncherProvider().updateMaxItemId(maxItemId);
- } else {
- TreeMap<Integer, Long> orderedScreens = loadWorkspaceScreensDb(mContext);
- for (Integer i : orderedScreens.keySet()) {
- sBgWorkspaceScreens.add(orderedScreens.get(i));
- }
- // Log to disk
- Launcher.addDumpLog(TAG, "11683562 - sBgWorkspaceScreens: " +
- TextUtils.join(", ", sBgWorkspaceScreens), true);
-
- // Remove any empty screens
- ArrayList<Long> unusedScreens = new ArrayList<Long>(sBgWorkspaceScreens);
- for (ItemInfo item: sBgItemsIdMap.values()) {
- long screenId = item.screenId;
- if (item.container == LauncherSettings.Favorites.CONTAINER_DESKTOP &&
- unusedScreens.contains(screenId)) {
- unusedScreens.remove(screenId);
- }
- }
-
- // If there are any empty screens remove them, and update.
- if (unusedScreens.size() != 0) {
- // Log to disk
- Launcher.addDumpLog(TAG, "11683562 - unusedScreens (to be removed): " +
- TextUtils.join(", ", unusedScreens), true);
+ }
- sBgWorkspaceScreens.removeAll(unusedScreens);
- updateWorkspaceScreenOrder(context, sBgWorkspaceScreens);
- }
+ // If there are any empty screens remove them, and update.
+ if (unusedScreens.size() != 0) {
+ sBgWorkspaceScreens.removeAll(unusedScreens);
+ updateWorkspaceScreenOrder(context, sBgWorkspaceScreens);
}
if (DEBUG_LOADERS) {
@@ -2408,14 +2319,13 @@ public class LauncherModel extends BroadcastReceiver
for (int y = 0; y < countY; y++) {
String line = "";
- Iterator<Long> iter = occupied.keySet().iterator();
- while (iter.hasNext()) {
- long screenId = iter.next();
+ for (int i = 0; i < nScreens; i++) {
+ long screenId = occupied.keyAt(i);
if (screenId > 0) {
line += " | ";
}
+ ItemInfo[][] screen = occupied.valueAt(i);
for (int x = 0; x < countX; x++) {
- ItemInfo[][] screen = occupied.get(screenId);
if (x < screen.length && y < screen[x].length) {
line += (screen[x][y] != null) ? "#" : ".";
} else {
@@ -2427,7 +2337,17 @@ public class LauncherModel extends BroadcastReceiver
}
}
}
- return loadedOldDb;
+ }
+
+ /**
+ * Partially updates the item without any notification. Must be called on the worker thread.
+ */
+ private void updateItem(long itemId, ContentValues update) {
+ mContext.getContentResolver().update(
+ LauncherSettings.Favorites.CONTENT_URI,
+ update,
+ BaseColumns._ID + "= ?",
+ new String[]{Long.toString(itemId)});
}
/** Filters the set of items who are directly or indirectly (via another container) on the
@@ -2496,14 +2416,17 @@ public class LauncherModel extends BroadcastReceiver
/** Filters the set of folders which are on the specified screen. */
private void filterCurrentFolders(long currentScreenId,
- HashMap<Long, ItemInfo> itemsIdMap,
- HashMap<Long, FolderInfo> folders,
- HashMap<Long, FolderInfo> currentScreenFolders,
- HashMap<Long, FolderInfo> otherScreenFolders) {
+ LongArrayMap<ItemInfo> itemsIdMap,
+ LongArrayMap<FolderInfo> folders,
+ LongArrayMap<FolderInfo> currentScreenFolders,
+ LongArrayMap<FolderInfo> otherScreenFolders) {
+
+ int total = folders.size();
+ for (int i = 0; i < total; i++) {
+ long id = folders.keyAt(i);
+ FolderInfo folder = folders.valueAt(i);
- for (long id : folders.keySet()) {
ItemInfo info = itemsIdMap.get(id);
- FolderInfo folder = folders.get(id);
if (info == null || folder == null) continue;
if (info.container == LauncherSettings.Favorites.CONTAINER_DESKTOP &&
info.screenId == currentScreenId) {
@@ -2518,13 +2441,13 @@ public class LauncherModel extends BroadcastReceiver
* right) */
private void sortWorkspaceItemsSpatially(ArrayList<ItemInfo> workspaceItems) {
final LauncherAppState app = LauncherAppState.getInstance();
- final DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
+ final InvariantDeviceProfile profile = app.getInvariantDeviceProfile();
// XXX: review this
Collections.sort(workspaceItems, new Comparator<ItemInfo>() {
@Override
public int compare(ItemInfo lhs, ItemInfo rhs) {
- int cellCountX = (int) grid.numColumns;
- int cellCountY = (int) grid.numRows;
+ int cellCountX = (int) profile.numColumns;
+ int cellCountY = (int) profile.numRows;
int screenOffset = cellCountX * cellCountY;
int containerOffset = screenOffset * (Launcher.SCREEN_COUNT + 1); // +1 hotseat
long lr = (lhs.container * containerOffset + lhs.screenId * screenOffset +
@@ -2547,13 +2470,13 @@ public class LauncherModel extends BroadcastReceiver
}
}
};
- runOnMainThread(r, MAIN_THREAD_BINDING_RUNNABLE);
+ runOnMainThread(r);
}
private void bindWorkspaceItems(final Callbacks oldCallbacks,
final ArrayList<ItemInfo> workspaceItems,
final ArrayList<LauncherAppWidgetInfo> appWidgets,
- final HashMap<Long, FolderInfo> folders,
+ final LongArrayMap<FolderInfo> folders,
ArrayList<Runnable> deferredBindRunnables) {
final boolean postOnMainThread = (deferredBindRunnables != null);
@@ -2578,7 +2501,7 @@ public class LauncherModel extends BroadcastReceiver
deferredBindRunnables.add(r);
}
} else {
- runOnMainThread(r, MAIN_THREAD_BINDING_RUNNABLE);
+ runOnMainThread(r);
}
}
@@ -2597,7 +2520,7 @@ public class LauncherModel extends BroadcastReceiver
deferredBindRunnables.add(r);
}
} else {
- runOnMainThread(r, MAIN_THREAD_BINDING_RUNNABLE);
+ runOnMainThread(r);
}
}
@@ -2616,7 +2539,7 @@ public class LauncherModel extends BroadcastReceiver
if (postOnMainThread) {
deferredBindRunnables.add(r);
} else {
- runOnMainThread(r, MAIN_THREAD_BINDING_RUNNABLE);
+ runOnMainThread(r);
}
}
}
@@ -2624,7 +2547,7 @@ public class LauncherModel extends BroadcastReceiver
/**
* Binds all loaded data to actual views on the main thread.
*/
- private void bindWorkspace(int synchronizeBindPage, final boolean isUpgradePath) {
+ private void bindWorkspace(int synchronizeBindPage) {
final long t = SystemClock.uptimeMillis();
Runnable r;
@@ -2641,15 +2564,18 @@ public class LauncherModel extends BroadcastReceiver
ArrayList<ItemInfo> workspaceItems = new ArrayList<ItemInfo>();
ArrayList<LauncherAppWidgetInfo> appWidgets =
new ArrayList<LauncherAppWidgetInfo>();
- HashMap<Long, FolderInfo> folders = new HashMap<Long, FolderInfo>();
- HashMap<Long, ItemInfo> itemsIdMap = new HashMap<Long, ItemInfo>();
ArrayList<Long> orderedScreenIds = new ArrayList<Long>();
+
+ final LongArrayMap<FolderInfo> folders;
+ final LongArrayMap<ItemInfo> itemsIdMap;
+
synchronized (sBgLock) {
workspaceItems.addAll(sBgWorkspaceItems);
appWidgets.addAll(sBgAppWidgets);
- folders.putAll(sBgFolders);
- itemsIdMap.putAll(sBgItemsIdMap);
orderedScreenIds.addAll(sBgWorkspaceScreens);
+
+ folders = sBgFolders.clone();
+ itemsIdMap = sBgItemsIdMap.clone();
}
final boolean isLoadingSynchronously =
@@ -2675,8 +2601,8 @@ public class LauncherModel extends BroadcastReceiver
new ArrayList<LauncherAppWidgetInfo>();
ArrayList<LauncherAppWidgetInfo> otherAppWidgets =
new ArrayList<LauncherAppWidgetInfo>();
- HashMap<Long, FolderInfo> currentFolders = new HashMap<Long, FolderInfo>();
- HashMap<Long, FolderInfo> otherFolders = new HashMap<Long, FolderInfo>();
+ LongArrayMap<FolderInfo> currentFolders = new LongArrayMap<>();
+ LongArrayMap<FolderInfo> otherFolders = new LongArrayMap<>();
filterCurrentWorkspaceItems(currentScreenId, workspaceItems, currentWorkspaceItems,
otherWorkspaceItems);
@@ -2696,7 +2622,7 @@ public class LauncherModel extends BroadcastReceiver
}
}
};
- runOnMainThread(r, MAIN_THREAD_BINDING_RUNNABLE);
+ runOnMainThread(r);
bindWorkspaceScreens(oldCallbacks, orderedScreenIds);
@@ -2712,7 +2638,7 @@ public class LauncherModel extends BroadcastReceiver
}
}
};
- runOnMainThread(r, MAIN_THREAD_BINDING_RUNNABLE);
+ runOnMainThread(r);
}
// Load all the remaining pages (if we are loading synchronously, we want to defer this
@@ -2728,7 +2654,7 @@ public class LauncherModel extends BroadcastReceiver
public void run() {
Callbacks callbacks = tryGetCallbacks(oldCallbacks);
if (callbacks != null) {
- callbacks.finishBindingItems(isUpgradePath);
+ callbacks.finishBindingItems();
}
// If we're profiling, ensure this is the last thing in the queue.
@@ -2745,7 +2671,7 @@ public class LauncherModel extends BroadcastReceiver
mDeferredBindRunnables.add(r);
}
} else {
- runOnMainThread(r, MAIN_THREAD_BINDING_RUNNABLE);
+ runOnMainThread(r);
}
}
@@ -2759,6 +2685,12 @@ public class LauncherModel extends BroadcastReceiver
if (mStopped) {
return;
}
+ }
+ updateIconCache();
+ synchronized (LoaderTask.this) {
+ if (mStopped) {
+ return;
+ }
mAllAppsLoaded = true;
}
} else {
@@ -2766,6 +2698,27 @@ public class LauncherModel extends BroadcastReceiver
}
}
+ private void updateIconCache() {
+ // Ignore packages which have a promise icon.
+ HashSet<String> packagesToIgnore = new HashSet<>();
+ synchronized (sBgLock) {
+ for (ItemInfo info : sBgItemsIdMap) {
+ if (info instanceof ShortcutInfo) {
+ ShortcutInfo si = (ShortcutInfo) info;
+ if (si.isPromise() && si.getTargetComponent() != null) {
+ packagesToIgnore.add(si.getTargetComponent().getPackageName());
+ }
+ } else if (info instanceof LauncherAppWidgetInfo) {
+ LauncherAppWidgetInfo lawi = (LauncherAppWidgetInfo) info;
+ if (lawi.hasRestoreFlag(LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY)) {
+ packagesToIgnore.add(lawi.providerName.getPackageName());
+ }
+ }
+ }
+ }
+ mIconCache.updateDbIcons(packagesToIgnore);
+ }
+
private void onlyBindAllApps() {
final Callbacks oldCallbacks = mCallbacks.get();
if (oldCallbacks == null) {
@@ -2778,12 +2731,14 @@ public class LauncherModel extends BroadcastReceiver
@SuppressWarnings("unchecked")
final ArrayList<AppInfo> list
= (ArrayList<AppInfo>) mBgAllAppsList.data.clone();
+ final WidgetsModel widgetList = mBgWidgetsModel.clone();
Runnable r = new Runnable() {
public void run() {
final long t = SystemClock.uptimeMillis();
final Callbacks callbacks = tryGetCallbacks(oldCallbacks);
if (callbacks != null) {
callbacks.bindAllApplications(list);
+ callbacks.bindAllPackages(widgetList);
}
if (DEBUG_LOADERS) {
Log.d(TAG, "bound all " + list.size() + " apps from cache in "
@@ -2809,19 +2764,14 @@ public class LauncherModel extends BroadcastReceiver
return;
}
- final Intent mainIntent = new Intent(Intent.ACTION_MAIN, null);
- mainIntent.addCategory(Intent.CATEGORY_LAUNCHER);
-
final List<UserHandleCompat> profiles = mUserManager.getUserProfiles();
// Clear the list of apps
mBgAllAppsList.clear();
- SharedPreferences prefs = mContext.getSharedPreferences(
- LauncherAppState.getSharedPreferencesKey(), Context.MODE_PRIVATE);
for (UserHandleCompat user : profiles) {
// Query for the set of apps
final long qiaTime = DEBUG_LOADERS ? SystemClock.uptimeMillis() : 0;
- List<LauncherActivityInfoCompat> apps = mLauncherApps.getActivityList(null, user);
+ final List<LauncherActivityInfoCompat> apps = mLauncherApps.getActivityList(null, user);
if (DEBUG_LOADERS) {
Log.d(TAG, "getActivityList took "
+ (SystemClock.uptimeMillis()-qiaTime) + "ms for user " + user);
@@ -2832,39 +2782,23 @@ public class LauncherModel extends BroadcastReceiver
if (apps == null || apps.isEmpty()) {
return;
}
- // Sort the applications by name
- final long sortTime = DEBUG_LOADERS ? SystemClock.uptimeMillis() : 0;
- Collections.sort(apps,
- new LauncherModel.ShortcutNameComparator(mLabelCache));
- if (DEBUG_LOADERS) {
- Log.d(TAG, "sort took "
- + (SystemClock.uptimeMillis()-sortTime) + "ms");
- }
// Create the ApplicationInfos
for (int i = 0; i < apps.size(); i++) {
LauncherActivityInfoCompat app = apps.get(i);
// This builds the icon bitmaps.
- mBgAllAppsList.add(new AppInfo(mContext, app, user, mIconCache, mLabelCache));
+ mBgAllAppsList.add(new AppInfo(mContext, app, user, mIconCache));
}
- if (ADD_MANAGED_PROFILE_SHORTCUTS && !user.equals(UserHandleCompat.myUserHandle())) {
- // Add shortcuts for packages which were installed while launcher was dead.
- String shortcutsSetKey = INSTALLED_SHORTCUTS_SET_PREFIX
- + mUserManager.getSerialNumberForUser(user);
- Set<String> packagesAdded = prefs.getStringSet(shortcutsSetKey, Collections.EMPTY_SET);
- HashSet<String> newPackageSet = new HashSet<String>();
+ final ManagedProfileHeuristic heuristic = ManagedProfileHeuristic.get(mContext, user);
+ if (heuristic != null) {
+ runAfterBindCompletes(new Runnable() {
- for (LauncherActivityInfoCompat info : apps) {
- String packageName = info.getComponentName().getPackageName();
- if (!packagesAdded.contains(packageName)
- && !newPackageSet.contains(packageName)) {
- InstallShortcutReceiver.queueInstallShortcut(info, mContext);
+ @Override
+ public void run() {
+ heuristic.processUserApps(apps);
}
- newPackageSet.add(packageName);
- }
-
- prefs.edit().putStringSet(shortcutsSetKey, newPackageSet).commit();
+ });
}
}
// Huh? Shouldn't this be inside the Runnable below?
@@ -2874,6 +2808,7 @@ public class LauncherModel extends BroadcastReceiver
// Post callback on main thread
mHandler.post(new Runnable() {
public void run() {
+
final long bindTime = SystemClock.uptimeMillis();
final Callbacks callbacks = tryGetCallbacks(oldCallbacks);
if (callbacks != null) {
@@ -2887,7 +2822,11 @@ public class LauncherModel extends BroadcastReceiver
}
}
});
+ // Cleanup any data stored for a deleted user.
+ ManagedProfileHeuristic.processAllUsers(profiles, mContext);
+ loadAndBindWidgetsAndShortcuts(mApp.getContext(), tryGetCallbacks(oldCallbacks),
+ true /* refresh */);
if (DEBUG_LOADERS) {
Log.d(TAG, "Icons processed in "
+ (SystemClock.uptimeMillis() - loadTime) + "ms");
@@ -2897,7 +2836,6 @@ public class LauncherModel extends BroadcastReceiver
public void dumpState() {
synchronized (sBgLock) {
Log.d(TAG, "mLoaderTask.mContext=" + mContext);
- Log.d(TAG, "mLoaderTask.mIsLaunching=" + mIsLaunching);
Log.d(TAG, "mLoaderTask.mStopped=" + mStopped);
Log.d(TAG, "mLoaderTask.mLoadAndBindStepFinished=" + mLoadAndBindStepFinished);
Log.d(TAG, "mItems size=" + sBgWorkspaceItems.size());
@@ -2905,11 +2843,66 @@ public class LauncherModel extends BroadcastReceiver
}
}
+ /**
+ * Called when the icons for packages have been updated in the icon cache.
+ */
+ public void onPackageIconsUpdated(HashSet<String> updatedPackages, UserHandleCompat user) {
+ final Callbacks callbacks = getCallback();
+ final ArrayList<AppInfo> updatedApps = new ArrayList<>();
+ final ArrayList<ShortcutInfo> updatedShortcuts = new ArrayList<>();
+
+ // If any package icon has changed (app was updated while launcher was dead),
+ // update the corresponding shortcuts.
+ synchronized (sBgLock) {
+ for (ItemInfo info : sBgItemsIdMap) {
+ if (info instanceof ShortcutInfo && user.equals(info.user)
+ && info.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION) {
+ ShortcutInfo si = (ShortcutInfo) info;
+ ComponentName cn = si.getTargetComponent();
+ if (cn != null && updatedPackages.contains(cn.getPackageName())) {
+ si.updateIcon(mIconCache);
+ updatedShortcuts.add(si);
+ }
+ }
+ }
+ mBgAllAppsList.updateIconsAndLabels(updatedPackages, user, updatedApps);
+ }
+
+ if (!updatedShortcuts.isEmpty()) {
+ final UserHandleCompat userFinal = user;
+ mHandler.post(new Runnable() {
+
+ public void run() {
+ Callbacks cb = getCallback();
+ if (cb != null && callbacks == cb) {
+ cb.bindShortcutsChanged(updatedShortcuts,
+ new ArrayList<ShortcutInfo>(), userFinal);
+ }
+ }
+ });
+ }
+
+ if (!updatedApps.isEmpty()) {
+ mHandler.post(new Runnable() {
+
+ public void run() {
+ Callbacks cb = getCallback();
+ if (cb != null && callbacks == cb) {
+ cb.bindAppsUpdated(updatedApps);
+ }
+ }
+ });
+ }
+
+ // Reload widget list. No need to refresh, as we only want to update the icons and labels.
+ loadAndBindWidgetsAndShortcuts(mApp.getContext(), callbacks, false);
+ }
+
void enqueuePackageUpdated(PackageUpdatedTask task) {
sWorker.post(task);
}
- private class AppsAvailabilityCheck extends BroadcastReceiver {
+ @Thunk class AppsAvailabilityCheck extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
@@ -2969,73 +2962,52 @@ public class LauncherModel extends BroadcastReceiver
}
public void run() {
+ if (!mHasLoaderCompletedOnce) {
+ // Loader has not yet run.
+ return;
+ }
final Context context = mApp.getContext();
final String[] packages = mPackages;
final int N = packages.length;
switch (mOp) {
- case OP_ADD:
+ case OP_ADD: {
for (int i=0; i<N; i++) {
if (DEBUG_LOADERS) Log.d(TAG, "mAllAppsList.addPackage " + packages[i]);
- mIconCache.remove(packages[i], mUser);
+ mIconCache.updateIconsForPkg(packages[i], mUser);
mBgAllAppsList.addPackage(context, packages[i], mUser);
}
- // Auto add shortcuts for added packages.
- if (ADD_MANAGED_PROFILE_SHORTCUTS
- && !UserHandleCompat.myUserHandle().equals(mUser)) {
- SharedPreferences prefs = context.getSharedPreferences(
- LauncherAppState.getSharedPreferencesKey(), Context.MODE_PRIVATE);
- String shortcutsSetKey = INSTALLED_SHORTCUTS_SET_PREFIX
- + mUserManager.getSerialNumberForUser(mUser);
- Set<String> shortcutSet = new HashSet<String>(
- prefs.getStringSet(shortcutsSetKey,Collections.EMPTY_SET));
-
- for (int i=0; i<N; i++) {
- if (!shortcutSet.contains(packages[i])) {
- shortcutSet.add(packages[i]);
- List<LauncherActivityInfoCompat> activities =
- mLauncherApps.getActivityList(packages[i], mUser);
- if (activities != null && !activities.isEmpty()) {
- InstallShortcutReceiver.queueInstallShortcut(
- activities.get(0), context);
- }
- }
- }
-
- prefs.edit().putStringSet(shortcutsSetKey, shortcutSet).commit();
+ ManagedProfileHeuristic heuristic = ManagedProfileHeuristic.get(context, mUser);
+ if (heuristic != null) {
+ heuristic.processPackageAdd(mPackages);
}
break;
+ }
case OP_UPDATE:
for (int i=0; i<N; i++) {
if (DEBUG_LOADERS) Log.d(TAG, "mAllAppsList.updatePackage " + packages[i]);
+ mIconCache.updateIconsForPkg(packages[i], mUser);
mBgAllAppsList.updatePackage(context, packages[i], mUser);
- WidgetPreviewLoader.removePackageFromDb(
- mApp.getWidgetPreviewCacheDb(), packages[i]);
+ mApp.getWidgetCache().removePackage(packages[i], mUser);
}
break;
- case OP_REMOVE:
- // Remove the packageName for the set of auto-installed shortcuts. This
- // will ensure that the shortcut when the app is installed again.
- if (ADD_MANAGED_PROFILE_SHORTCUTS
- && !UserHandleCompat.myUserHandle().equals(mUser)) {
- SharedPreferences prefs = context.getSharedPreferences(
- LauncherAppState.getSharedPreferencesKey(), Context.MODE_PRIVATE);
- String shortcutsSetKey = INSTALLED_SHORTCUTS_SET_PREFIX
- + mUserManager.getSerialNumberForUser(mUser);
- HashSet<String> shortcutSet = new HashSet<String>(
- prefs.getStringSet(shortcutsSetKey, Collections.EMPTY_SET));
- shortcutSet.removeAll(Arrays.asList(mPackages));
- prefs.edit().putStringSet(shortcutsSetKey, shortcutSet).commit();
+ case OP_REMOVE: {
+ ManagedProfileHeuristic heuristic = ManagedProfileHeuristic.get(context, mUser);
+ if (heuristic != null) {
+ heuristic.processPackageRemoved(mPackages);
+ }
+ for (int i=0; i<N; i++) {
+ if (DEBUG_LOADERS) Log.d(TAG, "mAllAppsList.removePackage " + packages[i]);
+ mIconCache.removeIconsForPkg(packages[i], mUser);
}
// Fall through
+ }
case OP_UNAVAILABLE:
- boolean clearCache = mOp == OP_REMOVE;
for (int i=0; i<N; i++) {
if (DEBUG_LOADERS) Log.d(TAG, "mAllAppsList.removePackage " + packages[i]);
- mBgAllAppsList.removePackage(packages[i], mUser, clearCache);
- WidgetPreviewLoader.removePackageFromDb(
- mApp.getWidgetPreviewCacheDb(), packages[i]);
+ mBgAllAppsList.removePackage(packages[i], mUser);
+ mApp.getWidgetCache().removePackage(packages[i], mUser);
}
break;
}
@@ -3067,13 +3039,7 @@ public class LauncherModel extends BroadcastReceiver
new HashMap<ComponentName, AppInfo>();
if (added != null) {
- // Ensure that we add all the workspace applications to the db
- if (LauncherAppState.isDisableAllApps()) {
- final ArrayList<ItemInfo> addedInfos = new ArrayList<ItemInfo>(added);
- addAndBindAddedWorkspaceApps(context, addedInfos);
- } else {
- addAppsToAllApps(context, added);
- }
+ addAppsToAllApps(context, added);
for (AppInfo ai : added) {
addedOrUpdatedApps.put(ai.componentName, ai);
}
@@ -3103,7 +3069,7 @@ public class LauncherModel extends BroadcastReceiver
HashSet<String> packageSet = new HashSet<String>(Arrays.asList(packages));
synchronized (sBgLock) {
- for (ItemInfo info : sBgItemsIdMap.values()) {
+ for (ItemInfo info : sBgItemsIdMap) {
if (info instanceof ShortcutInfo && mUser.equals(info.user)) {
ShortcutInfo si = (ShortcutInfo) info;
boolean infoUpdated = false;
@@ -3112,8 +3078,9 @@ public class LauncherModel extends BroadcastReceiver
// Update shortcuts which use iconResource.
if ((si.iconResource != null)
&& packageSet.contains(si.iconResource.packageName)) {
- Bitmap icon = Utilities.createIconBitmap(si.iconResource.packageName,
- si.iconResource.resourceName, mIconCache, context);
+ Bitmap icon = Utilities.createIconBitmap(
+ si.iconResource.packageName,
+ si.iconResource.resourceName, context);
if (icon != null) {
si.setIcon(icon);
si.usingFallbackIcon = false;
@@ -3126,7 +3093,6 @@ public class LauncherModel extends BroadcastReceiver
AppInfo appInfo = addedOrUpdatedApps.get(cn);
if (si.isPromise()) {
- mIconCache.deletePreloadedIcon(cn, mUser);
if (si.hasStatusFlag(ShortcutInfo.FLAG_AUTOINTALL_ICON)) {
// Auto install icon
PackageManager pm = context.getPackageManager();
@@ -3152,12 +3118,13 @@ public class LauncherModel extends BroadcastReceiver
}
// Restore the shortcut.
+ if (appInfo != null) {
+ si.flags = appInfo.flags;
+ }
+
si.intent = si.promisedIntent;
si.promisedIntent = null;
- si.status &= ~ShortcutInfo.FLAG_RESTORED_ICON
- & ~ShortcutInfo.FLAG_AUTOINTALL_ICON
- & ~ShortcutInfo.FLAG_INSTALL_SESSION_ACTIVE;
-
+ si.status = ShortcutInfo.DEFAULT;
infoUpdated = true;
si.updateIcon(mIconCache);
}
@@ -3165,7 +3132,7 @@ public class LauncherModel extends BroadcastReceiver
if (appInfo != null && Intent.ACTION_MAIN.equals(si.intent.getAction())
&& si.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION) {
si.updateIcon(mIconCache);
- si.title = appInfo.title.toString();
+ si.title = Utilities.trim(appInfo.title);
si.contentDescription = appInfo.contentDescription;
infoUpdated = true;
}
@@ -3268,17 +3235,8 @@ public class LauncherModel extends BroadcastReceiver
});
}
- final ArrayList<Object> widgetsAndShortcuts =
- getSortedWidgetsAndShortcuts(context);
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- Callbacks cb = getCallback();
- if (callbacks == cb && cb != null) {
- callbacks.bindPackagesUpdated(widgetsAndShortcuts);
- }
- }
- });
+ // onProvidersChanged method (API >= 17) already refreshed the widget list
+ loadAndBindWidgetsAndShortcuts(context, callbacks, Build.VERSION.SDK_INT < 17);
// Write all the logs to disk
mHandler.post(new Runnable() {
@@ -3292,19 +3250,106 @@ public class LauncherModel extends BroadcastReceiver
}
}
- // Returns a list of ResolveInfos/AppWindowInfos in sorted order
- public static ArrayList<Object> getSortedWidgetsAndShortcuts(Context context) {
+ public static List<LauncherAppWidgetProviderInfo> getWidgetProviders(Context context,
+ boolean refresh) {
+ ArrayList<LauncherAppWidgetProviderInfo> results =
+ new ArrayList<LauncherAppWidgetProviderInfo>();
+ try {
+ synchronized (sBgLock) {
+ if (sBgWidgetProviders == null || refresh) {
+ HashMap<ComponentKey, LauncherAppWidgetProviderInfo> tmpWidgetProviders
+ = new HashMap<>();
+ AppWidgetManagerCompat wm = AppWidgetManagerCompat.getInstance(context);
+ LauncherAppWidgetProviderInfo info;
+
+ List<AppWidgetProviderInfo> widgets = wm.getAllProviders();
+ for (AppWidgetProviderInfo pInfo : widgets) {
+ info = LauncherAppWidgetProviderInfo.fromProviderInfo(context, pInfo);
+ UserHandleCompat user = wm.getUser(info);
+ tmpWidgetProviders.put(new ComponentKey(info.provider, user), info);
+ }
+
+ Collection<CustomAppWidget> customWidgets = Launcher.getCustomAppWidgets().values();
+ for (CustomAppWidget widget : customWidgets) {
+ info = new LauncherAppWidgetProviderInfo(context, widget);
+ UserHandleCompat user = wm.getUser(info);
+ tmpWidgetProviders.put(new ComponentKey(info.provider, user), info);
+ }
+ // Replace the global list at the very end, so that if there is an exception,
+ // previously loaded provider list is used.
+ sBgWidgetProviders = tmpWidgetProviders;
+ }
+ results.addAll(sBgWidgetProviders.values());
+ return results;
+ }
+ } catch (Exception e) {
+ if (e.getCause() instanceof TransactionTooLargeException) {
+ // the returned value may be incomplete and will not be refreshed until the next
+ // time Launcher starts.
+ // TODO: after figuring out a repro step, introduce a dirty bit to check when
+ // onResume is called to refresh the widget provider list.
+ synchronized (sBgLock) {
+ if (sBgWidgetProviders != null) {
+ results.addAll(sBgWidgetProviders.values());
+ }
+ return results;
+ }
+ } else {
+ throw e;
+ }
+ }
+ }
+
+ public static LauncherAppWidgetProviderInfo getProviderInfo(Context ctx, ComponentName name,
+ UserHandleCompat user) {
+ synchronized (sBgLock) {
+ if (sBgWidgetProviders == null) {
+ getWidgetProviders(ctx, false /* refresh */);
+ }
+ return sBgWidgetProviders.get(new ComponentKey(name, user));
+ }
+ }
+
+ public void loadAndBindWidgetsAndShortcuts(final Context context, final Callbacks callbacks,
+ final boolean refresh) {
+
+ runOnWorkerThread(new Runnable() {
+ @Override
+ public void run() {
+ updateWidgetsModel(context, refresh);
+ final WidgetsModel model = mBgWidgetsModel.clone();
+
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ Callbacks cb = getCallback();
+ if (callbacks == cb && cb != null) {
+ callbacks.bindAllPackages(model);
+ }
+ }
+ });
+ // update the Widget entries inside DB on the worker thread.
+ LauncherAppState.getInstance().getWidgetCache().removeObsoletePreviews(
+ model.getRawList());
+ }
+ });
+ }
+
+ /**
+ * Returns a list of ResolveInfos/AppWidgetInfos.
+ *
+ * @see #loadAndBindWidgetsAndShortcuts
+ */
+ @Thunk void updateWidgetsModel(Context context, boolean refresh) {
PackageManager packageManager = context.getPackageManager();
final ArrayList<Object> widgetsAndShortcuts = new ArrayList<Object>();
- widgetsAndShortcuts.addAll(AppWidgetManagerCompat.getInstance(context).getAllProviders());
-
+ widgetsAndShortcuts.addAll(getWidgetProviders(context, refresh));
Intent shortcutsIntent = new Intent(Intent.ACTION_CREATE_SHORTCUT);
widgetsAndShortcuts.addAll(packageManager.queryIntentActivities(shortcutsIntent, 0));
- Collections.sort(widgetsAndShortcuts, new WidgetAndShortcutNameComparator(context));
- return widgetsAndShortcuts;
+ mBgWidgetsModel.setWidgetsAndShortcuts(widgetsAndShortcuts);
}
- private static boolean isPackageDisabled(Context context, String packageName,
+ @Thunk static boolean isPackageDisabled(Context context, String packageName,
UserHandleCompat user) {
final LauncherAppsCompat launcherApps = LauncherAppsCompat.getInstance(context);
return !launcherApps.isPackageEnabledForProfile(packageName, user);
@@ -3335,31 +3380,36 @@ public class LauncherModel extends BroadcastReceiver
* Make an ShortcutInfo object for a restored application or shortcut item that points
* to a package that is not yet installed on the system.
*/
- public ShortcutInfo getRestoredItemInfo(Cursor cursor, int titleIndex, Intent intent,
- int promiseType) {
+ public ShortcutInfo getRestoredItemInfo(Cursor c, int titleIndex, Intent intent,
+ int promiseType, int itemType, CursorIconInfo iconInfo, Context context) {
final ShortcutInfo info = new ShortcutInfo();
info.user = UserHandleCompat.myUserHandle();
- mIconCache.getTitleAndIcon(info, intent, info.user, true);
+
+ Bitmap icon = iconInfo.loadIcon(c, info, context);
+ // the fallback icon
+ if (icon == null) {
+ mIconCache.getTitleAndIcon(info, intent, info.user, false /* useLowResIcon */);
+ } else {
+ info.setIcon(icon);
+ }
if ((promiseType & ShortcutInfo.FLAG_RESTORED_ICON) != 0) {
- String title = (cursor != null) ? cursor.getString(titleIndex) : null;
+ String title = (c != null) ? c.getString(titleIndex) : null;
if (!TextUtils.isEmpty(title)) {
- info.title = title;
+ info.title = Utilities.trim(title);
}
- info.status = ShortcutInfo.FLAG_RESTORED_ICON;
} else if ((promiseType & ShortcutInfo.FLAG_AUTOINTALL_ICON) != 0) {
if (TextUtils.isEmpty(info.title)) {
- info.title = (cursor != null) ? cursor.getString(titleIndex) : "";
+ info.title = (c != null) ? Utilities.trim(c.getString(titleIndex)) : "";
}
- info.status = ShortcutInfo.FLAG_AUTOINTALL_ICON;
} else {
throw new InvalidParameterException("Invalid restoreType " + promiseType);
}
- info.contentDescription = mUserManager.getBadgedLabelForUser(
- info.title.toString(), info.user);
- info.itemType = LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT;
+ info.contentDescription = mUserManager.getBadgedLabelForUser(info.title, info.user);
+ info.itemType = itemType;
info.promisedIntent = intent;
+ info.status = promiseType;
return info;
}
@@ -3367,7 +3417,7 @@ public class LauncherModel extends BroadcastReceiver
* Make an Intent object for a restored application or shortcut item that points
* to the market page for the item.
*/
- private Intent getRestoredItemIntent(Cursor c, Context context, Intent intent) {
+ @Thunk Intent getRestoredItemIntent(Cursor c, Context context, Intent intent) {
ComponentName componentName = intent.getComponent();
return getMarketIntent(componentName.getPackageName());
}
@@ -3382,22 +3432,13 @@ public class LauncherModel extends BroadcastReceiver
}
/**
- * This is called from the code that adds shortcuts from the intent receiver. This
- * doesn't have a Cursor, but
- */
- public ShortcutInfo getShortcutInfo(PackageManager manager, Intent intent,
- UserHandleCompat user, Context context) {
- return getShortcutInfo(manager, intent, user, context, null, -1, -1, null, false);
- }
-
- /**
* Make an ShortcutInfo object for a shortcut that is an application.
*
* If c is not null, then it will be used to fill in missing data like the title and icon.
*/
- public ShortcutInfo getShortcutInfo(PackageManager manager, Intent intent,
+ public ShortcutInfo getAppShortcutInfo(PackageManager manager, Intent intent,
UserHandleCompat user, Context context, Cursor c, int iconIndex, int titleIndex,
- HashMap<Object, CharSequence> labelCache, boolean allowMissingTarget) {
+ boolean allowMissingTarget, boolean useLowResIcon) {
if (user == null) {
Log.d(TAG, "Null user found in getShortcutInfo");
return null;
@@ -3419,56 +3460,32 @@ public class LauncherModel extends BroadcastReceiver
}
final ShortcutInfo info = new ShortcutInfo();
-
- // the resource -- This may implicitly give us back the fallback icon,
- // but don't worry about that. All we're doing with usingFallbackIcon is
- // to avoid saving lots of copies of that in the database, and most apps
- // have icons anyway.
- Bitmap icon = mIconCache.getIcon(componentName, lai, labelCache);
-
- // the db
- if (icon == null) {
- if (c != null) {
- icon = getIconFromCursor(c, iconIndex, context);
- }
+ mIconCache.getTitleAndIcon(info, componentName, lai, user, false, useLowResIcon);
+ if (mIconCache.isDefaultIcon(info.getIcon(mIconCache), user) && c != null) {
+ Bitmap icon = Utilities.createIconBitmap(c, iconIndex, context);
+ info.setIcon(icon == null ? mIconCache.getDefaultIcon(user) : icon);
}
- // the fallback icon
- if (icon == null) {
- icon = mIconCache.getDefaultIcon(user);
- info.usingFallbackIcon = true;
- }
- info.setIcon(icon);
- // From the cache.
- if (labelCache != null) {
- info.title = labelCache.get(componentName);
- }
-
- // from the resource
- if (info.title == null && lai != null) {
- info.title = lai.getLabel();
- if (labelCache != null) {
- labelCache.put(componentName, info.title);
- }
- }
// from the db
- if (info.title == null) {
- if (c != null) {
- info.title = c.getString(titleIndex);
- }
+ if (TextUtils.isEmpty(info.title) && c != null) {
+ info.title = Utilities.trim(c.getString(titleIndex));
}
+
// fall back to the class name of the activity
if (info.title == null) {
info.title = componentName.getClassName();
}
+
info.itemType = LauncherSettings.Favorites.ITEM_TYPE_APPLICATION;
info.user = user;
- info.contentDescription = mUserManager.getBadgedLabelForUser(
- info.title.toString(), info.user);
+ info.contentDescription = mUserManager.getBadgedLabelForUser(info.title, info.user);
+ if (lai != null) {
+ info.flags = AppInfo.initFlags(lai);
+ }
return info;
}
- static ArrayList<ItemInfo> filterItemInfos(Collection<ItemInfo> infos,
+ static ArrayList<ItemInfo> filterItemInfos(Iterable<ItemInfo> infos,
ItemInfoFilter f) {
HashSet<ItemInfo> filtered = new HashSet<ItemInfo>();
for (ItemInfo i : infos) {
@@ -3497,7 +3514,7 @@ public class LauncherModel extends BroadcastReceiver
return new ArrayList<ItemInfo>(filtered);
}
- private ArrayList<ItemInfo> getItemInfoForComponentName(final ComponentName cname,
+ @Thunk ArrayList<ItemInfo> getItemInfoForComponentName(final ComponentName cname,
final UserHandleCompat user) {
ItemInfoFilter filter = new ItemInfoFilter() {
@Override
@@ -3509,17 +3526,14 @@ public class LauncherModel extends BroadcastReceiver
}
}
};
- return filterItemInfos(sBgItemsIdMap.values(), filter);
+ return filterItemInfos(sBgItemsIdMap, filter);
}
/**
* Make an ShortcutInfo object for a shortcut that isn't an application.
*/
- private ShortcutInfo getShortcutInfo(Cursor c, Context context,
- int iconTypeIndex, int iconPackageIndex, int iconResourceIndex, int iconIndex,
- int titleIndex) {
-
- Bitmap icon = null;
+ @Thunk ShortcutInfo getShortcutInfo(Cursor c, Context context,
+ int titleIndex, CursorIconInfo iconInfo) {
final ShortcutInfo info = new ShortcutInfo();
// Non-app shortcuts are only supported for current user.
info.user = UserHandleCompat.myUserHandle();
@@ -3527,77 +3541,18 @@ public class LauncherModel extends BroadcastReceiver
// TODO: If there's an explicit component and we can't install that, delete it.
- info.title = c.getString(titleIndex);
-
- int iconType = c.getInt(iconTypeIndex);
- switch (iconType) {
- case LauncherSettings.Favorites.ICON_TYPE_RESOURCE:
- String packageName = c.getString(iconPackageIndex);
- String resourceName = c.getString(iconResourceIndex);
- info.customIcon = false;
- // the resource
- icon = Utilities.createIconBitmap(packageName, resourceName, mIconCache, context);
- // the db
- if (icon == null) {
- icon = getIconFromCursor(c, iconIndex, context);
- }
- // the fallback icon
- if (icon == null) {
- icon = mIconCache.getDefaultIcon(info.user);
- info.usingFallbackIcon = true;
- }
- break;
- case LauncherSettings.Favorites.ICON_TYPE_BITMAP:
- icon = getIconFromCursor(c, iconIndex, context);
- if (icon == null) {
- icon = mIconCache.getDefaultIcon(info.user);
- info.customIcon = false;
- info.usingFallbackIcon = true;
- } else {
- info.customIcon = true;
- }
- break;
- default:
+ info.title = Utilities.trim(c.getString(titleIndex));
+
+ Bitmap icon = iconInfo.loadIcon(c, info, context);
+ // the fallback icon
+ if (icon == null) {
icon = mIconCache.getDefaultIcon(info.user);
info.usingFallbackIcon = true;
- info.customIcon = false;
- break;
}
info.setIcon(icon);
return info;
}
- Bitmap getIconFromCursor(Cursor c, int iconIndex, Context context) {
- @SuppressWarnings("all") // suppress dead code warning
- final boolean debug = false;
- if (debug) {
- Log.d(TAG, "getIconFromCursor app="
- + c.getString(c.getColumnIndexOrThrow(LauncherSettings.Favorites.TITLE)));
- }
- byte[] data = c.getBlob(iconIndex);
- try {
- return Utilities.createIconBitmap(
- BitmapFactory.decodeByteArray(data, 0, data.length), context);
- } catch (Exception e) {
- return null;
- }
- }
-
- /**
- * Attempts to find an AppWidgetProviderInfo that matches the given component.
- */
- static AppWidgetProviderInfo findAppWidgetProviderInfoWithComponent(Context context,
- ComponentName component) {
- List<AppWidgetProviderInfo> widgets =
- AppWidgetManager.getInstance(context).getInstalledProviders();
- for (AppWidgetProviderInfo info : widgets) {
- if (info.provider.equals(component)) {
- return info;
- }
- }
- return null;
- }
-
ShortcutInfo infoFromShortcutIntent(Context context, Intent data) {
Intent intent = data.getParcelableExtra(Intent.EXTRA_SHORTCUT_INTENT);
String name = data.getStringExtra(Intent.EXTRA_SHORTCUT_NAME);
@@ -3621,7 +3576,7 @@ public class LauncherModel extends BroadcastReceiver
if (extra instanceof ShortcutIconResource) {
iconResource = (ShortcutIconResource) extra;
icon = Utilities.createIconBitmap(iconResource.packageName,
- iconResource.resourceName, mIconCache, context);
+ iconResource.resourceName, context);
}
}
@@ -3636,9 +3591,8 @@ public class LauncherModel extends BroadcastReceiver
}
info.setIcon(icon);
- info.title = name;
- info.contentDescription = mUserManager.getBadgedLabelForUser(
- info.title.toString(), info.user);
+ info.title = Utilities.trim(name);
+ info.contentDescription = mUserManager.getBadgedLabelForUser(info.title, info.user);
info.intent = intent;
info.customIcon = customIcon;
info.iconResource = iconResource;
@@ -3646,50 +3600,11 @@ public class LauncherModel extends BroadcastReceiver
return info;
}
- boolean queueIconToBeChecked(HashMap<Object, byte[]> cache, ShortcutInfo info, Cursor c,
- int iconIndex) {
- // If apps can't be on SD, don't even bother.
- if (!mAppsCanBeOnRemoveableStorage) {
- return false;
- }
- // If this icon doesn't have a custom icon, check to see
- // what's stored in the DB, and if it doesn't match what
- // we're going to show, store what we are going to show back
- // into the DB. We do this so when we're loading, if the
- // package manager can't find an icon (for example because
- // the app is on SD) then we can use that instead.
- if (!info.customIcon && !info.usingFallbackIcon) {
- cache.put(info, c.getBlob(iconIndex));
- return true;
- }
- return false;
- }
- void updateSavedIcon(Context context, ShortcutInfo info, byte[] data) {
- boolean needSave = false;
- try {
- if (data != null) {
- Bitmap saved = BitmapFactory.decodeByteArray(data, 0, data.length);
- Bitmap loaded = info.getIcon(mIconCache);
- needSave = !saved.sameAs(loaded);
- } else {
- needSave = true;
- }
- } catch (Exception e) {
- needSave = true;
- }
- if (needSave) {
- Log.d(TAG, "going to save icon bitmap for info=" + info);
- // This is slower than is ideal, but this only happens once
- // or when the app is updated with a new icon.
- updateItemInDatabase(context, info);
- }
- }
-
/**
* Return an existing FolderInfo object if we have encountered this ID previously,
* or make a new one.
*/
- private static FolderInfo findOrMakeFolder(HashMap<Long, FolderInfo> folders, long id) {
+ @Thunk static FolderInfo findOrMakeFolder(LongArrayMap<FolderInfo> folders, long id) {
// See if a placeholder was created for us already
FolderInfo folderInfo = folders.get(id);
if (folderInfo == null) {
@@ -3700,105 +3615,6 @@ public class LauncherModel extends BroadcastReceiver
return folderInfo;
}
- public static final Comparator<AppInfo> getAppNameComparator() {
- final Collator collator = Collator.getInstance();
- return new Comparator<AppInfo>() {
- public final int compare(AppInfo a, AppInfo b) {
- if (a.user.equals(b.user)) {
- int result = collator.compare(a.title.toString().trim(),
- b.title.toString().trim());
- if (result == 0) {
- result = a.componentName.compareTo(b.componentName);
- }
- return result;
- } else {
- // TODO Need to figure out rules for sorting
- // profiles, this puts work second.
- return a.user.toString().compareTo(b.user.toString());
- }
- }
- };
- }
- public static final Comparator<AppInfo> APP_INSTALL_TIME_COMPARATOR
- = new Comparator<AppInfo>() {
- public final int compare(AppInfo a, AppInfo b) {
- if (a.firstInstallTime < b.firstInstallTime) return 1;
- if (a.firstInstallTime > b.firstInstallTime) return -1;
- return 0;
- }
- };
- static ComponentName getComponentNameFromResolveInfo(ResolveInfo info) {
- if (info.activityInfo != null) {
- return new ComponentName(info.activityInfo.packageName, info.activityInfo.name);
- } else {
- return new ComponentName(info.serviceInfo.packageName, info.serviceInfo.name);
- }
- }
- public static class ShortcutNameComparator implements Comparator<LauncherActivityInfoCompat> {
- private Collator mCollator;
- private HashMap<Object, CharSequence> mLabelCache;
- ShortcutNameComparator(PackageManager pm) {
- mLabelCache = new HashMap<Object, CharSequence>();
- mCollator = Collator.getInstance();
- }
- ShortcutNameComparator(HashMap<Object, CharSequence> labelCache) {
- mLabelCache = labelCache;
- mCollator = Collator.getInstance();
- }
- public final int compare(LauncherActivityInfoCompat a, LauncherActivityInfoCompat b) {
- String labelA, labelB;
- ComponentName keyA = a.getComponentName();
- ComponentName keyB = b.getComponentName();
- if (mLabelCache.containsKey(keyA)) {
- labelA = mLabelCache.get(keyA).toString();
- } else {
- labelA = a.getLabel().toString().trim();
-
- mLabelCache.put(keyA, labelA);
- }
- if (mLabelCache.containsKey(keyB)) {
- labelB = mLabelCache.get(keyB).toString();
- } else {
- labelB = b.getLabel().toString().trim();
-
- mLabelCache.put(keyB, labelB);
- }
- return mCollator.compare(labelA, labelB);
- }
- };
- public static class WidgetAndShortcutNameComparator implements Comparator<Object> {
- private final AppWidgetManagerCompat mManager;
- private final PackageManager mPackageManager;
- private final HashMap<Object, String> mLabelCache;
- private final Collator mCollator;
-
- WidgetAndShortcutNameComparator(Context context) {
- mManager = AppWidgetManagerCompat.getInstance(context);
- mPackageManager = context.getPackageManager();
- mLabelCache = new HashMap<Object, String>();
- mCollator = Collator.getInstance();
- }
- public final int compare(Object a, Object b) {
- String labelA, labelB;
- if (mLabelCache.containsKey(a)) {
- labelA = mLabelCache.get(a);
- } else {
- labelA = (a instanceof AppWidgetProviderInfo)
- ? mManager.loadLabel((AppWidgetProviderInfo) a)
- : ((ResolveInfo) a).loadLabel(mPackageManager).toString().trim();
- mLabelCache.put(a, labelA);
- }
- if (mLabelCache.containsKey(b)) {
- labelB = mLabelCache.get(b);
- } else {
- labelB = (b instanceof AppWidgetProviderInfo)
- ? mManager.loadLabel((AppWidgetProviderInfo) b)
- : ((ResolveInfo) b).loadLabel(mPackageManager).toString().trim();
- mLabelCache.put(b, labelB);
- }
- return mCollator.compare(labelA, labelB);
- }
- };
static boolean isValidProvider(AppWidgetProviderInfo provider) {
return (provider != null) && (provider.provider != null)
@@ -3821,4 +3637,20 @@ public class LauncherModel extends BroadcastReceiver
public Callbacks getCallback() {
return mCallbacks != null ? mCallbacks.get() : null;
}
+
+ /**
+ * @return {@link FolderInfo} if its already loaded.
+ */
+ public FolderInfo findFolderById(Long folderId) {
+ synchronized (sBgLock) {
+ return sBgFolders.get(folderId);
+ }
+ }
+
+ /**
+ * @return the looper for the worker thread which can be used to start background tasks.
+ */
+ public static Looper getWorkerLooper() {
+ return sWorkerThread.getLooper();
+ }
}
diff --git a/src/com/android/launcher3/LauncherProvider.java b/src/com/android/launcher3/LauncherProvider.java
index 1715b02bf..cc5e18bc1 100644
--- a/src/com/android/launcher3/LauncherProvider.java
+++ b/src/com/android/launcher3/LauncherProvider.java
@@ -16,9 +16,9 @@
package com.android.launcher3;
+import android.annotation.TargetApi;
import android.appwidget.AppWidgetHost;
import android.appwidget.AppWidgetManager;
-import android.appwidget.AppWidgetProviderInfo;
import android.content.ComponentName;
import android.content.ContentProvider;
import android.content.ContentProviderOperation;
@@ -30,6 +30,7 @@ import android.content.Context;
import android.content.Intent;
import android.content.OperationApplicationException;
import android.content.SharedPreferences;
+import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.Resources;
import android.database.Cursor;
import android.database.SQLException;
@@ -37,10 +38,13 @@ import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.database.sqlite.SQLiteQueryBuilder;
import android.database.sqlite.SQLiteStatement;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
import android.net.Uri;
-import android.provider.Settings;
+import android.os.Binder;
+import android.os.Build;
+import android.os.Bundle;
+import android.os.Process;
+import android.os.StrictMode;
+import android.os.UserManager;
import android.text.TextUtils;
import android.util.Log;
import android.util.SparseArray;
@@ -50,52 +54,42 @@ import com.android.launcher3.LauncherSettings.Favorites;
import com.android.launcher3.compat.UserHandleCompat;
import com.android.launcher3.compat.UserManagerCompat;
import com.android.launcher3.config.ProviderConfig;
+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;
import java.util.HashSet;
+import java.util.List;
public class LauncherProvider extends ContentProvider {
private static final String TAG = "Launcher.LauncherProvider";
private static final boolean LOGD = false;
- private static final int DATABASE_VERSION = 20;
+ private static final int DATABASE_VERSION = 26;
static final String OLD_AUTHORITY = "com.android.launcher2.settings";
static final String AUTHORITY = ProviderConfig.AUTHORITY;
- // Should we attempt to load anything from the com.android.launcher2 provider?
- static final boolean IMPORT_LAUNCHER2_DATABASE = false;
-
- static final String TABLE_FAVORITES = "favorites";
- static final String TABLE_WORKSPACE_SCREENS = "workspaceScreens";
- static final String PARAMETER_NOTIFY = "notify";
- static final String UPGRADED_FROM_OLD_DATABASE =
- "UPGRADED_FROM_OLD_DATABASE";
- static final String EMPTY_DATABASE_CREATED =
- "EMPTY_DATABASE_CREATED";
+ static final String TABLE_FAVORITES = LauncherSettings.Favorites.TABLE_NAME;
+ static final String TABLE_WORKSPACE_SCREENS = LauncherSettings.WorkspaceScreens.TABLE_NAME;
+ static final String EMPTY_DATABASE_CREATED = "EMPTY_DATABASE_CREATED";
private static final String URI_PARAM_IS_EXTERNAL_ADD = "isExternalAdd";
- private LauncherProviderChangeListener mListener;
+ private static final String RESTRICTION_PACKAGE_NAME = "workspace.configuration.package.name";
- /**
- * {@link Uri} triggered at any registered {@link android.database.ContentObserver} when
- * {@link AppWidgetHost#deleteHost()} is called during database creation.
- * Use this to recall {@link AppWidgetHost#startListening()} if needed.
- */
- static final Uri CONTENT_APPWIDGET_RESET_URI =
- Uri.parse("content://" + AUTHORITY + "/appWidgetReset");
-
- private DatabaseHelper mOpenHelper;
- private static boolean sJustLoadedFromOldDb;
+ @Thunk LauncherProviderChangeListener mListener;
+ @Thunk DatabaseHelper mOpenHelper;
@Override
public boolean onCreate() {
final Context context = getContext();
+ StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskWrites();
mOpenHelper = new DatabaseHelper(context);
+ StrictMode.setThreadPolicy(oldPolicy);
LauncherAppState.setLauncherProvider(this);
return true;
}
@@ -106,6 +100,7 @@ public class LauncherProvider extends ContentProvider {
public void setLauncherProviderChangeListener(LauncherProviderChangeListener listener) {
mListener = listener;
+ mOpenHelper.mListener = mListener;
}
@Override
@@ -133,7 +128,7 @@ public class LauncherProvider extends ContentProvider {
return result;
}
- private static long dbInsertAndCheck(DatabaseHelper helper,
+ @Thunk static long dbInsertAndCheck(DatabaseHelper helper,
SQLiteDatabase db, String table, String nullColumnHack, ContentValues values) {
if (values == null) {
throw new RuntimeException("Error: attempting to insert null values");
@@ -151,7 +146,8 @@ public class LauncherProvider extends ContentProvider {
// In very limited cases, we support system|signature permission apps to add to the db
String externalAdd = uri.getQueryParameter(URI_PARAM_IS_EXTERNAL_ADD);
- if (externalAdd != null && "true".equals(externalAdd)) {
+ final boolean isExternalAll = externalAdd != null && "true".equals(externalAdd);
+ if (isExternalAll) {
if (!mOpenHelper.initializeExternalAdd(initialValues)) {
return null;
}
@@ -160,10 +156,17 @@ public class LauncherProvider extends ContentProvider {
SQLiteDatabase db = mOpenHelper.getWritableDatabase();
addModifiedTime(initialValues);
final long rowId = dbInsertAndCheck(mOpenHelper, db, args.table, null, initialValues);
- if (rowId <= 0) return null;
+ if (rowId < 0) return null;
uri = ContentUris.withAppendedId(uri, rowId);
- sendNotify(uri);
+ notifyListeners();
+
+ if (isExternalAll) {
+ LauncherAppState app = LauncherAppState.getInstanceNoCreate();
+ if (app != null) {
+ app.reloadWorkspace();
+ }
+ }
return uri;
}
@@ -188,7 +191,7 @@ public class LauncherProvider extends ContentProvider {
db.endTransaction();
}
- sendNotify(uri);
+ notifyListeners();
return values.length;
}
@@ -212,7 +215,7 @@ public class LauncherProvider extends ContentProvider {
SQLiteDatabase db = mOpenHelper.getWritableDatabase();
int count = db.delete(args.table, args.where, args.args);
- if (count > 0) sendNotify(uri);
+ if (count > 0) notifyListeners();
return count;
}
@@ -224,17 +227,80 @@ public class LauncherProvider extends ContentProvider {
addModifiedTime(values);
SQLiteDatabase db = mOpenHelper.getWritableDatabase();
int count = db.update(args.table, values, args.where, args.args);
- if (count > 0) sendNotify(uri);
+ if (count > 0) notifyListeners();
return count;
}
- private void sendNotify(Uri uri) {
- String notify = uri.getQueryParameter(PARAMETER_NOTIFY);
- if (notify == null || "true".equals(notify)) {
- getContext().getContentResolver().notifyChange(uri, null);
+ @Override
+ public Bundle call(String method, String arg, Bundle extras) {
+ if (Binder.getCallingUid() != Process.myUid()) {
+ return null;
+ }
+
+ switch (method) {
+ 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)));
+ 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();
+ if (mListener != null) {
+ mListener.onSettingsChanged(arg, value);
+ }
+ Bundle result = new Bundle();
+ result.putBoolean(LauncherSettings.Settings.EXTRA_VALUE, value);
+ return result;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Deletes any empty folder from the DB.
+ * @return Ids of deleted folders.
+ */
+ public List<Long> deleteEmptyFolders() {
+ ArrayList<Long> folderIds = new ArrayList<Long>();
+ SQLiteDatabase db = mOpenHelper.getWritableDatabase();
+ db.beginTransaction();
+ try {
+ // Select folders whose id do not match any container value.
+ String selection = LauncherSettings.Favorites.ITEM_TYPE + " = "
+ + LauncherSettings.Favorites.ITEM_TYPE_FOLDER + " AND "
+ + LauncherSettings.Favorites._ID + " NOT IN (SELECT " +
+ LauncherSettings.Favorites.CONTAINER + " FROM "
+ + TABLE_FAVORITES + ")";
+ Cursor c = db.query(TABLE_FAVORITES,
+ new String[] {LauncherSettings.Favorites._ID},
+ selection, null, null, null, null);
+ while (c.moveToNext()) {
+ folderIds.add(c.getLong(0));
+ }
+ c.close();
+ if (folderIds.size() > 0) {
+ db.delete(TABLE_FAVORITES, Utilities.createDbSelectionQuery(
+ LauncherSettings.Favorites._ID, folderIds), null);
+ }
+ db.setTransactionSuccessful();
+ } catch (SQLException ex) {
+ Log.e(TAG, ex.getMessage(), ex);
+ folderIds.clear();
+ } finally {
+ db.endTransaction();
}
+ return folderIds;
+ }
+ private void notifyListeners() {
// always notify the backup agent
LauncherBackupAgentHelper.dataChanged(getContext());
if (mListener != null) {
@@ -242,7 +308,7 @@ public class LauncherProvider extends ContentProvider {
}
}
- private void addModifiedTime(ContentValues values) {
+ @Thunk static void addModifiedTime(ContentValues values) {
values.put(LauncherSettings.ChangeLogColumns.MODIFIED, System.currentTimeMillis());
}
@@ -258,32 +324,6 @@ public class LauncherProvider extends ContentProvider {
return mOpenHelper.generateNewScreenId();
}
- // This is only required one time while loading the workspace during the
- // upgrade path, and should never be called from anywhere else.
- public void updateMaxScreenId(long maxScreenId) {
- mOpenHelper.updateMaxScreenId(maxScreenId);
- }
-
- /**
- * @param Should we load the old db for upgrade? first run only.
- */
- synchronized public boolean justLoadedOldDb() {
- String spKey = LauncherAppState.getSharedPreferencesKey();
- SharedPreferences sp = getContext().getSharedPreferences(spKey, Context.MODE_PRIVATE);
-
- boolean loadedOldDb = false || sJustLoadedFromOldDb;
-
- sJustLoadedFromOldDb = false;
- if (sp.getBoolean(UPGRADED_FROM_OLD_DATABASE, false)) {
-
- SharedPreferences.Editor editor = sp.edit();
- editor.remove(UPGRADED_FROM_OLD_DATABASE);
- editor.commit();
- loadedOldDb = true;
- }
- return loadedOldDb;
- }
-
/**
* Clears all the data for a fresh start.
*/
@@ -301,9 +341,10 @@ public class LauncherProvider extends ContentProvider {
/**
* Loads the default workspace based on the following priority scheme:
- * 1) From a package provided by play store
- * 2) From a partner configuration APK, already in the system image
- * 3) The default configuration for the particular device
+ * 1) From the app restrictions
+ * 2) From a package provided by play store
+ * 3) From a partner configuration APK, already in the system image
+ * 4) The default configuration for the particular device
*/
synchronized public void loadDefaultFavoritesIfNecessary() {
String spKey = LauncherAppState.getSharedPreferencesKey();
@@ -312,9 +353,11 @@ public class LauncherProvider extends ContentProvider {
if (sp.getBoolean(EMPTY_DATABASE_CREATED, false)) {
Log.d(TAG, "loading default workspace");
- AutoInstallsLayout loader = AutoInstallsLayout.get(getContext(),
- mOpenHelper.mAppWidgetHost, mOpenHelper);
-
+ AutoInstallsLayout loader = createWorkspaceLoaderFromAppRestriction();
+ if (loader == null) {
+ loader = AutoInstallsLayout.get(getContext(),
+ mOpenHelper.mAppWidgetHost, mOpenHelper);
+ }
if (loader == null) {
final Partner partner = Partner.get(getContext().getPackageManager());
if (partner != null && partner.hasDefaultLayout()) {
@@ -332,6 +375,10 @@ public class LauncherProvider extends ContentProvider {
if (loader == null) {
loader = getDefaultLayoutParser();
}
+
+ // There might be some partially restored DB items, due to buggy restore logic in
+ // previous versions of launcher.
+ createEmptyDB();
// Populate favorites table with initial favorites
if ((mOpenHelper.loadFavorites(mOpenHelper.getWritableDatabase(), loader) <= 0)
&& usingExternallyProvidedLayout) {
@@ -344,9 +391,43 @@ public class LauncherProvider extends ContentProvider {
}
}
+ /**
+ * Creates workspace loader from an XML resource listed in the app restrictions.
+ *
+ * @return the loader if the restrictions are set and the resource exists; null otherwise.
+ */
+ @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2)
+ private AutoInstallsLayout createWorkspaceLoaderFromAppRestriction() {
+ // UserManager.getApplicationRestrictions() requires minSdkVersion >= 18
+ if (android.os.Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR2) {
+ return null;
+ }
+
+ Context ctx = getContext();
+ UserManager um = (UserManager) ctx.getSystemService(Context.USER_SERVICE);
+ Bundle bundle = um.getApplicationRestrictions(ctx.getPackageName());
+ if (bundle == null) {
+ return null;
+ }
+
+ String packageName = bundle.getString(RESTRICTION_PACKAGE_NAME);
+ if (packageName != null) {
+ try {
+ Resources targetResources = ctx.getPackageManager()
+ .getResourcesForApplication(packageName);
+ return AutoInstallsLayout.get(ctx, packageName, targetResources,
+ mOpenHelper.mAppWidgetHost, mOpenHelper);
+ } catch (NameNotFoundException e) {
+ Log.e(TAG, "Target package for restricted profile not found", e);
+ return null;
+ }
+ }
+ return null;
+ }
+
private DefaultLayoutParser getDefaultLayoutParser() {
int defaultLayout = LauncherAppState.getInstance()
- .getDynamicGrid().getDeviceProfile().defaultLayoutId;
+ .getInvariantDeviceProfile().defaultLayoutId;
return new DefaultLayoutParser(getContext(), mOpenHelper.mAppWidgetHost,
mOpenHelper, getContext().getResources(), defaultLayout);
}
@@ -356,17 +437,15 @@ public class LauncherProvider extends ContentProvider {
Uri.parse(getContext().getString(R.string.old_launcher_provider_uri)));
}
- private static interface ContentValuesCallback {
- public void onRow(ContentValues values);
+ public void updateFolderItemsRank() {
+ mOpenHelper.updateFolderItemsRank(mOpenHelper.getWritableDatabase(), false);
}
- private static boolean shouldImportLauncher2Database(Context context) {
- boolean isTablet = context.getResources().getBoolean(R.bool.is_tablet);
-
- // We don't import the old databse for tablets, as the grid size has changed.
- return !isTablet && IMPORT_LAUNCHER2_DATABASE;
+ public void convertShortcutsToLauncherActivities() {
+ mOpenHelper.convertShortcutsToLauncherActivities(mOpenHelper.getWritableDatabase());
}
+
public void deleteDatabase() {
// Are you sure? (y/n)
final SQLiteDatabase db = mOpenHelper.getWritableDatabase();
@@ -376,16 +455,19 @@ public class LauncherProvider extends ContentProvider {
SQLiteDatabase.deleteDatabase(dbFile);
}
mOpenHelper = new DatabaseHelper(getContext());
+ mOpenHelper.mListener = mListener;
}
private static class DatabaseHelper extends SQLiteOpenHelper implements LayoutParserCallback {
private final Context mContext;
- private final AppWidgetHost mAppWidgetHost;
+ @Thunk final AppWidgetHost mAppWidgetHost;
private long mMaxItemId = -1;
private long mMaxScreenId = -1;
private boolean mNewDbCreated = false;
+ @Thunk LauncherProviderChangeListener mListener;
+
DatabaseHelper(Context context) {
super(context, LauncherFiles.LAUNCHER_DB, null, DATABASE_VERSION);
mContext = context;
@@ -405,17 +487,6 @@ public class LauncherProvider extends ContentProvider {
return mNewDbCreated;
}
- /**
- * Send notification that we've deleted the {@link AppWidgetHost},
- * probably as part of the initial database creation. The receiver may
- * want to re-call {@link AppWidgetHost#startListening()} to ensure
- * callbacks are correctly set.
- */
- private void sendAppWidgetResetNotify() {
- final ContentResolver resolver = mContext.getContentResolver();
- resolver.notifyChange(CONTENT_APPWIDGET_RESET_URI, null);
- }
-
@Override
public void onCreate(SQLiteDatabase db) {
if (LOGD) Log.d(TAG, "creating new launcher database");
@@ -450,53 +521,44 @@ public class LauncherProvider extends ContentProvider {
"appWidgetProvider TEXT," +
"modified INTEGER NOT NULL DEFAULT 0," +
"restored INTEGER NOT NULL DEFAULT 0," +
- "profileId INTEGER DEFAULT " + userSerialNumber +
+ "profileId INTEGER DEFAULT " + userSerialNumber + "," +
+ "rank INTEGER NOT NULL DEFAULT 0," +
+ "options INTEGER NOT NULL DEFAULT 0" +
");");
addWorkspacesTable(db);
// Database was just created, so wipe any previous widgets
if (mAppWidgetHost != null) {
mAppWidgetHost.deleteHost();
- sendAppWidgetResetNotify();
- }
- if (shouldImportLauncher2Database(mContext)) {
- // Try converting the old database
- ContentValuesCallback permuteScreensCb = new ContentValuesCallback() {
- public void onRow(ContentValues values) {
- int container = values.getAsInteger(LauncherSettings.Favorites.CONTAINER);
- if (container == Favorites.CONTAINER_DESKTOP) {
- int screen = values.getAsInteger(LauncherSettings.Favorites.SCREEN);
- screen = (int) upgradeLauncherDb_permuteScreens(screen);
- values.put(LauncherSettings.Favorites.SCREEN, screen);
+ /**
+ * Send notification that we've deleted the {@link AppWidgetHost},
+ * probably as part of the initial database creation. The receiver may
+ * want to re-call {@link AppWidgetHost#startListening()} to ensure
+ * callbacks are correctly set.
+ */
+ new MainThreadExecutor().execute(new Runnable() {
+
+ @Override
+ public void run() {
+ if (mListener != null) {
+ mListener.onAppWidgetHostReset();
}
}
- };
- Uri uri = Uri.parse("content://" + Settings.AUTHORITY +
- "/old_favorites?notify=true");
- if (!convertDatabase(db, uri, permuteScreensCb, true)) {
- // Try and upgrade from the Launcher2 db
- uri = Uri.parse(mContext.getString(R.string.old_launcher_provider_uri));
- if (!convertDatabase(db, uri, permuteScreensCb, false)) {
- // If we fail, then set a flag to load the default workspace
- setFlagEmptyDbCreated();
- return;
- }
- }
- // Right now, in non-default workspace cases, we want to run the final
- // upgrade code (ie. to fix workspace screen indices -> ids, etc.), so
- // set that flag too.
- setFlagJustLoadedOldDb();
- } else {
- // Fresh and clean launcher DB.
- mMaxItemId = initializeMaxItemId(db);
- setFlagEmptyDbCreated();
+ });
}
+
+ // Fresh and clean launcher DB.
+ mMaxItemId = initializeMaxItemId(db);
+ setFlagEmptyDbCreated();
+
+ // When a new DB is created, remove all previously stored managed profile information.
+ ManagedProfileHeuristic.processAllUsers(Collections.<UserHandleCompat>emptyList(), mContext);
}
private void addWorkspacesTable(SQLiteDatabase db) {
db.execSQL("CREATE TABLE " + TABLE_WORKSPACE_SCREENS + " (" +
- LauncherSettings.WorkspaceScreens._ID + " INTEGER," +
+ LauncherSettings.WorkspaceScreens._ID + " INTEGER PRIMARY KEY," +
LauncherSettings.WorkspaceScreens.SCREEN_RANK + " INTEGER," +
LauncherSettings.ChangeLogColumns.MODIFIED + " INTEGER NOT NULL DEFAULT 0" +
");");
@@ -536,333 +598,120 @@ public class LauncherProvider extends ContentProvider {
private void setFlagJustLoadedOldDb() {
String spKey = LauncherAppState.getSharedPreferencesKey();
SharedPreferences sp = mContext.getSharedPreferences(spKey, Context.MODE_PRIVATE);
- SharedPreferences.Editor editor = sp.edit();
- editor.putBoolean(UPGRADED_FROM_OLD_DATABASE, true);
- editor.putBoolean(EMPTY_DATABASE_CREATED, false);
- editor.commit();
+ sp.edit().putBoolean(EMPTY_DATABASE_CREATED, false).commit();
}
private void setFlagEmptyDbCreated() {
String spKey = LauncherAppState.getSharedPreferencesKey();
SharedPreferences sp = mContext.getSharedPreferences(spKey, Context.MODE_PRIVATE);
- SharedPreferences.Editor editor = sp.edit();
- editor.putBoolean(EMPTY_DATABASE_CREATED, true);
- editor.putBoolean(UPGRADED_FROM_OLD_DATABASE, false);
- editor.commit();
- }
-
- // We rearrange the screens from the old launcher
- // 12345 -> 34512
- private long upgradeLauncherDb_permuteScreens(long screen) {
- if (screen >= 2) {
- return screen - 2;
- } else {
- return screen + 3;
- }
- }
-
- private boolean convertDatabase(SQLiteDatabase db, Uri uri,
- ContentValuesCallback cb, boolean deleteRows) {
- if (LOGD) Log.d(TAG, "converting database from an older format, but not onUpgrade");
- boolean converted = false;
-
- final ContentResolver resolver = mContext.getContentResolver();
- Cursor cursor = null;
-
- try {
- cursor = resolver.query(uri, null, null, null, null);
- } catch (Exception e) {
- // Ignore
- }
-
- // We already have a favorites database in the old provider
- if (cursor != null) {
- try {
- if (cursor.getCount() > 0) {
- converted = copyFromCursor(db, cursor, cb) > 0;
- if (converted && deleteRows) {
- resolver.delete(uri, null, null);
- }
- }
- } finally {
- cursor.close();
- }
- }
-
- if (converted) {
- // Convert widgets from this import into widgets
- if (LOGD) Log.d(TAG, "converted and now triggering widget upgrade");
- convertWidgets(db);
-
- // Update max item id
- mMaxItemId = initializeMaxItemId(db);
- if (LOGD) Log.d(TAG, "mMaxItemId: " + mMaxItemId);
- }
-
- return converted;
- }
-
- private int copyFromCursor(SQLiteDatabase db, Cursor c, ContentValuesCallback cb) {
- final int idIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites._ID);
- final int intentIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.INTENT);
- final int titleIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.TITLE);
- final int iconTypeIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ICON_TYPE);
- final int iconIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ICON);
- final int iconPackageIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ICON_PACKAGE);
- final int iconResourceIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ICON_RESOURCE);
- final int containerIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.CONTAINER);
- final int itemTypeIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ITEM_TYPE);
- final int screenIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.SCREEN);
- final int cellXIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.CELLX);
- final int cellYIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.CELLY);
- final int uriIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.URI);
- final int displayModeIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.DISPLAY_MODE);
-
- ContentValues[] rows = new ContentValues[c.getCount()];
- int i = 0;
- while (c.moveToNext()) {
- ContentValues values = new ContentValues(c.getColumnCount());
- values.put(LauncherSettings.Favorites._ID, c.getLong(idIndex));
- values.put(LauncherSettings.Favorites.INTENT, c.getString(intentIndex));
- values.put(LauncherSettings.Favorites.TITLE, c.getString(titleIndex));
- values.put(LauncherSettings.Favorites.ICON_TYPE, c.getInt(iconTypeIndex));
- values.put(LauncherSettings.Favorites.ICON, c.getBlob(iconIndex));
- values.put(LauncherSettings.Favorites.ICON_PACKAGE, c.getString(iconPackageIndex));
- values.put(LauncherSettings.Favorites.ICON_RESOURCE, c.getString(iconResourceIndex));
- values.put(LauncherSettings.Favorites.CONTAINER, c.getInt(containerIndex));
- values.put(LauncherSettings.Favorites.ITEM_TYPE, c.getInt(itemTypeIndex));
- values.put(LauncherSettings.Favorites.APPWIDGET_ID, -1);
- values.put(LauncherSettings.Favorites.SCREEN, c.getInt(screenIndex));
- values.put(LauncherSettings.Favorites.CELLX, c.getInt(cellXIndex));
- values.put(LauncherSettings.Favorites.CELLY, c.getInt(cellYIndex));
- values.put(LauncherSettings.Favorites.URI, c.getString(uriIndex));
- values.put(LauncherSettings.Favorites.DISPLAY_MODE, c.getInt(displayModeIndex));
- if (cb != null) {
- cb.onRow(values);
- }
- rows[i++] = values;
- }
-
- int total = 0;
- if (i > 0) {
- db.beginTransaction();
- try {
- int numValues = rows.length;
- for (i = 0; i < numValues; i++) {
- if (dbInsertAndCheck(this, db, TABLE_FAVORITES, null, rows[i]) < 0) {
- return 0;
- } else {
- total++;
- }
- }
- db.setTransactionSuccessful();
- } finally {
- db.endTransaction();
- }
- }
-
- return total;
+ sp.edit().putBoolean(EMPTY_DATABASE_CREATED, true).commit();
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
if (LOGD) Log.d(TAG, "onUpgrade triggered: " + oldVersion);
-
- int version = oldVersion;
- if (version < 3) {
- // upgrade 1,2 -> 3 added appWidgetId column
- db.beginTransaction();
- try {
- // Insert new column for holding appWidgetIds
- db.execSQL("ALTER TABLE favorites " +
- "ADD COLUMN appWidgetId INTEGER NOT NULL DEFAULT -1;");
- db.setTransactionSuccessful();
- version = 3;
- } catch (SQLException ex) {
- // Old version remains, which means we wipe old data
- Log.e(TAG, ex.getMessage(), ex);
- } finally {
- db.endTransaction();
+ switch (oldVersion) {
+ // The version cannot be lower that 12, as Launcher3 never supported a lower
+ // version of the DB.
+ case 12: {
+ // With the new shrink-wrapped and re-orderable workspaces, it makes sense
+ // to persist workspace screens and their relative order.
+ mMaxScreenId = 0;
+ addWorkspacesTable(db);
}
-
- // Convert existing widgets only if table upgrade was successful
- if (version == 3) {
- convertWidgets(db);
+ case 13: {
+ db.beginTransaction();
+ try {
+ // Insert new column for holding widget provider name
+ db.execSQL("ALTER TABLE favorites " +
+ "ADD COLUMN appWidgetProvider TEXT;");
+ db.setTransactionSuccessful();
+ } catch (SQLException ex) {
+ Log.e(TAG, ex.getMessage(), ex);
+ // Old version remains, which means we wipe old data
+ break;
+ } finally {
+ db.endTransaction();
+ }
}
- }
-
- if (version < 4) {
- version = 4;
- }
-
- // Where's version 5?
- // - Donut and sholes on 2.0 shipped with version 4 of launcher1.
- // - Passion shipped on 2.1 with version 6 of launcher3
- // - Sholes shipped on 2.1r1 (aka Mr. 3) with version 5 of launcher 1
- // but version 5 on there was the updateContactsShortcuts change
- // which was version 6 in launcher 2 (first shipped on passion 2.1r1).
- // The updateContactsShortcuts change is idempotent, so running it twice
- // is okay so we'll do that when upgrading the devices that shipped with it.
- if (version < 6) {
- // We went from 3 to 5 screens. Move everything 1 to the right
- db.beginTransaction();
- try {
- db.execSQL("UPDATE favorites SET screen=(screen + 1);");
- db.setTransactionSuccessful();
- } catch (SQLException ex) {
- // Old version remains, which means we wipe old data
- Log.e(TAG, ex.getMessage(), ex);
- } finally {
- db.endTransaction();
+ case 14: {
+ db.beginTransaction();
+ try {
+ // Insert new column for holding update timestamp
+ db.execSQL("ALTER TABLE favorites " +
+ "ADD COLUMN modified INTEGER NOT NULL DEFAULT 0;");
+ db.execSQL("ALTER TABLE workspaceScreens " +
+ "ADD COLUMN modified INTEGER NOT NULL DEFAULT 0;");
+ db.setTransactionSuccessful();
+ } catch (SQLException ex) {
+ Log.e(TAG, ex.getMessage(), ex);
+ // Old version remains, which means we wipe old data
+ break;
+ } finally {
+ db.endTransaction();
+ }
}
-
- // We added the fast track.
- if (updateContactsShortcuts(db)) {
- version = 6;
+ case 15: {
+ if (!addIntegerColumn(db, Favorites.RESTORED, 0)) {
+ // Old version remains, which means we wipe old data
+ break;
+ }
}
- }
-
- if (version < 7) {
- // Version 7 gets rid of the special search widget.
- convertWidgets(db);
- version = 7;
- }
-
- if (version < 8) {
- // Version 8 (froyo) has the icons all normalized. This should
- // already be the case in practice, but we now rely on it and don't
- // resample the images each time.
- normalizeIcons(db);
- version = 8;
- }
-
- if (version < 9) {
- // The max id is not yet set at this point (onUpgrade is triggered in the ctor
- // before it gets a change to get set, so we need to read it here when we use it)
- if (mMaxItemId == -1) {
- mMaxItemId = initializeMaxItemId(db);
+ case 16: {
+ // We use the db version upgrade here to identify users who may not have seen
+ // clings yet (because they weren't available), but for whom the clings are now
+ // 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);
}
-
- // Add default hotseat icons
- loadFavorites(db, new DefaultLayoutParser(mContext, mAppWidgetHost, this,
- mContext.getResources(), R.xml.update_workspace));
- version = 9;
- }
-
- // We bumped the version three time during JB, once to update the launch flags, once to
- // update the override for the default launch animation and once to set the mimetype
- // to improve startup performance
- if (version < 12) {
- // Contact shortcuts need a different set of flags to be launched now
- // The updateContactsShortcuts change is idempotent, so we can keep using it like
- // back in the Donut days
- updateContactsShortcuts(db);
- version = 12;
- }
-
- if (version < 13) {
- // With the new shrink-wrapped and re-orderable workspaces, it makes sense
- // to persist workspace screens and their relative order.
- mMaxScreenId = 0;
-
- // This will never happen in the wild, but when we switch to using workspace
- // screen ids, redo the import from old launcher.
- sJustLoadedFromOldDb = true;
-
- addWorkspacesTable(db);
- version = 13;
- }
-
- if (version < 14) {
- db.beginTransaction();
- try {
- // Insert new column for holding widget provider name
- db.execSQL("ALTER TABLE favorites " +
- "ADD COLUMN appWidgetProvider TEXT;");
- db.setTransactionSuccessful();
- version = 14;
- } catch (SQLException ex) {
- // Old version remains, which means we wipe old data
- Log.e(TAG, ex.getMessage(), ex);
- } finally {
- db.endTransaction();
+ case 17: {
+ // No-op
}
- }
-
- if (version < 15) {
- db.beginTransaction();
- try {
- // Insert new column for holding update timestamp
- db.execSQL("ALTER TABLE favorites " +
- "ADD COLUMN modified INTEGER NOT NULL DEFAULT 0;");
- db.execSQL("ALTER TABLE workspaceScreens " +
- "ADD COLUMN modified INTEGER NOT NULL DEFAULT 0;");
- db.setTransactionSuccessful();
- version = 15;
- } catch (SQLException ex) {
- // Old version remains, which means we wipe old data
- Log.e(TAG, ex.getMessage(), ex);
- } finally {
- db.endTransaction();
+ case 18: {
+ // Due to a data loss bug, some users may have items associated with screen ids
+ // which no longer exist. Since this can cause other problems, and since the user
+ // will never see these items anyway, we use database upgrade as an opportunity to
+ // clean things up.
+ removeOrphanedItems(db);
}
- }
-
-
- if (version < 16) {
- db.beginTransaction();
- try {
- // Insert new column for holding restore status
- db.execSQL("ALTER TABLE favorites " +
- "ADD COLUMN restored INTEGER NOT NULL DEFAULT 0;");
- db.setTransactionSuccessful();
- version = 16;
- } catch (SQLException ex) {
- // Old version remains, which means we wipe old data
- Log.e(TAG, ex.getMessage(), ex);
- } finally {
- db.endTransaction();
+ case 19: {
+ // Add userId column
+ if (!addProfileColumn(db)) {
+ // Old version remains, which means we wipe old data
+ break;
+ }
}
- }
-
- if (version < 17) {
- // We use the db version upgrade here to identify users who may not have seen
- // clings yet (because they weren't available), but for whom the clings are now
- // 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);
- version = 17;
- }
-
- if (version < 18) {
- // No-op
- version = 18;
- }
-
- if (version < 19) {
- // Due to a data loss bug, some users may have items associated with screen ids
- // which no longer exist. Since this can cause other problems, and since the user
- // will never see these items anyway, we use database upgrade as an opportunity to
- // clean things up.
- removeOrphanedItems(db);
- version = 19;
- }
-
- if (version < 20) {
- // Add userId column
- if (addProfileColumn(db)) {
- version = 20;
+ case 20:
+ if (!updateFolderItemsRank(db, true)) {
+ break;
+ }
+ case 21:
+ // Recreate workspace table with screen id a primary key
+ if (!recreateWorkspaceTable(db)) {
+ break;
+ }
+ case 22: {
+ if (!addIntegerColumn(db, Favorites.OPTIONS, 0)) {
+ // Old version remains, which means we wipe old data
+ break;
+ }
+ }
+ case 23:
+ // No-op
+ case 24:
+ ManagedProfileHeuristic.markExistingUsersForNoFolderCreation(mContext);
+ case 25:
+ convertShortcutsToLauncherActivities(db);
+ case 26: {
+ // DB Upgraded successfully
+ return;
}
- // else old version remains, which means we wipe old data
}
- if (version != DATABASE_VERSION) {
- Log.w(TAG, "Destroying all old data.");
- db.execSQL("DROP TABLE IF EXISTS " + TABLE_FAVORITES);
- db.execSQL("DROP TABLE IF EXISTS " + TABLE_WORKSPACE_SCREENS);
-
- onCreate(db);
- }
+ // DB was not upgraded
+ Log.w(TAG, "Destroying all old data.");
+ createEmptyDB(db);
}
@Override
@@ -873,7 +722,6 @@ public class LauncherProvider extends ContentProvider {
createEmptyDB(db);
}
-
/**
* Clears all the data for a fresh start.
*/
@@ -883,20 +731,102 @@ public class LauncherProvider extends ContentProvider {
onCreate(db);
}
- private boolean addProfileColumn(SQLiteDatabase db) {
+ /**
+ * Replaces all shortcuts of type {@link Favorites#ITEM_TYPE_SHORTCUT} which have a valid
+ * launcher activity target with {@link Favorites#ITEM_TYPE_APPLICATION}.
+ */
+ @Thunk void convertShortcutsToLauncherActivities(SQLiteDatabase db) {
db.beginTransaction();
+ Cursor c = null;
+ SQLiteStatement updateStmt = null;
+
try {
- UserManagerCompat userManager = UserManagerCompat.getInstance(mContext);
- // Default to the serial number of this user, for older
- // shortcuts.
- long userSerialNumber = userManager.getSerialNumberForUser(
- UserHandleCompat.myUserHandle());
- // Insert new column for holding user serial number
- db.execSQL("ALTER TABLE favorites " +
- "ADD COLUMN profileId INTEGER DEFAULT "
- + userSerialNumber + ";");
+ // Only consider the primary user as other users can't have a shortcut.
+ long userSerial = UserManagerCompat.getInstance(mContext)
+ .getSerialNumberForUser(UserHandleCompat.myUserHandle());
+ c = db.query(TABLE_FAVORITES, new String[] {
+ Favorites._ID,
+ Favorites.INTENT,
+ }, "itemType=" + Favorites.ITEM_TYPE_SHORTCUT + " AND profileId=" + userSerial,
+ null, null, null, null);
+
+ updateStmt = db.compileStatement("UPDATE favorites SET itemType="
+ + Favorites.ITEM_TYPE_APPLICATION + " WHERE _id=?");
+
+ final int idIndex = c.getColumnIndexOrThrow(Favorites._ID);
+ final int intentIndex = c.getColumnIndexOrThrow(Favorites.INTENT);
+
+ while (c.moveToNext()) {
+ String intentDescription = c.getString(intentIndex);
+ Intent intent;
+ try {
+ intent = Intent.parseUri(intentDescription, 0);
+ } catch (URISyntaxException e) {
+ Log.e(TAG, "Unable to parse intent", e);
+ continue;
+ }
+
+ if (!Utilities.isLauncherAppTarget(intent)) {
+ continue;
+ }
+
+ long id = c.getLong(idIndex);
+ updateStmt.bindLong(1, id);
+ updateStmt.executeUpdateDelete();
+ }
db.setTransactionSuccessful();
} catch (SQLException ex) {
+ Log.w(TAG, "Error deduping shortcuts", ex);
+ } finally {
+ db.endTransaction();
+ if (c != null) {
+ c.close();
+ }
+ if (updateStmt != null) {
+ updateStmt.close();
+ }
+ }
+ }
+
+ /**
+ * Recreates workspace table and migrates data to the new table.
+ */
+ public boolean recreateWorkspaceTable(SQLiteDatabase db) {
+ db.beginTransaction();
+ try {
+ Cursor c = db.query(TABLE_WORKSPACE_SCREENS,
+ new String[] {LauncherSettings.WorkspaceScreens._ID},
+ null, null, null, null,
+ LauncherSettings.WorkspaceScreens.SCREEN_RANK);
+ ArrayList<Long> sortedIDs = new ArrayList<Long>();
+ long maxId = 0;
+ try {
+ while (c.moveToNext()) {
+ Long id = c.getLong(0);
+ if (!sortedIDs.contains(id)) {
+ sortedIDs.add(id);
+ maxId = Math.max(maxId, id);
+ }
+ }
+ } finally {
+ c.close();
+ }
+
+ db.execSQL("DROP TABLE IF EXISTS " + TABLE_WORKSPACE_SCREENS);
+ addWorkspacesTable(db);
+
+ // Add all screen ids back
+ int total = sortedIDs.size();
+ for (int i = 0; i < total; i++) {
+ ContentValues values = new ContentValues();
+ values.put(LauncherSettings.WorkspaceScreens._ID, sortedIDs.get(i));
+ values.put(LauncherSettings.WorkspaceScreens.SCREEN_RANK, i);
+ addModifiedTime(values);
+ db.insertOrThrow(TABLE_WORKSPACE_SCREENS, null, values);
+ }
+ db.setTransactionSuccessful();
+ mMaxScreenId = maxId;
+ } catch (SQLException ex) {
// Old version remains, which means we wipe old data
Log.e(TAG, ex.getMessage(), ex);
return false;
@@ -906,140 +836,60 @@ public class LauncherProvider extends ContentProvider {
return true;
}
- private boolean updateContactsShortcuts(SQLiteDatabase db) {
- final String selectWhere = buildOrWhereString(Favorites.ITEM_TYPE,
- new int[] { Favorites.ITEM_TYPE_SHORTCUT });
-
- Cursor c = null;
- final String actionQuickContact = "com.android.contacts.action.QUICK_CONTACT";
+ @Thunk boolean updateFolderItemsRank(SQLiteDatabase db, boolean addRankColumn) {
db.beginTransaction();
try {
- // Select and iterate through each matching widget
- c = db.query(TABLE_FAVORITES,
- new String[] { Favorites._ID, Favorites.INTENT },
- selectWhere, null, null, null, null);
- if (c == null) return false;
-
- if (LOGD) Log.d(TAG, "found upgrade cursor count=" + c.getCount());
+ if (addRankColumn) {
+ // Insert new column for holding rank
+ db.execSQL("ALTER TABLE favorites ADD COLUMN rank INTEGER NOT NULL DEFAULT 0;");
+ }
- final int idIndex = c.getColumnIndex(Favorites._ID);
- final int intentIndex = c.getColumnIndex(Favorites.INTENT);
+ // Get a map for folder ID to folder width
+ Cursor c = db.rawQuery("SELECT container, MAX(cellX) FROM favorites"
+ + " WHERE container IN (SELECT _id FROM favorites WHERE itemType = ?)"
+ + " GROUP BY container;",
+ new String[] {Integer.toString(LauncherSettings.Favorites.ITEM_TYPE_FOLDER)});
while (c.moveToNext()) {
- long favoriteId = c.getLong(idIndex);
- final String intentUri = c.getString(intentIndex);
- if (intentUri != null) {
- try {
- final Intent intent = Intent.parseUri(intentUri, 0);
- android.util.Log.d("Home", intent.toString());
- final Uri uri = intent.getData();
- if (uri != null) {
- final String data = uri.toString();
- if ((Intent.ACTION_VIEW.equals(intent.getAction()) ||
- actionQuickContact.equals(intent.getAction())) &&
- (data.startsWith("content://contacts/people/") ||
- data.startsWith("content://com.android.contacts/" +
- "contacts/lookup/"))) {
-
- final Intent newIntent = new Intent(actionQuickContact);
- // When starting from the launcher, start in a new, cleared task
- // CLEAR_WHEN_TASK_RESET cannot reset the root of a task, so we
- // clear the whole thing preemptively here since
- // QuickContactActivity will finish itself when launching other
- // detail activities.
- newIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
- Intent.FLAG_ACTIVITY_CLEAR_TASK);
- newIntent.putExtra(
- Launcher.INTENT_EXTRA_IGNORE_LAUNCH_ANIMATION, true);
- newIntent.setData(uri);
- // Determine the type and also put that in the shortcut
- // (that can speed up launch a bit)
- newIntent.setDataAndType(uri, newIntent.resolveType(mContext));
-
- final ContentValues values = new ContentValues();
- values.put(LauncherSettings.Favorites.INTENT,
- newIntent.toUri(0));
-
- String updateWhere = Favorites._ID + "=" + favoriteId;
- db.update(TABLE_FAVORITES, values, updateWhere, null);
- }
- }
- } catch (RuntimeException ex) {
- Log.e(TAG, "Problem upgrading shortcut", ex);
- } catch (URISyntaxException e) {
- Log.e(TAG, "Problem upgrading shortcut", e);
- }
- }
+ db.execSQL("UPDATE favorites SET rank=cellX+(cellY*?) WHERE "
+ + "container=? AND cellX IS NOT NULL AND cellY IS NOT NULL;",
+ new Object[] {c.getLong(1) + 1, c.getLong(0)});
}
+ c.close();
db.setTransactionSuccessful();
} catch (SQLException ex) {
- Log.w(TAG, "Problem while upgrading contacts", ex);
+ // Old version remains, which means we wipe old data
+ Log.e(TAG, ex.getMessage(), ex);
return false;
} finally {
db.endTransaction();
- if (c != null) {
- c.close();
- }
}
-
return true;
}
- private void normalizeIcons(SQLiteDatabase db) {
- Log.d(TAG, "normalizing icons");
+ private boolean addProfileColumn(SQLiteDatabase db) {
+ UserManagerCompat userManager = UserManagerCompat.getInstance(mContext);
+ // Default to the serial number of this user, for older
+ // shortcuts.
+ long userSerialNumber = userManager.getSerialNumberForUser(
+ UserHandleCompat.myUserHandle());
+ return addIntegerColumn(db, Favorites.PROFILE_ID, userSerialNumber);
+ }
+ private boolean addIntegerColumn(SQLiteDatabase db, String columnName, long defaultValue) {
db.beginTransaction();
- Cursor c = null;
- SQLiteStatement update = null;
try {
- boolean logged = false;
- update = db.compileStatement("UPDATE favorites "
- + "SET icon=? WHERE _id=?");
-
- c = db.rawQuery("SELECT _id, icon FROM favorites WHERE iconType=" +
- Favorites.ICON_TYPE_BITMAP, null);
-
- final int idIndex = c.getColumnIndexOrThrow(Favorites._ID);
- final int iconIndex = c.getColumnIndexOrThrow(Favorites.ICON);
-
- while (c.moveToNext()) {
- long id = c.getLong(idIndex);
- byte[] data = c.getBlob(iconIndex);
- try {
- Bitmap bitmap = Utilities.createIconBitmap(
- BitmapFactory.decodeByteArray(data, 0, data.length),
- mContext);
- if (bitmap != null) {
- update.bindLong(1, id);
- data = ItemInfo.flattenBitmap(bitmap);
- if (data != null) {
- update.bindBlob(2, data);
- update.execute();
- }
- bitmap.recycle();
- }
- } catch (Exception e) {
- if (!logged) {
- Log.e(TAG, "Failed normalizing icon " + id, e);
- } else {
- Log.e(TAG, "Also failed normalizing icon " + id);
- }
- logged = true;
- }
- }
+ db.execSQL("ALTER TABLE favorites ADD COLUMN "
+ + columnName + " INTEGER NOT NULL DEFAULT " + defaultValue + ";");
db.setTransactionSuccessful();
} catch (SQLException ex) {
- Log.w(TAG, "Problem while allocating appWidgetIds for existing widgets", ex);
+ Log.e(TAG, ex.getMessage(), ex);
+ return false;
} finally {
db.endTransaction();
- if (update != null) {
- update.close();
- }
- if (c != null) {
- c.close();
- }
}
+ return true;
}
// Generates a new ID to use for an object in your database. This method should be only
@@ -1075,23 +925,7 @@ public class LauncherProvider extends ContentProvider {
}
private long initializeMaxItemId(SQLiteDatabase db) {
- Cursor c = db.rawQuery("SELECT MAX(_id) FROM favorites", null);
-
- // get the result
- final int maxIdIndex = 0;
- long id = -1;
- if (c != null && c.moveToNext()) {
- id = c.getLong(maxIdIndex);
- }
- if (c != null) {
- c.close();
- }
-
- if (id == -1) {
- throw new RuntimeException("Error: could not query max item id");
- }
-
- return id;
+ return getMaxId(db, TABLE_FAVORITES);
}
// Generates a new ID to use for an workspace screen in your database. This method
@@ -1104,128 +938,14 @@ public class LauncherProvider extends ContentProvider {
throw new RuntimeException("Error: max screen id was not initialized");
}
mMaxScreenId += 1;
- // Log to disk
- Launcher.addDumpLog(TAG, "11683562 - generateNewScreenId(): " + mMaxScreenId, true);
return mMaxScreenId;
}
- public void updateMaxScreenId(long maxScreenId) {
- // Log to disk
- Launcher.addDumpLog(TAG, "11683562 - updateMaxScreenId(): " + maxScreenId, true);
- mMaxScreenId = maxScreenId;
- }
-
private long initializeMaxScreenId(SQLiteDatabase db) {
- Cursor c = db.rawQuery("SELECT MAX(" + LauncherSettings.WorkspaceScreens._ID + ") FROM " + TABLE_WORKSPACE_SCREENS, null);
-
- // get the result
- final int maxIdIndex = 0;
- long id = -1;
- if (c != null && c.moveToNext()) {
- id = c.getLong(maxIdIndex);
- }
- if (c != null) {
- c.close();
- }
-
- if (id == -1) {
- throw new RuntimeException("Error: could not query max screen id");
- }
-
- // Log to disk
- Launcher.addDumpLog(TAG, "11683562 - initializeMaxScreenId(): " + id, true);
- return id;
+ return getMaxId(db, TABLE_WORKSPACE_SCREENS);
}
- /**
- * Upgrade existing clock and photo frame widgets into their new widget
- * equivalents.
- */
- private void convertWidgets(SQLiteDatabase db) {
- final AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(mContext);
- final int[] bindSources = new int[] {
- Favorites.ITEM_TYPE_WIDGET_CLOCK,
- Favorites.ITEM_TYPE_WIDGET_PHOTO_FRAME,
- Favorites.ITEM_TYPE_WIDGET_SEARCH,
- };
-
- final String selectWhere = buildOrWhereString(Favorites.ITEM_TYPE, bindSources);
-
- Cursor c = null;
-
- db.beginTransaction();
- try {
- // Select and iterate through each matching widget
- c = db.query(TABLE_FAVORITES, new String[] { Favorites._ID, Favorites.ITEM_TYPE },
- selectWhere, null, null, null, null);
-
- if (LOGD) Log.d(TAG, "found upgrade cursor count=" + c.getCount());
-
- final ContentValues values = new ContentValues();
- while (c != null && c.moveToNext()) {
- long favoriteId = c.getLong(0);
- int favoriteType = c.getInt(1);
-
- // Allocate and update database with new appWidgetId
- try {
- int appWidgetId = mAppWidgetHost.allocateAppWidgetId();
-
- if (LOGD) {
- Log.d(TAG, "allocated appWidgetId=" + appWidgetId
- + " for favoriteId=" + favoriteId);
- }
- values.clear();
- values.put(Favorites.ITEM_TYPE, Favorites.ITEM_TYPE_APPWIDGET);
- values.put(Favorites.APPWIDGET_ID, appWidgetId);
-
- // Original widgets might not have valid spans when upgrading
- if (favoriteType == Favorites.ITEM_TYPE_WIDGET_SEARCH) {
- values.put(LauncherSettings.Favorites.SPANX, 4);
- values.put(LauncherSettings.Favorites.SPANY, 1);
- } else {
- values.put(LauncherSettings.Favorites.SPANX, 2);
- values.put(LauncherSettings.Favorites.SPANY, 2);
- }
-
- String updateWhere = Favorites._ID + "=" + favoriteId;
- db.update(TABLE_FAVORITES, values, updateWhere, null);
-
- if (favoriteType == Favorites.ITEM_TYPE_WIDGET_CLOCK) {
- // TODO: check return value
- appWidgetManager.bindAppWidgetIdIfAllowed(appWidgetId,
- new ComponentName("com.android.alarmclock",
- "com.android.alarmclock.AnalogAppWidgetProvider"));
- } else if (favoriteType == Favorites.ITEM_TYPE_WIDGET_PHOTO_FRAME) {
- // TODO: check return value
- appWidgetManager.bindAppWidgetIdIfAllowed(appWidgetId,
- new ComponentName("com.android.camera",
- "com.android.camera.PhotoAppWidgetProvider"));
- } else if (favoriteType == Favorites.ITEM_TYPE_WIDGET_SEARCH) {
- // TODO: check return value
- appWidgetManager.bindAppWidgetIdIfAllowed(appWidgetId,
- getSearchWidgetProvider());
- }
- } catch (RuntimeException ex) {
- Log.e(TAG, "Problem allocating appWidgetId", ex);
- }
- }
-
- db.setTransactionSuccessful();
- } catch (SQLException ex) {
- Log.w(TAG, "Problem while allocating appWidgetIds for existing widgets", ex);
- } finally {
- db.endTransaction();
- if (c != null) {
- c.close();
- }
- }
-
- // Update max item id
- mMaxItemId = initializeMaxItemId(db);
- if (LOGD) Log.d(TAG, "mMaxItemId: " + mMaxItemId);
- }
-
- private boolean initializeExternalAdd(ContentValues values) {
+ @Thunk boolean initializeExternalAdd(ContentValues values) {
// 1. Ensure that externally added items have a valid item id
long id = generateNewItemId();
values.put(LauncherSettings.Favorites._ID, id);
@@ -1312,7 +1032,7 @@ public class LauncherProvider extends ContentProvider {
return rank;
}
- private int loadFavorites(SQLiteDatabase db, AutoInstallsLayout loader) {
+ @Thunk int loadFavorites(SQLiteDatabase db, AutoInstallsLayout loader) {
ArrayList<Long> screenIds = new ArrayList<Long>();
// TODO: Use multiple loaders with fall-back and transaction.
int count = loader.loadLayout(db, screenIds);
@@ -1339,12 +1059,7 @@ public class LauncherProvider extends ContentProvider {
return count;
}
- private ComponentName getSearchWidgetProvider() {
- AppWidgetProviderInfo searchProvider = Utilities.getSearchWidgetProvider(mContext);
- return (searchProvider == null) ? null : searchProvider.provider;
- }
-
- private void migrateLauncher2Shortcuts(SQLiteDatabase db, Uri uri) {
+ @Thunk void migrateLauncher2Shortcuts(SQLiteDatabase db, Uri uri) {
final ContentResolver resolver = mContext.getContentResolver();
Cursor c = null;
int count = 0;
@@ -1395,10 +1110,10 @@ public class LauncherProvider extends ContentProvider {
int curY = 0;
final LauncherAppState app = LauncherAppState.getInstance();
- final DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
- final int width = (int) grid.numColumns;
- final int height = (int) grid.numRows;
- final int hotseatWidth = (int) grid.numHotseatIcons;
+ final InvariantDeviceProfile profile = app.getInvariantDeviceProfile();
+ final int width = (int) profile.numColumns;
+ final int height = (int) profile.numRows;
+ final int hotseatWidth = (int) profile.numHotseatIcons;
final HashSet<String> seenIntents = new HashSet<String>(c.getCount());
@@ -1540,7 +1255,7 @@ public class LauncherProvider extends ContentProvider {
int hotseatX = hotseat.keyAt(idx);
ContentValues values = hotseat.valueAt(idx);
- if (hotseatX == grid.hotseatAllAppsRank) {
+ if (hotseatX == profile.hotseatAllAppsRank) {
// let's drop this in the next available hole in the hotseat
while (++hotseatX < hotseatWidth) {
if (hotseat.get(hotseatX) == null) {
@@ -1619,6 +1334,8 @@ public class LauncherProvider extends ContentProvider {
} finally {
db.endTransaction();
}
+
+ updateFolderItemsRank(db, false);
}
} finally {
c.close();
@@ -1639,18 +1356,24 @@ public class LauncherProvider extends ContentProvider {
}
/**
- * Build a query string that will match any row where the column matches
- * anything in the values list.
+ * @return the max _id in the provided table.
*/
- private static String buildOrWhereString(String column, int[] values) {
- StringBuilder selectWhere = new StringBuilder();
- for (int i = values.length - 1; i >= 0; i--) {
- selectWhere.append(column).append("=").append(values[i]);
- if (i > 0) {
- selectWhere.append(" OR ");
- }
+ @Thunk static long getMaxId(SQLiteDatabase db, String table) {
+ Cursor c = db.rawQuery("SELECT MAX(_id) FROM " + table, null);
+ // get the result
+ long id = -1;
+ if (c != null && c.moveToNext()) {
+ id = c.getLong(0);
}
- return selectWhere.toString();
+ if (c != null) {
+ c.close();
+ }
+
+ if (id == -1) {
+ throw new RuntimeException("Error: could not query max id in " + table);
+ }
+
+ return id;
}
static class SqlArguments {
diff --git a/src/com/android/launcher3/LauncherProviderChangeListener.java b/src/com/android/launcher3/LauncherProviderChangeListener.java
index 0de96fbc4..1b78e9c18 100644
--- a/src/com/android/launcher3/LauncherProviderChangeListener.java
+++ b/src/com/android/launcher3/LauncherProviderChangeListener.java
@@ -8,4 +8,8 @@ package com.android.launcher3;
public interface LauncherProviderChangeListener {
public void onLauncherProviderChange();
+
+ public void onSettingsChanged(String settings, boolean value);
+
+ public void onAppWidgetHostReset();
}
diff --git a/src/com/android/launcher3/LauncherScroller.java b/src/com/android/launcher3/LauncherScroller.java
index 3bd0a78c4..a9b49556b 100644
--- a/src/com/android/launcher3/LauncherScroller.java
+++ b/src/com/android/launcher3/LauncherScroller.java
@@ -20,7 +20,6 @@ import android.animation.TimeInterpolator;
import android.content.Context;
import android.hardware.SensorManager;
import android.os.Build;
-import android.util.FloatMath;
import android.view.ViewConfiguration;
import android.view.animation.AnimationUtils;
import android.view.animation.Interpolator;
@@ -409,7 +408,7 @@ public class LauncherScroller {
float dx = (float) (mFinalX - mStartX);
float dy = (float) (mFinalY - mStartY);
- float hyp = FloatMath.sqrt(dx * dx + dy * dy);
+ float hyp = (float) Math.hypot(dx, dy);
float ndx = dx / hyp;
float ndy = dy / hyp;
@@ -426,7 +425,7 @@ public class LauncherScroller {
mMode = FLING_MODE;
mFinished = false;
- float velocity = FloatMath.sqrt(velocityX * velocityX + velocityY * velocityY);
+ float velocity = (float) Math.hypot(velocityX, velocityY);
mVelocity = velocity;
mDuration = getSplineFlingDuration(velocity);
diff --git a/src/com/android/launcher3/LauncherSettings.java b/src/com/android/launcher3/LauncherSettings.java
index 355370283..f2c85a195 100644
--- a/src/com/android/launcher3/LauncherSettings.java
+++ b/src/com/android/launcher3/LauncherSettings.java
@@ -19,17 +19,19 @@ package com.android.launcher3;
import android.net.Uri;
import android.provider.BaseColumns;
+import com.android.launcher3.config.ProviderConfig;
+
/**
* Settings related utilities.
*/
-class LauncherSettings {
+public class LauncherSettings {
/** Columns required on table staht will be subject to backup and restore. */
static interface ChangeLogColumns extends BaseColumns {
/**
* The time of the last update to this row.
* <P>Type: INTEGER</P>
*/
- static final String MODIFIED = "modified";
+ public static final String MODIFIED = "modified";
}
static interface BaseLauncherColumns extends ChangeLogColumns {
@@ -37,7 +39,7 @@ class LauncherSettings {
* Descriptive name of the gesture that can be displayed to the user.
* <P>Type: TEXT</P>
*/
- static final String TITLE = "title";
+ public static final String TITLE = "title";
/**
* The Intent URL of the gesture, describing what it points to. This
@@ -45,58 +47,58 @@ class LauncherSettings {
* an Intent that can be launched.
* <P>Type: TEXT</P>
*/
- static final String INTENT = "intent";
+ public static final String INTENT = "intent";
/**
* The type of the gesture
*
* <P>Type: INTEGER</P>
*/
- static final String ITEM_TYPE = "itemType";
+ public static final String ITEM_TYPE = "itemType";
/**
* The gesture is an application
*/
- static final int ITEM_TYPE_APPLICATION = 0;
+ public static final int ITEM_TYPE_APPLICATION = 0;
/**
* The gesture is an application created shortcut
*/
- static final int ITEM_TYPE_SHORTCUT = 1;
+ public static final int ITEM_TYPE_SHORTCUT = 1;
/**
* The icon type.
* <P>Type: INTEGER</P>
*/
- static final String ICON_TYPE = "iconType";
+ public static final String ICON_TYPE = "iconType";
/**
* The icon is a resource identified by a package name and an integer id.
*/
- static final int ICON_TYPE_RESOURCE = 0;
+ public static final int ICON_TYPE_RESOURCE = 0;
/**
* The icon is a bitmap.
*/
- static final int ICON_TYPE_BITMAP = 1;
+ public static final int ICON_TYPE_BITMAP = 1;
/**
* The icon package name, if icon type is ICON_TYPE_RESOURCE.
* <P>Type: TEXT</P>
*/
- static final String ICON_PACKAGE = "iconPackage";
+ public static final String ICON_PACKAGE = "iconPackage";
/**
* The icon resource id, if icon type is ICON_TYPE_RESOURCE.
* <P>Type: TEXT</P>
*/
- static final String ICON_RESOURCE = "iconResource";
+ public static final String ICON_RESOURCE = "iconResource";
/**
* The custom icon bitmap, if icon type is ICON_TYPE_BITMAP.
* <P>Type: BLOB</P>
*/
- static final String ICON = "icon";
+ public static final String ICON = "icon";
}
/**
@@ -104,72 +106,59 @@ class LauncherSettings {
*
* Tracks the order of workspace screens.
*/
- static final class WorkspaceScreens implements ChangeLogColumns {
+ public static final class WorkspaceScreens implements ChangeLogColumns {
+
+ public static final String TABLE_NAME = "workspaceScreens";
+
/**
* The content:// style URL for this table
*/
static final Uri CONTENT_URI = Uri.parse("content://" +
- LauncherProvider.AUTHORITY + "/" + LauncherProvider.TABLE_WORKSPACE_SCREENS +
- "?" + LauncherProvider.PARAMETER_NOTIFY + "=true");
+ ProviderConfig.AUTHORITY + "/" + TABLE_NAME);
/**
* The rank of this screen -- ie. how it is ordered relative to the other screens.
* <P>Type: INTEGER</P>
*/
- static final String SCREEN_RANK = "screenRank";
+ public static final String SCREEN_RANK = "screenRank";
}
/**
* Favorites.
*/
- static final class Favorites implements BaseLauncherColumns {
- /**
- * The content:// style URL for this table
- */
- static final Uri CONTENT_URI = Uri.parse("content://" +
- LauncherProvider.AUTHORITY + "/" + LauncherProvider.TABLE_FAVORITES +
- "?" + LauncherProvider.PARAMETER_NOTIFY + "=true");
+ public static final class Favorites implements BaseLauncherColumns {
- /**
- * The content:// style URL for this table
- */
- static final Uri OLD_CONTENT_URI = Uri.parse("content://" +
- LauncherProvider.OLD_AUTHORITY + "/" + LauncherProvider.TABLE_FAVORITES +
- "?" + LauncherProvider.PARAMETER_NOTIFY + "=true");
+ public static final String TABLE_NAME = "favorites";
/**
- * The content:// style URL for this table. When this Uri is used, no notification is
- * sent if the content changes.
+ * The content:// style URL for this table
*/
- static final Uri CONTENT_URI_NO_NOTIFICATION = Uri.parse("content://" +
- LauncherProvider.AUTHORITY + "/" + LauncherProvider.TABLE_FAVORITES +
- "?" + LauncherProvider.PARAMETER_NOTIFY + "=false");
+ public static final Uri CONTENT_URI = Uri.parse("content://" +
+ ProviderConfig.AUTHORITY + "/" + TABLE_NAME);
/**
* The content:// style URL for a given row, identified by its id.
*
* @param id The row id.
- * @param notify True to send a notification is the content changes.
*
* @return The unique content URL for the specified row.
*/
- static Uri getContentUri(long id, boolean notify) {
- return Uri.parse("content://" + LauncherProvider.AUTHORITY +
- "/" + LauncherProvider.TABLE_FAVORITES + "/" + id + "?" +
- LauncherProvider.PARAMETER_NOTIFY + "=" + notify);
+ static Uri getContentUri(long id) {
+ return Uri.parse("content://" + ProviderConfig.AUTHORITY +
+ "/" + TABLE_NAME + "/" + id);
}
/**
* The container holding the favorite
* <P>Type: INTEGER</P>
*/
- static final String CONTAINER = "container";
+ public static final String CONTAINER = "container";
/**
* The icon is a resource identified by a package name and an integer id.
*/
- static final int CONTAINER_DESKTOP = -100;
- static final int CONTAINER_HOTSEAT = -101;
+ public static final int CONTAINER_DESKTOP = -100;
+ public static final int CONTAINER_HOTSEAT = -101;
static final String containerToString(int container) {
switch (container) {
@@ -183,33 +172,33 @@ class LauncherSettings {
* The screen holding the favorite (if container is CONTAINER_DESKTOP)
* <P>Type: INTEGER</P>
*/
- static final String SCREEN = "screen";
+ public static final String SCREEN = "screen";
/**
* The X coordinate of the cell holding the favorite
* (if container is CONTAINER_HOTSEAT or CONTAINER_HOTSEAT)
* <P>Type: INTEGER</P>
*/
- static final String CELLX = "cellX";
+ public static final String CELLX = "cellX";
/**
* The Y coordinate of the cell holding the favorite
* (if container is CONTAINER_DESKTOP)
* <P>Type: INTEGER</P>
*/
- static final String CELLY = "cellY";
+ public static final String CELLY = "cellY";
/**
* The X span of the cell holding the favorite
* <P>Type: INTEGER</P>
*/
- static final String SPANX = "spanX";
+ public static final String SPANX = "spanX";
/**
* The Y span of the cell holding the favorite
* <P>Type: INTEGER</P>
*/
- static final String SPANY = "spanY";
+ public static final String SPANY = "spanY";
/**
* The profile id of the item in the cell.
@@ -217,12 +206,12 @@ class LauncherSettings {
* Type: INTEGER
* </P>
*/
- static final String PROFILE_ID = "profileId";
+ public static final String PROFILE_ID = "profileId";
/**
* The favorite is a user created folder
*/
- static final int ITEM_TYPE_FOLDER = 2;
+ public static final int ITEM_TYPE_FOLDER = 2;
/**
* The favorite is a live folder
@@ -231,26 +220,35 @@ class LauncherSettings {
* exist within the launcher database will be ignored when loading. That said, these
* entries in the database may still exist, and are not automatically stripped.
*/
+ @Deprecated
static final int ITEM_TYPE_LIVE_FOLDER = 3;
/**
* The favorite is a widget
*/
- static final int ITEM_TYPE_APPWIDGET = 4;
+ public static final int ITEM_TYPE_APPWIDGET = 4;
+
+ /**
+ * The favorite is a custom widget provided by the launcher
+ */
+ public static final int ITEM_TYPE_CUSTOM_APPWIDGET = 5;
/**
* The favorite is a clock
*/
+ @Deprecated
static final int ITEM_TYPE_WIDGET_CLOCK = 1000;
/**
* The favorite is a search widget
*/
+ @Deprecated
static final int ITEM_TYPE_WIDGET_SEARCH = 1001;
/**
* The favorite is a photo frame
*/
+ @Deprecated
static final int ITEM_TYPE_WIDGET_PHOTO_FRAME = 1002;
/**
@@ -258,7 +256,7 @@ class LauncherSettings {
*
* <P>Type: INTEGER</P>
*/
- static final String APPWIDGET_ID = "appWidgetId";
+ public static final String APPWIDGET_ID = "appWidgetId";
/**
* The ComponentName of the widget provider
@@ -281,6 +279,7 @@ class LauncherSettings {
* live folders to find the content provider.
* <P>Type: TEXT</P>
*/
+ @Deprecated
static final String URI = "uri";
/**
@@ -290,12 +289,40 @@ class LauncherSettings {
* @see android.provider.LiveFolders#DISPLAY_MODE_GRID
* @see android.provider.LiveFolders#DISPLAY_MODE_LIST
*/
+ @Deprecated
static final String DISPLAY_MODE = "displayMode";
/**
* Boolean indicating that his item was restored and not yet successfully bound.
* <P>Type: INTEGER</P>
*/
- static final String RESTORED = "restored";
+ public static final String RESTORED = "restored";
+
+ /**
+ * Indicates the position of the item inside an auto-arranged view like folder or hotseat.
+ * <p>Type: INTEGER</p>
+ */
+ public static final String RANK = "rank";
+
+ /**
+ * Stores general flag based options for {@link ItemInfo}s.
+ * <p>Type: INTEGER</p>
+ */
+ public static final String OPTIONS = "options";
+ }
+
+ /**
+ * Launcher settings
+ */
+ public static final class Settings {
+
+ public static final Uri CONTENT_URI = Uri.parse("content://" +
+ ProviderConfig.AUTHORITY + "/settings");
+
+ public static final String METHOD_GET_BOOLEAN = "get_boolean_setting";
+ public static final String METHOD_SET_BOOLEAN = "set_boolean_setting";
+
+ public static final String EXTRA_VALUE = "value";
+ public static final String EXTRA_DEFAULT_VALUE = "default_value";
}
}
diff --git a/src/com/android/launcher3/LauncherStateTransitionAnimation.java b/src/com/android/launcher3/LauncherStateTransitionAnimation.java
new file mode 100644
index 000000000..d69b7432d
--- /dev/null
+++ b/src/com/android/launcher3/LauncherStateTransitionAnimation.java
@@ -0,0 +1,762 @@
+/*
+ * 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;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.AnimatorSet;
+import android.animation.ObjectAnimator;
+import android.animation.PropertyValuesHolder;
+import android.animation.TimeInterpolator;
+import android.annotation.SuppressLint;
+import android.content.res.Resources;
+import android.util.Log;
+import android.view.View;
+import android.view.animation.AccelerateInterpolator;
+import android.view.animation.DecelerateInterpolator;
+
+import com.android.launcher3.allapps.AllAppsContainerView;
+import com.android.launcher3.util.UiThreadCircularReveal;
+import com.android.launcher3.util.Thunk;
+import com.android.launcher3.widget.WidgetsContainerView;
+
+import java.util.HashMap;
+
+/**
+ * TODO: figure out what kind of tests we can write for this
+ *
+ * Things to test when changing the following class.
+ * - Home from workspace
+ * - from center screen
+ * - from other screens
+ * - Home from all apps
+ * - from center screen
+ * - from other screens
+ * - Back from all apps
+ * - from center screen
+ * - from other screens
+ * - Launch app from workspace and quit
+ * - with back
+ * - with home
+ * - Launch app from all apps and quit
+ * - with back
+ * - with home
+ * - Go to a screen that's not the default, then all
+ * apps, and launch and app, and go back
+ * - with back
+ * -with home
+ * - On workspace, long press power and go back
+ * - with back
+ * - with home
+ * - On all apps, long press power and go back
+ * - with back
+ * - with home
+ * - On workspace, power off
+ * - On all apps, power off
+ * - Launch an app and turn off the screen while in that app
+ * - Go back with home key
+ * - Go back with back key TODO: make this not go to workspace
+ * - From all apps
+ * - From workspace
+ * - Enter and exit car mode (becuase it causes an extra configuration changed)
+ * - From all apps
+ * - From the center workspace
+ * - From another workspace
+ */
+public class LauncherStateTransitionAnimation {
+
+ /**
+ * Callbacks made during the state transition
+ */
+ interface Callbacks {
+ public void onStateTransitionHideSearchBar();
+ }
+
+ /**
+ * Private callbacks made during transition setup.
+ */
+ static abstract class PrivateTransitionCallbacks {
+ float getMaterialRevealViewFinalAlpha(View revealView) {
+ return 0;
+ }
+ float getMaterialRevealViewStartFinalRadius() {
+ return 0;
+ }
+ AnimatorListenerAdapter getMaterialRevealViewAnimatorListener(View revealView,
+ View buttonView) {
+ return null;
+ }
+ void onTransitionComplete() {}
+ }
+
+ public static final String TAG = "LauncherStateTransitionAnimation";
+
+ // Flags to determine how to set the layers on views before the transition animation
+ public static final int BUILD_LAYER = 0;
+ public static final int BUILD_AND_SET_LAYER = 1;
+ public static final int SINGLE_FRAME_DELAY = 16;
+
+ @Thunk Launcher mLauncher;
+ @Thunk Callbacks mCb;
+ @Thunk AnimatorSet mStateAnimation;
+
+ public LauncherStateTransitionAnimation(Launcher l, Callbacks cb) {
+ mLauncher = l;
+ mCb = cb;
+ }
+
+ /**
+ * Starts an animation to the apps view.
+ *
+ * @param startSearchAfterTransition Immediately starts app search after the transition to
+ * All Apps is completed.
+ */
+ public void startAnimationToAllApps(final boolean animated,
+ final boolean startSearchAfterTransition) {
+ final AllAppsContainerView toView = mLauncher.getAppsView();
+ final View buttonView = mLauncher.getAllAppsButton();
+ PrivateTransitionCallbacks cb = new PrivateTransitionCallbacks() {
+ @Override
+ public float getMaterialRevealViewFinalAlpha(View revealView) {
+ return 1f;
+ }
+ @Override
+ public float getMaterialRevealViewStartFinalRadius() {
+ int allAppsButtonSize = mLauncher.getDeviceProfile().allAppsButtonVisualSize;
+ return allAppsButtonSize / 2;
+ }
+ @Override
+ public AnimatorListenerAdapter getMaterialRevealViewAnimatorListener(
+ final View revealView, final View allAppsButtonView) {
+ return new AnimatorListenerAdapter() {
+ public void onAnimationStart(Animator animation) {
+ allAppsButtonView.setVisibility(View.INVISIBLE);
+ }
+ public void onAnimationEnd(Animator animation) {
+ allAppsButtonView.setVisibility(View.VISIBLE);
+ }
+ };
+ }
+ @Override
+ void onTransitionComplete() {
+ if (startSearchAfterTransition) {
+ toView.startAppsSearch();
+ }
+ }
+ };
+ // Only animate the search bar if animating from spring loaded mode back to all apps
+ startAnimationToOverlay(Workspace.State.NORMAL_HIDDEN, buttonView, toView,
+ toView.getContentView(), toView.getRevealView(), toView.getSearchBarView(),
+ animated, true /* hideSearchBar */, cb);
+ }
+
+ /**
+ * Starts an animation to the widgets view.
+ */
+ public void startAnimationToWidgets(final boolean animated) {
+ final WidgetsContainerView toView = mLauncher.getWidgetsView();
+ final View buttonView = mLauncher.getWidgetsButton();
+
+ PrivateTransitionCallbacks cb = new PrivateTransitionCallbacks() {
+ @Override
+ public float getMaterialRevealViewFinalAlpha(View revealView) {
+ return 0.3f;
+ }
+ };
+ startAnimationToOverlay(Workspace.State.OVERVIEW_HIDDEN, buttonView, toView,
+ toView.getContentView(), toView.getRevealView(), null, animated,
+ true /* hideSearchBar */, cb);
+ }
+
+ /**
+ * Starts and animation to the workspace from the current overlay view.
+ */
+ public void startAnimationToWorkspace(final Launcher.State fromState,
+ final Workspace.State toWorkspaceState, final int toWorkspacePage,
+ final boolean animated, final Runnable onCompleteRunnable) {
+ if (toWorkspaceState != Workspace.State.NORMAL &&
+ toWorkspaceState != Workspace.State.SPRING_LOADED &&
+ toWorkspaceState != Workspace.State.OVERVIEW) {
+ Log.e(TAG, "Unexpected call to startAnimationToWorkspace");
+ }
+
+ if (fromState == Launcher.State.APPS || fromState == Launcher.State.APPS_SPRING_LOADED) {
+ startAnimationToWorkspaceFromAllApps(toWorkspaceState, toWorkspacePage,
+ animated, onCompleteRunnable);
+ } else {
+ startAnimationToWorkspaceFromWidgets(toWorkspaceState, toWorkspacePage,
+ animated, onCompleteRunnable);
+ }
+ }
+
+ /**
+ * Creates and starts a new animation to a particular overlay view.
+ */
+ @SuppressLint("NewApi")
+ private void startAnimationToOverlay(final Workspace.State toWorkspaceState,
+ final View buttonView, final View toView, final View contentView, final View revealView,
+ final View overlaySearchBarView, final boolean animated, final boolean hideSearchBar,
+ final PrivateTransitionCallbacks pCb) {
+ final Resources res = mLauncher.getResources();
+ final boolean material = Utilities.isLmpOrAbove();
+ final int revealDuration = res.getInteger(R.integer.config_overlayRevealTime);
+ final int itemsAlphaStagger =
+ res.getInteger(R.integer.config_overlayItemsAlphaStagger);
+
+ final View fromView = mLauncher.getWorkspace();
+
+ final HashMap<View, Integer> layerViews = new HashMap<>();
+
+ // If for some reason our views aren't initialized, don't animate
+ boolean initialized = buttonView != null;
+
+ // Cancel the current animation
+ cancelAnimation();
+
+ // Create the workspace animation.
+ // NOTE: this call apparently also sets the state for the workspace if !animated
+ Animator workspaceAnim = mLauncher.startWorkspaceStateChangeAnimation(toWorkspaceState, -1,
+ animated, overlaySearchBarView != null /* hasOverlaySearchBar */, layerViews);
+
+ if (animated && initialized) {
+ mStateAnimation = LauncherAnimUtils.createAnimatorSet();
+
+ // Setup the reveal view animation
+ int width = revealView.getMeasuredWidth();
+ int height = revealView.getMeasuredHeight();
+ float revealRadius = (float) Math.hypot(width / 2, height / 2);
+ revealView.setVisibility(View.VISIBLE);
+ revealView.setAlpha(0f);
+ revealView.setTranslationY(0f);
+ revealView.setTranslationX(0f);
+
+ // Calculate the final animation values
+ final float revealViewToAlpha;
+ final float revealViewToXDrift;
+ final float revealViewToYDrift;
+ if (material) {
+ int[] buttonViewToPanelDelta = Utilities.getCenterDeltaInScreenSpace(revealView,
+ buttonView, null);
+ revealViewToAlpha = pCb.getMaterialRevealViewFinalAlpha(revealView);
+ revealViewToYDrift = buttonViewToPanelDelta[1];
+ revealViewToXDrift = buttonViewToPanelDelta[0];
+ } else {
+ revealViewToAlpha = 0f;
+ revealViewToYDrift = 2 * height / 3;
+ revealViewToXDrift = 0;
+ }
+
+ // Create the animators
+ PropertyValuesHolder panelAlpha =
+ PropertyValuesHolder.ofFloat("alpha", revealViewToAlpha, 1f);
+ PropertyValuesHolder panelDriftY =
+ PropertyValuesHolder.ofFloat("translationY", revealViewToYDrift, 0);
+ PropertyValuesHolder panelDriftX =
+ PropertyValuesHolder.ofFloat("translationX", revealViewToXDrift, 0);
+ ObjectAnimator panelAlphaAndDrift = ObjectAnimator.ofPropertyValuesHolder(revealView,
+ panelAlpha, panelDriftY, panelDriftX);
+ panelAlphaAndDrift.setDuration(revealDuration);
+ panelAlphaAndDrift.setInterpolator(new LogDecelerateInterpolator(100, 0));
+
+ // Play the animation
+ layerViews.put(revealView, BUILD_AND_SET_LAYER);
+ mStateAnimation.play(panelAlphaAndDrift);
+
+ if (overlaySearchBarView != null) {
+ overlaySearchBarView.setAlpha(0f);
+ ObjectAnimator searchBarAlpha = ObjectAnimator.ofFloat(overlaySearchBarView, "alpha", 0f, 1f);
+ searchBarAlpha.setDuration(100);
+ searchBarAlpha.setInterpolator(new AccelerateInterpolator(1.5f));
+ layerViews.put(overlaySearchBarView, BUILD_AND_SET_LAYER);
+ mStateAnimation.play(searchBarAlpha);
+ }
+
+ // Setup the animation for the content view
+ contentView.setVisibility(View.VISIBLE);
+ contentView.setAlpha(0f);
+ contentView.setTranslationY(revealViewToYDrift);
+ layerViews.put(contentView, BUILD_AND_SET_LAYER);
+
+ // Create the individual animators
+ ObjectAnimator pageDrift = ObjectAnimator.ofFloat(contentView, "translationY",
+ revealViewToYDrift, 0);
+ pageDrift.setDuration(revealDuration);
+ pageDrift.setInterpolator(new LogDecelerateInterpolator(100, 0));
+ pageDrift.setStartDelay(itemsAlphaStagger);
+ mStateAnimation.play(pageDrift);
+
+ ObjectAnimator itemsAlpha = ObjectAnimator.ofFloat(contentView, "alpha", 0f, 1f);
+ itemsAlpha.setDuration(revealDuration);
+ itemsAlpha.setInterpolator(new AccelerateInterpolator(1.5f));
+ itemsAlpha.setStartDelay(itemsAlphaStagger);
+ mStateAnimation.play(itemsAlpha);
+
+ if (material) {
+ float startRadius = pCb.getMaterialRevealViewStartFinalRadius();
+ AnimatorListenerAdapter listener = pCb.getMaterialRevealViewAnimatorListener(
+ revealView, buttonView);
+ Animator reveal = UiThreadCircularReveal.createCircularReveal(revealView, width / 2,
+ height / 2, startRadius, revealRadius);
+ reveal.setDuration(revealDuration);
+ reveal.setInterpolator(new LogDecelerateInterpolator(100, 0));
+ if (listener != null) {
+ reveal.addListener(listener);
+ }
+ mStateAnimation.play(reveal);
+ }
+
+ mStateAnimation.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ dispatchOnLauncherTransitionEnd(fromView, animated, false);
+ dispatchOnLauncherTransitionEnd(toView, animated, false);
+
+ // Hide the reveal view
+ revealView.setVisibility(View.INVISIBLE);
+
+ // Disable all necessary layers
+ for (View v : layerViews.keySet()) {
+ if (layerViews.get(v) == BUILD_AND_SET_LAYER) {
+ v.setLayerType(View.LAYER_TYPE_NONE, null);
+ }
+ }
+
+ if (hideSearchBar) {
+ mCb.onStateTransitionHideSearchBar();
+ }
+
+ // This can hold unnecessary references to views.
+ mStateAnimation = null;
+ pCb.onTransitionComplete();
+ }
+
+ });
+
+ // Play the workspace animation
+ if (workspaceAnim != null) {
+ mStateAnimation.play(workspaceAnim);
+ }
+
+ // Dispatch the prepare transition signal
+ dispatchOnLauncherTransitionPrepare(fromView, animated, false);
+ dispatchOnLauncherTransitionPrepare(toView, animated, false);
+
+
+ final AnimatorSet stateAnimation = mStateAnimation;
+ final Runnable startAnimRunnable = new Runnable() {
+ public void run() {
+ // Check that mStateAnimation hasn't changed while
+ // we waited for a layout/draw pass
+ if (mStateAnimation != stateAnimation)
+ return;
+ dispatchOnLauncherTransitionStart(fromView, animated, false);
+ dispatchOnLauncherTransitionStart(toView, animated, false);
+
+ // Enable all necessary layers
+ boolean isLmpOrAbove = Utilities.isLmpOrAbove();
+ for (View v : layerViews.keySet()) {
+ if (layerViews.get(v) == BUILD_AND_SET_LAYER) {
+ v.setLayerType(View.LAYER_TYPE_HARDWARE, null);
+ }
+ if (isLmpOrAbove && Utilities.isViewAttachedToWindow(v)) {
+ v.buildLayer();
+ }
+ }
+
+ // Focus the new view
+ toView.requestFocus();
+
+ mStateAnimation.start();
+ }
+ };
+ toView.bringToFront();
+ toView.setVisibility(View.VISIBLE);
+ toView.post(startAnimRunnable);
+ } else {
+ toView.setTranslationX(0.0f);
+ toView.setTranslationY(0.0f);
+ toView.setScaleX(1.0f);
+ toView.setScaleY(1.0f);
+ toView.setVisibility(View.VISIBLE);
+ toView.bringToFront();
+
+ // Show the content view
+ contentView.setVisibility(View.VISIBLE);
+
+ if (hideSearchBar) {
+ mCb.onStateTransitionHideSearchBar();
+ }
+
+ dispatchOnLauncherTransitionPrepare(fromView, animated, false);
+ dispatchOnLauncherTransitionStart(fromView, animated, false);
+ dispatchOnLauncherTransitionEnd(fromView, animated, false);
+ dispatchOnLauncherTransitionPrepare(toView, animated, false);
+ dispatchOnLauncherTransitionStart(toView, animated, false);
+ dispatchOnLauncherTransitionEnd(toView, animated, false);
+ pCb.onTransitionComplete();
+ }
+ }
+
+ /**
+ * Starts and animation to the workspace from the apps view.
+ */
+ private void startAnimationToWorkspaceFromAllApps(final Workspace.State toWorkspaceState,
+ final int toWorkspacePage, final boolean animated, final Runnable onCompleteRunnable) {
+ AllAppsContainerView appsView = mLauncher.getAppsView();
+ PrivateTransitionCallbacks cb = new PrivateTransitionCallbacks() {
+ int[] mAllAppsToPanelDelta;
+
+ @Override
+ float getMaterialRevealViewFinalAlpha(View revealView) {
+ // No alpha anim from all apps
+ return 1f;
+ }
+ @Override
+ float getMaterialRevealViewStartFinalRadius() {
+ int allAppsButtonSize = mLauncher.getDeviceProfile().allAppsButtonVisualSize;
+ return allAppsButtonSize / 2;
+ }
+ @Override
+ public AnimatorListenerAdapter getMaterialRevealViewAnimatorListener(
+ final View revealView, final View allAppsButtonView) {
+ return new AnimatorListenerAdapter() {
+ public void onAnimationStart(Animator animation) {
+ // We set the alpha instead of visibility to ensure that the focus does not
+ // get taken from the all apps view
+ allAppsButtonView.setVisibility(View.VISIBLE);
+ allAppsButtonView.setAlpha(0f);
+ }
+ public void onAnimationEnd(Animator animation) {
+ // Hide the reveal view
+ revealView.setVisibility(View.INVISIBLE);
+
+ // Show the all apps button, and focus it
+ allAppsButtonView.setAlpha(1f);
+ }
+ };
+ }
+ };
+ // Only animate the search bar if animating to spring loaded mode from all apps
+ startAnimationToWorkspaceFromOverlay(toWorkspaceState, toWorkspacePage,
+ mLauncher.getAllAppsButton(), appsView, appsView.getContentView(),
+ appsView.getRevealView(), appsView.getSearchBarView(), animated,
+ onCompleteRunnable, cb);
+ }
+
+ /**
+ * Starts and animation to the workspace from the widgets view.
+ */
+ private void startAnimationToWorkspaceFromWidgets(final Workspace.State toWorkspaceState,
+ final int toWorkspacePage, final boolean animated, final Runnable onCompleteRunnable) {
+ final WidgetsContainerView widgetsView = mLauncher.getWidgetsView();
+ PrivateTransitionCallbacks cb = new PrivateTransitionCallbacks() {
+ @Override
+ float getMaterialRevealViewFinalAlpha(View revealView) {
+ return 0.3f;
+ }
+ @Override
+ public AnimatorListenerAdapter getMaterialRevealViewAnimatorListener(
+ final View revealView, final View widgetsButtonView) {
+ return new AnimatorListenerAdapter() {
+ public void onAnimationEnd(Animator animation) {
+ // Hide the reveal view
+ revealView.setVisibility(View.INVISIBLE);
+ }
+ };
+ }
+ };
+ startAnimationToWorkspaceFromOverlay(toWorkspaceState, toWorkspacePage,
+ mLauncher.getWidgetsButton(), widgetsView, widgetsView.getContentView(),
+ widgetsView.getRevealView(), null, animated, onCompleteRunnable, cb);
+ }
+
+ /**
+ * Creates and starts a new animation to the workspace.
+ */
+ private void startAnimationToWorkspaceFromOverlay(final Workspace.State toWorkspaceState,
+ final int toWorkspacePage, final View buttonView, final View fromView,
+ final View contentView, final View revealView, final View overlaySearchBarView,
+ final boolean animated, final Runnable onCompleteRunnable,
+ final PrivateTransitionCallbacks pCb) {
+ final Resources res = mLauncher.getResources();
+ final boolean material = Utilities.isLmpOrAbove();
+ final int revealDuration = res.getInteger(R.integer.config_overlayRevealTime);
+ final int itemsAlphaStagger =
+ res.getInteger(R.integer.config_overlayItemsAlphaStagger);
+
+ final View toView = mLauncher.getWorkspace();
+
+ final HashMap<View, Integer> layerViews = new HashMap<>();
+
+ // If for some reason our views aren't initialized, don't animate
+ boolean initialized = buttonView != null;
+
+ // Cancel the current animation
+ cancelAnimation();
+
+ // Create the workspace animation.
+ // NOTE: this call apparently also sets the state for the workspace if !animated
+ Animator workspaceAnim = mLauncher.startWorkspaceStateChangeAnimation(toWorkspaceState,
+ toWorkspacePage, animated, overlaySearchBarView != null /* hasOverlaySearchBar */,
+ layerViews);
+
+ if (animated && initialized) {
+ mStateAnimation = LauncherAnimUtils.createAnimatorSet();
+
+ // Play the workspace animation
+ if (workspaceAnim != null) {
+ mStateAnimation.play(workspaceAnim);
+ }
+
+ // 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.
+ if (fromView.getVisibility() == View.VISIBLE) {
+ int width = revealView.getMeasuredWidth();
+ int height = revealView.getMeasuredHeight();
+ float revealRadius = (float) Math.hypot(width / 2, height / 2);
+ revealView.setVisibility(View.VISIBLE);
+ revealView.setAlpha(1f);
+ revealView.setTranslationY(0);
+ layerViews.put(revealView, BUILD_AND_SET_LAYER);
+
+ // Calculate the final animation values
+ final float revealViewToXDrift;
+ final float revealViewToYDrift;
+ if (material) {
+ int[] buttonViewToPanelDelta = Utilities.getCenterDeltaInScreenSpace(revealView,
+ buttonView, null);
+ revealViewToYDrift = buttonViewToPanelDelta[1];
+ revealViewToXDrift = buttonViewToPanelDelta[0];
+ } else {
+ revealViewToYDrift = 2 * height / 3;
+ revealViewToXDrift = 0;
+ }
+
+ // The vertical motion of the apps panel should be delayed by one frame
+ // from the conceal animation in order to give the right feel. We correspondingly
+ // shorten the duration so that the slide and conceal end at the same time.
+ TimeInterpolator decelerateInterpolator = material ?
+ new LogDecelerateInterpolator(100, 0) :
+ new DecelerateInterpolator(1f);
+ ObjectAnimator panelDriftY = ObjectAnimator.ofFloat(revealView, "translationY",
+ 0, revealViewToYDrift);
+ panelDriftY.setDuration(revealDuration - SINGLE_FRAME_DELAY);
+ panelDriftY.setStartDelay(itemsAlphaStagger + SINGLE_FRAME_DELAY);
+ panelDriftY.setInterpolator(decelerateInterpolator);
+ mStateAnimation.play(panelDriftY);
+
+ ObjectAnimator panelDriftX = ObjectAnimator.ofFloat(revealView, "translationX",
+ 0, revealViewToXDrift);
+ panelDriftX.setDuration(revealDuration - SINGLE_FRAME_DELAY);
+ panelDriftX.setStartDelay(itemsAlphaStagger + SINGLE_FRAME_DELAY);
+ panelDriftX.setInterpolator(decelerateInterpolator);
+ mStateAnimation.play(panelDriftX);
+
+ // Setup animation for the reveal panel alpha
+ final float revealViewToAlpha = !material ? 0f :
+ pCb.getMaterialRevealViewFinalAlpha(revealView);
+ if (revealViewToAlpha != 1f) {
+ ObjectAnimator panelAlpha = ObjectAnimator.ofFloat(revealView, "alpha",
+ 1f, revealViewToAlpha);
+ panelAlpha.setDuration(material ? revealDuration : 150);
+ panelAlpha.setStartDelay(material ? 0 : itemsAlphaStagger + SINGLE_FRAME_DELAY);
+ panelAlpha.setInterpolator(decelerateInterpolator);
+ mStateAnimation.play(panelAlpha);
+ }
+
+ // Setup the animation for the content view
+ layerViews.put(contentView, BUILD_AND_SET_LAYER);
+
+ // Create the individual animators
+ ObjectAnimator pageDrift = ObjectAnimator.ofFloat(contentView, "translationY",
+ 0, revealViewToYDrift);
+ contentView.setTranslationY(0);
+ pageDrift.setDuration(revealDuration - SINGLE_FRAME_DELAY);
+ pageDrift.setInterpolator(decelerateInterpolator);
+ pageDrift.setStartDelay(itemsAlphaStagger + SINGLE_FRAME_DELAY);
+ mStateAnimation.play(pageDrift);
+
+ contentView.setAlpha(1f);
+ ObjectAnimator itemsAlpha = ObjectAnimator.ofFloat(contentView, "alpha", 1f, 0f);
+ itemsAlpha.setDuration(100);
+ itemsAlpha.setInterpolator(decelerateInterpolator);
+ mStateAnimation.play(itemsAlpha);
+
+ if (overlaySearchBarView != null) {
+ overlaySearchBarView.setAlpha(1f);
+ ObjectAnimator searchAlpha = ObjectAnimator.ofFloat(overlaySearchBarView, "alpha", 1f, 0f);
+ searchAlpha.setDuration(material ? 100 : 150);
+ searchAlpha.setInterpolator(decelerateInterpolator);
+ searchAlpha.setStartDelay(material ? 0 : itemsAlphaStagger + SINGLE_FRAME_DELAY);
+ layerViews.put(overlaySearchBarView, BUILD_AND_SET_LAYER);
+ mStateAnimation.play(searchAlpha);
+ }
+
+ if (material) {
+ // Animate the all apps button
+ float finalRadius = pCb.getMaterialRevealViewStartFinalRadius();
+ AnimatorListenerAdapter listener =
+ pCb.getMaterialRevealViewAnimatorListener(revealView, buttonView);
+ Animator reveal = UiThreadCircularReveal.createCircularReveal(revealView, width / 2,
+ height / 2, revealRadius, finalRadius);
+ reveal.setInterpolator(new LogDecelerateInterpolator(100, 0));
+ reveal.setDuration(revealDuration);
+ reveal.setStartDelay(itemsAlphaStagger);
+ if (listener != null) {
+ reveal.addListener(listener);
+ }
+ mStateAnimation.play(reveal);
+ }
+
+ dispatchOnLauncherTransitionPrepare(fromView, animated, true);
+ dispatchOnLauncherTransitionPrepare(toView, animated, true);
+ }
+
+ mStateAnimation.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ fromView.setVisibility(View.GONE);
+ dispatchOnLauncherTransitionEnd(fromView, animated, true);
+ dispatchOnLauncherTransitionEnd(toView, animated, true);
+
+ // Run any queued runnables
+ if (onCompleteRunnable != null) {
+ onCompleteRunnable.run();
+ }
+
+ // Disable all necessary layers
+ for (View v : layerViews.keySet()) {
+ if (layerViews.get(v) == BUILD_AND_SET_LAYER) {
+ v.setLayerType(View.LAYER_TYPE_NONE, null);
+ }
+ }
+
+ // Reset page transforms
+ if (contentView != null) {
+ contentView.setTranslationX(0);
+ contentView.setTranslationY(0);
+ contentView.setAlpha(1);
+ }
+ if (overlaySearchBarView != null) {
+ overlaySearchBarView.setAlpha(1f);
+ }
+
+ // This can hold unnecessary references to views.
+ mStateAnimation = null;
+ pCb.onTransitionComplete();
+ }
+ });
+
+ final AnimatorSet stateAnimation = mStateAnimation;
+ final Runnable startAnimRunnable = new Runnable() {
+ public void run() {
+ // Check that mStateAnimation hasn't changed while
+ // we waited for a layout/draw pass
+ if (mStateAnimation != stateAnimation)
+ return;
+ dispatchOnLauncherTransitionStart(fromView, animated, false);
+ dispatchOnLauncherTransitionStart(toView, animated, false);
+
+ // Enable all necessary layers
+ boolean isLmpOrAbove = Utilities.isLmpOrAbove();
+ for (View v : layerViews.keySet()) {
+ if (layerViews.get(v) == BUILD_AND_SET_LAYER) {
+ v.setLayerType(View.LAYER_TYPE_HARDWARE, null);
+ }
+ if (isLmpOrAbove && Utilities.isViewAttachedToWindow(v)) {
+ v.buildLayer();
+ }
+ }
+ mStateAnimation.start();
+ }
+ };
+ fromView.post(startAnimRunnable);
+ } else {
+ fromView.setVisibility(View.GONE);
+ dispatchOnLauncherTransitionPrepare(fromView, animated, true);
+ dispatchOnLauncherTransitionStart(fromView, animated, true);
+ dispatchOnLauncherTransitionEnd(fromView, animated, true);
+ dispatchOnLauncherTransitionPrepare(toView, animated, true);
+ dispatchOnLauncherTransitionStart(toView, animated, true);
+ dispatchOnLauncherTransitionEnd(toView, animated, true);
+ pCb.onTransitionComplete();
+
+ // Run any queued runnables
+ if (onCompleteRunnable != null) {
+ onCompleteRunnable.run();
+ }
+ }
+ }
+
+
+ /**
+ * Dispatches the prepare-transition event to suitable views.
+ */
+ void dispatchOnLauncherTransitionPrepare(View v, boolean animated, boolean toWorkspace) {
+ if (v instanceof LauncherTransitionable) {
+ ((LauncherTransitionable) v).onLauncherTransitionPrepare(mLauncher, animated,
+ toWorkspace);
+ }
+ }
+
+ /**
+ * Dispatches the start-transition event to suitable views.
+ */
+ void dispatchOnLauncherTransitionStart(View v, boolean animated, boolean toWorkspace) {
+ if (v instanceof LauncherTransitionable) {
+ ((LauncherTransitionable) v).onLauncherTransitionStart(mLauncher, animated,
+ toWorkspace);
+ }
+
+ // Update the workspace transition step as well
+ dispatchOnLauncherTransitionStep(v, 0f);
+ }
+
+ /**
+ * Dispatches the step-transition event to suitable views.
+ */
+ void dispatchOnLauncherTransitionStep(View v, float t) {
+ if (v instanceof LauncherTransitionable) {
+ ((LauncherTransitionable) v).onLauncherTransitionStep(mLauncher, t);
+ }
+ }
+
+ /**
+ * Dispatches the end-transition event to suitable views.
+ */
+ void dispatchOnLauncherTransitionEnd(View v, boolean animated, boolean toWorkspace) {
+ if (v instanceof LauncherTransitionable) {
+ ((LauncherTransitionable) v).onLauncherTransitionEnd(mLauncher, animated,
+ toWorkspace);
+ }
+
+ // Update the workspace transition step as well
+ dispatchOnLauncherTransitionStep(v, 1f);
+ }
+
+ /**
+ * Cancels the current animation.
+ */
+ private void cancelAnimation() {
+ if (mStateAnimation != null) {
+ mStateAnimation.setDuration(0);
+ mStateAnimation.cancel();
+ mStateAnimation = null;
+ }
+ }
+}
diff --git a/src/com/android/launcher3/LauncherApplication.java b/src/com/android/launcher3/LauncherTransitionable.java
index 8b179f1e7..49af6928a 100644
--- a/src/com/android/launcher3/LauncherApplication.java
+++ b/src/com/android/launcher3/LauncherTransitionable.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013 The Android Open Source Project
+ * 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.
@@ -16,19 +16,12 @@
package com.android.launcher3;
-import android.app.Application;
-
-public class LauncherApplication extends Application {
- @Override
- public void onCreate() {
- super.onCreate();
- LauncherAppState.setApplicationContext(this);
- LauncherAppState.getInstance();
- }
-
- @Override
- public void onTerminate() {
- super.onTerminate();
- LauncherAppState.getInstance().onTerminate();
- }
-} \ No newline at end of file
+/**
+ * An interface to get callbacks during a launcher transition.
+ */
+public interface LauncherTransitionable {
+ void onLauncherTransitionPrepare(Launcher l, boolean animated, boolean toWorkspace);
+ void onLauncherTransitionStart(Launcher l, boolean animated, boolean toWorkspace);
+ void onLauncherTransitionStep(Launcher l, float t);
+ void onLauncherTransitionEnd(Launcher l, boolean animated, boolean toWorkspace);
+}
diff --git a/src/com/android/launcher3/MemoryTracker.java b/src/com/android/launcher3/MemoryTracker.java
index 2d37c809e..067a50f97 100644
--- a/src/com/android/launcher3/MemoryTracker.java
+++ b/src/com/android/launcher3/MemoryTracker.java
@@ -101,7 +101,7 @@ public class MemoryTracker extends Service {
public void startTrackingProcess(int pid, String name, long start) {
synchronized (mLock) {
- final Long lpid = new Long(pid);
+ final Long lpid = Long.valueOf(pid);
if (mPids.contains(lpid)) return;
diff --git a/src/com/android/launcher3/PackageChangedReceiver.java b/src/com/android/launcher3/PackageChangedReceiver.java
deleted file mode 100644
index e59f6d81d..000000000
--- a/src/com/android/launcher3/PackageChangedReceiver.java
+++ /dev/null
@@ -1,21 +0,0 @@
-package com.android.launcher3;
-
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-
-public class PackageChangedReceiver extends BroadcastReceiver {
- @Override
- public void onReceive(final Context context, Intent intent) {
- final String packageName = intent.getData().getSchemeSpecificPart();
-
- if (packageName == null || packageName.length() == 0) {
- // they sent us a bad intent
- return;
- }
- // in rare cases the receiver races with the application to set up LauncherAppState
- LauncherAppState.setApplicationContext(context.getApplicationContext());
- LauncherAppState app = LauncherAppState.getInstance();
- WidgetPreviewLoader.removePackageFromDb(app.getWidgetPreviewCacheDb(), packageName);
- }
-}
diff --git a/src/com/android/launcher3/PagedView.java b/src/com/android/launcher3/PagedView.java
index 7d65f4686..218c1a36f 100644
--- a/src/com/android/launcher3/PagedView.java
+++ b/src/com/android/launcher3/PagedView.java
@@ -19,16 +19,16 @@ package com.android.launcher3;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
+import android.animation.LayoutTransition;
import android.animation.ObjectAnimator;
import android.animation.TimeInterpolator;
-import android.animation.ValueAnimator;
-import android.animation.ValueAnimator.AnimatorUpdateListener;
+import android.annotation.TargetApi;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Matrix;
-import android.graphics.PointF;
import android.graphics.Rect;
+import android.os.Build;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
@@ -46,20 +46,12 @@ import android.view.ViewParent;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityManager;
import android.view.accessibility.AccessibilityNodeInfo;
-import android.view.animation.AnimationUtils;
-import android.view.animation.DecelerateInterpolator;
import android.view.animation.Interpolator;
-import android.view.animation.LinearInterpolator;
-import java.util.ArrayList;
+import com.android.launcher3.util.LauncherEdgeEffect;
+import com.android.launcher3.util.Thunk;
-interface Page {
- public int getPageChildCount();
- public View getChildOnPageAt(int i);
- public void removeAllViewsOnPage();
- public void removeViewOnPageAt(int i);
- public int indexOfChildOnPage(View v);
-}
+import java.util.ArrayList;
/**
* An abstraction of the original Workspace which supports browsing through a
@@ -74,28 +66,21 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
private static final int MIN_LENGTH_FOR_FLING = 25;
protected static final int PAGE_SNAP_ANIMATION_DURATION = 750;
- protected static final int OVER_SCROLL_PAGE_SNAP_ANIMATION_DURATION = 350;
protected static final int SLOW_PAGE_SNAP_ANIMATION_DURATION = 950;
protected static final float NANOTIME_DIV = 1000000000.0f;
- private static final float OVERSCROLL_ACCELERATE_FACTOR = 2;
- private static final float OVERSCROLL_DAMP_FACTOR = 0.07f;
-
private static final float RETURN_TO_ORIGINAL_PAGE_THRESHOLD = 0.33f;
// The page is moved more than halfway, automatically move to the next page on touch up.
private static final float SIGNIFICANT_MOVE_THRESHOLD = 0.4f;
+ private static final float MAX_SCROLL_PROGRESS = 1.0f;
+
// The following constants need to be scaled based on density. The scaled versions will be
// assigned to the corresponding member variables below.
private static final int FLING_THRESHOLD_VELOCITY = 500;
private static final int MIN_SNAP_VELOCITY = 1500;
private static final int MIN_FLING_VELOCITY = 250;
- // We are disabling touch interaction of the widget region for factory ROM.
- private static final boolean DISABLE_TOUCH_INTERACTION = false;
- private static final boolean DISABLE_TOUCH_SIDE_PAGES = true;
- private static final boolean DISABLE_FLING_TO_DELETE = true;
-
public static final int INVALID_RESTORE_PAGE = -1001;
private boolean mFreeScroll = false;
@@ -124,7 +109,7 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
protected LauncherScroller mScroller;
private Interpolator mDefaultInterpolator;
private VelocityTracker mVelocityTracker;
- private int mPageSpacing = 0;
+ @Thunk int mPageSpacing = 0;
private float mParentDownMotionX;
private float mParentDownMotionY;
@@ -156,7 +141,6 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
protected OnLongClickListener mLongClickListener;
protected int mTouchSlop;
- private int mPagingTouchSlop;
private int mMaximumVelocity;
protected int mPageLayoutWidthGap;
protected int mPageLayoutHeightGap;
@@ -164,15 +148,8 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
protected int mCellCountY = 0;
protected boolean mCenterPagesVertically;
protected boolean mAllowOverScroll = true;
- protected int mUnboundedScrollX;
protected int[] mTempVisiblePagesRange = new int[2];
protected boolean mForceDrawAllChildrenNextFrame;
- private boolean mSpacePagesAutomatically = false;
-
- // mOverScrollX is equal to getScrollX() when we're within the normal scroll range. Otherwise
- // it is equal to the scaled overscroll position. We use a separate value so as to prevent
- // the screens from continuing to translate beyond the normal bounds.
- protected int mOverScrollX;
protected static final int INVALID_POINTER = -1;
@@ -180,37 +157,16 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
private PageSwitchListener mPageSwitchListener;
- protected ArrayList<Boolean> mDirtyPageContent;
-
- // If true, syncPages and syncPageItems will be called to refresh pages
- protected boolean mContentIsRefreshable = true;
-
// If true, modify alpha of neighboring pages as user scrolls left/right
protected boolean mFadeInAdjacentScreens = false;
- // It true, use a different slop parameter (pagingTouchSlop = 2 * touchSlop) for deciding
- // to switch to a new page
- protected boolean mUsePagingTouchSlop = true;
-
- // If true, the subclass should directly update scrollX itself in its computeScroll method
- // (SmoothPagedView does this)
- protected boolean mDeferScrollUpdate = false;
- protected boolean mDeferLoadAssociatedPagesUntilScrollCompletes = false;
-
protected boolean mIsPageMoving = false;
- // All syncs and layout passes are deferred until data is ready.
- protected boolean mIsDataReady = false;
-
- protected boolean mAllowLongPress = true;
-
private boolean mWasInOverscroll = false;
// Page Indicator
- private int mPageIndicatorViewId;
- private PageIndicator mPageIndicator;
- private boolean mAllowPagedViewAnimations = true;
-
+ @Thunk int mPageIndicatorViewId;
+ @Thunk PageIndicator mPageIndicator;
// The viewport whether the pages are to be contained (the actual view may be larger than the
// viewport)
private Rect mViewport = new Rect();
@@ -218,16 +174,15 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
// Reordering
// We use the min scale to determine how much to expand the actually PagedView measured
// dimensions such that when we are zoomed out, the view is not clipped
- private int REORDERING_DROP_REPOSITION_DURATION = 200;
- protected int REORDERING_REORDER_REPOSITION_DURATION = 300;
- protected int REORDERING_ZOOM_IN_OUT_DURATION = 250;
- private int REORDERING_SIDE_PAGE_HOVER_TIMEOUT = 80;
+ private static int REORDERING_DROP_REPOSITION_DURATION = 200;
+ @Thunk static int REORDERING_REORDER_REPOSITION_DURATION = 300;
+ private static int REORDERING_SIDE_PAGE_HOVER_TIMEOUT = 80;
+
private float mMinScale = 1f;
private boolean mUseMinScale = false;
protected View mDragView;
- protected AnimatorSet mZoomInOutAnim;
private Runnable mSidePageHoverRunnable;
- private int mSidePageHoverIndex = -1;
+ @Thunk int mSidePageHoverIndex = -1;
// This variable's scope is only for the duration of startReordering() and endReordering()
private boolean mReorderingStarted = false;
// This variable's scope is for the duration of startReordering() and after the zoomIn()
@@ -239,30 +194,17 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
private Runnable mPostReorderingPreZoomInRunnable;
// Convenience/caching
- private Matrix mTmpInvMatrix = new Matrix();
- private float[] mTmpPoint = new float[2];
- private int[] mTmpIntPoint = new int[2];
- private Rect mTmpRect = new Rect();
- private Rect mAltTmpRect = new Rect();
-
- // Fling to delete
- private int FLING_TO_DELETE_FADE_OUT_DURATION = 350;
- private float FLING_TO_DELETE_FRICTION = 0.035f;
- // The degrees specifies how much deviation from the up vector to still consider a fling "up"
- private float FLING_TO_DELETE_MAX_FLING_DEGREES = 65f;
- protected int mFlingToDeleteThresholdVelocity = -1400;
- // Drag to delete
- private boolean mDeferringForDelete = false;
- private int DELETE_SLIDE_IN_SIDE_PAGE_DURATION = 250;
- private int DRAG_TO_DELETE_FADE_OUT_DURATION = 350;
-
- // Drop to delete
- private View mDeleteDropTarget;
-
- // Bouncer
- private boolean mTopAlignPageWhenShrinkingForBouncer = false;
+ private static final Matrix sTmpInvMatrix = new Matrix();
+ private static final float[] sTmpPoint = new float[2];
+ private static final int[] sTmpIntPoint = new int[2];
+ private static final Rect sTmpRect = new Rect();
protected final Rect mInsets = new Rect();
+ protected final boolean mIsRtl;
+
+ // Edge effect
+ private final LauncherEdgeEffect mEdgeGlowLeft = new LauncherEdgeEffect();
+ private final LauncherEdgeEffect mEdgeGlowRight = new LauncherEdgeEffect();
public interface PageSwitchListener {
void onPageSwitch(View newPage, int newPageIndex);
@@ -290,6 +232,7 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
a.recycle();
setHapticFeedbackEnabled(false);
+ mIsRtl = Utilities.isRtl(getResources());
init();
}
@@ -297,8 +240,6 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
* Initializes various states for this workspace.
*/
protected void init() {
- mDirtyPageContent = new ArrayList<Boolean>();
- mDirtyPageContent.ensureCapacity(32);
mScroller = new LauncherScroller(getContext());
setDefaultInterpolator(new ScrollInterpolator());
mCurrentPage = 0;
@@ -306,18 +247,19 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
final ViewConfiguration configuration = ViewConfiguration.get(getContext());
mTouchSlop = configuration.getScaledPagingTouchSlop();
- mPagingTouchSlop = configuration.getScaledPagingTouchSlop();
mMaximumVelocity = configuration.getScaledMaximumFlingVelocity();
mDensity = getResources().getDisplayMetrics().density;
- // Scale the fling-to-delete threshold by the density
- mFlingToDeleteThresholdVelocity =
- (int) (mFlingToDeleteThresholdVelocity * mDensity);
-
mFlingThresholdVelocity = (int) (FLING_THRESHOLD_VELOCITY * mDensity);
mMinFlingVelocity = (int) (MIN_FLING_VELOCITY * mDensity);
mMinSnapVelocity = (int) (MIN_SNAP_VELOCITY * mDensity);
setOnHierarchyChangeListener(this);
+ setWillNotDraw(false);
+ }
+
+ protected void setEdgeGlowColor(int color) {
+ mEdgeGlowLeft.setColor(color);
+ mEdgeGlowRight.setColor(color);
}
protected void setDefaultInterpolator(Interpolator interpolator) {
@@ -333,7 +275,7 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
ViewGroup grandParent = (ViewGroup) parent.getParent();
if (mPageIndicator == null && mPageIndicatorViewId > -1) {
mPageIndicator = (PageIndicator) grandParent.findViewById(mPageIndicatorViewId);
- mPageIndicator.removeAllMarkers(mAllowPagedViewAnimations);
+ mPageIndicator.removeAllMarkers(true);
ArrayList<PageIndicator.PageMarkerResources> markers =
new ArrayList<PageIndicator.PageMarkerResources>();
@@ -341,7 +283,7 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
markers.add(getPageIndicatorMarker(i));
}
- mPageIndicator.addMarkers(markers, mAllowPagedViewAnimations);
+ mPageIndicator.addMarkers(markers, true);
OnClickListener listener = getPageIndicatorClickListener();
if (listener != null) {
@@ -359,33 +301,31 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
return null;
}
+ @Override
protected void onDetachedFromWindow() {
+ super.onDetachedFromWindow();
// Unhook the page indicator
mPageIndicator = null;
}
- void setDeleteDropTarget(View v) {
- mDeleteDropTarget = v;
- }
-
// Convenience methods to map points from self to parent and vice versa
- float[] mapPointFromViewToParent(View v, float x, float y) {
- mTmpPoint[0] = x;
- mTmpPoint[1] = y;
- v.getMatrix().mapPoints(mTmpPoint);
- mTmpPoint[0] += v.getLeft();
- mTmpPoint[1] += v.getTop();
- return mTmpPoint;
- }
- float[] mapPointFromParentToView(View v, float x, float y) {
- mTmpPoint[0] = x - v.getLeft();
- mTmpPoint[1] = y - v.getTop();
- v.getMatrix().invert(mTmpInvMatrix);
- mTmpInvMatrix.mapPoints(mTmpPoint);
- return mTmpPoint;
- }
-
- void updateDragViewTranslationDuringDrag() {
+ private float[] mapPointFromViewToParent(View v, float x, float y) {
+ sTmpPoint[0] = x;
+ sTmpPoint[1] = y;
+ v.getMatrix().mapPoints(sTmpPoint);
+ sTmpPoint[0] += v.getLeft();
+ sTmpPoint[1] += v.getTop();
+ return sTmpPoint;
+ }
+ private float[] mapPointFromParentToView(View v, float x, float y) {
+ sTmpPoint[0] = x - v.getLeft();
+ sTmpPoint[1] = y - v.getTop();
+ v.getMatrix().invert(sTmpInvMatrix);
+ sTmpInvMatrix.mapPoints(sTmpPoint);
+ return sTmpPoint;
+ }
+
+ private void updateDragViewTranslationDuringDrag() {
if (mDragView != null) {
float x = (mLastMotionX - mDownMotionX) + (getScrollX() - mDownScrollX) +
(mDragViewBaselineLeft - mDragView.getLeft());
@@ -453,33 +393,15 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
}
/**
- * Note: this is a reimplementation of View.isLayoutRtl() since that is currently hidden api.
- */
- public boolean isLayoutRtl() {
- return (getLayoutDirection() == LAYOUT_DIRECTION_RTL);
- }
-
- /**
- * Called by subclasses to mark that data is ready, and that we can begin loading and laying
- * out pages.
- */
- protected void setDataIsReady() {
- mIsDataReady = true;
- }
-
- protected boolean isDataReady() {
- return mIsDataReady;
- }
-
- /**
* Returns the index of the currently displayed page.
- *
- * @return The index of the currently displayed page.
*/
- int getCurrentPage() {
+ public int getCurrentPage() {
return mCurrentPage;
}
+ /**
+ * Returns the index of page to be shown immediately afterwards.
+ */
int getNextPage() {
return (mNextPage != INVALID_PAGE) ? mNextPage : mCurrentPage;
}
@@ -488,7 +410,7 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
return getChildCount();
}
- View getPageAt(int index) {
+ public View getPageAt(int index) {
return getChildAt(index);
}
@@ -512,17 +434,6 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
forceFinishScroller();
}
- /**
- * Called during AllApps/Home transitions to avoid unnecessary work. When that other animation
- * {@link #updateCurrentPageScroll()} should be called, to correctly set the final state and
- * re-enable scrolling.
- */
- void stopScrolling() {
- mCurrentPage = getNextPage();
- notifyPageSwitchListener();
- forceFinishScroller();
- }
-
private void abortScrollerAnimation(boolean resetNextPage) {
mScroller.abortAnimation();
// We need to clean up the next page here to avoid computeScrollHelper from
@@ -555,7 +466,7 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
/**
* Sets the current page.
*/
- void setCurrentPage(int currentPage) {
+ public void setCurrentPage(int currentPage) {
if (!mScroller.isFinished()) {
abortScrollerAnimation(true);
}
@@ -647,37 +558,41 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
@Override
public void scrollBy(int x, int y) {
- scrollTo(mUnboundedScrollX + x, getScrollY() + y);
+ scrollTo(getScrollX() + x, getScrollY() + y);
}
@Override
public void scrollTo(int x, int y) {
// In free scroll mode, we clamp the scrollX
if (mFreeScroll) {
+ // If the scroller is trying to move to a location beyond the maximum allowed
+ // in the free scroll mode, we make sure to end the scroll operation.
+ if (!mScroller.isFinished() &&
+ (x > mFreeScrollMaxScrollX || x < mFreeScrollMinScrollX)) {
+ forceFinishScroller();
+ }
+
x = Math.min(x, mFreeScrollMaxScrollX);
x = Math.max(x, mFreeScrollMinScrollX);
}
- final boolean isRtl = isLayoutRtl();
- mUnboundedScrollX = x;
-
- boolean isXBeforeFirstPage = isRtl ? (x > mMaxScrollX) : (x < 0);
- boolean isXAfterLastPage = isRtl ? (x < 0) : (x > mMaxScrollX);
+ boolean isXBeforeFirstPage = mIsRtl ? (x > mMaxScrollX) : (x < 0);
+ boolean isXAfterLastPage = mIsRtl ? (x < 0) : (x > mMaxScrollX);
if (isXBeforeFirstPage) {
- super.scrollTo(0, y);
+ super.scrollTo(mIsRtl ? mMaxScrollX : 0, y);
if (mAllowOverScroll) {
mWasInOverscroll = true;
- if (isRtl) {
+ if (mIsRtl) {
overScroll(x - mMaxScrollX);
} else {
overScroll(x);
}
}
} else if (isXAfterLastPage) {
- super.scrollTo(mMaxScrollX, y);
+ super.scrollTo(mIsRtl ? 0 : mMaxScrollX, y);
if (mAllowOverScroll) {
mWasInOverscroll = true;
- if (isRtl) {
+ if (mIsRtl) {
overScroll(x);
} else {
overScroll(x - mMaxScrollX);
@@ -688,7 +603,6 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
overScroll(0);
mWasInOverscroll = false;
}
- mOverScrollX = x;
super.scrollTo(x, y);
}
@@ -708,21 +622,17 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
AccessibilityManager am =
(AccessibilityManager) getContext().getSystemService(Context.ACCESSIBILITY_SERVICE);
if (am.isEnabled()) {
- AccessibilityEvent ev =
- AccessibilityEvent.obtain(AccessibilityEvent.TYPE_VIEW_SCROLLED);
- ev.setItemCount(getChildCount());
- ev.setFromIndex(mCurrentPage);
- ev.setToIndex(getNextPage());
-
- final int action;
- if (getNextPage() >= mCurrentPage) {
- action = AccessibilityNodeInfo.ACTION_SCROLL_FORWARD;
- } else {
- action = AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD;
+ if (mCurrentPage != getNextPage()) {
+ AccessibilityEvent ev =
+ AccessibilityEvent.obtain(AccessibilityEvent.TYPE_VIEW_SCROLLED);
+ ev.setScrollable(true);
+ ev.setScrollX(getScrollX());
+ ev.setScrollY(getScrollY());
+ ev.setMaxScrollX(mMaxScrollX);
+ ev.setMaxScrollY(0);
+
+ sendAccessibilityEventUnchecked(ev);
}
-
- ev.setAction(action);
- sendAccessibilityEventUnchecked(ev);
}
}
@@ -731,8 +641,7 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
if (mScroller.computeScrollOffset()) {
// Don't bother scrolling if the page does not need to be moved
if (getScrollX() != mScroller.getCurrX()
- || getScrollY() != mScroller.getCurrY()
- || mOverScrollX != mScroller.getCurrX()) {
+ || getScrollY() != mScroller.getCurrY()) {
float scaleX = mFreeScroll ? getScaleX() : 1f;
int scrollX = (int) (mScroller.getCurrX() * (1 / scaleX));
scrollTo(scrollX, mScroller.getCurrY());
@@ -746,12 +655,6 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
mNextPage = INVALID_PAGE;
notifyPageSwitchListener();
- // Load the associated pages if necessary
- if (mDeferLoadAssociatedPagesUntilScrollCompletes) {
- loadAssociatedPages(mCurrentPage);
- mDeferLoadAssociatedPagesUntilScrollCompletes = false;
- }
-
// We don't want to trigger a page end moving unless the page has settled
// and the user has stopped scrolling
if (mTouchState == TOUCH_STATE_REST) {
@@ -775,10 +678,6 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
computeScrollHelper();
}
- protected boolean shouldSetTopAlignedPivotForWidget(int childIndex) {
- return mTopAlignPageWhenShrinkingForBouncer;
- }
-
public static class LayoutParams extends ViewGroup.LayoutParams {
public boolean isFullScreenPage = false;
@@ -789,15 +688,35 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
super(width, height);
}
+ public LayoutParams(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
public LayoutParams(ViewGroup.LayoutParams source) {
super(source);
}
}
+ @Override
+ public LayoutParams generateLayoutParams(AttributeSet attrs) {
+ return new LayoutParams(getContext(), attrs);
+ }
+
+ @Override
protected LayoutParams generateDefaultLayoutParams() {
return new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
}
+ @Override
+ protected ViewGroup.LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) {
+ return new LayoutParams(p);
+ }
+
+ @Override
+ protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
+ return p instanceof LayoutParams;
+ }
+
public void addFullScreenPage(View page) {
LayoutParams lp = generateDefaultLayoutParams();
lp.isFullScreenPage = true;
@@ -810,7 +729,7 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- if (!mIsDataReady || getChildCount() == 0) {
+ if (getChildCount() == 0) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
return;
}
@@ -914,27 +833,12 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
}
}
- if (mSpacePagesAutomatically) {
- int spacing = (getViewportWidth() - mInsets.left - mInsets.right
- - referenceChildWidth) / 2;
- if (spacing >= 0) {
- setPageSpacing(spacing);
- }
- mSpacePagesAutomatically = false;
- }
setMeasuredDimension(scaledWidthSize, scaledHeightSize);
}
- /**
- * This method should be called once before first layout / measure pass.
- */
- protected void setSinglePageInViewport() {
- mSpacePagesAutomatically = true;
- }
-
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
- if (!mIsDataReady || getChildCount() == 0) {
+ if (getChildCount() == 0) {
return;
}
@@ -945,13 +849,11 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
int offsetY = getViewportOffsetY();
// Update the viewport offsets
- mViewport.offset(offsetX, offsetY);
-
- final boolean isRtl = isLayoutRtl();
+ mViewport.offset(offsetX, offsetY);
- final int startIndex = isRtl ? childCount - 1 : 0;
- final int endIndex = isRtl ? -1 : childCount;
- final int delta = isRtl ? -1 : 1;
+ final int startIndex = mIsRtl ? childCount - 1 : 0;
+ final int endIndex = mIsRtl ? -1 : childCount;
+ final int delta = mIsRtl ? -1 : 1;
int verticalPadding = getPaddingTop() + getPaddingBottom();
@@ -959,8 +861,8 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
LayoutParams nextLp;
int childLeft = offsetX + (lp.isFullScreenPage ? 0 : getPaddingLeft());
- if (mPageScrolls == null || getChildCount() != mChildCountOnLastLayout) {
- mPageScrolls = new int[getChildCount()];
+ if (mPageScrolls == null || childCount != mChildCountOnLastLayout) {
+ mPageScrolls = new int[childCount];
}
for (int i = startIndex; i != endIndex; i += delta) {
@@ -1003,24 +905,40 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
pageGap = getPaddingRight();
}
- childLeft += childWidth + pageGap;
+ childLeft += childWidth + pageGap + getChildGap();
}
}
- if (mFirstLayout && mCurrentPage >= 0 && mCurrentPage < getChildCount()) {
- updateCurrentPageScroll();
- mFirstLayout = false;
- }
+ final LayoutTransition transition = getLayoutTransition();
+ // If the transition is running defer updating max scroll, as some empty pages could
+ // still be present, and a max scroll change could cause sudden jumps in scroll.
+ if (transition != null && transition.isRunning()) {
+ transition.addTransitionListener(new LayoutTransition.TransitionListener() {
- if (childCount > 0) {
- final int index = isLayoutRtl() ? 0 : childCount - 1;
- mMaxScrollX = getScrollForPage(index);
+ @Override
+ public void startTransition(LayoutTransition transition, ViewGroup container,
+ View view, int transitionType) { }
+
+ @Override
+ public void endTransition(LayoutTransition transition, ViewGroup container,
+ View view, int transitionType) {
+ // Wait until all transitions are complete.
+ if (!transition.isRunning()) {
+ transition.removeTransitionListener(this);
+ updateMaxScrollX();
+ }
+ }
+ });
} else {
- mMaxScrollX = 0;
+ updateMaxScrollX();
}
- if (mScroller.isFinished() && mChildCountOnLastLayout != getChildCount() &&
- !mDeferringForDelete) {
+ if (mFirstLayout && mCurrentPage >= 0 && mCurrentPage < childCount) {
+ updateCurrentPageScroll();
+ mFirstLayout = false;
+ }
+
+ if (mScroller.isFinished() && mChildCountOnLastLayout != childCount) {
if (mRestorePage != INVALID_RESTORE_PAGE) {
setCurrentPage(mRestorePage);
mRestorePage = INVALID_RESTORE_PAGE;
@@ -1028,42 +946,37 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
setCurrentPage(getNextPage());
}
}
- mChildCountOnLastLayout = getChildCount();
+ mChildCountOnLastLayout = childCount;
if (isReordering(true)) {
updateDragViewTranslationDuringDrag();
}
}
- public void setPageSpacing(int pageSpacing) {
- mPageSpacing = pageSpacing;
- requestLayout();
+ protected int getChildGap() {
+ return 0;
}
- protected void screenScrolled(int screenCenter) {
- boolean isInOverscroll = mOverScrollX < 0 || mOverScrollX > mMaxScrollX;
-
- if (mFadeInAdjacentScreens && !isInOverscroll) {
- for (int i = 0; i < getChildCount(); i++) {
- View child = getChildAt(i);
- if (child != null) {
- float scrollProgress = getScrollProgress(screenCenter, child, i);
- float alpha = 1 - Math.abs(scrollProgress);
- child.setAlpha(alpha);
- }
- }
- invalidate();
+ @Thunk void updateMaxScrollX() {
+ int childCount = getChildCount();
+ if (childCount > 0) {
+ final int index = mIsRtl ? 0 : childCount - 1;
+ mMaxScrollX = getScrollForPage(index);
+ } else {
+ mMaxScrollX = 0;
}
}
- protected void enablePagedViewAnimations() {
- mAllowPagedViewAnimations = true;
-
- }
- protected void disablePagedViewAnimations() {
- mAllowPagedViewAnimations = false;
+ public void setPageSpacing(int pageSpacing) {
+ mPageSpacing = pageSpacing;
+ requestLayout();
}
+ /**
+ * Called when the center screen changes during scrolling.
+ */
+ protected void screenScrolled(int screenCenter) { }
+
@Override
public void onChildViewAdded(View parent, View child) {
// Update the page indicator, we don't update the page indicator as we
@@ -1072,7 +985,7 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
int pageIndex = indexOfChild(child);
mPageIndicator.addMarker(pageIndex,
getPageIndicatorMarker(pageIndex),
- mAllowPagedViewAnimations);
+ true);
}
// This ensures that when children are added, they get the correct transforms / alphas
@@ -1093,7 +1006,7 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
// Update the page indicator, we don't update the page indicator as we
// add/remove pages
if (mPageIndicator != null && !isReordering(false)) {
- mPageIndicator.removeMarker(index, mAllowPagedViewAnimations);
+ mPageIndicator.removeMarker(index, true);
}
}
@@ -1115,7 +1028,7 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
public void removeViewAt(int index) {
// XXX: We should find a better way to hook into this before the view
// gets removed form its parent...
- removeViewAt(index);
+ removeMarkerForView(index);
super.removeViewAt(index);
}
@Override
@@ -1123,7 +1036,7 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
// Update the page indicator, we don't update the page indicator as we
// add/remove pages
if (mPageIndicator != null) {
- mPageIndicator.removeAllMarkers(mAllowPagedViewAnimations);
+ mPageIndicator.removeAllMarkers(true);
}
super.removeAllViewsInLayout();
@@ -1144,7 +1057,7 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
protected void getVisiblePages(int[] range) {
final int pageCount = getChildCount();
- mTmpIntPoint[0] = mTmpIntPoint[1] = 0;
+ sTmpIntPoint[0] = sTmpIntPoint[1] = 0;
range[0] = -1;
range[1] = -1;
@@ -1157,9 +1070,9 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
for (int i = 0; i < count; i++) {
View currPage = getPageAt(i);
- mTmpIntPoint[0] = 0;
- Utilities.getDescendantCoordRelativeToParent(currPage, this, mTmpIntPoint, false);
- if (mTmpIntPoint[0] > viewportWidth) {
+ sTmpIntPoint[0] = 0;
+ Utilities.getDescendantCoordRelativeToParent(currPage, this, sTmpIntPoint, false);
+ if (sTmpIntPoint[0] > viewportWidth) {
if (range[0] == -1) {
continue;
} else {
@@ -1167,9 +1080,9 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
}
}
- mTmpIntPoint[0] = currPage.getMeasuredWidth();
- Utilities.getDescendantCoordRelativeToParent(currPage, this, mTmpIntPoint, false);
- if (mTmpIntPoint[0] < 0) {
+ sTmpIntPoint[0] = currPage.getMeasuredWidth();
+ Utilities.getDescendantCoordRelativeToParent(currPage, this, sTmpIntPoint, false);
+ if (sTmpIntPoint[0] < 0) {
if (range[0] == -1) {
continue;
} else {
@@ -1199,9 +1112,7 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
final int pageCount = getChildCount();
if (pageCount > 0) {
int halfScreenSize = getViewportWidth() / 2;
- // mOverScrollX is equal to getScrollX() when we're within the normal scroll range.
- // Otherwise it is equal to the scaled overscroll position.
- int screenCenter = mOverScrollX + halfScreenSize;
+ int screenCenter = getScrollX() + halfScreenSize;
if (screenCenter != mLastScreenCenter || mForceScreenScrolled) {
// set mForceScreenScrolled before calling screenScrolled so that screenScrolled can
@@ -1242,6 +1153,46 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
}
@Override
+ public void draw(Canvas canvas) {
+ super.draw(canvas);
+ if (getPageCount() > 0) {
+ if (!mEdgeGlowLeft.isFinished()) {
+ final int restoreCount = canvas.save();
+ Rect display = mViewport;
+ canvas.translate(display.left, display.top);
+ canvas.rotate(270);
+
+ getEdgeVerticalPostion(sTmpIntPoint);
+ canvas.translate(display.top - sTmpIntPoint[1], 0);
+ mEdgeGlowLeft.setSize(sTmpIntPoint[1] - sTmpIntPoint[0], display.width());
+ if (mEdgeGlowLeft.draw(canvas)) {
+ postInvalidateOnAnimation();
+ }
+ canvas.restoreToCount(restoreCount);
+ }
+ if (!mEdgeGlowRight.isFinished()) {
+ final int restoreCount = canvas.save();
+ Rect display = mViewport;
+ canvas.translate(display.left + mPageScrolls[mIsRtl ? 0 : (getPageCount() - 1)], display.top);
+ 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)) {
+ postInvalidateOnAnimation();
+ }
+ canvas.restoreToCount(restoreCount);
+ }
+ }
+ }
+
+ /**
+ * Returns the top and bottom position for the edge effect.
+ */
+ protected abstract void getEdgeVerticalPostion(int[] pos);
+
+ @Override
public boolean requestChildRectangleOnScreen(View child, Rect rectangle, boolean immediate) {
int page = indexToPage(indexOfChild(child));
if (page != mCurrentPage || !mScroller.isFinished()) {
@@ -1346,7 +1297,7 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
* Return true if a tap at (x, y) should trigger a flip to the previous page.
*/
protected boolean hitsPreviousPage(float x, float y) {
- if (isLayoutRtl()) {
+ if (mIsRtl) {
return (x > (getViewportOffsetX() + getViewportWidth() -
getPaddingRight() - mPageSpacing));
}
@@ -1357,7 +1308,7 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
* Return true if a tap at (x, y) should trigger a flip to the next page.
*/
protected boolean hitsNextPage(float x, float y) {
- if (isLayoutRtl()) {
+ if (mIsRtl) {
return (x < getViewportOffsetX() + getPaddingLeft() + mPageSpacing);
}
return (x > (getViewportOffsetX() + getViewportWidth() -
@@ -1366,17 +1317,13 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
/** Returns whether x and y originated within the buffered viewport */
private boolean isTouchPointInViewportWithBuffer(int x, int y) {
- mTmpRect.set(mViewport.left - mViewport.width() / 2, mViewport.top,
+ sTmpRect.set(mViewport.left - mViewport.width() / 2, mViewport.top,
mViewport.right + mViewport.width() / 2, mViewport.bottom);
- return mTmpRect.contains(x, y);
+ return sTmpRect.contains(x, y);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
- if (DISABLE_TOUCH_INTERACTION) {
- return false;
- }
-
/*
* This method JUST determines whether we want to intercept the motion.
* If we return true, onTouchEvent will be called and we do the actual
@@ -1453,19 +1400,6 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
}
}
- // check if this can be the beginning of a tap on the side of the pages
- // to scroll the current page
- if (!DISABLE_TOUCH_SIDE_PAGES) {
- if (mTouchState != TOUCH_STATE_PREV_PAGE && mTouchState != TOUCH_STATE_NEXT_PAGE) {
- if (getChildCount() > 0) {
- if (hitsPreviousPage(x, y)) {
- mTouchState = TOUCH_STATE_PREV_PAGE;
- } else if (hitsNextPage(x, y)) {
- mTouchState = TOUCH_STATE_NEXT_PAGE;
- }
- }
- }
- }
break;
}
@@ -1506,54 +1440,33 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
if (!isTouchPointInViewportWithBuffer((int) x, (int) y)) return;
final int xDiff = (int) Math.abs(x - mLastMotionX);
- final int yDiff = (int) Math.abs(y - mLastMotionY);
final int touchSlop = Math.round(touchSlopScale * mTouchSlop);
- boolean xPaged = xDiff > mPagingTouchSlop;
boolean xMoved = xDiff > touchSlop;
- boolean yMoved = yDiff > touchSlop;
- if (xMoved || xPaged || yMoved) {
- if (mUsePagingTouchSlop ? xPaged : xMoved) {
- // Scroll if the user moved far enough along the X axis
- mTouchState = TOUCH_STATE_SCROLLING;
- mTotalMotionX += Math.abs(mLastMotionX - x);
- mLastMotionX = x;
- mLastMotionXRemainder = 0;
- mTouchX = getViewportOffsetX() + getScrollX();
- mSmoothingTime = System.nanoTime() / NANOTIME_DIV;
- onScrollInteractionBegin();
- pageBeginMoving();
- }
+ if (xMoved) {
+ // Scroll if the user moved far enough along the X axis
+ mTouchState = TOUCH_STATE_SCROLLING;
+ mTotalMotionX += Math.abs(mLastMotionX - x);
+ mLastMotionX = x;
+ mLastMotionXRemainder = 0;
+ mTouchX = getViewportOffsetX() + getScrollX();
+ mSmoothingTime = System.nanoTime() / NANOTIME_DIV;
+ onScrollInteractionBegin();
+ pageBeginMoving();
}
}
- protected float getMaxScrollProgress() {
- return 1.0f;
- }
-
protected void cancelCurrentPageLongPress() {
- if (mAllowLongPress) {
- //mAllowLongPress = false;
- // Try canceling the long press. It could also have been scheduled
- // by a distant descendant, so use the mAllowLongPress flag to block
- // everything
- final View currentPage = getPageAt(mCurrentPage);
- if (currentPage != null) {
- currentPage.cancelLongPress();
- }
+ // Try canceling the long press. It could also have been scheduled
+ // by a distant descendant, so use the mAllowLongPress flag to block
+ // everything
+ final View currentPage = getPageAt(mCurrentPage);
+ if (currentPage != null) {
+ currentPage.cancelLongPress();
}
}
- protected float getBoundedScrollProgress(int screenCenter, View v, int page) {
- final int halfScreenSize = getViewportWidth() / 2;
-
- screenCenter = Math.min(getScrollX() + halfScreenSize, screenCenter);
- screenCenter = Math.max(halfScreenSize, screenCenter);
-
- return getScrollProgress(screenCenter, v, page);
- }
-
protected float getScrollProgress(int screenCenter, View v, int page) {
final int halfScreenSize = getViewportWidth() / 2;
@@ -1563,7 +1476,7 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
final int totalDistance;
int adjacentPage = page + 1;
- if ((delta < 0 && !isLayoutRtl()) || (delta > 0 && isLayoutRtl())) {
+ if ((delta < 0 && !mIsRtl) || (delta > 0 && mIsRtl)) {
adjacentPage = page - 1;
}
@@ -1574,8 +1487,8 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
}
float scrollProgress = delta / (totalDistance * 1.0f);
- scrollProgress = Math.min(scrollProgress, getMaxScrollProgress());
- scrollProgress = Math.max(scrollProgress, - getMaxScrollProgress());
+ scrollProgress = Math.min(scrollProgress, MAX_SCROLL_PROGRESS);
+ scrollProgress = Math.max(scrollProgress, - MAX_SCROLL_PROGRESS);
return scrollProgress;
}
@@ -1598,7 +1511,7 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
int scrollOffset = 0;
LayoutParams lp = (LayoutParams) child.getLayoutParams();
if (!lp.isFullScreenPage) {
- scrollOffset = isLayoutRtl() ? getPaddingRight() : getPaddingLeft();
+ scrollOffset = mIsRtl ? getPaddingRight() : getPaddingLeft();
}
int baselineX = mPageScrolls[index] + scrollOffset + getViewportOffsetX();
@@ -1606,49 +1519,15 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
}
}
- // This curve determines how the effect of scrolling over the limits of the page dimishes
- // as the user pulls further and further from the bounds
- private float overScrollInfluenceCurve(float f) {
- f -= 1.0f;
- return f * f * f + 1.0f;
- }
-
- protected float acceleratedOverFactor(float amount) {
- int screenSize = getViewportWidth();
-
- // We want to reach the max over scroll effect when the user has
- // over scrolled half the size of the screen
- float f = OVERSCROLL_ACCELERATE_FACTOR * (amount / screenSize);
-
- if (f == 0) return 0;
-
- // Clamp this factor, f, to -1 < f < 1
- if (Math.abs(f) >= 1) {
- f /= Math.abs(f);
- }
- return f;
- }
-
protected void dampedOverScroll(float amount) {
int screenSize = getViewportWidth();
-
float f = (amount / screenSize);
-
- if (f == 0) return;
- f = f / (Math.abs(f)) * (overScrollInfluenceCurve(Math.abs(f)));
-
- // Clamp this factor, f, to -1 < f < 1
- if (Math.abs(f) >= 1) {
- f /= Math.abs(f);
- }
-
- int overScrollAmount = (int) Math.round(OVERSCROLL_DAMP_FACTOR * f * screenSize);
- if (amount < 0) {
- mOverScrollX = overScrollAmount;
- super.scrollTo(mOverScrollX, getScrollY());
+ if (f < 0) {
+ mEdgeGlowLeft.onPull(-f);
+ } else if (f > 0) {
+ mEdgeGlowRight.onPull(f);
} else {
- mOverScrollX = mMaxScrollX + overScrollAmount;
- super.scrollTo(mOverScrollX, getScrollY());
+ return;
}
invalidate();
}
@@ -1657,25 +1536,17 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
dampedOverScroll(amount);
}
- protected float maxOverScroll() {
- // Using the formula in overScroll, assuming that f = 1.0 (which it should generally not
- // exceed). Used to find out how much extra wallpaper we need for the over scroll effect
- float f = 1.0f;
- f = f / (Math.abs(f)) * (overScrollInfluenceCurve(Math.abs(f)));
- return OVERSCROLL_DAMP_FACTOR * f;
- }
-
- protected void enableFreeScroll() {
+ public void enableFreeScroll() {
setEnableFreeScroll(true);
}
- protected void disableFreeScroll() {
+ public void disableFreeScroll() {
setEnableFreeScroll(false);
}
void updateFreescrollBounds() {
getFreeScrollPageRange(mTempVisiblePagesRange);
- if (isLayoutRtl()) {
+ if (mIsRtl) {
mFreeScrollMinScrollX = getScrollForPage(mTempVisiblePagesRange[1]);
mFreeScrollMaxScrollX = getScrollForPage(mTempVisiblePagesRange[0]);
} else {
@@ -1700,11 +1571,11 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
setEnableOverscroll(!freeScroll);
}
- private void setEnableOverscroll(boolean enable) {
+ protected void setEnableOverscroll(boolean enable) {
mAllowOverScroll = enable;
}
- int getNearestHoverOverPageIndex() {
+ private int getNearestHoverOverPageIndex() {
if (mDragView != null) {
int dragX = (int) (mDragView.getLeft() + (mDragView.getMeasuredWidth() / 2)
+ mDragView.getTranslationX());
@@ -1727,10 +1598,6 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
@Override
public boolean onTouchEvent(MotionEvent ev) {
- if (DISABLE_TOUCH_INTERACTION) {
- return false;
- }
-
super.onTouchEvent(ev);
// Skip touch handling if there are no pages to swipe
@@ -1785,12 +1652,7 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
if (Math.abs(deltaX) >= 1.0f) {
mTouchX += deltaX;
mSmoothingTime = System.nanoTime() / NANOTIME_DIV;
- if (!mDeferScrollUpdate) {
- scrollBy((int) deltaX, 0);
- if (DEBUG) Log.d(TAG, "onTouchEvent().Scrolling: " + deltaX);
- } else {
- invalidate();
- }
+ scrollBy((int) deltaX, 0);
mLastMotionX = x;
mLastMotionXRemainder = deltaX - (int) deltaX;
} else {
@@ -1811,19 +1673,13 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
// Find the closest page to the touch point
final int dragViewIndex = indexOfChild(mDragView);
- // Change the drag view if we are hovering over the drop target
- boolean isHoveringOverDelete = isHoveringOverDeleteDropTarget(
- (int) mParentDownMotionX, (int) mParentDownMotionY);
- setPageHoveringOverDeleteDropTarget(dragViewIndex, isHoveringOverDelete);
-
if (DEBUG) Log.d(TAG, "mLastMotionX: " + mLastMotionX);
if (DEBUG) Log.d(TAG, "mLastMotionY: " + mLastMotionY);
if (DEBUG) Log.d(TAG, "mParentDownMotionX: " + mParentDownMotionX);
if (DEBUG) Log.d(TAG, "mParentDownMotionY: " + mParentDownMotionY);
final int pageUnderPointIndex = getNearestHoverOverPageIndex();
- if (pageUnderPointIndex > -1 && pageUnderPointIndex != indexOfChild(mDragView) &&
- !isHoveringOverDelete) {
+ if (pageUnderPointIndex > -1 && pageUnderPointIndex != indexOfChild(mDragView)) {
mTempVisiblePagesRange[0] = 0;
mTempVisiblePagesRange[1] = getPageCount() - 1;
getFreeScrollPageRange(mTempVisiblePagesRange);
@@ -1870,9 +1726,7 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
}
removeView(mDragView);
- onRemoveView(mDragView, false);
addView(mDragView, pageUnderPointIndex);
- onAddView(mDragView, pageUnderPointIndex);
mSidePageHoverIndex = -1;
if (mPageIndicator != null) {
mPageIndicator.setActiveMarker(getNextPage());
@@ -1922,9 +1776,8 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
// We give flings precedence over large moves, which is why we short-circuit our
// test for a large move if a fling has been registered. That is, a large
// move to the left and fling to the right will register as a fling to the right.
- final boolean isRtl = isLayoutRtl();
- boolean isDeltaXLeft = isRtl ? deltaX > 0 : deltaX < 0;
- boolean isVelocityXLeft = isRtl ? velocityX > 0 : velocityX < 0;
+ boolean isDeltaXLeft = mIsRtl ? deltaX > 0 : deltaX < 0;
+ boolean isVelocityXLeft = mIsRtl ? velocityX > 0 : velocityX < 0;
if (((isSignificantMove && !isDeltaXLeft && !isFling) ||
(isFling && !isVelocityXLeft)) && mCurrentPage > 0) {
finalPage = returnToOriginalPage ? mCurrentPage : mCurrentPage - 1;
@@ -1983,19 +1836,6 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
mParentDownMotionX = pt[0];
mParentDownMotionY = pt[1];
updateDragViewTranslationDuringDrag();
- boolean handledFling = false;
- if (!DISABLE_FLING_TO_DELETE) {
- // Check the velocity and see if we are flinging-to-delete
- PointF flingToDeleteVector = isFlingingToDelete();
- if (flingToDeleteVector != null) {
- onFlingToDelete(flingToDeleteVector);
- handledFling = true;
- }
- }
- if (!handledFling && isHoveringOverDeleteDropTarget((int) mParentDownMotionX,
- (int) mParentDownMotionY)) {
- onDropToDelete();
- }
} else {
if (!mCancelTap) {
onUnhandledTap(ev);
@@ -2024,17 +1864,14 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
return true;
}
- public void onFlingToDelete(View v) {}
- public void onRemoveView(View v, boolean deletePermanently) {}
- public void onRemoveViewAnimationCompleted() {}
- public void onAddView(View v, int index) {}
-
private void resetTouchState() {
releaseVelocityTracker();
endReordering();
mCancelTap = false;
mTouchState = TOUCH_STATE_REST;
mActivePointerId = INVALID_POINTER;
+ mEdgeGlowLeft.onRelease();
+ mEdgeGlowRight.onRelease();
}
/**
@@ -2066,7 +1903,7 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
hscroll = event.getAxisValue(MotionEvent.AXIS_HSCROLL);
}
if (hscroll != 0 || vscroll != 0) {
- boolean isForwardScroll = isLayoutRtl() ? (hscroll < 0 || vscroll < 0)
+ boolean isForwardScroll = mIsRtl ? (hscroll < 0 || vscroll < 0)
: (hscroll > 0 || vscroll > 0);
if (isForwardScroll) {
scrollRight();
@@ -2124,22 +1961,6 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
}
}
- protected int getChildWidth(int index) {
- return getPageAt(index).getMeasuredWidth();
- }
-
- int getPageNearestToPoint(float x) {
- int index = 0;
- for (int i = 0; i < getChildCount(); ++i) {
- if (x < getChildAt(i).getRight() - getScrollX()) {
- return index;
- } else {
- index++;
- }
- }
- return Math.min(index, getChildCount() - 1);
- }
-
int getPageNearestToCenterOfScreen() {
int minDistanceFromScreenCenter = Integer.MAX_VALUE;
int minDistanceFromScreenCenterIndex = -1;
@@ -2159,20 +1980,8 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
return minDistanceFromScreenCenterIndex;
}
- protected boolean isInOverScroll() {
- return (mOverScrollX > mMaxScrollX || mOverScrollX < 0);
- }
-
- protected int getPageSnapDuration() {
- if (isInOverScroll()) {
- return OVER_SCROLL_PAGE_SNAP_ANIMATION_DURATION;
- }
- return PAGE_SNAP_ANIMATION_DURATION;
-
- }
-
protected void snapToDestination() {
- snapToPage(getPageNearestToCenterOfScreen(), getPageSnapDuration());
+ snapToPage(getPageNearestToCenterOfScreen(), PAGE_SNAP_ANIMATION_DURATION);
}
private static class ScrollInterpolator implements Interpolator {
@@ -2189,7 +1998,7 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
// the screen has to travel, however, we don't want this duration to be effected in a
// purely linear fashion. Instead, we use this method to moderate the effect that the distance
// of travel has on the overall snap duration.
- float distanceInfluenceForSnapDuration(float f) {
+ private float distanceInfluenceForSnapDuration(float f) {
f -= 0.5f; // center the values about 0.
f *= 0.3f * Math.PI / 2.0f;
return (float) Math.sin(f);
@@ -2200,13 +2009,13 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
int halfScreenSize = getViewportWidth() / 2;
final int newX = getScrollForPage(whichPage);
- int delta = newX - mUnboundedScrollX;
+ int delta = newX - getScrollX();
int duration = 0;
- if (Math.abs(velocity) < mMinFlingVelocity || isInOverScroll()) {
+ if (Math.abs(velocity) < mMinFlingVelocity) {
// If the velocity is low enough, then treat this more as an automatic page advance
// as opposed to an apparent physical response to flinging
- snapToPage(whichPage, getPageSnapDuration());
+ snapToPage(whichPage, PAGE_SNAP_ANIMATION_DURATION);
return;
}
@@ -2229,12 +2038,12 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
snapToPage(whichPage, delta, duration);
}
- protected void snapToPage(int whichPage) {
- snapToPage(whichPage, getPageSnapDuration());
+ public void snapToPage(int whichPage) {
+ snapToPage(whichPage, PAGE_SNAP_ANIMATION_DURATION);
}
protected void snapToPageImmediately(int whichPage) {
- snapToPage(whichPage, getPageSnapDuration(), true, null);
+ snapToPage(whichPage, PAGE_SNAP_ANIMATION_DURATION, true, null);
}
protected void snapToPage(int whichPage, int duration) {
@@ -2250,8 +2059,7 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
whichPage = validateNewPage(whichPage);
int newX = getScrollForPage(whichPage);
- final int sX = mUnboundedScrollX;
- final int delta = newX - sX;
+ final int delta = newX - getScrollX();
snapToPage(whichPage, delta, duration, immediate, interpolator);
}
@@ -2270,8 +2078,6 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
focusedChild.clearFocus();
}
- sendScrollAccessibilityEvent();
-
pageBeginMoving();
awakenScrollBars(duration);
if (immediate) {
@@ -2290,7 +2096,7 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
mScroller.setInterpolator(mDefaultInterpolator);
}
- mScroller.startScroll(mUnboundedScrollX, 0, delta, 0, duration);
+ mScroller.startScroll(getScrollX(), 0, delta, 0, duration);
updatePageIndicator();
@@ -2299,9 +2105,6 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
computeScroll();
}
- // Defer loading associated pages until the scroll settles
- mDeferLoadAssociatedPagesUntilScrollCompletes = true;
-
mForceScreenScrolled = true;
invalidate();
}
@@ -2328,27 +2131,12 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
return result;
}
- /**
- * @return True is long presses are still allowed for the current touch
- */
- public boolean allowLongPress() {
- return mAllowLongPress;
- }
-
@Override
public boolean performLongClick() {
mCancelTap = true;
return super.performLongClick();
}
- /**
- * Set true to allow long-press events to be triggered, usually checked by
- * {@link Launcher} to accept or block dpad-initiated long-presses.
- */
- public void setAllowLongPress(boolean allowLongPress) {
- mAllowLongPress = allowLongPress;
- }
-
public static class SavedState extends BaseSavedState {
int currentPage = -1;
@@ -2356,7 +2144,7 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
super(superState);
}
- private SavedState(Parcel in) {
+ @Thunk SavedState(Parcel in) {
super(in);
currentPage = in.readInt();
}
@@ -2379,113 +2167,8 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
};
}
- protected void loadAssociatedPages(int page) {
- loadAssociatedPages(page, false);
- }
- protected void loadAssociatedPages(int page, boolean immediateAndOnly) {
- if (mContentIsRefreshable) {
- final int count = getChildCount();
- if (page < count) {
- int lowerPageBound = getAssociatedLowerPageBound(page);
- int upperPageBound = getAssociatedUpperPageBound(page);
- if (DEBUG) Log.d(TAG, "loadAssociatedPages: " + lowerPageBound + "/"
- + upperPageBound);
- // First, clear any pages that should no longer be loaded
- for (int i = 0; i < count; ++i) {
- Page layout = (Page) getPageAt(i);
- if ((i < lowerPageBound) || (i > upperPageBound)) {
- if (layout.getPageChildCount() > 0) {
- layout.removeAllViewsOnPage();
- }
- mDirtyPageContent.set(i, true);
- }
- }
- // Next, load any new pages
- for (int i = 0; i < count; ++i) {
- if ((i != page) && immediateAndOnly) {
- continue;
- }
- if (lowerPageBound <= i && i <= upperPageBound) {
- if (mDirtyPageContent.get(i)) {
- syncPageItems(i, (i == page) && immediateAndOnly);
- mDirtyPageContent.set(i, false);
- }
- }
- }
- }
- }
- }
-
- protected int getAssociatedLowerPageBound(int page) {
- return Math.max(0, page - 1);
- }
- protected int getAssociatedUpperPageBound(int page) {
- final int count = getChildCount();
- return Math.min(page + 1, count - 1);
- }
-
- /**
- * This method is called ONLY to synchronize the number of pages that the paged view has.
- * To actually fill the pages with information, implement syncPageItems() below. It is
- * guaranteed that syncPageItems() will be called for a particular page before it is shown,
- * and therefore, individual page items do not need to be updated in this method.
- */
- public abstract void syncPages();
-
- /**
- * This method is called to synchronize the items that are on a particular page. If views on
- * the page can be reused, then they should be updated within this method.
- */
- public abstract void syncPageItems(int page, boolean immediate);
-
- protected void invalidatePageData() {
- invalidatePageData(-1, false);
- }
- protected void invalidatePageData(int currentPage) {
- invalidatePageData(currentPage, false);
- }
- protected void invalidatePageData(int currentPage, boolean immediateAndOnly) {
- if (!mIsDataReady) {
- return;
- }
-
- if (mContentIsRefreshable) {
- // Force all scrolling-related behavior to end
- forceFinishScroller();
-
- // Update all the pages
- syncPages();
-
- // We must force a measure after we've loaded the pages to update the content width and
- // to determine the full scroll width
- measure(MeasureSpec.makeMeasureSpec(getMeasuredWidth(), MeasureSpec.EXACTLY),
- MeasureSpec.makeMeasureSpec(getMeasuredHeight(), MeasureSpec.EXACTLY));
-
- // Set a new page as the current page if necessary
- if (currentPage > -1) {
- setCurrentPage(Math.min(getPageCount() - 1, currentPage));
- }
-
- // Mark each of the pages as dirty
- final int count = getChildCount();
- mDirtyPageContent.clear();
- for (int i = 0; i < count; ++i) {
- mDirtyPageContent.add(true);
- }
-
- // Load any pages that are necessary for the current window of views
- loadAssociatedPages(mCurrentPage, immediateAndOnly);
- requestLayout();
- }
- if (isPageMoving()) {
- // If the page is moving, then snap it to the final position to ensure we don't get
- // stuck between pages
- snapToDestination();
- }
- }
-
// Animate the drag view back to the original position
- void animateDragViewToOriginalPosition() {
+ private void animateDragViewToOriginalPosition() {
if (mDragView != null) {
AnimatorSet anim = new AnimatorSet();
anim.setDuration(REORDERING_DROP_REPOSITION_DURATION);
@@ -2504,7 +2187,7 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
}
}
- protected void onStartReordering() {
+ public void onStartReordering() {
// Set the touch state to reordering (allows snapping to pages, dragging a child, etc.)
mTouchState = TOUCH_STATE_REORDERING;
mIsReordering = true;
@@ -2514,7 +2197,7 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
invalidate();
}
- private void onPostReorderingAnimationCompleted() {
+ @Thunk void onPostReorderingAnimationCompleted() {
// Trigger the callback when reordering has settled
--mPostReorderingPreZoomInRemainingAnimationCount;
if (mPostReorderingPreZoomInRunnable != null &&
@@ -2524,7 +2207,7 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
}
}
- protected void onEndReordering() {
+ public void onEndReordering() {
mIsReordering = false;
}
@@ -2574,281 +2257,26 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
onEndReordering();
}
};
- if (!mDeferringForDelete) {
- mPostReorderingPreZoomInRunnable = new Runnable() {
- public void run() {
- onCompleteRunnable.run();
- enableFreeScroll();
- };
- };
-
- mPostReorderingPreZoomInRemainingAnimationCount =
- NUM_ANIMATIONS_RUNNING_BEFORE_ZOOM_OUT;
- // Snap to the current page
- snapToPage(indexOfChild(mDragView), 0);
- // Animate the drag view back to the front position
- animateDragViewToOriginalPosition();
- } else {
- // Handled in post-delete-animation-callbacks
- }
- }
-
- /*
- * Flinging to delete - IN PROGRESS
- */
- private PointF isFlingingToDelete() {
- ViewConfiguration config = ViewConfiguration.get(getContext());
- mVelocityTracker.computeCurrentVelocity(1000, config.getScaledMaximumFlingVelocity());
-
- if (mVelocityTracker.getYVelocity() < mFlingToDeleteThresholdVelocity) {
- // Do a quick dot product test to ensure that we are flinging upwards
- PointF vel = new PointF(mVelocityTracker.getXVelocity(),
- mVelocityTracker.getYVelocity());
- PointF upVec = new PointF(0f, -1f);
- float theta = (float) Math.acos(((vel.x * upVec.x) + (vel.y * upVec.y)) /
- (vel.length() * upVec.length()));
- if (theta <= Math.toRadians(FLING_TO_DELETE_MAX_FLING_DEGREES)) {
- return vel;
- }
- }
- return null;
- }
- /**
- * Creates an animation from the current drag view along its current velocity vector.
- * For this animation, the alpha runs for a fixed duration and we update the position
- * progressively.
- */
- private static class FlingAlongVectorAnimatorUpdateListener implements AnimatorUpdateListener {
- private View mDragView;
- private PointF mVelocity;
- private Rect mFrom;
- private long mPrevTime;
- private float mFriction;
-
- private final TimeInterpolator mAlphaInterpolator = new DecelerateInterpolator(0.75f);
-
- public FlingAlongVectorAnimatorUpdateListener(View dragView, PointF vel, Rect from,
- long startTime, float friction) {
- mDragView = dragView;
- mVelocity = vel;
- mFrom = from;
- mPrevTime = startTime;
- mFriction = 1f - (mDragView.getResources().getDisplayMetrics().density * friction);
- }
-
- @Override
- public void onAnimationUpdate(ValueAnimator animation) {
- float t = ((Float) animation.getAnimatedValue()).floatValue();
- long curTime = AnimationUtils.currentAnimationTimeMillis();
-
- mFrom.left += (mVelocity.x * (curTime - mPrevTime) / 1000f);
- mFrom.top += (mVelocity.y * (curTime - mPrevTime) / 1000f);
-
- mDragView.setTranslationX(mFrom.left);
- mDragView.setTranslationY(mFrom.top);
- mDragView.setAlpha(1f - mAlphaInterpolator.getInterpolation(t));
-
- mVelocity.x *= mFriction;
- mVelocity.y *= mFriction;
- mPrevTime = curTime;
- }
- };
-
- private static final int ANIM_TAG_KEY = 100;
-
- private Runnable createPostDeleteAnimationRunnable(final View dragView) {
- return new Runnable() {
- @Override
+ mPostReorderingPreZoomInRunnable = new Runnable() {
public void run() {
- int dragViewIndex = indexOfChild(dragView);
-
- // For each of the pages around the drag view, animate them from the previous
- // position to the new position in the layout (as a result of the drag view moving
- // in the layout)
- // NOTE: We can make an assumption here because we have side-bound pages that we
- // will always have pages to animate in from the left
- getFreeScrollPageRange(mTempVisiblePagesRange);
- boolean isLastWidgetPage = (mTempVisiblePagesRange[0] == mTempVisiblePagesRange[1]);
- boolean slideFromLeft = (isLastWidgetPage ||
- dragViewIndex > mTempVisiblePagesRange[0]);
-
- // Setup the scroll to the correct page before we swap the views
- if (slideFromLeft) {
- snapToPageImmediately(dragViewIndex - 1);
- }
-
- int firstIndex = (isLastWidgetPage ? 0 : mTempVisiblePagesRange[0]);
- int lastIndex = Math.min(mTempVisiblePagesRange[1], getPageCount() - 1);
- int lowerIndex = (slideFromLeft ? firstIndex : dragViewIndex + 1 );
- int upperIndex = (slideFromLeft ? dragViewIndex - 1 : lastIndex);
- ArrayList<Animator> animations = new ArrayList<Animator>();
- for (int i = lowerIndex; i <= upperIndex; ++i) {
- View v = getChildAt(i);
- // dragViewIndex < pageUnderPointIndex, so after we remove the
- // drag view all subsequent views to pageUnderPointIndex will
- // shift down.
- int oldX = 0;
- int newX = 0;
- if (slideFromLeft) {
- if (i == 0) {
- // Simulate the page being offscreen with the page spacing
- oldX = getViewportOffsetX() + getChildOffset(i) - getChildWidth(i)
- - mPageSpacing;
- } else {
- oldX = getViewportOffsetX() + getChildOffset(i - 1);
- }
- newX = getViewportOffsetX() + getChildOffset(i);
- } else {
- oldX = getChildOffset(i) - getChildOffset(i - 1);
- newX = 0;
- }
-
- // Animate the view translation from its old position to its new
- // position
- AnimatorSet anim = (AnimatorSet) v.getTag();
- if (anim != null) {
- anim.cancel();
- }
-
- // Note: Hacky, but we want to skip any optimizations to not draw completely
- // hidden views
- v.setAlpha(Math.max(v.getAlpha(), 0.01f));
- v.setTranslationX(oldX - newX);
- anim = new AnimatorSet();
- anim.playTogether(
- ObjectAnimator.ofFloat(v, "translationX", 0f),
- ObjectAnimator.ofFloat(v, "alpha", 1f));
- animations.add(anim);
- v.setTag(ANIM_TAG_KEY, anim);
- }
-
- AnimatorSet slideAnimations = new AnimatorSet();
- slideAnimations.playTogether(animations);
- slideAnimations.setDuration(DELETE_SLIDE_IN_SIDE_PAGE_DURATION);
- slideAnimations.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- mDeferringForDelete = false;
- onEndReordering();
- onRemoveViewAnimationCompleted();
- }
- });
- slideAnimations.start();
-
- removeView(dragView);
- onRemoveView(dragView, true);
- }
- };
- }
-
- public void onFlingToDelete(PointF vel) {
- final long startTime = AnimationUtils.currentAnimationTimeMillis();
-
- // NOTE: Because it takes time for the first frame of animation to actually be
- // called and we expect the animation to be a continuation of the fling, we have
- // to account for the time that has elapsed since the fling finished. And since
- // we don't have a startDelay, we will always get call to update when we call
- // start() (which we want to ignore).
- final TimeInterpolator tInterpolator = new TimeInterpolator() {
- private int mCount = -1;
- private long mStartTime;
- private float mOffset;
- /* Anonymous inner class ctor */ {
- mStartTime = startTime;
- }
-
- @Override
- public float getInterpolation(float t) {
- if (mCount < 0) {
- mCount++;
- } else if (mCount == 0) {
- mOffset = Math.min(0.5f, (float) (AnimationUtils.currentAnimationTimeMillis() -
- mStartTime) / FLING_TO_DELETE_FADE_OUT_DURATION);
- mCount++;
- }
- return Math.min(1f, mOffset + t);
- }
+ onCompleteRunnable.run();
+ enableFreeScroll();
+ };
};
- final Rect from = new Rect();
- final View dragView = mDragView;
- from.left = (int) dragView.getTranslationX();
- from.top = (int) dragView.getTranslationY();
- AnimatorUpdateListener updateCb = new FlingAlongVectorAnimatorUpdateListener(dragView, vel,
- from, startTime, FLING_TO_DELETE_FRICTION);
-
- final Runnable onAnimationEndRunnable = createPostDeleteAnimationRunnable(dragView);
-
- // Create and start the animation
- ValueAnimator mDropAnim = new ValueAnimator();
- mDropAnim.setInterpolator(tInterpolator);
- mDropAnim.setDuration(FLING_TO_DELETE_FADE_OUT_DURATION);
- mDropAnim.setFloatValues(0f, 1f);
- mDropAnim.addUpdateListener(updateCb);
- mDropAnim.addListener(new AnimatorListenerAdapter() {
- public void onAnimationEnd(Animator animation) {
- onAnimationEndRunnable.run();
- }
- });
- mDropAnim.start();
- mDeferringForDelete = true;
- }
-
- /* Drag to delete */
- private boolean isHoveringOverDeleteDropTarget(int x, int y) {
- if (mDeleteDropTarget != null) {
- mAltTmpRect.set(0, 0, 0, 0);
- View parent = (View) mDeleteDropTarget.getParent();
- if (parent != null) {
- parent.getGlobalVisibleRect(mAltTmpRect);
- }
- mDeleteDropTarget.getGlobalVisibleRect(mTmpRect);
- mTmpRect.offset(-mAltTmpRect.left, -mAltTmpRect.top);
- return mTmpRect.contains(x, y);
- }
- return false;
+ mPostReorderingPreZoomInRemainingAnimationCount =
+ NUM_ANIMATIONS_RUNNING_BEFORE_ZOOM_OUT;
+ // Snap to the current page
+ snapToPage(indexOfChild(mDragView), 0);
+ // Animate the drag view back to the front position
+ animateDragViewToOriginalPosition();
}
- protected void setPageHoveringOverDeleteDropTarget(int viewIndex, boolean isHovering) {}
-
- private void onDropToDelete() {
- final View dragView = mDragView;
-
- final float toScale = 0f;
- final float toAlpha = 0f;
-
- // Create and start the complex animation
- ArrayList<Animator> animations = new ArrayList<Animator>();
- AnimatorSet motionAnim = new AnimatorSet();
- motionAnim.setInterpolator(new DecelerateInterpolator(2));
- motionAnim.playTogether(
- ObjectAnimator.ofFloat(dragView, "scaleX", toScale),
- ObjectAnimator.ofFloat(dragView, "scaleY", toScale));
- animations.add(motionAnim);
-
- AnimatorSet alphaAnim = new AnimatorSet();
- alphaAnim.setInterpolator(new LinearInterpolator());
- alphaAnim.playTogether(
- ObjectAnimator.ofFloat(dragView, "alpha", toAlpha));
- animations.add(alphaAnim);
-
- final Runnable onAnimationEndRunnable = createPostDeleteAnimationRunnable(dragView);
-
- AnimatorSet anim = new AnimatorSet();
- anim.playTogether(animations);
- anim.setDuration(DRAG_TO_DELETE_FADE_OUT_DURATION);
- anim.addListener(new AnimatorListenerAdapter() {
- public void onAnimationEnd(Animator animation) {
- onAnimationEndRunnable.run();
- }
- });
- anim.start();
-
- mDeferringForDelete = true;
- }
+ private static final int ANIM_TAG_KEY = 100;
/* Accessibility */
+ @TargetApi(Build.VERSION_CODES.LOLLIPOP)
@Override
public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
super.onInitializeAccessibilityNodeInfo(info);
@@ -2859,6 +2287,15 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
if (getCurrentPage() > 0) {
info.addAction(AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD);
}
+ info.setClassName(getClass().getName());
+
+ // Accessibility-wise, PagedView doesn't support long click, so disabling it.
+ // Besides disabling the accessibility long-click, this also prevents this view from getting
+ // accessibility focus.
+ info.setLongClickable(false);
+ if (Utilities.isLmpOrAbove()) {
+ info.removeAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_LONG_CLICK);
+ }
}
@Override
@@ -2872,7 +2309,7 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
@Override
public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
super.onInitializeAccessibilityEvent(event);
- event.setScrollable(true);
+ event.setScrollable(getPageCount() > 1);
}
@Override
diff --git a/src/com/android/launcher3/PagedViewCellLayout.java b/src/com/android/launcher3/PagedViewCellLayout.java
deleted file mode 100644
index 2d9e10b9d..000000000
--- a/src/com/android/launcher3/PagedViewCellLayout.java
+++ /dev/null
@@ -1,492 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.launcher3;
-
-import android.content.Context;
-import android.util.AttributeSet;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.ViewDebug;
-import android.view.ViewGroup;
-
-/**
- * An abstraction of the original CellLayout which supports laying out items
- * which span multiple cells into a grid-like layout. Also supports dimming
- * to give a preview of its contents.
- */
-public class PagedViewCellLayout extends ViewGroup implements Page {
- static final String TAG = "PagedViewCellLayout";
-
- private int mCellCountX;
- private int mCellCountY;
- private int mOriginalCellWidth;
- private int mOriginalCellHeight;
- private int mCellWidth;
- private int mCellHeight;
- private int mOriginalWidthGap;
- private int mOriginalHeightGap;
- private int mWidthGap;
- private int mHeightGap;
- protected PagedViewCellLayoutChildren mChildren;
-
- public PagedViewCellLayout(Context context) {
- this(context, null);
- }
-
- public PagedViewCellLayout(Context context, AttributeSet attrs) {
- this(context, attrs, 0);
- }
-
- public PagedViewCellLayout(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
-
- setAlwaysDrawnWithCacheEnabled(false);
-
- // setup default cell parameters
- LauncherAppState app = LauncherAppState.getInstance();
- DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
- mOriginalCellWidth = mCellWidth = grid.cellWidthPx;
- mOriginalCellHeight = mCellHeight = grid.cellHeightPx;
- mCellCountX = (int) grid.numColumns;
- mCellCountY = (int) grid.numRows;
- mOriginalWidthGap = mOriginalHeightGap = mWidthGap = mHeightGap = -1;
-
- mChildren = new PagedViewCellLayoutChildren(context);
- mChildren.setCellDimensions(mCellWidth, mCellHeight);
- mChildren.setGap(mWidthGap, mHeightGap);
-
- addView(mChildren);
- }
-
- public int getCellWidth() {
- return mCellWidth;
- }
-
- public int getCellHeight() {
- return mCellHeight;
- }
-
- @Override
- public void cancelLongPress() {
- super.cancelLongPress();
-
- // Cancel long press for all children
- final int count = getChildCount();
- for (int i = 0; i < count; i++) {
- final View child = getChildAt(i);
- child.cancelLongPress();
- }
- }
-
- public boolean addViewToCellLayout(View child, int index, int childId,
- PagedViewCellLayout.LayoutParams params) {
- final PagedViewCellLayout.LayoutParams lp = params;
-
- // Generate an id for each view, this assumes we have at most 256x256 cells
- // per workspace screen
- if (lp.cellX >= 0 && lp.cellX <= (mCellCountX - 1) &&
- lp.cellY >= 0 && (lp.cellY <= mCellCountY - 1)) {
- // If the horizontal or vertical span is set to -1, it is taken to
- // mean that it spans the extent of the CellLayout
- if (lp.cellHSpan < 0) lp.cellHSpan = mCellCountX;
- if (lp.cellVSpan < 0) lp.cellVSpan = mCellCountY;
-
- child.setId(childId);
- mChildren.addView(child, index, lp);
-
- return true;
- }
- return false;
- }
-
- @Override
- public void removeAllViewsOnPage() {
- mChildren.removeAllViews();
- setLayerType(LAYER_TYPE_NONE, null);
- }
-
- @Override
- public void removeViewOnPageAt(int index) {
- mChildren.removeViewAt(index);
- }
-
- /**
- * Clears all the key listeners for the individual icons.
- */
- public void resetChildrenOnKeyListeners() {
- int childCount = mChildren.getChildCount();
- for (int j = 0; j < childCount; ++j) {
- mChildren.getChildAt(j).setOnKeyListener(null);
- }
- }
-
- @Override
- public int getPageChildCount() {
- return mChildren.getChildCount();
- }
-
- public PagedViewCellLayoutChildren getChildrenLayout() {
- return mChildren;
- }
-
- @Override
- public View getChildOnPageAt(int i) {
- return mChildren.getChildAt(i);
- }
-
- @Override
- public int indexOfChildOnPage(View v) {
- return mChildren.indexOfChild(v);
- }
-
- public int getCellCountX() {
- return mCellCountX;
- }
-
- public int getCellCountY() {
- return mCellCountY;
- }
-
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec);
- int widthSpecSize = MeasureSpec.getSize(widthMeasureSpec);
-
- int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec);
- int heightSpecSize = MeasureSpec.getSize(heightMeasureSpec);
-
- if (widthSpecMode == MeasureSpec.UNSPECIFIED || heightSpecMode == MeasureSpec.UNSPECIFIED) {
- throw new RuntimeException("CellLayout cannot have UNSPECIFIED dimensions");
- }
-
- int numWidthGaps = mCellCountX - 1;
- int numHeightGaps = mCellCountY - 1;
-
- if (mOriginalWidthGap < 0 || mOriginalHeightGap < 0) {
- int hSpace = widthSpecSize - getPaddingLeft() - getPaddingRight();
- int vSpace = heightSpecSize - getPaddingTop() - getPaddingBottom();
- int hFreeSpace = hSpace - (mCellCountX * mOriginalCellWidth);
- int vFreeSpace = vSpace - (mCellCountY * mOriginalCellHeight);
- mWidthGap = numWidthGaps > 0 ? (hFreeSpace / numWidthGaps) : 0;
- mHeightGap = numHeightGaps > 0 ? (vFreeSpace / numHeightGaps) : 0;
-
- mChildren.setGap(mWidthGap, mHeightGap);
- } else {
- mWidthGap = mOriginalWidthGap;
- mHeightGap = mOriginalHeightGap;
- }
-
- // Initial values correspond to widthSpecMode == MeasureSpec.EXACTLY
- int newWidth = widthSpecSize;
- int newHeight = heightSpecSize;
- if (widthSpecMode == MeasureSpec.AT_MOST) {
- newWidth = getPaddingLeft() + getPaddingRight() + (mCellCountX * mCellWidth) +
- ((mCellCountX - 1) * mWidthGap);
- newHeight = getPaddingTop() + getPaddingBottom() + (mCellCountY * mCellHeight) +
- ((mCellCountY - 1) * mHeightGap);
- setMeasuredDimension(newWidth, newHeight);
- }
-
- final int count = getChildCount();
- for (int i = 0; i < count; i++) {
- View child = getChildAt(i);
- int childWidthMeasureSpec =
- MeasureSpec.makeMeasureSpec(newWidth - getPaddingLeft() -
- getPaddingRight(), MeasureSpec.EXACTLY);
- int childheightMeasureSpec =
- MeasureSpec.makeMeasureSpec(newHeight - getPaddingTop() -
- getPaddingBottom(), MeasureSpec.EXACTLY);
- child.measure(childWidthMeasureSpec, childheightMeasureSpec);
- }
-
- setMeasuredDimension(newWidth, newHeight);
- }
-
- int getContentWidth() {
- return getWidthBeforeFirstLayout() + getPaddingLeft() + getPaddingRight();
- }
-
- int getContentHeight() {
- if (mCellCountY > 0) {
- return mCellCountY * mCellHeight + (mCellCountY - 1) * Math.max(0, mHeightGap);
- }
- return 0;
- }
-
- int getWidthBeforeFirstLayout() {
- if (mCellCountX > 0) {
- return mCellCountX * mCellWidth + (mCellCountX - 1) * Math.max(0, mWidthGap);
- }
- return 0;
- }
-
- @Override
- protected void onLayout(boolean changed, int l, int t, int r, int b) {
- int count = getChildCount();
- for (int i = 0; i < count; i++) {
- View child = getChildAt(i);
- child.layout(getPaddingLeft(), getPaddingTop(),
- r - l - getPaddingRight(), b - t - getPaddingBottom());
- }
- }
-
- @Override
- public boolean onTouchEvent(MotionEvent event) {
- boolean result = super.onTouchEvent(event);
- int count = getPageChildCount();
- if (count > 0) {
- // We only intercept the touch if we are tapping in empty space after the final row
- View child = getChildOnPageAt(count - 1);
- int bottom = child.getBottom();
- int numRows = (int) Math.ceil((float) getPageChildCount() / getCellCountX());
- if (numRows < getCellCountY()) {
- // Add a little bit of buffer if there is room for another row
- bottom += mCellHeight / 2;
- }
- result = result || (event.getY() < bottom);
- }
- return result;
- }
-
- public void enableCenteredContent(boolean enabled) {
- mChildren.enableCenteredContent(enabled);
- }
-
- @Override
- protected void setChildrenDrawingCacheEnabled(boolean enabled) {
- mChildren.setChildrenDrawingCacheEnabled(enabled);
- }
-
- public void setCellCount(int xCount, int yCount) {
- mCellCountX = xCount;
- mCellCountY = yCount;
- requestLayout();
- }
-
- public void setGap(int widthGap, int heightGap) {
- mOriginalWidthGap = mWidthGap = widthGap;
- mOriginalHeightGap = mHeightGap = heightGap;
- mChildren.setGap(widthGap, heightGap);
- }
-
- public int[] getCellCountForDimensions(int width, int height) {
- // Always assume we're working with the smallest span to make sure we
- // reserve enough space in both orientations
- int smallerSize = Math.min(mCellWidth, mCellHeight);
-
- // Always round up to next largest cell
- int spanX = (width + smallerSize) / smallerSize;
- int spanY = (height + smallerSize) / smallerSize;
-
- return new int[] { spanX, spanY };
- }
-
- /**
- * Start dragging the specified child
- *
- * @param child The child that is being dragged
- */
- void onDragChild(View child) {
- PagedViewCellLayout.LayoutParams lp = (PagedViewCellLayout.LayoutParams) child.getLayoutParams();
- lp.isDragging = true;
- }
-
- /**
- * Estimates the number of cells that the specified width would take up.
- */
- public int estimateCellHSpan(int width) {
- // We don't show the next/previous pages any more, so we use the full width, minus the
- // padding
- int availWidth = width - (getPaddingLeft() + getPaddingRight());
-
- // We know that we have to fit N cells with N-1 width gaps, so we just juggle to solve for N
- int n = Math.max(1, (availWidth + mWidthGap) / (mCellWidth + mWidthGap));
-
- // We don't do anything fancy to determine if we squeeze another row in.
- return n;
- }
-
- /**
- * Estimates the number of cells that the specified height would take up.
- */
- public int estimateCellVSpan(int height) {
- // The space for a page is the height - top padding (current page) - bottom padding (current
- // page)
- int availHeight = height - (getPaddingTop() + getPaddingBottom());
-
- // We know that we have to fit N cells with N-1 height gaps, so we juggle to solve for N
- int n = Math.max(1, (availHeight + mHeightGap) / (mCellHeight + mHeightGap));
-
- // We don't do anything fancy to determine if we squeeze another row in.
- return n;
- }
-
- /** Returns an estimated center position of the cell at the specified index */
- public int[] estimateCellPosition(int x, int y) {
- return new int[] {
- getPaddingLeft() + (x * mCellWidth) + (x * mWidthGap) + (mCellWidth / 2),
- getPaddingTop() + (y * mCellHeight) + (y * mHeightGap) + (mCellHeight / 2)
- };
- }
-
- public void calculateCellCount(int width, int height, int maxCellCountX, int maxCellCountY) {
- mCellCountX = Math.min(maxCellCountX, estimateCellHSpan(width));
- mCellCountY = Math.min(maxCellCountY, estimateCellVSpan(height));
- requestLayout();
- }
-
- /**
- * Estimates the width that the number of hSpan cells will take up.
- */
- public int estimateCellWidth(int hSpan) {
- // TODO: we need to take widthGap into effect
- return hSpan * mCellWidth;
- }
-
- /**
- * Estimates the height that the number of vSpan cells will take up.
- */
- public int estimateCellHeight(int vSpan) {
- // TODO: we need to take heightGap into effect
- return vSpan * mCellHeight;
- }
-
- @Override
- public ViewGroup.LayoutParams generateLayoutParams(AttributeSet attrs) {
- return new PagedViewCellLayout.LayoutParams(getContext(), attrs);
- }
-
- @Override
- protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
- return p instanceof PagedViewCellLayout.LayoutParams;
- }
-
- @Override
- protected ViewGroup.LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) {
- return new PagedViewCellLayout.LayoutParams(p);
- }
-
- public static class LayoutParams extends ViewGroup.MarginLayoutParams {
- /**
- * Horizontal location of the item in the grid.
- */
- @ViewDebug.ExportedProperty
- public int cellX;
-
- /**
- * Vertical location of the item in the grid.
- */
- @ViewDebug.ExportedProperty
- public int cellY;
-
- /**
- * Number of cells spanned horizontally by the item.
- */
- @ViewDebug.ExportedProperty
- public int cellHSpan;
-
- /**
- * Number of cells spanned vertically by the item.
- */
- @ViewDebug.ExportedProperty
- public int cellVSpan;
-
- /**
- * Is this item currently being dragged
- */
- public boolean isDragging;
-
- // a data object that you can bind to this layout params
- private Object mTag;
-
- // X coordinate of the view in the layout.
- @ViewDebug.ExportedProperty
- int x;
- // Y coordinate of the view in the layout.
- @ViewDebug.ExportedProperty
- int y;
-
- public LayoutParams() {
- super(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
- cellHSpan = 1;
- cellVSpan = 1;
- }
-
- public LayoutParams(Context c, AttributeSet attrs) {
- super(c, attrs);
- cellHSpan = 1;
- cellVSpan = 1;
- }
-
- public LayoutParams(ViewGroup.LayoutParams source) {
- super(source);
- cellHSpan = 1;
- cellVSpan = 1;
- }
-
- public LayoutParams(LayoutParams source) {
- super(source);
- this.cellX = source.cellX;
- this.cellY = source.cellY;
- this.cellHSpan = source.cellHSpan;
- this.cellVSpan = source.cellVSpan;
- }
-
- public LayoutParams(int cellX, int cellY, int cellHSpan, int cellVSpan) {
- super(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
- this.cellX = cellX;
- this.cellY = cellY;
- this.cellHSpan = cellHSpan;
- this.cellVSpan = cellVSpan;
- }
-
- public void setup(Context context,
- int cellWidth, int cellHeight, int widthGap, int heightGap,
- int hStartPadding, int vStartPadding) {
-
- final int myCellHSpan = cellHSpan;
- final int myCellVSpan = cellVSpan;
- final int myCellX = cellX;
- final int myCellY = cellY;
-
- width = myCellHSpan * cellWidth + ((myCellHSpan - 1) * widthGap) -
- leftMargin - rightMargin;
- height = myCellVSpan * cellHeight + ((myCellVSpan - 1) * heightGap) -
- topMargin - bottomMargin;
-
- if (LauncherAppState.getInstance().isScreenLarge()) {
- x = hStartPadding + myCellX * (cellWidth + widthGap) + leftMargin;
- y = vStartPadding + myCellY * (cellHeight + heightGap) + topMargin;
- } else {
- x = myCellX * (cellWidth + widthGap) + leftMargin;
- y = myCellY * (cellHeight + heightGap) + topMargin;
- }
- }
-
- public Object getTag() {
- return mTag;
- }
-
- public void setTag(Object tag) {
- mTag = tag;
- }
-
- public String toString() {
- return "(" + this.cellX + ", " + this.cellY + ", " +
- this.cellHSpan + ", " + this.cellVSpan + ")";
- }
- }
-} \ No newline at end of file
diff --git a/src/com/android/launcher3/PagedViewCellLayoutChildren.java b/src/com/android/launcher3/PagedViewCellLayoutChildren.java
deleted file mode 100644
index 84d2b1dd3..000000000
--- a/src/com/android/launcher3/PagedViewCellLayoutChildren.java
+++ /dev/null
@@ -1,161 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.launcher3;
-
-import android.content.Context;
-import android.graphics.Rect;
-import android.view.View;
-import android.view.ViewGroup;
-
-/**
- * An abstraction of the original CellLayout which supports laying out items
- * which span multiple cells into a grid-like layout. Also supports dimming
- * to give a preview of its contents.
- */
-public class PagedViewCellLayoutChildren extends ViewGroup {
- static final String TAG = "PagedViewCellLayout";
-
- private boolean mCenterContent;
-
- private int mCellWidth;
- private int mCellHeight;
- private int mWidthGap;
- private int mHeightGap;
-
- public PagedViewCellLayoutChildren(Context context) {
- super(context);
- }
-
- @Override
- public void cancelLongPress() {
- super.cancelLongPress();
-
- // Cancel long press for all children
- final int count = getChildCount();
- for (int i = 0; i < count; i++) {
- final View child = getChildAt(i);
- child.cancelLongPress();
- }
- }
-
- public void setGap(int widthGap, int heightGap) {
- mWidthGap = widthGap;
- mHeightGap = heightGap;
- requestLayout();
- }
-
- public void setCellDimensions(int width, int height) {
- mCellWidth = width;
- mCellHeight = height;
- requestLayout();
- }
-
- @Override
- public void requestChildFocus(View child, View focused) {
- super.requestChildFocus(child, focused);
- if (child != null) {
- Rect r = new Rect();
- child.getDrawingRect(r);
- requestRectangleOnScreen(r);
- }
- }
-
- @Override
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec);
- int widthSpecSize = MeasureSpec.getSize(widthMeasureSpec);
-
- int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec);
- int heightSpecSize = MeasureSpec.getSize(heightMeasureSpec);
-
- if (widthSpecMode == MeasureSpec.UNSPECIFIED || heightSpecMode == MeasureSpec.UNSPECIFIED) {
- throw new RuntimeException("CellLayout cannot have UNSPECIFIED dimensions");
- }
-
- final int count = getChildCount();
- for (int i = 0; i < count; i++) {
- View child = getChildAt(i);
- PagedViewCellLayout.LayoutParams lp =
- (PagedViewCellLayout.LayoutParams) child.getLayoutParams();
- lp.setup(getContext(),
- mCellWidth, mCellHeight, mWidthGap, mHeightGap,
- getPaddingLeft(),
- getPaddingTop());
-
- int childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(lp.width,
- MeasureSpec.EXACTLY);
- int childheightMeasureSpec = MeasureSpec.makeMeasureSpec(lp.height,
- MeasureSpec.EXACTLY);
-
- child.measure(childWidthMeasureSpec, childheightMeasureSpec);
- }
-
- setMeasuredDimension(widthSpecSize, heightSpecSize);
- }
-
- @Override
- protected void onLayout(boolean changed, int l, int t, int r, int b) {
- int count = getChildCount();
-
- int offsetX = 0;
- if (mCenterContent && count > 0) {
- // determine the max width of all the rows and center accordingly
- int maxRowX = 0;
- int minRowX = Integer.MAX_VALUE;
- for (int i = 0; i < count; i++) {
- View child = getChildAt(i);
- if (child.getVisibility() != GONE) {
- PagedViewCellLayout.LayoutParams lp =
- (PagedViewCellLayout.LayoutParams) child.getLayoutParams();
- minRowX = Math.min(minRowX, lp.x);
- maxRowX = Math.max(maxRowX, lp.x + lp.width);
- }
- }
- int maxRowWidth = maxRowX - minRowX;
- offsetX = (getMeasuredWidth() - maxRowWidth) / 2;
- }
-
- for (int i = 0; i < count; i++) {
- View child = getChildAt(i);
- if (child.getVisibility() != GONE) {
- PagedViewCellLayout.LayoutParams lp =
- (PagedViewCellLayout.LayoutParams) child.getLayoutParams();
-
- int childLeft = offsetX + lp.x;
- int childTop = lp.y;
- child.layout(childLeft, childTop, childLeft + lp.width, childTop + lp.height);
- }
- }
- }
-
- public void enableCenteredContent(boolean enabled) {
- mCenterContent = enabled;
- }
-
- @Override
- protected void setChildrenDrawingCacheEnabled(boolean enabled) {
- final int count = getChildCount();
- for (int i = 0; i < count; i++) {
- final View view = getChildAt(i);
- view.setDrawingCacheEnabled(enabled);
- // Update the drawing caches
- if (!view.isHardwareAccelerated()) {
- view.buildDrawingCache(true);
- }
- }
- }
-}
diff --git a/src/com/android/launcher3/PagedViewGridLayout.java b/src/com/android/launcher3/PagedViewGridLayout.java
deleted file mode 100644
index f69fa562d..000000000
--- a/src/com/android/launcher3/PagedViewGridLayout.java
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.launcher3;
-
-import android.content.Context;
-import android.view.MotionEvent;
-import android.view.View;
-import android.widget.FrameLayout;
-import android.widget.GridLayout;
-
-/**
- * The grid based layout used strictly for the widget/wallpaper tab of the AppsCustomize pane
- */
-public class PagedViewGridLayout extends GridLayout implements Page {
- static final String TAG = "PagedViewGridLayout";
-
- private int mCellCountX;
- private int mCellCountY;
- private Runnable mOnLayoutListener;
-
- public PagedViewGridLayout(Context context, int cellCountX, int cellCountY) {
- super(context, null, 0);
- mCellCountX = cellCountX;
- mCellCountY = cellCountY;
- }
-
- int getCellCountX() {
- return mCellCountX;
- }
-
- int getCellCountY() {
- return mCellCountY;
- }
-
- /**
- * Clears all the key listeners for the individual widgets.
- */
- public void resetChildrenOnKeyListeners() {
- int childCount = getChildCount();
- for (int j = 0; j < childCount; ++j) {
- getChildAt(j).setOnKeyListener(null);
- }
- }
-
- @Override
- protected void onDetachedFromWindow() {
- super.onDetachedFromWindow();
- mOnLayoutListener = null;
- }
-
- public void setOnLayoutListener(Runnable r) {
- mOnLayoutListener = r;
- }
-
- protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
- super.onLayout(changed, left, top, right, bottom);
- if (mOnLayoutListener != null) {
- mOnLayoutListener.run();
- }
- }
-
- @Override
- public boolean onTouchEvent(MotionEvent event) {
- boolean result = super.onTouchEvent(event);
- int count = getPageChildCount();
- if (count > 0) {
- // We only intercept the touch if we are tapping in empty space after the final row
- View child = getChildOnPageAt(count - 1);
- int bottom = child.getBottom();
- result = result || (event.getY() < bottom);
- }
- return result;
- }
-
- @Override
- public void removeAllViewsOnPage() {
- removeAllViews();
- mOnLayoutListener = null;
- setLayerType(LAYER_TYPE_NONE, null);
- }
-
- @Override
- public void removeViewOnPageAt(int index) {
- removeViewAt(index);
- }
-
- @Override
- public int getPageChildCount() {
- return getChildCount();
- }
-
- @Override
- public View getChildOnPageAt(int i) {
- return getChildAt(i);
- }
-
- @Override
- public int indexOfChildOnPage(View v) {
- return indexOfChild(v);
- }
-
- public static class LayoutParams extends FrameLayout.LayoutParams {
- public LayoutParams(int width, int height) {
- super(width, height);
- }
- }
-}
diff --git a/src/com/android/launcher3/PagedViewWidget.java b/src/com/android/launcher3/PagedViewWidget.java
deleted file mode 100644
index e6e11a312..000000000
--- a/src/com/android/launcher3/PagedViewWidget.java
+++ /dev/null
@@ -1,262 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.launcher3;
-
-import android.appwidget.AppWidgetProviderInfo;
-import android.content.Context;
-import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
-import android.content.res.Resources;
-import android.graphics.Rect;
-import android.util.AttributeSet;
-import android.util.TypedValue;
-import android.view.MotionEvent;
-import android.view.View;
-import android.widget.ImageView;
-import android.widget.LinearLayout;
-import android.widget.TextView;
-
-import com.android.launcher3.compat.AppWidgetManagerCompat;
-
-/**
- * The linear layout used strictly for the widget/wallpaper tab of the customization tray
- */
-public class PagedViewWidget extends LinearLayout {
- static final String TAG = "PagedViewWidgetLayout";
-
- private static boolean sDeletePreviewsWhenDetachedFromWindow = true;
- private static boolean sRecyclePreviewsWhenDetachedFromWindow = true;
-
- private String mDimensionsFormatString;
- CheckForShortPress mPendingCheckForShortPress = null;
- ShortPressListener mShortPressListener = null;
- boolean mShortPressTriggered = false;
- static PagedViewWidget sShortpressTarget = null;
- boolean mIsAppWidget;
- private final Rect mOriginalImagePadding = new Rect();
- private Object mInfo;
- private WidgetPreviewLoader mWidgetPreviewLoader;
-
- public PagedViewWidget(Context context) {
- this(context, null);
- }
-
- public PagedViewWidget(Context context, AttributeSet attrs) {
- this(context, attrs, 0);
- }
-
- public PagedViewWidget(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
-
- final Resources r = context.getResources();
- mDimensionsFormatString = r.getString(R.string.widget_dims_format);
-
- setWillNotDraw(false);
- setClipToPadding(false);
- }
-
- @Override
- protected void onFinishInflate() {
- super.onFinishInflate();
-
- final ImageView image = (ImageView) findViewById(R.id.widget_preview);
- mOriginalImagePadding.left = image.getPaddingLeft();
- mOriginalImagePadding.top = image.getPaddingTop();
- mOriginalImagePadding.right = image.getPaddingRight();
- mOriginalImagePadding.bottom = image.getPaddingBottom();
-
- // Ensure we are using the right text size
- LauncherAppState app = LauncherAppState.getInstance();
- DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
- TextView name = (TextView) findViewById(R.id.widget_name);
- if (name != null) {
- name.setTextSize(TypedValue.COMPLEX_UNIT_PX, grid.iconTextSizePx);
- }
- TextView dims = (TextView) findViewById(R.id.widget_dims);
- if (dims != null) {
- dims.setTextSize(TypedValue.COMPLEX_UNIT_PX, grid.iconTextSizePx);
- }
- }
-
- public static void setDeletePreviewsWhenDetachedFromWindow(boolean value) {
- sDeletePreviewsWhenDetachedFromWindow = value;
- }
-
- public static void setRecyclePreviewsWhenDetachedFromWindow(boolean value) {
- sRecyclePreviewsWhenDetachedFromWindow = value;
- }
-
- @Override
- protected void onDetachedFromWindow() {
- super.onDetachedFromWindow();
-
- if (sDeletePreviewsWhenDetachedFromWindow) {
- final ImageView image = (ImageView) findViewById(R.id.widget_preview);
- if (image != null) {
- FastBitmapDrawable preview = (FastBitmapDrawable) image.getDrawable();
- if (sRecyclePreviewsWhenDetachedFromWindow &&
- mInfo != null && preview != null && preview.getBitmap() != null) {
- mWidgetPreviewLoader.recycleBitmap(mInfo, preview.getBitmap());
- }
- image.setImageDrawable(null);
- }
- }
- }
-
- public void applyFromAppWidgetProviderInfo(AppWidgetProviderInfo info,
- int maxWidth, int[] cellSpan, WidgetPreviewLoader loader) {
- LauncherAppState app = LauncherAppState.getInstance();
- DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
-
- mIsAppWidget = true;
- mInfo = info;
- final ImageView image = (ImageView) findViewById(R.id.widget_preview);
- if (maxWidth > -1) {
- image.setMaxWidth(maxWidth);
- }
- final TextView name = (TextView) findViewById(R.id.widget_name);
- name.setText(AppWidgetManagerCompat.getInstance(getContext()).loadLabel(info));
- final TextView dims = (TextView) findViewById(R.id.widget_dims);
- if (dims != null) {
- int hSpan = Math.min(cellSpan[0], (int) grid.numColumns);
- int vSpan = Math.min(cellSpan[1], (int) grid.numRows);
- dims.setText(String.format(mDimensionsFormatString, hSpan, vSpan));
- }
- mWidgetPreviewLoader = loader;
- }
-
- public void applyFromResolveInfo(
- PackageManager pm, ResolveInfo info, WidgetPreviewLoader loader) {
- mIsAppWidget = false;
- mInfo = info;
- CharSequence label = info.loadLabel(pm);
- final TextView name = (TextView) findViewById(R.id.widget_name);
- name.setText(label);
- final TextView dims = (TextView) findViewById(R.id.widget_dims);
- if (dims != null) {
- dims.setText(String.format(mDimensionsFormatString, 1, 1));
- }
- mWidgetPreviewLoader = loader;
- }
-
- public int[] getPreviewSize() {
- final ImageView i = (ImageView) findViewById(R.id.widget_preview);
- int[] maxSize = new int[2];
- maxSize[0] = i.getWidth() - mOriginalImagePadding.left - mOriginalImagePadding.right;
- maxSize[1] = i.getHeight() - mOriginalImagePadding.top;
- return maxSize;
- }
-
- void applyPreview(FastBitmapDrawable preview, int index) {
- final PagedViewWidgetImageView image =
- (PagedViewWidgetImageView) findViewById(R.id.widget_preview);
- if (preview != null) {
- image.mAllowRequestLayout = false;
- image.setImageDrawable(preview);
- if (mIsAppWidget) {
- // center horizontally
- int[] imageSize = getPreviewSize();
- int centerAmount = (imageSize[0] - preview.getIntrinsicWidth()) / 2;
- image.setPadding(mOriginalImagePadding.left + centerAmount,
- mOriginalImagePadding.top,
- mOriginalImagePadding.right,
- mOriginalImagePadding.bottom);
- }
- image.setAlpha(1f);
- image.mAllowRequestLayout = true;
- }
- }
-
- void setShortPressListener(ShortPressListener listener) {
- mShortPressListener = listener;
- }
-
- interface ShortPressListener {
- void onShortPress(View v);
- void cleanUpShortPress(View v);
- }
-
- class CheckForShortPress implements Runnable {
- public void run() {
- if (sShortpressTarget != null) return;
- if (mShortPressListener != null) {
- mShortPressListener.onShortPress(PagedViewWidget.this);
- sShortpressTarget = PagedViewWidget.this;
- }
- mShortPressTriggered = true;
- }
- }
-
- private void checkForShortPress() {
- if (sShortpressTarget != null) return;
- if (mPendingCheckForShortPress == null) {
- mPendingCheckForShortPress = new CheckForShortPress();
- }
- postDelayed(mPendingCheckForShortPress, 120);
- }
-
- /**
- * Remove the longpress detection timer.
- */
- private void removeShortPressCallback() {
- if (mPendingCheckForShortPress != null) {
- removeCallbacks(mPendingCheckForShortPress);
- }
- }
-
- private void cleanUpShortPress() {
- removeShortPressCallback();
- if (mShortPressTriggered) {
- if (mShortPressListener != null) {
- mShortPressListener.cleanUpShortPress(PagedViewWidget.this);
- }
- mShortPressTriggered = false;
- }
- }
-
- static void resetShortPressTarget() {
- sShortpressTarget = null;
- }
-
- @Override
- public boolean onTouchEvent(MotionEvent event) {
- super.onTouchEvent(event);
-
- switch (event.getAction()) {
- case MotionEvent.ACTION_UP:
- cleanUpShortPress();
- break;
- case MotionEvent.ACTION_DOWN:
- checkForShortPress();
- break;
- case MotionEvent.ACTION_CANCEL:
- cleanUpShortPress();
- break;
- case MotionEvent.ACTION_MOVE:
- break;
- }
-
- // We eat up the touch events here, since the PagedView (which uses the same swiping
- // touch code as Workspace previously) uses onInterceptTouchEvent() to determine when
- // the user is scrolling between pages. This means that if the pages themselves don't
- // handle touch events, it gets forwarded up to PagedView itself, and it's own
- // onTouchEvent() handling will prevent further intercept touch events from being called
- // (it's the same view in that case). This is not ideal, but to prevent more changes,
- // we just always mark the touch event as handled.
- return true;
- }
-}
diff --git a/src/com/android/launcher3/PagedViewWidgetImageView.java b/src/com/android/launcher3/PagedViewWidgetImageView.java
deleted file mode 100644
index 7d8279547..000000000
--- a/src/com/android/launcher3/PagedViewWidgetImageView.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.launcher3;
-
-import android.content.Context;
-import android.graphics.Canvas;
-import android.util.AttributeSet;
-import android.widget.ImageView;
-
-public class PagedViewWidgetImageView extends ImageView {
- public boolean mAllowRequestLayout = true;
-
- public PagedViewWidgetImageView(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- public void requestLayout() {
- if (mAllowRequestLayout) {
- super.requestLayout();
- }
- }
-
- @Override
- protected void onDraw(Canvas canvas) {
- canvas.save();
- canvas.clipRect(getScrollX() + getPaddingLeft(),
- getScrollY() + getPaddingTop(),
- getScrollX() + getRight() - getLeft() - getPaddingRight(),
- getScrollY() + getBottom() - getTop() - getPaddingBottom());
-
- super.onDraw(canvas);
- canvas.restore();
-
- }
-}
diff --git a/src/com/android/launcher3/PagedViewWithDraggableItems.java b/src/com/android/launcher3/PagedViewWithDraggableItems.java
deleted file mode 100644
index 0e593698d..000000000
--- a/src/com/android/launcher3/PagedViewWithDraggableItems.java
+++ /dev/null
@@ -1,174 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.launcher3;
-
-import android.content.Context;
-import android.util.AttributeSet;
-import android.view.MotionEvent;
-import android.view.View;
-
-
-/* Class that does most of the work of enabling dragging items out of a PagedView by performing a
- * vertical drag. Used by both CustomizePagedView and AllAppsPagedView.
- * Subclasses must do the following:
- * * call setDragSlopeThreshold after making an instance of the PagedViewWithDraggableItems
- * * call child.setOnLongClickListener(this) and child.setOnTouchListener(this) on all children
- * (good place to do it is in syncPageItems)
- * * override beginDragging(View) (but be careful to call super.beginDragging(View)
- *
- */
-public abstract class PagedViewWithDraggableItems extends PagedView
- implements View.OnLongClickListener, View.OnTouchListener {
- private View mLastTouchedItem;
- private boolean mIsDragging;
- private boolean mIsDragEnabled;
- private float mDragSlopeThreshold;
- private Launcher mLauncher;
-
- public PagedViewWithDraggableItems(Context context) {
- this(context, null);
- }
-
- public PagedViewWithDraggableItems(Context context, AttributeSet attrs) {
- this(context, attrs, 0);
- }
-
- public PagedViewWithDraggableItems(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
- mLauncher = (Launcher) context;
- }
-
- protected boolean beginDragging(View v) {
- boolean wasDragging = mIsDragging;
- mIsDragging = true;
- return !wasDragging;
- }
-
- protected void cancelDragging() {
- mIsDragging = false;
- mLastTouchedItem = null;
- mIsDragEnabled = false;
- }
-
- private void handleTouchEvent(MotionEvent ev) {
- final int action = ev.getAction();
- switch (action & MotionEvent.ACTION_MASK) {
- case MotionEvent.ACTION_DOWN:
- cancelDragging();
- mIsDragEnabled = true;
- break;
- case MotionEvent.ACTION_MOVE:
- if (mTouchState != TOUCH_STATE_SCROLLING && !mIsDragging && mIsDragEnabled) {
- determineDraggingStart(ev);
- }
- break;
- }
- }
-
- @Override
- public boolean onInterceptTouchEvent(MotionEvent ev) {
- handleTouchEvent(ev);
- return super.onInterceptTouchEvent(ev);
- }
-
- @Override
- public boolean onTouchEvent(MotionEvent ev) {
- handleTouchEvent(ev);
- return super.onTouchEvent(ev);
- }
-
- public void trimMemory() {
- mLastTouchedItem = null;
- }
-
- @Override
- public boolean onTouch(View v, MotionEvent event) {
- mLastTouchedItem = v;
- mIsDragEnabled = true;
- return false;
- }
-
- @Override
- public boolean onLongClick(View v) {
- // Return early if this is not initiated from a touch
- if (!v.isInTouchMode()) return false;
- // Return early if we are still animating the pages
- if (mNextPage != INVALID_PAGE) return false;
- // When we have exited all apps or are in transition, disregard long clicks
- if (!mLauncher.isAllAppsVisible() ||
- mLauncher.getWorkspace().isSwitchingState()) return false;
- // Return if global dragging is not enabled
- if (!mLauncher.isDraggingEnabled()) return false;
-
- return beginDragging(v);
- }
-
- /*
- * Determines if we should change the touch state to start scrolling after the
- * user moves their touch point too far.
- */
- protected void determineScrollingStart(MotionEvent ev) {
- if (!mIsDragging) super.determineScrollingStart(ev);
- }
-
- /*
- * Determines if we should change the touch state to start dragging after the
- * user moves their touch point far enough.
- */
- protected void determineDraggingStart(MotionEvent ev) {
- /*
- * Locally do absolute value. mLastMotionX is set to the y value
- * of the down event.
- */
- final int pointerIndex = ev.findPointerIndex(mActivePointerId);
- final float x = ev.getX(pointerIndex);
- final float y = ev.getY(pointerIndex);
- final int xDiff = (int) Math.abs(x - mLastMotionX);
- final int yDiff = (int) Math.abs(y - mLastMotionY);
-
- final int touchSlop = mTouchSlop;
- boolean yMoved = yDiff > touchSlop;
- boolean isUpwardMotion = (yDiff / (float) xDiff) > mDragSlopeThreshold;
-
- if (isUpwardMotion && yMoved && mLastTouchedItem != null) {
- // Drag if the user moved far enough along the Y axis
- beginDragging(mLastTouchedItem);
-
- // Cancel any pending long press
- if (mAllowLongPress) {
- mAllowLongPress = false;
- // Try canceling the long press. It could also have been scheduled
- // by a distant descendant, so use the mAllowLongPress flag to block
- // everything
- final View currentPage = getPageAt(mCurrentPage);
- if (currentPage != null) {
- currentPage.cancelLongPress();
- }
- }
- }
- }
-
- public void setDragSlopeThreshold(float dragSlopeThreshold) {
- mDragSlopeThreshold = dragSlopeThreshold;
- }
-
- @Override
- protected void onDetachedFromWindow() {
- cancelDragging();
- super.onDetachedFromWindow();
- }
-}
diff --git a/src/com/android/launcher3/Partner.java b/src/com/android/launcher3/Partner.java
index e1913193b..380078b26 100644
--- a/src/com/android/launcher3/Partner.java
+++ b/src/com/android/launcher3/Partner.java
@@ -47,8 +47,6 @@ public class Partner {
public static final String RES_REQUIRE_FIRST_RUN_FLOW = "requires_first_run_flow";
/** These resources are used to override the device profile */
- public static final String RES_GRID_AA_SHORT_EDGE_COUNT = "grid_aa_short_edge_count";
- public static final String RES_GRID_AA_LONG_EDGE_COUNT = "grid_aa_long_edge_count";
public static final String RES_GRID_NUM_ROWS = "grid_num_rows";
public static final String RES_GRID_NUM_COLUMNS = "grid_num_columns";
public static final String RES_GRID_ICON_SIZE_DP = "grid_icon_size_dp";
@@ -116,56 +114,42 @@ public class Partner {
return resId != 0 && getResources().getBoolean(resId);
}
- public DeviceProfile getDeviceProfileOverride(DisplayMetrics dm) {
- boolean containsProfileOverrides = false;
-
- DeviceProfile dp = new DeviceProfile();
-
- // We initialize customizable fields to be invalid
- dp.numRows = -1;
- dp.numColumns = -1;
- dp.allAppsShortEdgeCount = -1;
- dp.allAppsLongEdgeCount = -1;
+ public void applyInvariantDeviceProfileOverrides(InvariantDeviceProfile inv, DisplayMetrics dm) {
+ int numRows = -1;
+ int numColumns = -1;
+ float iconSize = -1;
try {
int resId = getResources().getIdentifier(RES_GRID_NUM_ROWS,
"integer", getPackageName());
if (resId > 0) {
- containsProfileOverrides = true;
- dp.numRows = getResources().getInteger(resId);
+ numRows = getResources().getInteger(resId);
}
resId = getResources().getIdentifier(RES_GRID_NUM_COLUMNS,
"integer", getPackageName());
if (resId > 0) {
- containsProfileOverrides = true;
- dp.numColumns = getResources().getInteger(resId);
- }
-
- resId = getResources().getIdentifier(RES_GRID_AA_SHORT_EDGE_COUNT,
- "integer", getPackageName());
- if (resId > 0) {
- containsProfileOverrides = true;
- dp.allAppsShortEdgeCount = getResources().getInteger(resId);
- }
-
- resId = getResources().getIdentifier(RES_GRID_AA_LONG_EDGE_COUNT,
- "integer", getPackageName());
- if (resId > 0) {
- containsProfileOverrides = true;
- dp.allAppsLongEdgeCount = getResources().getInteger(resId);
+ numColumns = getResources().getInteger(resId);
}
resId = getResources().getIdentifier(RES_GRID_ICON_SIZE_DP,
"dimen", getPackageName());
if (resId > 0) {
- containsProfileOverrides = true;
int px = getResources().getDimensionPixelSize(resId);
- dp.iconSize = DynamicGrid.dpiFromPx(px, dm);
+ iconSize = Utilities.dpiFromPx(px, dm);
}
} catch (Resources.NotFoundException ex) {
Log.e(TAG, "Invalid Partner grid resource!", ex);
+ return;
+ }
+
+ if (numRows > 0 && numColumns > 0) {
+ inv.numRows = numRows;
+ inv.numColumns = numColumns;
+ }
+
+ if (iconSize > 0) {
+ inv.iconSize = iconSize;
}
- return containsProfileOverrides ? dp : null;
}
}
diff --git a/src/com/android/launcher3/PendingAddItemInfo.java b/src/com/android/launcher3/PendingAddItemInfo.java
index 967cc928e..1aaf85bbd 100644
--- a/src/com/android/launcher3/PendingAddItemInfo.java
+++ b/src/com/android/launcher3/PendingAddItemInfo.java
@@ -16,92 +16,17 @@
package com.android.launcher3;
-import android.appwidget.AppWidgetHostView;
-import android.appwidget.AppWidgetProviderInfo;
import android.content.ComponentName;
-import android.content.pm.ActivityInfo;
-import android.os.Bundle;
-import android.os.Parcelable;
/**
- * We pass this object with a drag from the customization tray
+ * Meta data that is used for deferred binding.
+ * e.g., this object is used to pass information on dragable targets when they are dropped onto
+ * the workspace from another container.
*/
-class PendingAddItemInfo extends ItemInfo {
+public class PendingAddItemInfo extends ItemInfo {
+
/**
* The component that will be created.
*/
- ComponentName componentName;
-}
-
-class PendingAddShortcutInfo extends PendingAddItemInfo {
-
- ActivityInfo shortcutActivityInfo;
-
- public PendingAddShortcutInfo(ActivityInfo activityInfo) {
- shortcutActivityInfo = activityInfo;
- }
-
- @Override
- public String toString() {
- return "Shortcut: " + shortcutActivityInfo.packageName;
- }
-}
-
-class PendingAddWidgetInfo extends PendingAddItemInfo {
- int minWidth;
- int minHeight;
- int minResizeWidth;
- int minResizeHeight;
- int previewImage;
- int icon;
- AppWidgetProviderInfo info;
- AppWidgetHostView boundWidget;
- Bundle bindOptions = null;
-
- // Any configuration data that we want to pass to a configuration activity when
- // starting up a widget
- String mimeType;
- Parcelable configurationData;
-
- public PendingAddWidgetInfo(AppWidgetProviderInfo i, String dataMimeType, Parcelable data) {
- itemType = LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET;
- this.info = i;
- componentName = i.provider;
- minWidth = i.minWidth;
- minHeight = i.minHeight;
- minResizeWidth = i.minResizeWidth;
- minResizeHeight = i.minResizeHeight;
- previewImage = i.previewImage;
- icon = i.icon;
- if (dataMimeType != null && data != null) {
- mimeType = dataMimeType;
- configurationData = data;
- }
- }
-
- // Copy constructor
- public PendingAddWidgetInfo(PendingAddWidgetInfo copy) {
- minWidth = copy.minWidth;
- minHeight = copy.minHeight;
- minResizeWidth = copy.minResizeWidth;
- minResizeHeight = copy.minResizeHeight;
- previewImage = copy.previewImage;
- icon = copy.icon;
- info = copy.info;
- boundWidget = copy.boundWidget;
- mimeType = copy.mimeType;
- configurationData = copy.configurationData;
- componentName = copy.componentName;
- itemType = copy.itemType;
- spanX = copy.spanX;
- spanY = copy.spanY;
- minSpanX = copy.minSpanX;
- minSpanY = copy.minSpanY;
- bindOptions = copy.bindOptions == null ? null : (Bundle) copy.bindOptions.clone();
- }
-
- @Override
- public String toString() {
- return "Widget: " + componentName.toShortString();
- }
+ public ComponentName componentName;
}
diff --git a/src/com/android/launcher3/PendingAppWidgetHostView.java b/src/com/android/launcher3/PendingAppWidgetHostView.java
index 179c60a98..08f8e5601 100644
--- a/src/com/android/launcher3/PendingAppWidgetHostView.java
+++ b/src/com/android/launcher3/PendingAppWidgetHostView.java
@@ -42,6 +42,7 @@ public class PendingAppWidgetHostView extends LauncherAppWidgetHostView implemen
private final int mStartState;
private final Intent mIconLookupIntent;
private final boolean mDisabledForSafeMode;
+ private Launcher mLauncher;
private Bitmap mIcon;
@@ -56,6 +57,8 @@ public class PendingAppWidgetHostView extends LauncherAppWidgetHostView implemen
public PendingAppWidgetHostView(Context context, LauncherAppWidgetInfo info,
boolean disabledForSafeMode) {
super(context);
+
+ mLauncher = (Launcher) context;
mInfo = info;
mStartState = info.restoreStatus;
mIconLookupIntent = new Intent().setComponent(info.providerName);
@@ -64,7 +67,7 @@ public class PendingAppWidgetHostView extends LauncherAppWidgetHostView implemen
mPaint = new TextPaint();
mPaint.setColor(0xFFFFFFFF);
mPaint.setTextSize(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_PX,
- getDeviceProfile().iconTextSizePx, getResources().getDisplayMetrics()));
+ mLauncher.getDeviceProfile().iconTextSizePx, getResources().getDisplayMetrics()));
setBackgroundResource(R.drawable.quantum_panel_dark);
setWillNotDraw(false);
}
@@ -118,7 +121,7 @@ public class PendingAppWidgetHostView extends LauncherAppWidgetHostView implemen
// 2) Preload icon in the center
// 3) Setup icon in the center and app icon in the top right corner.
if (mDisabledForSafeMode) {
- FastBitmapDrawable disabledIcon = Utilities.createIconDrawable(mIcon);
+ FastBitmapDrawable disabledIcon = mLauncher.createIconDrawable(mIcon);
disabledIcon.setGhostModeEnabled(true);
mCenterDrawable = disabledIcon;
mTopCornerDrawable = null;
@@ -131,7 +134,7 @@ public class PendingAppWidgetHostView extends LauncherAppWidgetHostView implemen
sPreloaderTheme.applyStyle(R.style.PreloadIcon, true);
}
- FastBitmapDrawable drawable = Utilities.createIconDrawable(mIcon);
+ FastBitmapDrawable drawable = mLauncher.createIconDrawable(mIcon);
mCenterDrawable = new PreloadIconDrawable(drawable, sPreloaderTheme);
mCenterDrawable.setCallback(this);
mTopCornerDrawable = null;
@@ -173,12 +176,12 @@ public class PendingAppWidgetHostView extends LauncherAppWidgetHostView implemen
return;
}
+ DeviceProfile grid = mLauncher.getDeviceProfile();
if (mTopCornerDrawable == null) {
if (mDrawableSizeChanged) {
int outset = (mCenterDrawable instanceof PreloadIconDrawable) ?
((PreloadIconDrawable) mCenterDrawable).getOutset() : 0;
- int maxSize = LauncherAppState.getInstance().getDynamicGrid()
- .getDeviceProfile().iconSizePx + 2 * outset;
+ int maxSize = grid.iconSizePx + 2 * outset;
int size = Math.min(maxSize, Math.min(
getWidth() - getPaddingLeft() - getPaddingRight(),
getHeight() - getPaddingTop() - getPaddingBottom()));
@@ -193,7 +196,6 @@ public class PendingAppWidgetHostView extends LauncherAppWidgetHostView implemen
} else {
// Draw the top corner icon and "Setup" text is possible
if (mDrawableSizeChanged) {
- DeviceProfile grid = getDeviceProfile();
int iconSize = grid.iconSizePx;
int paddingTop = getPaddingTop();
int paddingBottom = getPaddingBottom();
@@ -251,8 +253,4 @@ public class PendingAppWidgetHostView extends LauncherAppWidgetHostView implemen
}
}
}
-
- private DeviceProfile getDeviceProfile() {
- return LauncherAppState.getInstance().getDynamicGrid().getDeviceProfile();
- }
}
diff --git a/src/com/android/launcher3/PreloadIconDrawable.java b/src/com/android/launcher3/PreloadIconDrawable.java
index 2972c4f9b..bcb59c448 100644
--- a/src/com/android/launcher3/PreloadIconDrawable.java
+++ b/src/com/android/launcher3/PreloadIconDrawable.java
@@ -54,12 +54,11 @@ class PreloadIconDrawable extends Drawable {
mPaint.setStrokeCap(Paint.Cap.ROUND);
setBounds(icon.getBounds());
- applyTheme(theme);
+ applyPreloaderTheme(theme);
onLevelChange(0);
}
- @Override
- public void applyTheme(Theme t) {
+ public void applyPreloaderTheme(Theme t) {
TypedArray ta = t.obtainStyledAttributes(R.styleable.PreloadIconDrawable);
mBgDrawable = ta.getDrawable(R.styleable.PreloadIconDrawable_background);
mBgDrawable.setFilterBitmap(true);
diff --git a/src/com/android/launcher3/SearchDropTargetBar.java b/src/com/android/launcher3/SearchDropTargetBar.java
index 99c2e0859..4cdf1cac9 100644
--- a/src/com/android/launcher3/SearchDropTargetBar.java
+++ b/src/com/android/launcher3/SearchDropTargetBar.java
@@ -33,23 +33,22 @@ import android.widget.FrameLayout;
*/
public class SearchDropTargetBar extends FrameLayout implements DragController.DragListener {
- private static final int sTransitionInDuration = 200;
- private static final int sTransitionOutDuration = 175;
+ private static final int TRANSITION_DURATION = 200;
- private ObjectAnimator mDropTargetBarAnim;
- private ValueAnimator mQSBSearchBarAnim;
+ private ObjectAnimator mShowDropTargetBarAnim;
+ private ValueAnimator mHideSearchBarAnim;
private static final AccelerateInterpolator sAccelerateInterpolator =
new AccelerateInterpolator();
private boolean mIsSearchBarHidden;
private View mQSBSearchBar;
private View mDropTargetBar;
- private ButtonDropTarget mInfoDropTarget;
- private ButtonDropTarget mDeleteDropTarget;
- private int mBarHeight;
private boolean mDeferOnDragEnd = false;
- private boolean mEnableDropDownDropTargets;
+ // Drop targets
+ private ButtonDropTarget mInfoDropTarget;
+ private ButtonDropTarget mDeleteDropTarget;
+ private ButtonDropTarget mUninstallDropTarget;
public SearchDropTargetBar(Context context, AttributeSet attrs) {
this(context, attrs, 0);
@@ -61,29 +60,30 @@ public class SearchDropTargetBar extends FrameLayout implements DragController.D
public void setup(Launcher launcher, DragController dragController) {
dragController.addDragListener(this);
+ dragController.setFlingToDeleteDropTarget(mDeleteDropTarget);
+
dragController.addDragListener(mInfoDropTarget);
dragController.addDragListener(mDeleteDropTarget);
+ dragController.addDragListener(mUninstallDropTarget);
+
dragController.addDropTarget(mInfoDropTarget);
dragController.addDropTarget(mDeleteDropTarget);
- dragController.setFlingToDeleteDropTarget(mDeleteDropTarget);
+ dragController.addDropTarget(mUninstallDropTarget);
+
mInfoDropTarget.setLauncher(launcher);
mDeleteDropTarget.setLauncher(launcher);
+ mUninstallDropTarget.setLauncher(launcher);
}
public void setQsbSearchBar(View qsb) {
mQSBSearchBar = qsb;
if (mQSBSearchBar != null) {
- if (mEnableDropDownDropTargets) {
- mQSBSearchBarAnim = LauncherAnimUtils.ofFloat(mQSBSearchBar, "translationY", 0,
- -mBarHeight);
- } else {
- mQSBSearchBarAnim = LauncherAnimUtils.ofFloat(mQSBSearchBar, "alpha", 1f, 0f);
- }
- setupAnimation(mQSBSearchBarAnim, mQSBSearchBar);
+ mHideSearchBarAnim = LauncherAnimUtils.ofFloat(mQSBSearchBar, "alpha", 1f, 0f);
+ setupAnimation(mHideSearchBarAnim, mQSBSearchBar);
} else {
// Create a no-op animation of the search bar is null
- mQSBSearchBarAnim = ValueAnimator.ofFloat(0, 0);
- mQSBSearchBarAnim.setDuration(sTransitionInDuration);
+ mHideSearchBarAnim = ValueAnimator.ofFloat(0, 0);
+ mHideSearchBarAnim.setDuration(TRANSITION_DURATION);
}
}
@@ -97,7 +97,7 @@ public class SearchDropTargetBar extends FrameLayout implements DragController.D
private void setupAnimation(ValueAnimator anim, final View v) {
anim.setInterpolator(sAccelerateInterpolator);
- anim.setDuration(sTransitionInDuration);
+ anim.setDuration(TRANSITION_DURATION);
anim.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
@@ -116,80 +116,80 @@ public class SearchDropTargetBar extends FrameLayout implements DragController.D
mDropTargetBar = findViewById(R.id.drag_target_bar);
mInfoDropTarget = (ButtonDropTarget) mDropTargetBar.findViewById(R.id.info_target_text);
mDeleteDropTarget = (ButtonDropTarget) mDropTargetBar.findViewById(R.id.delete_target_text);
+ mUninstallDropTarget = (ButtonDropTarget) mDropTargetBar.findViewById(R.id.uninstall_target_text);
mInfoDropTarget.setSearchDropTargetBar(this);
mDeleteDropTarget.setSearchDropTargetBar(this);
-
- mEnableDropDownDropTargets =
- getResources().getBoolean(R.bool.config_useDropTargetDownTransition);
+ mUninstallDropTarget.setSearchDropTargetBar(this);
// Create the various fade animations
- if (mEnableDropDownDropTargets) {
- LauncherAppState app = LauncherAppState.getInstance();
- DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
- mBarHeight = grid.searchBarSpaceHeightPx;
- mDropTargetBar.setTranslationY(-mBarHeight);
- mDropTargetBarAnim = LauncherAnimUtils.ofFloat(mDropTargetBar, "translationY",
- -mBarHeight, 0f);
-
- } else {
- mDropTargetBar.setAlpha(0f);
- mDropTargetBarAnim = LauncherAnimUtils.ofFloat(mDropTargetBar, "alpha", 0f, 1f);
- }
- setupAnimation(mDropTargetBarAnim, mDropTargetBar);
+ mDropTargetBar.setAlpha(0f);
+ mShowDropTargetBarAnim = LauncherAnimUtils.ofFloat(mDropTargetBar, "alpha", 0f, 1f);
+ setupAnimation(mShowDropTargetBarAnim, mDropTargetBar);
}
+ /**
+ * Finishes all the animations on the search and drop target bars.
+ */
public void finishAnimations() {
prepareStartAnimation(mDropTargetBar);
- mDropTargetBarAnim.reverse();
+ mShowDropTargetBarAnim.reverse();
prepareStartAnimation(mQSBSearchBar);
- mQSBSearchBarAnim.reverse();
+ mHideSearchBarAnim.reverse();
}
- /*
- * Shows and hides the search bar.
+ /**
+ * Shows the search bar.
*/
public void showSearchBar(boolean animated) {
- boolean needToCancelOngoingAnimation = mQSBSearchBarAnim.isRunning() && !animated;
- if (!mIsSearchBarHidden && !needToCancelOngoingAnimation) return;
+ if (!mIsSearchBarHidden) return;
if (animated) {
prepareStartAnimation(mQSBSearchBar);
- mQSBSearchBarAnim.reverse();
+ mHideSearchBarAnim.reverse();
} else {
- mQSBSearchBarAnim.cancel();
- if (mQSBSearchBar != null && mEnableDropDownDropTargets) {
- mQSBSearchBar.setTranslationY(0);
- } else if (mQSBSearchBar != null) {
+ mHideSearchBarAnim.cancel();
+ if (mQSBSearchBar != null) {
mQSBSearchBar.setAlpha(1f);
}
}
mIsSearchBarHidden = false;
}
+
+ /**
+ * Hides the search bar. We only use this for clings.
+ */
public void hideSearchBar(boolean animated) {
- boolean needToCancelOngoingAnimation = mQSBSearchBarAnim.isRunning() && !animated;
- if (mIsSearchBarHidden && !needToCancelOngoingAnimation) return;
+ if (mIsSearchBarHidden) return;
if (animated) {
prepareStartAnimation(mQSBSearchBar);
- mQSBSearchBarAnim.start();
+ mHideSearchBarAnim.start();
} else {
- mQSBSearchBarAnim.cancel();
- if (mQSBSearchBar != null && mEnableDropDownDropTargets) {
- mQSBSearchBar.setTranslationY(-mBarHeight);
- } else if (mQSBSearchBar != null) {
+ mHideSearchBarAnim.cancel();
+ if (mQSBSearchBar != null) {
mQSBSearchBar.setAlpha(0f);
}
}
mIsSearchBarHidden = true;
}
- /*
- * Gets various transition durations.
+ /**
+ * Shows the drop target bar.
*/
- public int getTransitionInDuration() {
- return sTransitionInDuration;
+ public void showDeleteTarget() {
+ // Animate out the QSB search bar, and animate in the drop target bar
+ prepareStartAnimation(mDropTargetBar);
+ mShowDropTargetBarAnim.start();
+ hideSearchBar(true);
}
- public int getTransitionOutDuration() {
- return sTransitionOutDuration;
+
+ /**
+ * Hides the drop target bar.
+ */
+ public void hideDeleteTarget() {
+ // Restore the QSB search bar, and animate out the drop target bar
+ prepareStartAnimation(mDropTargetBar);
+ mShowDropTargetBarAnim.reverse();
+ showSearchBar(true);
}
/*
@@ -197,13 +197,7 @@ public class SearchDropTargetBar extends FrameLayout implements DragController.D
*/
@Override
public void onDragStart(DragSource source, Object info, int dragAction) {
- // Animate out the QSB search bar, and animate in the drop target bar
- prepareStartAnimation(mDropTargetBar);
- mDropTargetBarAnim.start();
- if (!mIsSearchBarHidden) {
- prepareStartAnimation(mQSBSearchBar);
- mQSBSearchBarAnim.start();
- }
+ showDeleteTarget();
}
public void deferOnDragEnd() {
@@ -213,13 +207,7 @@ public class SearchDropTargetBar extends FrameLayout implements DragController.D
@Override
public void onDragEnd() {
if (!mDeferOnDragEnd) {
- // Restore the QSB search bar, and animate out the drop target bar
- prepareStartAnimation(mDropTargetBar);
- mDropTargetBarAnim.reverse();
- if (!mIsSearchBarHidden) {
- prepareStartAnimation(mQSBSearchBar);
- mQSBSearchBarAnim.reverse();
- }
+ hideDeleteTarget();
} else {
mDeferOnDragEnd = false;
}
@@ -240,4 +228,13 @@ public class SearchDropTargetBar extends FrameLayout implements DragController.D
return null;
}
}
+
+ public void enableAccessibleDrag(boolean enable) {
+ if (mQSBSearchBar != null) {
+ mQSBSearchBar.setVisibility(enable ? View.GONE : View.VISIBLE);
+ }
+ mInfoDropTarget.enableAccessibleDrag(enable);
+ mDeleteDropTarget.enableAccessibleDrag(enable);
+ mUninstallDropTarget.enableAccessibleDrag(enable);
+ }
}
diff --git a/src/com/android/launcher3/SettingsActivity.java b/src/com/android/launcher3/SettingsActivity.java
new file mode 100644
index 000000000..dab71c862
--- /dev/null
+++ b/src/com/android/launcher3/SettingsActivity.java
@@ -0,0 +1,76 @@
+/*
+ * 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;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.preference.Preference;
+import android.preference.Preference.OnPreferenceChangeListener;
+import android.preference.PreferenceFragment;
+import android.preference.SwitchPreference;
+
+/**
+ * Settings activity for Launcher. Currently implements the following setting: Allow rotation
+ */
+public class SettingsActivity extends Activity {
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ // Display the fragment as the main content.
+ getFragmentManager().beginTransaction()
+ .replace(android.R.id.content, new LauncherSettingsFragment())
+ .commit();
+ }
+
+ /**
+ * This fragment shows the launcher preferences.
+ */
+ public static class LauncherSettingsFragment extends PreferenceFragment
+ implements OnPreferenceChangeListener {
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ addPreferencesFromResource(R.xml.launcher_preferences);
+
+ SwitchPreference pref = (SwitchPreference) findPreference(
+ Utilities.ALLOW_ROTATION_PREFERENCE_KEY);
+ pref.setPersistent(false);
+
+ Bundle extras = new Bundle();
+ extras.putBoolean(LauncherSettings.Settings.EXTRA_DEFAULT_VALUE, false);
+ Bundle value = getActivity().getContentResolver().call(
+ LauncherSettings.Settings.CONTENT_URI,
+ LauncherSettings.Settings.METHOD_GET_BOOLEAN,
+ Utilities.ALLOW_ROTATION_PREFERENCE_KEY, extras);
+ pref.setChecked(value.getBoolean(LauncherSettings.Settings.EXTRA_VALUE));
+
+ pref.setOnPreferenceChangeListener(this);
+ }
+
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ Bundle extras = new Bundle();
+ extras.putBoolean(LauncherSettings.Settings.EXTRA_VALUE, (Boolean) newValue);
+ getActivity().getContentResolver().call(
+ LauncherSettings.Settings.CONTENT_URI,
+ LauncherSettings.Settings.METHOD_SET_BOOLEAN,
+ preference.getKey(), extras);
+ return true;
+ }
+ }
+}
diff --git a/src/com/android/launcher3/ShortcutAndWidgetContainer.java b/src/com/android/launcher3/ShortcutAndWidgetContainer.java
index bb5601e90..157b48a39 100644
--- a/src/com/android/launcher3/ShortcutAndWidgetContainer.java
+++ b/src/com/android/launcher3/ShortcutAndWidgetContainer.java
@@ -23,6 +23,7 @@ import android.graphics.Paint;
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";
@@ -44,10 +45,13 @@ public class ShortcutAndWidgetContainer extends ViewGroup {
private int mCountX;
private int mCountY;
+ private Launcher mLauncher;
+
private boolean mInvertIfRtl = false;
public ShortcutAndWidgetContainer(Context context) {
super(context);
+ mLauncher = (Launcher) context;
mWallpaperManager = WallpaperManager.getInstance(context);
}
@@ -124,22 +128,19 @@ public class ShortcutAndWidgetContainer extends ViewGroup {
}
int getCellContentWidth() {
- final LauncherAppState app = LauncherAppState.getInstance();
- final DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
+ final DeviceProfile grid = mLauncher.getDeviceProfile();
return Math.min(getMeasuredHeight(), mIsHotseatLayout ?
grid.hotseatCellWidthPx: grid.cellWidthPx);
}
int getCellContentHeight() {
- final LauncherAppState app = LauncherAppState.getInstance();
- final DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
+ final DeviceProfile grid = mLauncher.getDeviceProfile();
return Math.min(getMeasuredHeight(), mIsHotseatLayout ?
grid.hotseatCellHeightPx : grid.cellHeightPx);
}
public void measureChild(View child) {
- final LauncherAppState app = LauncherAppState.getInstance();
- final DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
+ final DeviceProfile grid = mLauncher.getDeviceProfile();
final int cellWidth = mCellWidth;
final int cellHeight = mCellHeight;
CellLayout.LayoutParams lp = (CellLayout.LayoutParams) child.getLayoutParams();
@@ -168,12 +169,8 @@ public class ShortcutAndWidgetContainer extends ViewGroup {
child.measure(childWidthMeasureSpec, childheightMeasureSpec);
}
- private boolean invertLayoutHorizontally() {
- return mInvertIfRtl && isLayoutRtl();
- }
-
- public boolean isLayoutRtl() {
- return (getLayoutDirection() == LAYOUT_DIRECTION_RTL);
+ public boolean invertLayoutHorizontally() {
+ return mInvertIfRtl && Utilities.isRtl(getResources());
}
@Override
diff --git a/src/com/android/launcher3/ShortcutInfo.java b/src/com/android/launcher3/ShortcutInfo.java
index 01f79314e..56c0b9d2f 100644
--- a/src/com/android/launcher3/ShortcutInfo.java
+++ b/src/com/android/launcher3/ShortcutInfo.java
@@ -23,7 +23,10 @@ import android.content.Intent;
import android.graphics.Bitmap;
import android.util.Log;
+import com.android.launcher3.LauncherSettings.Favorites;
+import com.android.launcher3.compat.LauncherActivityInfoCompat;
import com.android.launcher3.compat.UserHandleCompat;
+import com.android.launcher3.compat.UserManagerCompat;
import java.util.ArrayList;
import java.util.Arrays;
@@ -46,18 +49,24 @@ public class ShortcutInfo extends ItemInfo {
* be present along with {@link #FLAG_RESTORED_ICON}, and is set during default layout
* parsing.
*/
- public static final int FLAG_AUTOINTALL_ICON = 2;
+ public static final int FLAG_AUTOINTALL_ICON = 2; //0B10;
/**
* 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;
+ public static final int FLAG_INSTALL_SESSION_ACTIVE = 4; // 0B100;
/**
* Indicates that the widget restore has started.
*/
- public static final int FLAG_RESTORE_STARTED = 8;
+ public static final int FLAG_RESTORE_STARTED = 8; //0B1000;
+
+ /**
+ * Indicates if it represents a common type mentioned in {@link CommonAppTypeParser}.
+ * Upto 15 different types supported.
+ */
+ public static final int FLAG_RESTORED_APP_TYPE = 0B0011110000;
/**
* The intent used to start the application.
@@ -67,8 +76,9 @@ public class ShortcutInfo extends ItemInfo {
/**
* Indicates whether the icon comes from an application's resource (if false)
* or from a custom Bitmap (if true.)
+ * TODO: remove this flag
*/
- boolean customIcon;
+ public boolean customIcon;
/**
* Indicates whether we're using the default fallback icon instead of something from the
@@ -77,10 +87,15 @@ public class ShortcutInfo extends ItemInfo {
boolean usingFallbackIcon;
/**
+ * Indicates whether we're using a low res icon
+ */
+ boolean usingLowResIcon;
+
+ /**
* If isShortcut=true and customIcon=false, this contains a reference to the
* shortcut icon as an application's resource.
*/
- Intent.ShortcutIconResource iconResource;
+ public Intent.ShortcutIconResource iconResource;
/**
* The application icon.
@@ -113,7 +128,7 @@ public class ShortcutInfo extends ItemInfo {
/**
* Refer {@link AppInfo#firstInstallTime}.
*/
- long firstInstallTime;
+ public long firstInstallTime;
/**
* TODO move this to {@link status}
@@ -139,7 +154,7 @@ public class ShortcutInfo extends ItemInfo {
Bitmap icon, UserHandleCompat user) {
this();
this.intent = intent;
- this.title = title;
+ this.title = Utilities.trim(title);
this.contentDescription = contentDescription;
mIcon = icon;
this.user = user;
@@ -147,7 +162,7 @@ public class ShortcutInfo extends ItemInfo {
public ShortcutInfo(Context context, ShortcutInfo info) {
super(info);
- title = info.title.toString();
+ title = Utilities.trim(info.title);
intent = new Intent(info.intent);
if (info.iconResource != null) {
iconResource = new Intent.ShortcutIconResource();
@@ -165,7 +180,7 @@ public class ShortcutInfo extends ItemInfo {
/** TODO: Remove this. It's only called by ApplicationInfo.makeShortcut. */
public ShortcutInfo(AppInfo info) {
super(info);
- title = info.title.toString();
+ title = Utilities.trim(info.title);
intent = new Intent(info.intent);
customIcon = false;
flags = info.flags;
@@ -184,8 +199,10 @@ public class ShortcutInfo extends ItemInfo {
}
public void updateIcon(IconCache iconCache) {
- mIcon = iconCache.getIcon(promisedIntent != null ? promisedIntent : intent, user);
- usingFallbackIcon = iconCache.isDefaultIcon(mIcon, user);
+ if (itemType == Favorites.ITEM_TYPE_APPLICATION) {
+ iconCache.getTitleAndIcon(this, promisedIntent != null ? promisedIntent : intent, user,
+ shouldUseLowResIcon());
+ }
}
@Override
@@ -198,6 +215,7 @@ public class ShortcutInfo extends ItemInfo {
String uri = promisedIntent != null ? promisedIntent.toUri(0)
: (intent != null ? intent.toUri(0) : null);
values.put(LauncherSettings.BaseLauncherColumns.INTENT, uri);
+ values.put(LauncherSettings.Favorites.RESTORED, status);
if (customIcon) {
values.put(LauncherSettings.BaseLauncherColumns.ICON_TYPE,
@@ -207,9 +225,9 @@ public class ShortcutInfo extends ItemInfo {
if (!usingFallbackIcon) {
writeBitmap(values, mIcon);
}
- values.put(LauncherSettings.BaseLauncherColumns.ICON_TYPE,
- LauncherSettings.BaseLauncherColumns.ICON_TYPE_RESOURCE);
if (iconResource != null) {
+ values.put(LauncherSettings.BaseLauncherColumns.ICON_TYPE,
+ LauncherSettings.BaseLauncherColumns.ICON_TYPE_RESOURCE);
values.put(LauncherSettings.BaseLauncherColumns.ICON_PACKAGE,
iconResource.packageName);
values.put(LauncherSettings.BaseLauncherColumns.ICON_RESOURCE,
@@ -256,5 +274,23 @@ public class ShortcutInfo extends ItemInfo {
mInstallProgress = progress;
status |= FLAG_INSTALL_SESSION_ACTIVE;
}
+
+ public boolean shouldUseLowResIcon() {
+ return usingLowResIcon && container >= 0 && rank >= FolderIcon.NUM_ITEMS_IN_PREVIEW;
+ }
+
+ public static ShortcutInfo fromActivityInfo(LauncherActivityInfoCompat info, Context context) {
+ final ShortcutInfo shortcut = new ShortcutInfo();
+ shortcut.user = info.getUser();
+ shortcut.title = Utilities.trim(info.getLabel());
+ shortcut.contentDescription = UserManagerCompat.getInstance(context)
+ .getBadgedLabelForUser(info.getLabel(), info.getUser());
+ shortcut.customIcon = false;
+ 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/SmoothPagedView.java b/src/com/android/launcher3/SmoothPagedView.java
deleted file mode 100644
index 4e331aa2c..000000000
--- a/src/com/android/launcher3/SmoothPagedView.java
+++ /dev/null
@@ -1,185 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.launcher3;
-
-import android.content.Context;
-import android.util.AttributeSet;
-import android.view.animation.Interpolator;
-
-public abstract class SmoothPagedView extends PagedView {
- private static final float SMOOTHING_SPEED = 0.75f;
- private static final float SMOOTHING_CONSTANT = (float) (0.016 / Math.log(SMOOTHING_SPEED));
-
- private float mBaseLineFlingVelocity;
- private float mFlingVelocityInfluence;
-
- static final int DEFAULT_MODE = 0;
- static final int X_LARGE_MODE = 1;
-
- int mScrollMode;
-
- private Interpolator mScrollInterpolator;
-
- public static class OvershootInterpolator implements Interpolator {
- private static final float DEFAULT_TENSION = 1.3f;
- private float mTension;
-
- public OvershootInterpolator() {
- mTension = DEFAULT_TENSION;
- }
-
- public void setDistance(int distance) {
- mTension = distance > 0 ? DEFAULT_TENSION / distance : DEFAULT_TENSION;
- }
-
- public void disableSettle() {
- mTension = 0.f;
- }
-
- public float getInterpolation(float t) {
- t -= 1.0f;
- return t * t * ((mTension + 1) * t + mTension) + 1.0f;
- }
- }
-
- /**
- * Used to inflate the Workspace from XML.
- *
- * @param context The application's context.
- * @param attrs The attributes set containing the Workspace's customization values.
- */
- public SmoothPagedView(Context context, AttributeSet attrs) {
- this(context, attrs, 0);
- }
-
- /**
- * Used to inflate the Workspace from XML.
- *
- * @param context The application's context.
- * @param attrs The attributes set containing the Workspace's customization values.
- * @param defStyle Unused.
- */
- public SmoothPagedView(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
-
- mUsePagingTouchSlop = false;
-
- // This means that we'll take care of updating the scroll parameter ourselves (we do it
- // in computeScroll), we only do this in the OVERSHOOT_MODE, ie. on phones
- mDeferScrollUpdate = mScrollMode != X_LARGE_MODE;
- }
-
- protected int getScrollMode() {
- return X_LARGE_MODE;
- }
-
- /**
- * Initializes various states for this workspace.
- */
- @Override
- protected void init() {
- super.init();
-
- mScrollMode = getScrollMode();
- if (mScrollMode == DEFAULT_MODE) {
- mBaseLineFlingVelocity = 2500.0f;
- mFlingVelocityInfluence = 0.4f;
- mScrollInterpolator = new OvershootInterpolator();
- setDefaultInterpolator(mScrollInterpolator);
- }
- }
-
- @Override
- protected void snapToDestination() {
- if (mScrollMode == X_LARGE_MODE) {
- super.snapToDestination();
- } else {
- snapToPageWithVelocity(getPageNearestToCenterOfScreen(), 0);
- }
- }
-
- @Override
- protected void snapToPageWithVelocity(int whichPage, int velocity) {
- if (mScrollMode == X_LARGE_MODE) {
- super.snapToPageWithVelocity(whichPage, velocity);
- } else {
- snapToPageWithVelocity(whichPage, 0, true);
- }
- }
-
- private void snapToPageWithVelocity(int whichPage, int velocity, boolean settle) {
- // if (!mScroller.isFinished()) return;
-
- whichPage = Math.max(0, Math.min(whichPage, getChildCount() - 1));
-
- final int screenDelta = Math.max(1, Math.abs(whichPage - mCurrentPage));
- final int newX = getScrollForPage(whichPage);
- final int delta = newX - mUnboundedScrollX;
- int duration = (screenDelta + 1) * 100;
-
- if (!mScroller.isFinished()) {
- mScroller.abortAnimation();
- }
-
- if (settle) {
- ((OvershootInterpolator) mScrollInterpolator).setDistance(screenDelta);
- } else {
- ((OvershootInterpolator) mScrollInterpolator).disableSettle();
- }
-
- velocity = Math.abs(velocity);
- if (velocity > 0) {
- duration += (duration / (velocity / mBaseLineFlingVelocity)) * mFlingVelocityInfluence;
- } else {
- duration += 100;
- }
-
- snapToPage(whichPage, delta, duration);
- }
-
- @Override
- protected void snapToPage(int whichPage) {
- if (mScrollMode == X_LARGE_MODE) {
- super.snapToPage(whichPage);
- } else {
- snapToPageWithVelocity(whichPage, 0, false);
- }
- }
-
- @Override
- public void computeScroll() {
- if (mScrollMode == X_LARGE_MODE) {
- super.computeScroll();
- } else {
- boolean scrollComputed = computeScrollHelper();
-
- if (!scrollComputed && mTouchState == TOUCH_STATE_SCROLLING) {
- final float now = System.nanoTime() / NANOTIME_DIV;
- final float e = (float) Math.exp((now - mSmoothingTime) / SMOOTHING_CONSTANT);
-
- final float dx = mTouchX - mUnboundedScrollX;
- scrollTo(Math.round(mUnboundedScrollX + dx * e), getScrollY());
- mSmoothingTime = now;
-
- // Keep generating points as long as we're more than 1px away from the target
- if (dx > 1.f || dx < -1.f) {
- invalidate();
- }
- }
- }
- }
-}
diff --git a/src/com/android/launcher3/Stats.java b/src/com/android/launcher3/Stats.java
index a87986562..cb0e252b2 100644
--- a/src/com/android/launcher3/Stats.java
+++ b/src/com/android/launcher3/Stats.java
@@ -20,16 +20,64 @@ import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.os.Bundle;
import android.util.Log;
-
-import java.io.*;
-import java.util.ArrayList;
+import android.view.View;
+import android.view.ViewParent;
public class Stats {
- private static final boolean DEBUG_BROADCASTS = false;
- private static final String TAG = "Launcher3/Stats";
- private static final boolean LOCAL_LAUNCH_LOG = true;
+ /**
+ * Implemented by containers to provide a launch source for a given child.
+ */
+ public interface LaunchSourceProvider {
+ void fillInLaunchSourceData(Bundle sourceData);
+ }
+
+ /**
+ * Helpers to add the source to a launch intent.
+ */
+ public static class LaunchSourceUtils {
+ /**
+ * Create a default bundle for LaunchSourceProviders to fill in their data.
+ */
+ public static Bundle createSourceData() {
+ Bundle sourceData = new Bundle();
+ sourceData.putString(SOURCE_EXTRA_CONTAINER, CONTAINER_HOMESCREEN);
+ // Have default container/sub container pages
+ sourceData.putInt(SOURCE_EXTRA_CONTAINER_PAGE, 0);
+ sourceData.putInt(SOURCE_EXTRA_SUB_CONTAINER_PAGE, 0);
+ return sourceData;
+ }
+
+ /**
+ * Finds the next launch source provider in the parents of the view hierarchy and populates
+ * the source data from that provider.
+ */
+ public static void populateSourceDataFromAncestorProvider(View v, Bundle sourceData) {
+ if (v == null) {
+ return;
+ }
+
+ Stats.LaunchSourceProvider provider = null;
+ ViewParent parent = v.getParent();
+ while (parent != null && parent instanceof View) {
+ if (parent instanceof Stats.LaunchSourceProvider) {
+ provider = (Stats.LaunchSourceProvider) parent;
+ break;
+ }
+ parent = parent.getParent();
+ }
+
+ if (provider != null) {
+ provider.fillInLaunchSourceData(sourceData);
+ } else if (LauncherAppState.isDogfoodBuild()) {
+ throw new RuntimeException("Expected LaunchSourceProvider");
+ }
+ }
+ }
+
+ private static final boolean DEBUG_BROADCASTS = false;
public static final String ACTION_LAUNCH = "com.android.launcher3.action.LAUNCH";
public static final String EXTRA_INTENT = "intent";
@@ -37,55 +85,37 @@ public class Stats {
public static final String EXTRA_SCREEN = "screen";
public static final String EXTRA_CELLX = "cellX";
public static final String EXTRA_CELLY = "cellY";
+ public static final String EXTRA_SOURCE = "source";
- private static final int LOG_VERSION = 1;
- private static final int LOG_TAG_VERSION = 0x1;
- private static final int LOG_TAG_LAUNCH = 0x1000;
+ public static final String SOURCE_EXTRA_CONTAINER = "container";
+ public static final String SOURCE_EXTRA_CONTAINER_PAGE = "container_page";
+ public static final String SOURCE_EXTRA_SUB_CONTAINER = "sub_container";
+ public static final String SOURCE_EXTRA_SUB_CONTAINER_PAGE = "sub_container_page";
- private static final int STATS_VERSION = 1;
- private static final int INITIAL_STATS_SIZE = 100;
+ public static final String CONTAINER_SEARCH_BOX = "search_box";
+ public static final String CONTAINER_ALL_APPS = "all_apps";
+ public static final String CONTAINER_HOMESCREEN = "homescreen"; // aka. Workspace
+ public static final String CONTAINER_HOTSEAT = "hotseat";
- // TODO: delayed/batched writes
- private static final boolean FLUSH_IMMEDIATELY = true;
+ public static final String SUB_CONTAINER_FOLDER = "folder";
+ public static final String SUB_CONTAINER_ALL_APPS_A_Z = "a-z";
+ public static final String SUB_CONTAINER_ALL_APPS_PREDICTION = "prediction";
+ public static final String SUB_CONTAINER_ALL_APPS_SEARCH = "search";
private final Launcher mLauncher;
-
private final String mLaunchBroadcastPermission;
- DataOutputStream mLog;
-
- ArrayList<String> mIntents;
- ArrayList<Integer> mHistogram;
-
public Stats(Launcher launcher) {
mLauncher = launcher;
-
mLaunchBroadcastPermission =
launcher.getResources().getString(R.string.receive_launch_broadcasts_permission);
- loadStats();
-
- if (LOCAL_LAUNCH_LOG) {
- try {
- mLog = new DataOutputStream(mLauncher.openFileOutput(
- LauncherFiles.LAUNCHES_LOG, Context.MODE_APPEND));
- mLog.writeInt(LOG_TAG_VERSION);
- mLog.writeInt(LOG_VERSION);
- } catch (FileNotFoundException e) {
- Log.e(TAG, "unable to create stats log: " + e);
- mLog = null;
- } catch (IOException e) {
- Log.e(TAG, "unable to write to stats log: " + e);
- mLog = null;
- }
- }
-
if (DEBUG_BROADCASTS) {
launcher.registerReceiver(
new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
- android.util.Log.v("Stats", "got broadcast: " + intent + " for launched intent: "
+ Log.v("Stats", "got broadcast: " + intent + " for launched intent: "
+ intent.getStringExtra(EXTRA_INTENT));
}
},
@@ -96,26 +126,11 @@ public class Stats {
}
}
- public void incrementLaunch(String intentStr) {
- int pos = mIntents.indexOf(intentStr);
- if (pos < 0) {
- mIntents.add(intentStr);
- mHistogram.add(1);
- } else {
- mHistogram.set(pos, mHistogram.get(pos) + 1);
- }
- }
-
- public void recordLaunch(Intent intent) {
- recordLaunch(intent, null);
- }
-
- public void recordLaunch(Intent intent, ShortcutInfo shortcut) {
+ public void recordLaunch(View v, Intent intent, ShortcutInfo shortcut) {
intent = new Intent(intent);
intent.setSourceBounds(null);
final String flat = intent.toUri(0);
-
Intent broadcastIntent = new Intent(ACTION_LAUNCH).putExtra(EXTRA_INTENT, flat);
if (shortcut != null) {
broadcastIntent.putExtra(EXTRA_CONTAINER, shortcut.container)
@@ -123,95 +138,10 @@ public class Stats {
.putExtra(EXTRA_CELLX, shortcut.cellX)
.putExtra(EXTRA_CELLY, shortcut.cellY);
}
- mLauncher.sendBroadcast(broadcastIntent, mLaunchBroadcastPermission);
-
- incrementLaunch(flat);
-
- if (FLUSH_IMMEDIATELY) {
- saveStats();
- }
-
- if (LOCAL_LAUNCH_LOG && mLog != null) {
- try {
- mLog.writeInt(LOG_TAG_LAUNCH);
- mLog.writeLong(System.currentTimeMillis());
- if (shortcut == null) {
- mLog.writeShort(0);
- mLog.writeShort(0);
- mLog.writeShort(0);
- mLog.writeShort(0);
- } else {
- mLog.writeShort((short) shortcut.container);
- mLog.writeShort((short) shortcut.screenId);
- mLog.writeShort((short) shortcut.cellX);
- mLog.writeShort((short) shortcut.cellY);
- }
- mLog.writeUTF(flat);
- if (FLUSH_IMMEDIATELY) {
- mLog.flush(); // TODO: delayed writes
- }
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- }
-
- private void saveStats() {
- DataOutputStream stats = null;
- try {
- stats = new DataOutputStream(mLauncher.openFileOutput(
- LauncherFiles.STATS_LOG + ".tmp", Context.MODE_PRIVATE));
- stats.writeInt(STATS_VERSION);
- final int N = mHistogram.size();
- stats.writeInt(N);
- for (int i=0; i<N; i++) {
- stats.writeUTF(mIntents.get(i));
- stats.writeInt(mHistogram.get(i));
- }
- stats.close();
- stats = null;
- mLauncher.getFileStreamPath(LauncherFiles.STATS_LOG + ".tmp")
- .renameTo(mLauncher.getFileStreamPath(LauncherFiles.STATS_LOG));
- } catch (FileNotFoundException e) {
- Log.e(TAG, "unable to create stats data: " + e);
- } catch (IOException e) {
- Log.e(TAG, "unable to write to stats data: " + e);
- } finally {
- if (stats != null) {
- try {
- stats.close();
- } catch (IOException e) { }
- }
- }
- }
- private void loadStats() {
- mIntents = new ArrayList<String>(INITIAL_STATS_SIZE);
- mHistogram = new ArrayList<Integer>(INITIAL_STATS_SIZE);
- DataInputStream stats = null;
- try {
- stats = new DataInputStream(mLauncher.openFileInput(LauncherFiles.STATS_LOG));
- final int version = stats.readInt();
- if (version == STATS_VERSION) {
- final int N = stats.readInt();
- for (int i=0; i<N; i++) {
- final String pkg = stats.readUTF();
- final int count = stats.readInt();
- mIntents.add(pkg);
- mHistogram.add(count);
- }
- }
- } catch (FileNotFoundException e) {
- // not a problem
- } catch (IOException e) {
- // more of a problem
-
- } finally {
- if (stats != null) {
- try {
- stats.close();
- } catch (IOException e) { }
- }
- }
+ Bundle sourceExtras = LaunchSourceUtils.createSourceData();
+ LaunchSourceUtils.populateSourceDataFromAncestorProvider(v, sourceExtras);
+ broadcastIntent.putExtra(EXTRA_SOURCE, sourceExtras);
+ mLauncher.sendBroadcast(broadcastIntent, mLaunchBroadcastPermission);
}
}
diff --git a/src/com/android/launcher3/StylusEventHelper.java b/src/com/android/launcher3/StylusEventHelper.java
new file mode 100644
index 000000000..da46e6a54
--- /dev/null
+++ b/src/com/android/launcher3/StylusEventHelper.java
@@ -0,0 +1,84 @@
+package com.android.launcher3;
+
+import com.android.launcher3.Utilities;
+
+import android.util.Log;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewConfiguration;
+
+/**
+ * Helper for identifying when a stylus touches a view while the primary stylus button is pressed.
+ * This can occur in {@value MotionEvent#ACTION_DOWN} or {@value MotionEvent#ACTION_MOVE}. On a
+ * stylus button press this performs the view's {@link View#performLongClick()} method, if the view
+ * is long clickable.
+ */
+public class StylusEventHelper {
+ private boolean mIsButtonPressed;
+ private View mView;
+
+ public StylusEventHelper(View view) {
+ mView = view;
+ }
+
+ /**
+ * Call this in onTouchEvent method of a view to identify a stylus button press and perform a
+ * long click (if the view is long clickable).
+ *
+ * @param event The event to check for a stylus button press.
+ * @return Whether a stylus event occurred and was handled.
+ */
+ public boolean checkAndPerformStylusEvent(MotionEvent event) {
+ final float slop = ViewConfiguration.get(mView.getContext()).getScaledTouchSlop();
+
+ if (!mView.isLongClickable()) {
+ // We don't do anything unless the view is long clickable.
+ return false;
+ }
+
+ final boolean stylusButtonPressed = isStylusButtonPressed(event);
+ switch (event.getAction()) {
+ case MotionEvent.ACTION_DOWN:
+ mIsButtonPressed = false;
+ if (stylusButtonPressed && mView.performLongClick()) {
+ mIsButtonPressed = true;
+ return true;
+ }
+ break;
+ case MotionEvent.ACTION_MOVE:
+ if (Utilities.pointInView(mView, event.getX(), event.getY(), slop)) {
+ if (!mIsButtonPressed && stylusButtonPressed && mView.performLongClick()) {
+ mIsButtonPressed = true;
+ return true;
+ } else if (mIsButtonPressed && !stylusButtonPressed) {
+ mIsButtonPressed = false;
+ }
+ }
+ break;
+ case MotionEvent.ACTION_UP:
+ case MotionEvent.ACTION_CANCEL:
+ mIsButtonPressed = false;
+ break;
+ }
+ return false;
+ }
+
+ /**
+ * Whether a stylus button press is occurring.
+ */
+ public boolean inStylusButtonPressed() {
+ return mIsButtonPressed;
+ }
+
+ /**
+ * Identifies if the provided {@link MotionEvent} is a stylus with the primary stylus button
+ * pressed.
+ *
+ * @param event The event to check.
+ * @return Whether a stylus button press occurred.
+ */
+ public static boolean isStylusButtonPressed(MotionEvent event) {
+ return event.getToolType(0) == MotionEvent.TOOL_TYPE_STYLUS
+ && event.isButtonPressed(MotionEvent.BUTTON_SECONDARY);
+ }
+} \ No newline at end of file
diff --git a/src/com/android/launcher3/UninstallDropTarget.java b/src/com/android/launcher3/UninstallDropTarget.java
new file mode 100644
index 000000000..0819f8ce0
--- /dev/null
+++ b/src/com/android/launcher3/UninstallDropTarget.java
@@ -0,0 +1,132 @@
+package com.android.launcher3;
+
+import android.annotation.TargetApi;
+import android.content.ComponentName;
+import android.content.Context;
+import android.os.Build;
+import android.os.Bundle;
+import android.os.UserManager;
+import android.util.AttributeSet;
+import android.util.Pair;
+import com.android.launcher3.R;
+import com.android.launcher3.compat.UserHandleCompat;
+import com.android.launcher3.util.Thunk;
+
+public class UninstallDropTarget extends ButtonDropTarget {
+
+ public UninstallDropTarget(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public UninstallDropTarget(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ }
+
+ @Override
+ protected void onFinishInflate() {
+ super.onFinishInflate();
+ // Get the hover color
+ mHoverColor = getResources().getColor(R.color.uninstall_target_hover_tint);
+
+ setDrawable(R.drawable.ic_uninstall_launcher);
+ }
+
+ @Override
+ protected boolean supportsDrop(DragSource source, Object info) {
+ return supportsDrop(getContext(), info);
+ }
+
+ @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2)
+ public static boolean supportsDrop(Context context, Object info) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
+ UserManager userManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
+ Bundle restrictions = userManager.getUserRestrictions();
+ if (restrictions.getBoolean(UserManager.DISALLOW_APPS_CONTROL, false)
+ || restrictions.getBoolean(UserManager.DISALLOW_UNINSTALL_APPS, false)) {
+ return false;
+ }
+ }
+
+ Pair<ComponentName, Integer> componentInfo = getAppInfoFlags(info);
+ return componentInfo != null && (componentInfo.second & AppInfo.DOWNLOADED_FLAG) != 0;
+ }
+
+ /**
+ * @return the component name and flags if {@param info} is an AppInfo or an app shortcut.
+ */
+ private static Pair<ComponentName, Integer> getAppInfoFlags(Object item) {
+ if (item instanceof AppInfo) {
+ AppInfo info = (AppInfo) item;
+ return Pair.create(info.componentName, info.flags);
+ } else if (item instanceof ShortcutInfo) {
+ ShortcutInfo info = (ShortcutInfo) item;
+ ComponentName component = info.getTargetComponent();
+ if (info.itemType == LauncherSettings.BaseLauncherColumns.ITEM_TYPE_APPLICATION
+ && component != null) {
+ return Pair.create(component, info.flags);
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public void onDrop(DragObject d) {
+ // Differ item deletion
+ if (d.dragSource instanceof UninstallSource) {
+ ((UninstallSource) d.dragSource).deferCompleteDropAfterUninstallActivity();
+ }
+ super.onDrop(d);
+ }
+
+ @Override
+ void completeDrop(final DragObject d) {
+ final Pair<ComponentName, Integer> componentInfo = getAppInfoFlags(d.dragInfo);
+ final UserHandleCompat user = ((ItemInfo) d.dragInfo).user;
+ if (startUninstallActivity(mLauncher, d.dragInfo)) {
+
+ final Runnable checkIfUninstallWasSuccess = new Runnable() {
+ @Override
+ public void run() {
+ String packageName = componentInfo.first.getPackageName();
+ boolean uninstallSuccessful = !AllAppsList.packageHasActivities(
+ getContext(), packageName, user);
+ sendUninstallResult(d.dragSource, uninstallSuccessful);
+ }
+ };
+ mLauncher.addOnResumeCallback(checkIfUninstallWasSuccess);
+ } else {
+ sendUninstallResult(d.dragSource, false);
+ }
+ }
+
+ public static boolean startUninstallActivity(Launcher launcher, Object info) {
+ final Pair<ComponentName, Integer> componentInfo = getAppInfoFlags(info);
+ final UserHandleCompat user = ((ItemInfo) info).user;
+ return launcher.startApplicationUninstallActivity(
+ componentInfo.first, componentInfo.second, user);
+ }
+
+ @Thunk void sendUninstallResult(DragSource target, boolean result) {
+ if (target instanceof UninstallSource) {
+ ((UninstallSource) target).onUninstallActivityReturned(result);
+ }
+ }
+
+ /**
+ * Interface defining an object that can provide uninstallable drag objects.
+ */
+ public static interface UninstallSource {
+
+ /**
+ * A pending uninstall operation was complete.
+ * @param result true if uninstall was successful, false otherwise.
+ */
+ void onUninstallActivityReturned(boolean result);
+
+ /**
+ * Indicates that an uninstall request are made and the actual result may come
+ * after some time.
+ */
+ void deferCompleteDropAfterUninstallActivity();
+ }
+}
diff --git a/src/com/android/launcher3/UninstallShortcutReceiver.java b/src/com/android/launcher3/UninstallShortcutReceiver.java
deleted file mode 100644
index ccea4ec0c..000000000
--- a/src/com/android/launcher3/UninstallShortcutReceiver.java
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.launcher3;
-
-import android.content.BroadcastReceiver;
-import android.content.ContentResolver;
-import android.content.Context;
-import android.content.Intent;
-import android.database.Cursor;
-import android.net.Uri;
-import android.widget.Toast;
-
-import java.net.URISyntaxException;
-import java.util.ArrayList;
-import java.util.Iterator;
-
-public class UninstallShortcutReceiver extends BroadcastReceiver {
- private static final String ACTION_UNINSTALL_SHORTCUT =
- "com.android.launcher.action.UNINSTALL_SHORTCUT";
-
- // The set of shortcuts that are pending uninstall
- private static ArrayList<PendingUninstallShortcutInfo> mUninstallQueue =
- new ArrayList<PendingUninstallShortcutInfo>();
-
- // Determines whether to defer uninstalling shortcuts immediately until
- // disableAndFlushUninstallQueue() is called.
- private static boolean mUseUninstallQueue = false;
-
- private static class PendingUninstallShortcutInfo {
- Intent data;
-
- public PendingUninstallShortcutInfo(Intent rawData) {
- data = rawData;
- }
- }
-
- public void onReceive(Context context, Intent data) {
- if (!ACTION_UNINSTALL_SHORTCUT.equals(data.getAction())) {
- return;
- }
-
- PendingUninstallShortcutInfo info = new PendingUninstallShortcutInfo(data);
- if (mUseUninstallQueue) {
- mUninstallQueue.add(info);
- } else {
- processUninstallShortcut(context, info);
- }
- }
-
- static void enableUninstallQueue() {
- mUseUninstallQueue = true;
- }
-
- static void disableAndFlushUninstallQueue(Context context) {
- mUseUninstallQueue = false;
- Iterator<PendingUninstallShortcutInfo> iter = mUninstallQueue.iterator();
- while (iter.hasNext()) {
- processUninstallShortcut(context, iter.next());
- iter.remove();
- }
- }
-
- private static void processUninstallShortcut(Context context,
- PendingUninstallShortcutInfo pendingInfo) {
- final Intent data = pendingInfo.data;
-
- LauncherAppState.setApplicationContext(context.getApplicationContext());
- LauncherAppState app = LauncherAppState.getInstance();
- synchronized (app) { // TODO: make removeShortcut internally threadsafe
- removeShortcut(context, data);
- }
- }
-
- private static void removeShortcut(Context context, Intent data) {
- Intent intent = data.getParcelableExtra(Intent.EXTRA_SHORTCUT_INTENT);
- String name = data.getStringExtra(Intent.EXTRA_SHORTCUT_NAME);
- boolean duplicate = data.getBooleanExtra(Launcher.EXTRA_SHORTCUT_DUPLICATE, true);
-
- if (intent != null && name != null) {
- final ContentResolver cr = context.getContentResolver();
- Cursor c = cr.query(LauncherSettings.Favorites.CONTENT_URI,
- new String[] { LauncherSettings.Favorites._ID, LauncherSettings.Favorites.INTENT },
- LauncherSettings.Favorites.TITLE + "=?", new String[] { name }, null);
-
- final int intentIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.INTENT);
- final int idIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites._ID);
-
- boolean changed = false;
-
- try {
- while (c.moveToNext()) {
- try {
- if (intent.filterEquals(Intent.parseUri(c.getString(intentIndex), 0))) {
- final long id = c.getLong(idIndex);
- final Uri uri = LauncherSettings.Favorites.getContentUri(id, false);
- cr.delete(uri, null, null);
- changed = true;
- if (!duplicate) {
- break;
- }
- }
- } catch (URISyntaxException e) {
- // Ignore
- }
- }
- } finally {
- c.close();
- }
-
- if (changed) {
- cr.notifyChange(LauncherSettings.Favorites.CONTENT_URI, null);
- Toast.makeText(context, context.getString(R.string.shortcut_uninstalled, name),
- Toast.LENGTH_SHORT).show();
- }
- }
- }
-}
diff --git a/src/com/android/launcher3/UserInitializeReceiver.java b/src/com/android/launcher3/UserInitializeReceiver.java
deleted file mode 100644
index d8e17b12f..000000000
--- a/src/com/android/launcher3/UserInitializeReceiver.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (C) 2012 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;
-
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-
-/**
- * Takes care of setting initial wallpaper for a user, by selecting the
- * first wallpaper that is not in use by another user.
- */
-public class UserInitializeReceiver extends BroadcastReceiver {
- @Override
- public void onReceive(Context context, Intent intent) {
- // TODO: initial wallpaper now that wallpapers are owned by another app
- }
-}
diff --git a/src/com/android/launcher3/Utilities.java b/src/com/android/launcher3/Utilities.java
index 215d63d2e..8fd298df7 100644
--- a/src/com/android/launcher3/Utilities.java
+++ b/src/com/android/launcher3/Utilities.java
@@ -25,13 +25,16 @@ import android.content.ActivityNotFoundException;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
+import android.content.SharedPreferences;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ResolveInfo;
import android.content.res.Resources;
+import android.database.Cursor;
import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
@@ -42,26 +45,38 @@ import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.PaintDrawable;
import android.os.Build;
+import android.os.Bundle;
+import android.os.Process;
+import android.text.TextUtils;
+import android.util.DisplayMetrics;
import android.util.Log;
import android.util.Pair;
import android.util.SparseArray;
+import android.util.TypedValue;
import android.view.View;
import android.widget.Toast;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
import java.util.ArrayList;
+import java.util.Locale;
+import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
/**
* Various utilities shared amongst the Launcher's classes.
*/
public final class Utilities {
- private static final String TAG = "Launcher.Utilities";
- private static int sIconWidth = -1;
- private static int sIconHeight = -1;
+ private static final String TAG = "Launcher.Utilities";
private static final Rect sOldBounds = new Rect();
private static final Canvas sCanvas = new Canvas();
+ private static final Pattern sTrimPattern =
+ Pattern.compile("^[\\s|\\p{javaSpaceChar}]*(.*)[\\s|\\p{javaSpaceChar}]*$");
+
static {
sCanvas.setDrawFilter(new PaintFlagsDrawFilter(Paint.DITHER_FLAG,
Paint.FILTER_BITMAP_FLAG));
@@ -69,39 +84,30 @@ public final class Utilities {
static int sColors[] = { 0xffff0000, 0xff00ff00, 0xff0000ff };
static int sColorIndex = 0;
- static int[] sLoc0 = new int[2];
- static int[] sLoc1 = new int[2];
+ private static final int[] sLoc0 = new int[2];
+ private static final int[] sLoc1 = new int[2];
// To turn on these properties, type
// adb shell setprop log.tag.PROPERTY_NAME [VERBOSE | SUPPRESS]
- static final String FORCE_ENABLE_ROTATION_PROPERTY = "launcher_force_rotate";
- public static boolean sForceEnableRotation = isPropertyEnabled(FORCE_ENABLE_ROTATION_PROPERTY);
+ private static final String FORCE_ENABLE_ROTATION_PROPERTY = "launcher_force_rotate";
+ private static boolean sForceEnableRotation = isPropertyEnabled(FORCE_ENABLE_ROTATION_PROPERTY);
- /**
- * Returns a FastBitmapDrawable with the icon, accurately sized.
- */
- public static FastBitmapDrawable createIconDrawable(Bitmap icon) {
- FastBitmapDrawable d = new FastBitmapDrawable(icon);
- d.setFilterBitmap(true);
- resizeIconDrawable(d);
- return d;
- }
-
- /**
- * Resizes an icon drawable to the correct icon size.
- */
- static void resizeIconDrawable(Drawable icon) {
- icon.setBounds(0, 0, sIconWidth, sIconHeight);
- }
+ public static final String ALLOW_ROTATION_PREFERENCE_KEY = "pref_allowRotation";
public static boolean isPropertyEnabled(String propertyName) {
return Log.isLoggable(propertyName, Log.VERBOSE);
}
- public static boolean isRotationEnabled(Context c) {
- boolean enableRotation = sForceEnableRotation ||
- c.getResources().getBoolean(R.bool.allow_rotation);
- return enableRotation;
+ public static boolean isAllowRotationPrefEnabled(Context context, boolean multiProcess) {
+ SharedPreferences sharedPrefs = context.getSharedPreferences(
+ LauncherAppState.getSharedPreferencesKey(), Context.MODE_PRIVATE | (multiProcess ?
+ Context.MODE_MULTI_PROCESS : 0));
+ boolean allowRotationPref = sharedPrefs.getBoolean(ALLOW_ROTATION_PREFERENCE_KEY, false);
+ return sForceEnableRotation || allowRotationPref;
+ }
+
+ public static boolean isRotationAllowedForDevice(Context context) {
+ return sForceEnableRotation || context.getResources().getBoolean(R.bool.allow_rotation);
}
/**
@@ -111,11 +117,30 @@ public final class Utilities {
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP;
}
+ public static boolean isLmpMR1OrAbove() {
+ // TODO(adamcohen): update to Build.VERSION_CODES.LOLLIPOP_MR1 once building against 22;
+ return Build.VERSION.SDK_INT >= 22;
+ }
+
+ public static boolean isLmpMR1() {
+ // TODO(adamcohen): update to Build.VERSION_CODES.LOLLIPOP_MR1 once building against 22;
+ return Build.VERSION.SDK_INT == 22;
+ }
+
+ public static Bitmap createIconBitmap(Cursor c, int iconIndex, Context context) {
+ byte[] data = c.getBlob(iconIndex);
+ try {
+ return createIconBitmap(BitmapFactory.decodeByteArray(data, 0, data.length), context);
+ } catch (Exception e) {
+ return null;
+ }
+ }
+
/**
* Returns a bitmap suitable for the all apps view. If the package or the resource do not
* exist, it returns null.
*/
- static Bitmap createIconBitmap(String packageName, String resourceName, IconCache cache,
+ public static Bitmap createIconBitmap(String packageName, String resourceName,
Context context) {
PackageManager packageManager = context.getPackageManager();
// the resource
@@ -124,7 +149,8 @@ public final class Utilities {
if (resources != null) {
final int id = resources.getIdentifier(resourceName, null, null);
return createIconBitmap(
- resources.getDrawableForDensity(id, cache.getFullResIconDpi()), context);
+ resources.getDrawableForDensity(id, LauncherAppState.getInstance()
+ .getInvariantDeviceProfile().fillResIconDpi), context);
}
} catch (Exception e) {
// Icon not found.
@@ -132,16 +158,16 @@ public final class Utilities {
return null;
}
+ private static int getIconBitmapSize() {
+ return LauncherAppState.getInstance().getInvariantDeviceProfile().iconBitmapSize;
+ }
+
/**
* Returns a bitmap which is of the appropriate size to be displayed as an icon
*/
- static Bitmap createIconBitmap(Bitmap icon, Context context) {
- synchronized (sCanvas) { // we share the statics :-(
- if (sIconWidth == -1) {
- initStatics(context);
- }
- }
- if (sIconWidth == icon.getWidth() && sIconHeight == icon.getHeight()) {
+ public static Bitmap createIconBitmap(Bitmap icon, Context context) {
+ final int iconBitmapSize = getIconBitmapSize();
+ if (iconBitmapSize == icon.getWidth() && iconBitmapSize == icon.getHeight()) {
return icon;
}
return createIconBitmap(new BitmapDrawable(context.getResources(), icon), context);
@@ -151,13 +177,11 @@ public final class Utilities {
* Returns a bitmap suitable for the all apps view.
*/
public static Bitmap createIconBitmap(Drawable icon, Context context) {
- synchronized (sCanvas) { // we share the statics :-(
- if (sIconWidth == -1) {
- initStatics(context);
- }
+ synchronized (sCanvas) {
+ final int iconBitmapSize = getIconBitmapSize();
- int width = sIconWidth;
- int height = sIconHeight;
+ int width = iconBitmapSize;
+ int height = iconBitmapSize;
if (icon instanceof PaintDrawable) {
PaintDrawable painter = (PaintDrawable) icon;
@@ -184,8 +208,8 @@ public final class Utilities {
}
// no intrinsic size --> use default size
- int textureWidth = sIconWidth;
- int textureHeight = sIconHeight;
+ int textureWidth = iconBitmapSize;
+ int textureHeight = iconBitmapSize;
final Bitmap bitmap = Bitmap.createBitmap(textureWidth, textureHeight,
Bitmap.Config.ARGB_8888);
@@ -315,15 +339,6 @@ public final class Utilities {
localY < (v.getHeight() + slop);
}
- private static void initStatics(Context context) {
- final Resources resources = context.getResources();
- sIconWidth = sIconHeight = (int) resources.getDimension(R.dimen.app_icon_size);
- }
-
- public static void setIconSize(int widthPx) {
- sIconWidth = sIconHeight = widthPx;
- }
-
public static void scaleRect(Rect r, float scale) {
if (scale != 1.0f) {
r.left = (int) (r.left * scale + 0.5f);
@@ -542,4 +557,156 @@ public final class Utilities {
}
return defaultWidgetForSearchPackage;
}
+
+ /**
+ * Compresses the bitmap to a byte array for serialization.
+ */
+ public static byte[] flattenBitmap(Bitmap bitmap) {
+ // Try go guesstimate how much space the icon will take when serialized
+ // to avoid unnecessary allocations/copies during the write.
+ int size = bitmap.getWidth() * bitmap.getHeight() * 4;
+ ByteArrayOutputStream out = new ByteArrayOutputStream(size);
+ try {
+ bitmap.compress(Bitmap.CompressFormat.PNG, 100, out);
+ out.flush();
+ out.close();
+ return out.toByteArray();
+ } catch (IOException e) {
+ Log.w(TAG, "Could not write bitmap");
+ return null;
+ }
+ }
+
+ /**
+ * Find the first vacant cell, if there is one.
+ *
+ * @param vacant Holds the x and y coordinate of the vacant cell
+ * @param spanX Horizontal cell span.
+ * @param spanY Vertical cell span.
+ *
+ * @return true if a vacant cell was found
+ */
+ public static boolean findVacantCell(int[] vacant, int spanX, int spanY,
+ int xCount, int yCount, boolean[][] occupied) {
+
+ for (int y = 0; (y + spanY) <= yCount; y++) {
+ for (int x = 0; (x + spanX) <= xCount; x++) {
+ boolean available = !occupied[x][y];
+ out: for (int i = x; i < x + spanX; i++) {
+ for (int j = y; j < y + spanY; j++) {
+ available = available && !occupied[i][j];
+ if (!available) break out;
+ }
+ }
+
+ if (available) {
+ vacant[0] = x;
+ vacant[1] = y;
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Trims the string, removing all whitespace at the beginning and end of the string.
+ * Non-breaking whitespaces are also removed.
+ */
+ public static String trim(CharSequence s) {
+ if (s == null) {
+ return null;
+ }
+
+ // Just strip any sequence of whitespace or java space characters from the beginning and end
+ Matcher m = sTrimPattern.matcher(s);
+ return m.replaceAll("$1");
+ }
+
+ /**
+ * Calculates the height of a given string at a specific text size.
+ */
+ public static float calculateTextHeight(float textSizePx) {
+ Paint p = new Paint();
+ p.setTextSize(textSizePx);
+ Paint.FontMetrics fm = p.getFontMetrics();
+ return -fm.top + fm.bottom;
+ }
+
+ /**
+ * Convenience println with multiple args.
+ */
+ public static void println(String key, Object... args) {
+ StringBuilder b = new StringBuilder();
+ b.append(key);
+ b.append(": ");
+ boolean isFirstArgument = true;
+ for (Object arg : args) {
+ if (isFirstArgument) {
+ isFirstArgument = false;
+ } else {
+ b.append(", ");
+ }
+ b.append(arg);
+ }
+ System.out.println(b.toString());
+ }
+
+ @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
+ public static boolean isRtl(Resources res) {
+ return (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) &&
+ (res.getConfiguration().getLayoutDirection() == View.LAYOUT_DIRECTION_RTL);
+ }
+
+ public static void assertWorkerThread() {
+ if (LauncherAppState.isDogfoodBuild() &&
+ (LauncherModel.sWorkerThread.getThreadId() != Process.myTid())) {
+ throw new IllegalStateException();
+ }
+ }
+
+ /**
+ * Returns true if the intent is a valid launch intent for a launcher activity of an app.
+ * This is used to identify shortcuts which are different from the ones exposed by the
+ * applications' manifest file.
+ *
+ * @param launchIntent The intent that will be launched when the shortcut is clicked.
+ */
+ public static boolean isLauncherAppTarget(Intent launchIntent) {
+ if (launchIntent != null
+ && Intent.ACTION_MAIN.equals(launchIntent.getAction())
+ && launchIntent.getComponent() != null
+ && launchIntent.getCategories() != null
+ && launchIntent.getCategories().size() == 1
+ && launchIntent.hasCategory(Intent.CATEGORY_LAUNCHER)
+ && TextUtils.isEmpty(launchIntent.getDataString())) {
+ // An app target can either have no extra or have ItemInfo.EXTRA_PROFILE.
+ Bundle extras = launchIntent.getExtras();
+ if (extras == null) {
+ return true;
+ } else {
+ Set<String> keys = extras.keySet();
+ return keys.size() == 1 && keys.contains(ItemInfo.EXTRA_PROFILE);
+ }
+ };
+ return false;
+ }
+
+ public static float dpiFromPx(int size, DisplayMetrics metrics){
+ float densityRatio = (float) metrics.densityDpi / DisplayMetrics.DENSITY_DEFAULT;
+ return (size / densityRatio);
+ }
+ public static int pxFromDp(float size, DisplayMetrics metrics) {
+ return (int) Math.round(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
+ size, metrics));
+ }
+ public static int pxFromSp(float size, DisplayMetrics metrics) {
+ return (int) Math.round(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,
+ size, metrics));
+ }
+
+ public static String createDbSelectionQuery(String columnName, Iterable<?> values) {
+ return String.format(Locale.ENGLISH, "%s IN (%s)", columnName, TextUtils.join(", ", values));
+ }
}
diff --git a/src/com/android/launcher3/WeightWatcher.java b/src/com/android/launcher3/WeightWatcher.java
index 70b8afea8..75684797f 100644
--- a/src/com/android/launcher3/WeightWatcher.java
+++ b/src/com/android/launcher3/WeightWatcher.java
@@ -34,6 +34,8 @@ import android.view.View;
import android.widget.LinearLayout;
import android.widget.TextView;
+import com.android.launcher3.util.Thunk;
+
public class WeightWatcher extends LinearLayout {
private static final int RAM_GRAPH_RSS_COLOR = 0xFF990000;
private static final int RAM_GRAPH_PSS_COLOR = 0xFF99CC00;
@@ -81,7 +83,7 @@ public class WeightWatcher extends LinearLayout {
}
}
};
- private MemoryTracker mMemoryService;
+ @Thunk MemoryTracker mMemoryService;
public WeightWatcher(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -134,7 +136,7 @@ public class WeightWatcher extends LinearLayout {
GraphView mRamGraph;
TextView mText;
int mPid;
- private MemoryTracker.ProcessMemInfo mMemInfo;
+ @Thunk MemoryTracker.ProcessMemInfo mMemInfo;
public ProcessWatcher(Context context) {
this(context, null);
diff --git a/src/com/android/launcher3/WidgetPreviewLoader.java b/src/com/android/launcher3/WidgetPreviewLoader.java
index 4e6fe1f88..629387ed0 100644
--- a/src/com/android/launcher3/WidgetPreviewLoader.java
+++ b/src/com/android/launcher3/WidgetPreviewLoader.java
@@ -1,526 +1,353 @@
package com.android.launcher3;
-import android.appwidget.AppWidgetProviderInfo;
import android.content.ComponentName;
import android.content.ContentValues;
import android.content.Context;
-import android.content.SharedPreferences;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ResolveInfo;
import android.content.res.Resources;
import android.database.Cursor;
-import android.database.sqlite.SQLiteCantOpenDatabaseException;
+import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
-import android.database.sqlite.SQLiteDiskIOException;
import android.database.sqlite.SQLiteOpenHelper;
-import android.database.sqlite.SQLiteReadOnlyDatabaseException;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory;
-import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.ColorMatrix;
import android.graphics.ColorMatrixColorFilter;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.Rect;
-import android.graphics.Shader;
+import android.graphics.RectF;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
-import android.os.Build;
+import android.os.Handler;
import android.util.Log;
+import android.util.LongSparseArray;
+
import com.android.launcher3.compat.AppWidgetManagerCompat;
+import com.android.launcher3.compat.UserHandleCompat;
+import com.android.launcher3.compat.UserManagerCompat;
+import com.android.launcher3.util.ComponentKey;
+import com.android.launcher3.util.Thunk;
+import com.android.launcher3.widget.WidgetCell;
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.IOException;
-import java.lang.ref.SoftReference;
-import java.lang.ref.WeakReference;
import java.util.ArrayList;
-import java.util.Arrays;
+import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
-import java.util.List;
+import java.util.Set;
+import java.util.WeakHashMap;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
public class WidgetPreviewLoader {
- private static abstract class SoftReferenceThreadLocal<T> {
- private ThreadLocal<SoftReference<T>> mThreadLocal;
- public SoftReferenceThreadLocal() {
- mThreadLocal = new ThreadLocal<SoftReference<T>>();
- }
-
- abstract T initialValue();
-
- public void set(T t) {
- mThreadLocal.set(new SoftReference<T>(t));
- }
-
- public T get() {
- SoftReference<T> reference = mThreadLocal.get();
- T obj;
- if (reference == null) {
- obj = initialValue();
- mThreadLocal.set(new SoftReference<T>(obj));
- return obj;
- } else {
- obj = reference.get();
- if (obj == null) {
- obj = initialValue();
- mThreadLocal.set(new SoftReference<T>(obj));
- }
- return obj;
- }
- }
- }
-
- private static class CanvasCache extends SoftReferenceThreadLocal<Canvas> {
- @Override
- protected Canvas initialValue() {
- return new Canvas();
- }
- }
-
- private static class PaintCache extends SoftReferenceThreadLocal<Paint> {
- @Override
- protected Paint initialValue() {
- return null;
- }
- }
-
- private static class BitmapCache extends SoftReferenceThreadLocal<Bitmap> {
- @Override
- protected Bitmap initialValue() {
- return null;
- }
- }
-
- private static class RectCache extends SoftReferenceThreadLocal<Rect> {
- @Override
- protected Rect initialValue() {
- return new Rect();
- }
- }
-
- private static class BitmapFactoryOptionsCache extends
- SoftReferenceThreadLocal<BitmapFactory.Options> {
- @Override
- protected BitmapFactory.Options initialValue() {
- return new BitmapFactory.Options();
- }
- }
-
private static final String TAG = "WidgetPreviewLoader";
- private static final String ANDROID_INCREMENTAL_VERSION_NAME_KEY = "android.incremental.version";
+ private static final boolean DEBUG = false;
private static final float WIDGET_PREVIEW_ICON_PADDING_PERCENTAGE = 0.25f;
- private static final HashSet<String> sInvalidPackages = new HashSet<String>();
-
- // Used for drawing shortcut previews
- private final BitmapCache mCachedShortcutPreviewBitmap = new BitmapCache();
- private final PaintCache mCachedShortcutPreviewPaint = new PaintCache();
- private final CanvasCache mCachedShortcutPreviewCanvas = new CanvasCache();
- // Used for drawing widget previews
- private final CanvasCache mCachedAppWidgetPreviewCanvas = new CanvasCache();
- private final RectCache mCachedAppWidgetPreviewSrcRect = new RectCache();
- private final RectCache mCachedAppWidgetPreviewDestRect = new RectCache();
- private final PaintCache mCachedAppWidgetPreviewPaint = new PaintCache();
- private final PaintCache mDefaultAppWidgetPreviewPaint = new PaintCache();
- private final BitmapFactoryOptionsCache mCachedBitmapFactoryOptions = new BitmapFactoryOptionsCache();
+ private final HashMap<String, long[]> mPackageVersions = new HashMap<>();
- private final HashMap<String, WeakReference<Bitmap>> mLoadedPreviews = new HashMap<String, WeakReference<Bitmap>>();
- private final ArrayList<SoftReference<Bitmap>> mUnusedBitmaps = new ArrayList<SoftReference<Bitmap>>();
+ /**
+ * Weak reference objects, do not prevent their referents from being made finalizable,
+ * finalized, and then reclaimed.
+ * Note: synchronized block used for this variable is expensive and the block should always
+ * be posted to a background thread.
+ */
+ @Thunk final Set<Bitmap> mUnusedBitmaps =
+ Collections.newSetFromMap(new WeakHashMap<Bitmap, Boolean>());
private final Context mContext;
- private final int mAppIconSize;
private final IconCache mIconCache;
+ private final UserManagerCompat mUserManager;
private final AppWidgetManagerCompat mManager;
-
- private int mPreviewBitmapWidth;
- private int mPreviewBitmapHeight;
- private String mSize;
- private PagedViewCellLayout mWidgetSpacingLayout;
-
- private String mCachedSelectQuery;
-
-
- private CacheDb mDb;
+ private final CacheDb mDb;
+ private final int mProfileBadgeMargin;
private final MainThreadExecutor mMainThreadExecutor = new MainThreadExecutor();
+ @Thunk final Handler mWorkerHandler;
- public WidgetPreviewLoader(Context context) {
- LauncherAppState app = LauncherAppState.getInstance();
- DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
-
+ public WidgetPreviewLoader(Context context, IconCache iconCache) {
mContext = context;
- mAppIconSize = grid.iconSizePx;
- mIconCache = app.getIconCache();
+ mIconCache = iconCache;
mManager = AppWidgetManagerCompat.getInstance(context);
-
- mDb = app.getWidgetPreviewCacheDb();
-
- SharedPreferences sp = context.getSharedPreferences(
- LauncherAppState.getSharedPreferencesKey(), Context.MODE_PRIVATE);
- final String lastVersionName = sp.getString(ANDROID_INCREMENTAL_VERSION_NAME_KEY, null);
- final String versionName = android.os.Build.VERSION.INCREMENTAL;
- final boolean isLollipopOrGreater = Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP;
- if (!versionName.equals(lastVersionName)) {
- try {
- // clear all the previews whenever the system version changes, to ensure that
- // previews are up-to-date for any apps that might have been updated with the system
- clearDb();
- } catch (SQLiteReadOnlyDatabaseException e) {
- if (isLollipopOrGreater) {
- // Workaround for Bug. 18554839, if we fail to clear the db due to the read-only
- // issue, then ignore this error and leave the old previews
- } else {
- throw e;
- }
- } finally {
- SharedPreferences.Editor editor = sp.edit();
- editor.putString(ANDROID_INCREMENTAL_VERSION_NAME_KEY, versionName);
- editor.commit();
- }
- }
+ mUserManager = UserManagerCompat.getInstance(context);
+ mDb = new CacheDb(context);
+ mWorkerHandler = new Handler(LauncherModel.getWorkerLooper());
+ mProfileBadgeMargin = context.getResources()
+ .getDimensionPixelSize(R.dimen.profile_badge_margin);
}
- public void recreateDb() {
- LauncherAppState app = LauncherAppState.getInstance();
- app.recreateWidgetPreviewDb();
- mDb = app.getWidgetPreviewCacheDb();
- }
-
- public void setPreviewSize(int previewWidth, int previewHeight,
- PagedViewCellLayout widgetSpacingLayout) {
- mPreviewBitmapWidth = previewWidth;
- mPreviewBitmapHeight = previewHeight;
- mSize = previewWidth + "x" + previewHeight;
- mWidgetSpacingLayout = widgetSpacingLayout;
- }
-
- public Bitmap getPreview(final Object o) {
- final String name = getObjectName(o);
- final String packageName = getObjectPackage(o);
- // check if the package is valid
- synchronized(sInvalidPackages) {
- boolean packageValid = !sInvalidPackages.contains(packageName);
- if (!packageValid) {
- return null;
- }
- }
- synchronized(mLoadedPreviews) {
- // check if it exists in our existing cache
- if (mLoadedPreviews.containsKey(name)) {
- WeakReference<Bitmap> bitmapReference = mLoadedPreviews.get(name);
- Bitmap bitmap = bitmapReference.get();
- if (bitmap != null) {
- return bitmap;
- }
- }
- }
-
- Bitmap unusedBitmap = null;
- synchronized(mUnusedBitmaps) {
- // not in cache; we need to load it from the db
- while (unusedBitmap == null && mUnusedBitmaps.size() > 0) {
- Bitmap candidate = mUnusedBitmaps.remove(0).get();
- if (candidate != null && candidate.isMutable() &&
- candidate.getWidth() == mPreviewBitmapWidth &&
- candidate.getHeight() == mPreviewBitmapHeight) {
- unusedBitmap = candidate;
- }
- }
- if (unusedBitmap != null) {
- final Canvas c = mCachedAppWidgetPreviewCanvas.get();
- c.setBitmap(unusedBitmap);
- c.drawColor(0, PorterDuff.Mode.CLEAR);
- c.setBitmap(null);
- }
- }
-
- if (unusedBitmap == null) {
- unusedBitmap = Bitmap.createBitmap(mPreviewBitmapWidth, mPreviewBitmapHeight,
- Bitmap.Config.ARGB_8888);
- }
- Bitmap preview = readFromDb(name, unusedBitmap);
-
- if (preview != null) {
- synchronized(mLoadedPreviews) {
- mLoadedPreviews.put(name, new WeakReference<Bitmap>(preview));
- }
- return preview;
- } else {
- // it's not in the db... we need to generate it
- final Bitmap generatedPreview = generatePreview(o, unusedBitmap);
- preview = generatedPreview;
- if (preview != unusedBitmap) {
- throw new RuntimeException("generatePreview is not recycling the bitmap " + o);
- }
-
- synchronized(mLoadedPreviews) {
- mLoadedPreviews.put(name, new WeakReference<Bitmap>(preview));
- }
-
- // write to db on a thread pool... this can be done lazily and improves the performance
- // of the first time widget previews are loaded
- new AsyncTask<Void, Void, Void>() {
- public Void doInBackground(Void ... args) {
- writeToDb(o, generatedPreview);
- return null;
- }
- }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void) null);
-
- return preview;
- }
- }
-
- public void recycleBitmap(Object o, Bitmap bitmapToRecycle) {
- String name = getObjectName(o);
- synchronized (mLoadedPreviews) {
- if (mLoadedPreviews.containsKey(name)) {
- Bitmap b = mLoadedPreviews.get(name).get();
- if (b == bitmapToRecycle) {
- mLoadedPreviews.remove(name);
- if (bitmapToRecycle.isMutable()) {
- synchronized (mUnusedBitmaps) {
- mUnusedBitmaps.add(new SoftReference<Bitmap>(b));
- }
- }
- } else {
- throw new RuntimeException("Bitmap passed in doesn't match up");
- }
- }
- }
+ /**
+ * Generates the widget preview on {@link AsyncTask#THREAD_POOL_EXECUTOR}. Must be
+ * called on UI thread
+ *
+ * @param o either {@link LauncherAppWidgetProviderInfo} or {@link ResolveInfo}
+ * @return a request id which can be used to cancel the request.
+ */
+ public PreviewLoadRequest getPreview(final Object o, int previewWidth,
+ int previewHeight, WidgetCell caller) {
+ String size = previewWidth + "x" + previewHeight;
+ WidgetCacheKey key = getObjectKey(o, size);
+
+ PreviewLoadTask task = new PreviewLoadTask(key, o, previewWidth, previewHeight, caller);
+ task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+ return new PreviewLoadRequest(task);
}
- static class CacheDb extends SQLiteOpenHelper {
- final static int DB_VERSION = 2;
- final static String TABLE_NAME = "shortcut_and_widget_previews";
- final static String COLUMN_NAME = "name";
- final static String COLUMN_SIZE = "size";
- final static String COLUMN_PREVIEW_BITMAP = "preview_bitmap";
- Context mContext;
+ /**
+ * 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 final int DB_VERSION = 3;
+
+ private static final String TABLE_NAME = "shortcut_and_widget_previews";
+ private static final String COLUMN_COMPONENT = "componentName";
+ private static final String COLUMN_USER = "profileId";
+ private static final String COLUMN_SIZE = "size";
+ private static final String COLUMN_PACKAGE = "packageName";
+ private static final String COLUMN_LAST_UPDATED = "lastUpdated";
+ private static final String COLUMN_VERSION = "version";
+ private static final String COLUMN_PREVIEW_BITMAP = "preview_bitmap";
public CacheDb(Context context) {
- super(context, new File(context.getCacheDir(),
- LauncherFiles.WIDGET_PREVIEWS_DB).getPath(), null, DB_VERSION);
- // Store the context for later use
- mContext = context;
+ super(context, LauncherFiles.WIDGET_PREVIEWS_DB, null, DB_VERSION);
}
@Override
public void onCreate(SQLiteDatabase database) {
database.execSQL("CREATE TABLE IF NOT EXISTS " + TABLE_NAME + " (" +
- COLUMN_NAME + " TEXT NOT NULL, " +
+ COLUMN_COMPONENT + " TEXT NOT NULL, " +
+ COLUMN_USER + " INTEGER NOT NULL, " +
COLUMN_SIZE + " TEXT NOT NULL, " +
- COLUMN_PREVIEW_BITMAP + " BLOB NOT NULL, " +
- "PRIMARY KEY (" + COLUMN_NAME + ", " + COLUMN_SIZE + ") " +
+ COLUMN_PACKAGE + " TEXT NOT NULL, " +
+ COLUMN_LAST_UPDATED + " INTEGER NOT NULL DEFAULT 0, " +
+ COLUMN_VERSION + " INTEGER NOT NULL DEFAULT 0, " +
+ COLUMN_PREVIEW_BITMAP + " BLOB, " +
+ "PRIMARY KEY (" + COLUMN_COMPONENT + ", " + COLUMN_USER + ", " + COLUMN_SIZE + ") " +
");");
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
if (oldVersion != newVersion) {
- // Delete all the records; they'll be repopulated as this is a cache
- db.execSQL("DELETE FROM " + TABLE_NAME);
+ clearDB(db);
}
}
- }
-
- private static final String WIDGET_PREFIX = "Widget:";
- private static final String SHORTCUT_PREFIX = "Shortcut:";
- private static String getObjectName(Object o) {
- // should cache the string builder
- StringBuilder sb = new StringBuilder();
- String output;
- if (o instanceof AppWidgetProviderInfo) {
- sb.append(WIDGET_PREFIX);
- sb.append(((AppWidgetProviderInfo) o).toString());
- output = sb.toString();
- sb.setLength(0);
- } else {
- sb.append(SHORTCUT_PREFIX);
+ @Override
+ public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {
+ if (oldVersion != newVersion) {
+ clearDB(db);
+ }
+ }
- ResolveInfo info = (ResolveInfo) o;
- sb.append(new ComponentName(info.activityInfo.packageName,
- info.activityInfo.name).flattenToString());
- output = sb.toString();
- sb.setLength(0);
+ private void clearDB(SQLiteDatabase db) {
+ db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME);
+ onCreate(db);
}
- return output;
}
- private String getObjectPackage(Object o) {
- if (o instanceof AppWidgetProviderInfo) {
- return ((AppWidgetProviderInfo) o).provider.getPackageName();
+ private WidgetCacheKey getObjectKey(Object o, String size) {
+ // should cache the string builder
+ if (o instanceof LauncherAppWidgetProviderInfo) {
+ LauncherAppWidgetProviderInfo info = (LauncherAppWidgetProviderInfo) o;
+ return new WidgetCacheKey(info.provider, mManager.getUser(info), size);
} else {
ResolveInfo info = (ResolveInfo) o;
- return info.activityInfo.packageName;
+ return new WidgetCacheKey(
+ new ComponentName(info.activityInfo.packageName, info.activityInfo.name),
+ UserHandleCompat.myUserHandle(), size);
}
}
- private void writeToDb(Object o, Bitmap preview) {
- String name = getObjectName(o);
- SQLiteDatabase db = mDb.getWritableDatabase();
+ @Thunk void writeToDb(WidgetCacheKey key, long[] versions, Bitmap preview) {
ContentValues values = new ContentValues();
+ values.put(CacheDb.COLUMN_COMPONENT, key.componentName.flattenToShortString());
+ values.put(CacheDb.COLUMN_USER, mUserManager.getSerialNumberForUser(key.user));
+ values.put(CacheDb.COLUMN_SIZE, key.size);
+ values.put(CacheDb.COLUMN_PACKAGE, key.componentName.getPackageName());
+ values.put(CacheDb.COLUMN_VERSION, versions[0]);
+ values.put(CacheDb.COLUMN_LAST_UPDATED, versions[1]);
+ values.put(CacheDb.COLUMN_PREVIEW_BITMAP, Utilities.flattenBitmap(preview));
- values.put(CacheDb.COLUMN_NAME, name);
- ByteArrayOutputStream stream = new ByteArrayOutputStream();
- preview.compress(Bitmap.CompressFormat.PNG, 100, stream);
- values.put(CacheDb.COLUMN_PREVIEW_BITMAP, stream.toByteArray());
- values.put(CacheDb.COLUMN_SIZE, mSize);
try {
- db.insert(CacheDb.TABLE_NAME, null, values);
- } catch (SQLiteDiskIOException e) {
- recreateDb();
- } catch (SQLiteCantOpenDatabaseException e) {
- dumpOpenFiles();
- throw e;
+ mDb.getWritableDatabase().insertWithOnConflict(CacheDb.TABLE_NAME, null, values,
+ SQLiteDatabase.CONFLICT_REPLACE);
+ } catch (SQLException e) {
+ Log.e(TAG, "Error saving image to DB", e);
}
}
- private void clearDb() {
- SQLiteDatabase db = mDb.getWritableDatabase();
- // Delete everything
+ public void removePackage(String packageName, UserHandleCompat user) {
+ removePackage(packageName, user, mUserManager.getSerialNumberForUser(user));
+ }
+
+ private void removePackage(String packageName, UserHandleCompat user, long userSerial) {
+ synchronized(mPackageVersions) {
+ mPackageVersions.remove(packageName);
+ }
+
try {
- db.delete(CacheDb.TABLE_NAME, null, null);
- } catch (SQLiteDiskIOException e) {
- } catch (SQLiteCantOpenDatabaseException e) {
- dumpOpenFiles();
- throw e;
+ 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);
}
}
- public static void removePackageFromDb(final CacheDb cacheDb, final String packageName) {
- synchronized(sInvalidPackages) {
- sInvalidPackages.add(packageName);
+ /**
+ * Updates the persistent DB:
+ * 1. Any preview generated for an old package version is removed
+ * 2. Any preview for an absent package is removed
+ * This ensures that we remove entries for packages which changed while the launcher was dead.
+ */
+ public void removeObsoletePreviews(ArrayList<Object> list) {
+ Utilities.assertWorkerThread();
+
+ LongSparseArray<UserHandleCompat> userIdCache = new LongSparseArray<>();
+ LongSparseArray<HashSet<String>> validPackages = new LongSparseArray<>();
+
+ for (Object obj : list) {
+ final UserHandleCompat user;
+ final String pkg;
+ if (obj instanceof ResolveInfo) {
+ user = UserHandleCompat.myUserHandle();
+ pkg = ((ResolveInfo) obj).activityInfo.packageName;
+ } else {
+ LauncherAppWidgetProviderInfo info = (LauncherAppWidgetProviderInfo) obj;
+ user = mManager.getUser(info);
+ pkg = info.provider.getPackageName();
+ }
+
+ int userIdIndex = userIdCache.indexOfValue(user);
+ final long userId;
+ if (userIdIndex < 0) {
+ userId = mUserManager.getSerialNumberForUser(user);
+ userIdCache.put(userId, user);
+ } else {
+ userId = userIdCache.keyAt(userIdIndex);
+ }
+
+ HashSet<String> packages = validPackages.get(userId);
+ if (packages == null) {
+ packages = new HashSet<>();
+ validPackages.put(userId, packages);
+ }
+ packages.add(pkg);
}
- new AsyncTask<Void, Void, Void>() {
- public Void doInBackground(Void ... args) {
- SQLiteDatabase db = cacheDb.getWritableDatabase();
- try {
- db.delete(CacheDb.TABLE_NAME,
- CacheDb.COLUMN_NAME + " LIKE ? OR " +
- CacheDb.COLUMN_NAME + " LIKE ?", // SELECT query
- new String[] {
- WIDGET_PREFIX + packageName + "/%",
- SHORTCUT_PREFIX + packageName + "/%"
- } // args to SELECT query
- );
- } catch (SQLiteDiskIOException e) {
- } catch (SQLiteCantOpenDatabaseException e) {
- dumpOpenFiles();
- throw e;
+
+ 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);
+ while (c.moveToNext()) {
+ long userId = c.getLong(0);
+ String pkg = c.getString(1);
+ long lastUpdated = c.getLong(2);
+ long version = c.getLong(3);
+
+ HashSet<String> packages = validPackages.get(userId);
+ if (packages != null && packages.contains(pkg)) {
+ long[] versions = getPackageVersion(pkg);
+ if (versions[0] == version && versions[1] == lastUpdated) {
+ // Every thing checks out
+ continue;
+ }
}
- synchronized(sInvalidPackages) {
- sInvalidPackages.remove(packageName);
+
+ // We need to delete this package.
+ packages = packagesToDelete.get(userId);
+ if (packages == null) {
+ packages = new HashSet<>();
+ packagesToDelete.put(userId, packages);
}
- return null;
+ packages.add(pkg);
}
- }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void) null);
- }
- private static void removeItemFromDb(final CacheDb cacheDb, final String objectName) {
- new AsyncTask<Void, Void, Void>() {
- public Void doInBackground(Void ... args) {
- SQLiteDatabase db = cacheDb.getWritableDatabase();
- try {
- db.delete(CacheDb.TABLE_NAME,
- CacheDb.COLUMN_NAME + " = ? ", // SELECT query
- new String[] { objectName }); // args to SELECT query
- } catch (SQLiteDiskIOException e) {
- } catch (SQLiteCantOpenDatabaseException e) {
- dumpOpenFiles();
- throw e;
+ for (int i = 0; i < packagesToDelete.size(); i++) {
+ long userId = packagesToDelete.keyAt(i);
+ UserHandleCompat user = mUserManager.getUserForSerialNumber(userId);
+ for (String pkg : packagesToDelete.valueAt(i)) {
+ removePackage(pkg, user, userId);
}
- return null;
}
- }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void) null);
+ } catch (SQLException e) {
+ Log.e(TAG, "Error updatating widget previews", e);
+ } finally {
+ if (c != null) {
+ c.close();
+ }
+ }
}
- private Bitmap readFromDb(String name, Bitmap b) {
- if (mCachedSelectQuery == null) {
- mCachedSelectQuery = CacheDb.COLUMN_NAME + " = ? AND " +
- CacheDb.COLUMN_SIZE + " = ?";
- }
- SQLiteDatabase db = mDb.getReadableDatabase();
- Cursor result;
+ /**
+ * Reads the preview bitmap from the DB or null if the preview is not in the DB.
+ */
+ @Thunk Bitmap readFromDb(WidgetCacheKey key, Bitmap recycle, PreviewLoadTask loadTask) {
+ Cursor cursor = null;
try {
- result = db.query(CacheDb.TABLE_NAME,
- new String[] { CacheDb.COLUMN_PREVIEW_BITMAP }, // cols to return
- mCachedSelectQuery, // select query
- new String[] { name, mSize }, // args to select query
- null,
- null,
- null,
- null);
- } catch (SQLiteDiskIOException e) {
- recreateDb();
- return null;
- } catch (SQLiteCantOpenDatabaseException e) {
- dumpOpenFiles();
- throw e;
- }
- if (result.getCount() > 0) {
- result.moveToFirst();
- byte[] blob = result.getBlob(0);
- result.close();
- final BitmapFactory.Options opts = mCachedBitmapFactoryOptions.get();
- opts.inBitmap = b;
- opts.inSampleSize = 1;
- try {
- return BitmapFactory.decodeByteArray(blob, 0, blob.length, opts);
- } catch (IllegalArgumentException e) {
- removeItemFromDb(mDb, name);
+ 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[] {
+ 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;
}
- } else {
- result.close();
- return null;
+ if (cursor.moveToNext()) {
+ byte[] blob = cursor.getBlob(0);
+ BitmapFactory.Options opts = new BitmapFactory.Options();
+ opts.inBitmap = recycle;
+ try {
+ if (!loadTask.isCancelled()) {
+ return BitmapFactory.decodeByteArray(blob, 0, blob.length, opts);
+ }
+ } catch (Exception e) {
+ return null;
+ }
+ }
+ } catch (SQLException e) {
+ Log.w(TAG, "Error loading preview from DB", e);
+ } finally {
+ if (cursor != null) {
+ cursor.close();
+ }
}
+ return null;
}
- private Bitmap generatePreview(Object info, Bitmap preview) {
- if (preview != null &&
- (preview.getWidth() != mPreviewBitmapWidth ||
- preview.getHeight() != mPreviewBitmapHeight)) {
- throw new RuntimeException("Improperly sized bitmap passed as argument");
- }
- if (info instanceof AppWidgetProviderInfo) {
- return generateWidgetPreview((AppWidgetProviderInfo) info, preview);
+ @Thunk Bitmap generatePreview(Launcher launcher, Object info, Bitmap recycle,
+ int previewWidth, int previewHeight) {
+ if (info instanceof LauncherAppWidgetProviderInfo) {
+ return generateWidgetPreview(launcher, (LauncherAppWidgetProviderInfo) info,
+ previewWidth, recycle, null);
} else {
- return generateShortcutPreview(
- (ResolveInfo) info, mPreviewBitmapWidth, mPreviewBitmapHeight, preview);
+ return generateShortcutPreview(launcher,
+ (ResolveInfo) info, previewWidth, previewHeight, recycle);
}
}
- public Bitmap generateWidgetPreview(AppWidgetProviderInfo info, Bitmap preview) {
- int[] cellSpans = Launcher.getSpanForWidget(mContext, info);
- int maxWidth = maxWidthForWidgetPreview(cellSpans[0]);
- int maxHeight = maxHeightForWidgetPreview(cellSpans[1]);
- return generateWidgetPreview(info, cellSpans[0], cellSpans[1],
- maxWidth, maxHeight, preview, null);
- }
-
- public int maxWidthForWidgetPreview(int spanX) {
- return Math.min(mPreviewBitmapWidth,
- mWidgetSpacingLayout.estimateCellWidth(spanX));
- }
-
- public int maxHeightForWidgetPreview(int spanY) {
- return Math.min(mPreviewBitmapHeight,
- mWidgetSpacingLayout.estimateCellHeight(spanY));
- }
-
- public Bitmap generateWidgetPreview(AppWidgetProviderInfo info, int cellHSpan, int cellVSpan,
- int maxPreviewWidth, int maxPreviewHeight, Bitmap preview, int[] preScaledWidthOut) {
+ public Bitmap generateWidgetPreview(Launcher launcher, LauncherAppWidgetProviderInfo info,
+ int maxPreviewWidth, Bitmap preview, int[] preScaledWidthOut) {
// Load the preview image if possible
if (maxPreviewWidth < 0) maxPreviewWidth = Integer.MAX_VALUE;
- if (maxPreviewHeight < 0) maxPreviewHeight = Integer.MAX_VALUE;
Drawable drawable = null;
if (info.previewImage != 0) {
@@ -533,61 +360,23 @@ public class WidgetPreviewLoader {
}
}
+ final boolean widgetPreviewExists = (drawable != null);
+ final int spanX = info.getSpanX(launcher) < 1 ? 1 : info.getSpanX(launcher);
+ final int spanY = info.getSpanY(launcher) < 1 ? 1 : info.getSpanY(launcher);
+
int previewWidth;
int previewHeight;
- Bitmap defaultPreview = null;
- boolean widgetPreviewExists = (drawable != null);
+ Bitmap tileBitmap = null;
+
if (widgetPreviewExists) {
previewWidth = drawable.getIntrinsicWidth();
previewHeight = drawable.getIntrinsicHeight();
} else {
// Generate a preview image if we couldn't load one
- if (cellHSpan < 1) cellHSpan = 1;
- if (cellVSpan < 1) cellVSpan = 1;
-
- // This Drawable is not directly drawn, so there's no need to mutate it.
- BitmapDrawable previewDrawable = (BitmapDrawable) mContext.getResources()
- .getDrawable(R.drawable.widget_tile);
- final int previewDrawableWidth = previewDrawable
- .getIntrinsicWidth();
- final int previewDrawableHeight = previewDrawable
- .getIntrinsicHeight();
- previewWidth = previewDrawableWidth * cellHSpan;
- previewHeight = previewDrawableHeight * cellVSpan;
-
- defaultPreview = Bitmap.createBitmap(previewWidth, previewHeight, Config.ARGB_8888);
- final Canvas c = mCachedAppWidgetPreviewCanvas.get();
- c.setBitmap(defaultPreview);
- Paint p = mDefaultAppWidgetPreviewPaint.get();
- if (p == null) {
- p = new Paint();
- p.setShader(new BitmapShader(previewDrawable.getBitmap(),
- Shader.TileMode.REPEAT, Shader.TileMode.REPEAT));
- mDefaultAppWidgetPreviewPaint.set(p);
- }
- final Rect dest = mCachedAppWidgetPreviewDestRect.get();
- dest.set(0, 0, previewWidth, previewHeight);
- c.drawRect(dest, p);
- c.setBitmap(null);
-
- // Draw the icon in the top left corner
- int minOffset = (int) (mAppIconSize * WIDGET_PREVIEW_ICON_PADDING_PERCENTAGE);
- int smallestSide = Math.min(previewWidth, previewHeight);
- float iconScale = Math.min((float) smallestSide
- / (mAppIconSize + 2 * minOffset), 1f);
-
- try {
- Drawable icon = mManager.loadIcon(info, mIconCache);
- if (icon != null) {
- int hoffset = (int) ((previewDrawableWidth - mAppIconSize * iconScale) / 2);
- int yoffset = (int) ((previewDrawableHeight - mAppIconSize * iconScale) / 2);
- icon = mutateOnMainThread(icon);
- renderDrawableToBitmap(icon, defaultPreview, hoffset,
- yoffset, (int) (mAppIconSize * iconScale),
- (int) (mAppIconSize * iconScale));
- }
- } catch (Resources.NotFoundException e) {
- }
+ tileBitmap = ((BitmapDrawable) mContext.getResources().getDrawable(
+ R.drawable.widget_tile)).getBitmap();
+ previewWidth = tileBitmap.getWidth() * spanX;
+ previewHeight = tileBitmap.getHeight() * spanY;
}
// Scale to fit width only - let the widget preview be clipped in the
@@ -605,102 +394,110 @@ public class WidgetPreviewLoader {
}
// If a bitmap is passed in, we use it; otherwise, we create a bitmap of the right size
+ final Canvas c = new Canvas();
if (preview == null) {
preview = Bitmap.createBitmap(previewWidth, previewHeight, Config.ARGB_8888);
+ c.setBitmap(preview);
+ } else {
+ // Reusing bitmap. Clear it.
+ c.setBitmap(preview);
+ c.drawColor(0, PorterDuff.Mode.CLEAR);
}
// Draw the scaled preview into the final bitmap
- int x = (preview.getWidth() - previewWidth) / 2;
+ int x = (preview.getWidth() - previewWidth - mProfileBadgeMargin) / 2;
if (widgetPreviewExists) {
- renderDrawableToBitmap(drawable, preview, x, 0, previewWidth,
- previewHeight);
+ drawable.setBounds(x, 0, x + previewWidth, previewHeight);
+ drawable.draw(c);
} else {
- final Canvas c = mCachedAppWidgetPreviewCanvas.get();
- final Rect src = mCachedAppWidgetPreviewSrcRect.get();
- final Rect dest = mCachedAppWidgetPreviewDestRect.get();
- c.setBitmap(preview);
- src.set(0, 0, defaultPreview.getWidth(), defaultPreview.getHeight());
- dest.set(x, 0, x + previewWidth, previewHeight);
-
- Paint p = mCachedAppWidgetPreviewPaint.get();
- if (p == null) {
- p = new Paint();
- p.setFilterBitmap(true);
- mCachedAppWidgetPreviewPaint.set(p);
+ final Paint p = new Paint();
+ p.setFilterBitmap(true);
+ int appIconSize = launcher.getDeviceProfile().iconSizePx;
+
+ // draw the spanX x spanY tiles
+ final Rect src = new Rect(0, 0, tileBitmap.getWidth(), tileBitmap.getHeight());
+
+ float tileW = scale * tileBitmap.getWidth();
+ float tileH = scale * tileBitmap.getHeight();
+ final RectF dst = new RectF(0, 0, tileW, tileH);
+
+ float tx = x;
+ for (int i = 0; i < spanX; i++, tx += tileW) {
+ float ty = 0;
+ for (int j = 0; j < spanY; j++, ty += tileH) {
+ dst.offsetTo(tx, ty);
+ c.drawBitmap(tileBitmap, src, dst, p);
+ }
}
- c.drawBitmap(defaultPreview, src, dest, p);
+
+ // Draw the icon in the top left corner
+ // TODO: use top right for RTL
+ int minOffset = (int) (appIconSize * WIDGET_PREVIEW_ICON_PADDING_PERCENTAGE);
+ int smallestSide = Math.min(previewWidth, previewHeight);
+ float iconScale = Math.min((float) smallestSide / (appIconSize + 2 * minOffset), scale);
+
+ try {
+ Drawable icon = mutateOnMainThread(mManager.loadIcon(info, mIconCache));
+ if (icon != null) {
+ int hoffset = (int) ((tileW - appIconSize * iconScale) / 2) + x;
+ int yoffset = (int) ((tileH - appIconSize * iconScale) / 2);
+ icon.setBounds(hoffset, yoffset,
+ hoffset + (int) (appIconSize * iconScale),
+ yoffset + (int) (appIconSize * iconScale));
+ icon.draw(c);
+ }
+ } catch (Resources.NotFoundException e) { }
c.setBitmap(null);
}
- return mManager.getBadgeBitmap(info, preview);
+ int imageHeight = Math.min(preview.getHeight(), previewHeight + mProfileBadgeMargin);
+ return mManager.getBadgeBitmap(info, preview, imageHeight);
}
private Bitmap generateShortcutPreview(
- ResolveInfo info, int maxWidth, int maxHeight, Bitmap preview) {
- Bitmap tempBitmap = mCachedShortcutPreviewBitmap.get();
- final Canvas c = mCachedShortcutPreviewCanvas.get();
- if (tempBitmap == null ||
- tempBitmap.getWidth() != maxWidth ||
- tempBitmap.getHeight() != maxHeight) {
- tempBitmap = Bitmap.createBitmap(maxWidth, maxHeight, Config.ARGB_8888);
- mCachedShortcutPreviewBitmap.set(tempBitmap);
+ Launcher launcher, ResolveInfo info, int maxWidth, int maxHeight, Bitmap preview) {
+ final Canvas c = new Canvas();
+ if (preview == null) {
+ preview = Bitmap.createBitmap(maxWidth, maxHeight, Config.ARGB_8888);
+ c.setBitmap(preview);
+ } else if (preview.getWidth() != maxWidth || preview.getHeight() != maxHeight) {
+ throw new RuntimeException("Improperly sized bitmap passed as argument");
} else {
- c.setBitmap(tempBitmap);
+ // Reusing bitmap. Clear it.
+ c.setBitmap(preview);
c.drawColor(0, PorterDuff.Mode.CLEAR);
- c.setBitmap(null);
}
- // Render the icon
- Drawable icon = mutateOnMainThread(mIconCache.getFullResIcon(info.activityInfo));
- int paddingTop = mContext.
- getResources().getDimensionPixelOffset(R.dimen.shortcut_preview_padding_top);
- int paddingLeft = mContext.
- getResources().getDimensionPixelOffset(R.dimen.shortcut_preview_padding_left);
- int paddingRight = mContext.
- getResources().getDimensionPixelOffset(R.dimen.shortcut_preview_padding_right);
+ Drawable icon = mutateOnMainThread(mIconCache.getFullResIcon(info.activityInfo));
+ icon.setFilterBitmap(true);
+ // Draw a desaturated/scaled version of the icon in the background as a watermark
+ ColorMatrix colorMatrix = new ColorMatrix();
+ colorMatrix.setSaturation(0);
+ icon.setColorFilter(new ColorMatrixColorFilter(colorMatrix));
+ icon.setAlpha((int) (255 * 0.06f));
+
+ Resources res = mContext.getResources();
+ int paddingTop = res.getDimensionPixelOffset(R.dimen.shortcut_preview_padding_top);
+ int paddingLeft = res.getDimensionPixelOffset(R.dimen.shortcut_preview_padding_left);
+ int paddingRight = res.getDimensionPixelOffset(R.dimen.shortcut_preview_padding_right);
int scaledIconWidth = (maxWidth - paddingLeft - paddingRight);
+ icon.setBounds(paddingLeft, paddingTop,
+ paddingLeft + scaledIconWidth, paddingTop + scaledIconWidth);
+ icon.draw(c);
- renderDrawableToBitmap(
- icon, tempBitmap, paddingLeft, paddingTop, scaledIconWidth, scaledIconWidth);
+ // Draw the final icon at top left corner.
+ // TODO: use top right for RTL
+ int appIconSize = launcher.getDeviceProfile().iconSizePx;
- if (preview != null &&
- (preview.getWidth() != maxWidth || preview.getHeight() != maxHeight)) {
- throw new RuntimeException("Improperly sized bitmap passed as argument");
- } else if (preview == null) {
- preview = Bitmap.createBitmap(maxWidth, maxHeight, Config.ARGB_8888);
- }
+ icon.setAlpha(255);
+ icon.setColorFilter(null);
+ icon.setBounds(0, 0, appIconSize, appIconSize);
+ icon.draw(c);
- c.setBitmap(preview);
- // Draw a desaturated/scaled version of the icon in the background as a watermark
- Paint p = mCachedShortcutPreviewPaint.get();
- if (p == null) {
- p = new Paint();
- ColorMatrix colorMatrix = new ColorMatrix();
- colorMatrix.setSaturation(0);
- p.setColorFilter(new ColorMatrixColorFilter(colorMatrix));
- p.setAlpha((int) (255 * 0.06f));
- mCachedShortcutPreviewPaint.set(p);
- }
- c.drawBitmap(tempBitmap, 0, 0, p);
c.setBitmap(null);
-
- renderDrawableToBitmap(icon, preview, 0, 0, mAppIconSize, mAppIconSize);
-
return preview;
}
- private static void renderDrawableToBitmap(
- Drawable d, Bitmap bitmap, int x, int y, int w, int h) {
- if (bitmap != null) {
- Canvas c = new Canvas(bitmap);
- Rect oldBounds = d.copyBounds();
- d.setBounds(x, y, x + w, y + h);
- d.draw(c);
- d.setBounds(oldBounds); // Restore the bounds
- c.setBitmap(null);
- }
- }
-
private Drawable mutateOnMainThread(final Drawable drawable) {
try {
return mMainThreadExecutor.submit(new Callable<Drawable>() {
@@ -717,82 +514,195 @@ public class WidgetPreviewLoader {
}
}
- private static final int MAX_OPEN_FILES = 1024;
- private static final int SAMPLE_RATE = 23;
/**
- * Dumps all files that are open in this process without allocating a file descriptor.
+ * @return an array of containing versionCode and lastUpdatedTime for the package.
*/
- private static void dumpOpenFiles() {
- try {
- Log.i(TAG, "DUMP OF OPEN FILES (sample rate: 1 every " + SAMPLE_RATE + "):");
- final String TYPE_APK = "apk";
- final String TYPE_JAR = "jar";
- final String TYPE_PIPE = "pipe";
- final String TYPE_SOCKET = "socket";
- final String TYPE_DB = "db";
- final String TYPE_ANON_INODE = "anon_inode";
- final String TYPE_DEV = "dev";
- final String TYPE_NON_FS = "non-fs";
- final String TYPE_OTHER = "other";
- List<String> types = Arrays.asList(TYPE_APK, TYPE_JAR, TYPE_PIPE, TYPE_SOCKET, TYPE_DB,
- TYPE_ANON_INODE, TYPE_DEV, TYPE_NON_FS, TYPE_OTHER);
- int[] count = new int[types.size()];
- int[] duplicates = new int[types.size()];
- HashSet<String> files = new HashSet<String>();
- int total = 0;
- for (int i = 0; i < MAX_OPEN_FILES; i++) {
- // This is a gigantic hack but unfortunately the only way to resolve an fd
- // to a file name. Note that we have to loop over all possible fds because
- // reading the directory would require allocating a new fd. The kernel is
- // currently implemented such that no fd is larger then the current rlimit,
- // which is why it's safe to loop over them in such a way.
- String fd = "/proc/self/fd/" + i;
+ @Thunk long[] getPackageVersion(String packageName) {
+ synchronized (mPackageVersions) {
+ long[] versions = mPackageVersions.get(packageName);
+ if (versions == null) {
+ versions = new long[2];
try {
- // getCanonicalPath() uses readlink behind the scene which doesn't require
- // a file descriptor.
- String resolved = new File(fd).getCanonicalPath();
- int type = types.indexOf(TYPE_OTHER);
- if (resolved.startsWith("/dev/")) {
- type = types.indexOf(TYPE_DEV);
- } else if (resolved.endsWith(".apk")) {
- type = types.indexOf(TYPE_APK);
- } else if (resolved.endsWith(".jar")) {
- type = types.indexOf(TYPE_JAR);
- } else if (resolved.contains("/fd/pipe:")) {
- type = types.indexOf(TYPE_PIPE);
- } else if (resolved.contains("/fd/socket:")) {
- type = types.indexOf(TYPE_SOCKET);
- } else if (resolved.contains("/fd/anon_inode:")) {
- type = types.indexOf(TYPE_ANON_INODE);
- } else if (resolved.endsWith(".db") || resolved.contains("/databases/")) {
- type = types.indexOf(TYPE_DB);
- } else if (resolved.startsWith("/proc/") && resolved.contains("/fd/")) {
- // Those are the files that don't point anywhere on the file system.
- // getCanonicalPath() wrongly interprets these as relative symlinks and
- // resolves them within /proc/<pid>/fd/.
- type = types.indexOf(TYPE_NON_FS);
- }
- count[type]++;
- total++;
- if (files.contains(resolved)) {
- duplicates[type]++;
+ PackageInfo info = mContext.getPackageManager().getPackageInfo(packageName, 0);
+ versions[0] = info.versionCode;
+ versions[1] = info.lastUpdateTime;
+ } catch (NameNotFoundException e) {
+ Log.e(TAG, "PackageInfo not found", e);
+ }
+ mPackageVersions.put(packageName, versions);
+ }
+ return versions;
+ }
+ }
+
+ /**
+ * A request Id which can be used by the client to cancel any request.
+ */
+ public class PreviewLoadRequest {
+
+ @Thunk final PreviewLoadTask mTask;
+
+ public PreviewLoadRequest(PreviewLoadTask task) {
+ mTask = task;
+ }
+
+ public void cleanup() {
+ if (mTask != null) {
+ mTask.cancel(true);
+ }
+
+ // This only handles the case where the PreviewLoadTask is cancelled after the task has
+ // successfully completed (including having written to disk when necessary). In the
+ // other cases where it is cancelled while the task is running, it will be cleaned up
+ // in the tasks's onCancelled() call, and if cancelled while the task is writing to
+ // disk, it will be cancelled in the task's onPostExecute() call.
+ if (mTask.mBitmapToRecycle != null) {
+ mWorkerHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ synchronized (mUnusedBitmaps) {
+ mUnusedBitmaps.add(mTask.mBitmapToRecycle);
+ }
+ mTask.mBitmapToRecycle = null;
}
- files.add(resolved);
- if (total % SAMPLE_RATE == 0) {
- Log.i(TAG, " fd " + i + ": " + resolved
- + " (" + types.get(type) + ")");
+ });
+ }
+ }
+ }
+
+ public class PreviewLoadTask extends AsyncTask<Void, Void, Bitmap> {
+ @Thunk final WidgetCacheKey mKey;
+ private final Object mInfo;
+ private final int mPreviewHeight;
+ private final int mPreviewWidth;
+ private final WidgetCell mCaller;
+ @Thunk long[] mVersions;
+ @Thunk Bitmap mBitmapToRecycle;
+
+ PreviewLoadTask(WidgetCacheKey key, Object info, int previewWidth,
+ int previewHeight, WidgetCell caller) {
+ mKey = key;
+ mInfo = info;
+ mPreviewHeight = previewHeight;
+ mPreviewWidth = previewWidth;
+ mCaller = caller;
+ if (DEBUG) {
+ Log.d(TAG, String.format("%s, %s, %d, %d",
+ mKey, mInfo, mPreviewHeight, mPreviewWidth));
+ }
+ }
+
+ @Override
+ protected Bitmap doInBackground(Void... params) {
+ Bitmap unusedBitmap = null;
+
+ // If already cancelled before this gets to run in the background, then return early
+ if (isCancelled()) {
+ return null;
+ }
+ synchronized (mUnusedBitmaps) {
+ // Check if we can re-use a bitmap
+ for (Bitmap candidate : mUnusedBitmaps) {
+ if (candidate != null && candidate.isMutable() &&
+ candidate.getWidth() == mPreviewWidth &&
+ candidate.getHeight() == mPreviewHeight) {
+ unusedBitmap = candidate;
+ mUnusedBitmaps.remove(unusedBitmap);
+ break;
}
- } catch (IOException e) {
- // Ignoring exceptions for non-existing file descriptors.
}
}
- for (int i = 0; i < types.size(); i++) {
- Log.i(TAG, String.format("Open %10s files: %4d total, %4d duplicates",
- types.get(i), count[i], duplicates[i]));
+
+ // creating a bitmap is expensive. Do not do this inside synchronized block.
+ if (unusedBitmap == null) {
+ unusedBitmap = Bitmap.createBitmap(mPreviewWidth, mPreviewHeight, Config.ARGB_8888);
+ }
+ // If cancelled now, don't bother reading the preview from the DB
+ if (isCancelled()) {
+ return unusedBitmap;
+ }
+ Bitmap preview = readFromDb(mKey, unusedBitmap, this);
+ // Only consider generating the preview if we have not cancelled the task already
+ if (!isCancelled() && preview == null) {
+ // Fetch the version info before we generate the preview, so that, in-case the
+ // app was updated while we are generating the preview, we use the old version info,
+ // which would gets re-written next time.
+ mVersions = getPackageVersion(mKey.componentName.getPackageName());
+
+ Launcher launcher = (Launcher) mCaller.getContext();
+
+ // it's not in the db... we need to generate it
+ preview = generatePreview(launcher, mInfo, unusedBitmap, mPreviewWidth, mPreviewHeight);
+ }
+ return preview;
+ }
+
+ @Override
+ protected void onPostExecute(final Bitmap preview) {
+ mCaller.applyPreview(preview);
+
+ // Write the generated preview to the DB in the worker thread
+ if (mVersions != null) {
+ mWorkerHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ if (!isCancelled()) {
+ // If we are still using this preview, then write it to the DB and then
+ // let the normal clear mechanism recycle the bitmap
+ writeToDb(mKey, mVersions, preview);
+ mBitmapToRecycle = preview;
+ } else {
+ // If we've already cancelled, then skip writing the bitmap to the DB
+ // and manually add the bitmap back to the recycled set
+ synchronized (mUnusedBitmaps) {
+ mUnusedBitmaps.add(preview);
+ }
+ }
+ }
+ });
+ } else {
+ // If we don't need to write to disk, then ensure the preview gets recycled by
+ // the normal clear mechanism
+ mBitmapToRecycle = preview;
+ }
+ }
+
+ @Override
+ protected void onCancelled(final Bitmap preview) {
+ // If we've cancelled while the task is running, then can return the bitmap to the
+ // recycled set immediately. Otherwise, it will be recycled after the preview is written
+ // to disk.
+ if (preview != null) {
+ mWorkerHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ synchronized (mUnusedBitmaps) {
+ mUnusedBitmaps.add(preview);
+ }
+ }
+ });
}
- } catch (Throwable t) {
- // Catch everything. This is called from an exception handler that we shouldn't upset.
- Log.e(TAG, "Unable to log open files.", t);
+ }
+ }
+
+ private static final class WidgetCacheKey extends ComponentKey {
+
+ // TODO: remove dependency on size
+ @Thunk final String size;
+
+ public WidgetCacheKey(ComponentName componentName, UserHandleCompat user, String size) {
+ super(componentName, user);
+ this.size = size;
+ }
+
+ @Override
+ public int hashCode() {
+ return super.hashCode() ^ size.hashCode();
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ return super.equals(o) && ((WidgetCacheKey) o).size.equals(size);
}
}
}
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index 8bd799198..4a6b90afe 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -17,24 +17,18 @@
package com.android.launcher3;
import android.animation.Animator;
-import android.animation.Animator.AnimatorListener;
import android.animation.AnimatorListenerAdapter;
-import android.animation.AnimatorSet;
import android.animation.LayoutTransition;
import android.animation.ObjectAnimator;
import android.animation.PropertyValuesHolder;
-import android.animation.TimeInterpolator;
-import android.animation.ValueAnimator;
-import android.animation.ValueAnimator.AnimatorUpdateListener;
+import android.annotation.SuppressLint;
+import android.annotation.TargetApi;
import android.app.WallpaperManager;
import android.appwidget.AppWidgetHostView;
import android.appwidget.AppWidgetProviderInfo;
import android.content.ComponentName;
import android.content.Context;
-import android.content.Intent;
import android.content.SharedPreferences;
-import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
@@ -46,12 +40,12 @@ import android.graphics.PointF;
import android.graphics.Rect;
import android.graphics.Region.Op;
import android.graphics.drawable.Drawable;
-import android.net.Uri;
import android.os.AsyncTask;
+import android.os.Build;
+import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Parcelable;
-import android.support.v4.view.ViewCompat;
import android.util.AttributeSet;
import android.util.Log;
import android.util.SparseArray;
@@ -69,16 +63,20 @@ import com.android.launcher3.FolderIcon.FolderRingAnimator;
import com.android.launcher3.Launcher.CustomContentCallbacks;
import com.android.launcher3.Launcher.LauncherOverlay;
import com.android.launcher3.LauncherSettings.Favorites;
-import com.android.launcher3.compat.PackageInstallerCompat;
-import com.android.launcher3.compat.PackageInstallerCompat.PackageInstallInfo;
+import com.android.launcher3.UninstallDropTarget.UninstallSource;
+import com.android.launcher3.accessibility.LauncherAccessibilityDelegate;
+import com.android.launcher3.accessibility.LauncherAccessibilityDelegate.AccessibilityDragSource;
+import com.android.launcher3.accessibility.OverviewScreenAccessibilityDelegate;
import com.android.launcher3.compat.UserHandleCompat;
+import com.android.launcher3.util.LongArrayMap;
+import com.android.launcher3.util.Thunk;
+import com.android.launcher3.util.WallpaperUtils;
+import com.android.launcher3.widget.PendingAddShortcutInfo;
+import com.android.launcher3.widget.PendingAddWidgetInfo;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
/**
@@ -86,63 +84,45 @@ import java.util.concurrent.atomic.AtomicInteger;
* Each page contains a number of icons, folders or widgets the user can
* interact with. A workspace is meant to be used with a fixed width only.
*/
-public class Workspace extends SmoothPagedView
+public class Workspace extends PagedView
implements DropTarget, DragSource, DragScroller, View.OnTouchListener,
DragController.DragListener, LauncherTransitionable, ViewGroup.OnHierarchyChangeListener,
- Insettable {
+ Insettable, UninstallSource, AccessibilityDragSource, Stats.LaunchSourceProvider {
private static final String TAG = "Launcher.Workspace";
- // Y rotation to apply to the workspace screens
- private static final float WORKSPACE_OVERSCROLL_ROTATION = 24f;
-
- private static final int CHILDREN_OUTLINE_FADE_OUT_DELAY = 0;
- private static final int CHILDREN_OUTLINE_FADE_OUT_DURATION = 375;
- private static final int CHILDREN_OUTLINE_FADE_IN_DURATION = 100;
+ private static boolean ENFORCE_DRAG_EVENT_ORDER = false;
protected static final int SNAP_OFF_EMPTY_SCREEN_DURATION = 400;
protected static final int FADE_EMPTY_SCREEN_DURATION = 150;
- private static final int BACKGROUND_FADE_OUT_DURATION = 350;
private static final int ADJACENT_SCREEN_DROP_DURATION = 300;
- private static final int FLING_THRESHOLD_VELOCITY = 500;
-
- private static final float ALPHA_CUTOFF_THRESHOLD = 0.01f;
static final boolean MAP_NO_RECURSE = false;
static final boolean MAP_RECURSE = true;
- // These animators are used to fade the children's outlines
- private ObjectAnimator mChildrenOutlineFadeInAnimation;
- private ObjectAnimator mChildrenOutlineFadeOutAnimation;
- private float mChildrenOutlineAlpha = 0;
-
- // These properties refer to the background protection gradient used for AllApps and Customize
- private ValueAnimator mBackgroundFadeInAnimation;
- private ValueAnimator mBackgroundFadeOutAnimation;
-
private static final long CUSTOM_CONTENT_GESTURE_DELAY = 200;
private long mTouchDownTime = -1;
private long mCustomContentShowTime = -1;
private LayoutTransition mLayoutTransition;
- private final WallpaperManager mWallpaperManager;
- private IBinder mWindowToken;
+ @Thunk final WallpaperManager mWallpaperManager;
+ @Thunk IBinder mWindowToken;
private int mOriginalDefaultPage;
private int mDefaultPage;
private ShortcutAndWidgetContainer mDragSourceInternal;
- private static boolean sAccessibilityEnabled;
// The screen id used for the empty screen always present to the right.
final static long EXTRA_EMPTY_SCREEN_ID = -201;
private final static long CUSTOM_CONTENT_SCREEN_ID = -301;
- private HashMap<Long, CellLayout> mWorkspaceScreens = new HashMap<Long, CellLayout>();
- private ArrayList<Long> mScreenOrder = new ArrayList<Long>();
+ @Thunk LongArrayMap<CellLayout> mWorkspaceScreens = new LongArrayMap<>();
+ @Thunk ArrayList<Long> mScreenOrder = new ArrayList<Long>();
- private Runnable mRemoveEmptyScreenRunnable;
- private boolean mDeferRemoveExtraEmptyScreen = false;
+ @Thunk Runnable mRemoveEmptyScreenRunnable;
+ @Thunk boolean mDeferRemoveExtraEmptyScreen = false;
+ @Thunk boolean mAddNewPageOnDrag = true;
/**
* CellInfo for the cell that is currently being dragged
@@ -152,7 +132,7 @@ public class Workspace extends SmoothPagedView
/**
* Target drop area calculated during last acceptDrop call.
*/
- private int[] mTargetCell = new int[2];
+ @Thunk int[] mTargetCell = new int[2];
private int mDragOverX = -1;
private int mDragOverY = -1;
@@ -167,7 +147,7 @@ public class Workspace extends SmoothPagedView
/**
* The CellLayout that is currently being dragged over
*/
- private CellLayout mDragTargetLayout = null;
+ @Thunk CellLayout mDragTargetLayout = null;
/**
* The CellLayout that we will show as glowing
*/
@@ -178,16 +158,16 @@ public class Workspace extends SmoothPagedView
*/
private CellLayout mDropToLayout = null;
- private Launcher mLauncher;
- private IconCache mIconCache;
- private DragController mDragController;
+ @Thunk Launcher mLauncher;
+ @Thunk IconCache mIconCache;
+ @Thunk DragController mDragController;
// 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.
private int[] mTempCell = new int[2];
private int[] mTempPt = new int[2];
private int[] mTempEstimate = new int[2];
- private float[] mDragViewVisualCenter = new float[2];
+ @Thunk float[] mDragViewVisualCenter = new float[2];
private float[] mTempCellLayoutCenterCoordinates = new float[2];
private Matrix mTempInverseMatrix = new Matrix();
@@ -212,34 +192,31 @@ public class Workspace extends SmoothPagedView
private boolean mInScrollArea = false;
private HolographicOutlineHelper mOutlineHelper;
- private Bitmap mDragOutline = null;
+ @Thunk Bitmap mDragOutline = null;
private static final Rect sTempRect = new Rect();
private final int[] mTempXY = new int[2];
private int[] mTempVisiblePagesRange = new int[2];
- private boolean mOverscrollEffectSet;
public static final int DRAG_BITMAP_PADDING = 2;
private boolean mWorkspaceFadeInAdjacentScreens;
WallpaperOffsetInterpolator mWallpaperOffset;
- private boolean mWallpaperIsLiveWallpaper;
- private int mNumPagesForWallpaperParallax;
- private float mLastSetWallpaperOffsetSteps = 0;
+ @Thunk boolean mWallpaperIsLiveWallpaper;
+ @Thunk int mNumPagesForWallpaperParallax;
+ @Thunk float mLastSetWallpaperOffsetSteps = 0;
- private Runnable mDelayedResizeRunnable;
+ @Thunk Runnable mDelayedResizeRunnable;
private Runnable mDelayedSnapToPageRunnable;
private Point mDisplaySize = new Point();
- private int mCameraDistance;
// Variables relating to the creation of user folders by hovering shortcuts over shortcuts
private static final int FOLDER_CREATION_TIMEOUT = 0;
public static final int REORDER_TIMEOUT = 350;
private final Alarm mFolderCreationAlarm = new Alarm();
private final Alarm mReorderAlarm = new Alarm();
- private FolderRingAnimator mDragFolderRingAnimator = null;
+ @Thunk FolderRingAnimator mDragFolderRingAnimator = null;
private FolderIcon mDragOverFolderIcon = null;
private boolean mCreateUserFolderOnDrop = false;
private boolean mAddToExistingFolderOnDrop = false;
- private DropTarget.DragEnforcer mDragEnforcer;
private float mMaxDistanceForFolderCreation;
private final Canvas mCanvas = new Canvas();
@@ -264,30 +241,16 @@ public class Workspace extends SmoothPagedView
private static final int DRAG_MODE_ADD_TO_FOLDER = 2;
private static final int DRAG_MODE_REORDER = 3;
private int mDragMode = DRAG_MODE_NONE;
- private int mLastReorderX = -1;
- private int mLastReorderY = -1;
+ @Thunk int mLastReorderX = -1;
+ @Thunk int mLastReorderY = -1;
private SparseArray<Parcelable> mSavedStates;
private final ArrayList<Integer> mRestoredPages = new ArrayList<Integer>();
- // These variables are used for storing the initial and final values during workspace animations
- private int mSavedScrollX;
- private float mSavedRotationY;
- private float mSavedTranslationX;
-
private float mCurrentScale;
- private float mNewScale;
- private float[] mOldBackgroundAlphas;
- private float[] mOldAlphas;
- private float[] mNewBackgroundAlphas;
- private float[] mNewAlphas;
- private int mLastChildCount = -1;
private float mTransitionProgress;
- private Animator mStateAnimator = null;
-
- float mOverScrollEffect = 0f;
- private Runnable mDeferredAction;
+ @Thunk Runnable mDeferredAction;
private boolean mDeferDropAfterUninstall;
private boolean mUninstallSuccessful;
@@ -298,6 +261,11 @@ public class Workspace extends SmoothPagedView
boolean mShouldSendPageSettled;
int mLastOverlaySroll = 0;
+ // Handles workspace state transitions
+ private WorkspaceStateTransitionAnimation mStateTransitionAnimation;
+
+ private AccessibilityDelegate mPagesAccessibilityDelegate;
+
private final Runnable mBindPages = new Runnable() {
@Override
public void run() {
@@ -324,29 +292,22 @@ public class Workspace extends SmoothPagedView
*/
public Workspace(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
- mContentIsRefreshable = false;
mOutlineHelper = HolographicOutlineHelper.obtain(context);
- mDragEnforcer = new DropTarget.DragEnforcer(context);
- // With workspace, data is available straight from the get-go
- setDataIsReady();
-
mLauncher = (Launcher) context;
+ mStateTransitionAnimation = new WorkspaceStateTransitionAnimation(mLauncher, this);
final Resources res = getResources();
- mWorkspaceFadeInAdjacentScreens = LauncherAppState.getInstance().getDynamicGrid().
- getDeviceProfile().shouldFadeAdjacentWorkspaceScreens();
+ DeviceProfile grid = mLauncher.getDeviceProfile();
+ mWorkspaceFadeInAdjacentScreens = grid.shouldFadeAdjacentWorkspaceScreens();
mFadeInAdjacentScreens = false;
mWallpaperManager = WallpaperManager.getInstance(context);
- LauncherAppState app = LauncherAppState.getInstance();
- DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
TypedArray a = context.obtainStyledAttributes(attrs,
R.styleable.Workspace, defStyle, 0);
mSpringLoadedShrinkFactor =
res.getInteger(R.integer.config_workspaceSpringLoadShrinkPercentage) / 100.0f;
- mOverviewModeShrinkFactor = grid.getOverviewModeScale();
- mCameraDistance = res.getInteger(R.integer.config_cameraDistance);
+ mOverviewModeShrinkFactor = grid.getOverviewModeScale(mIsRtl);
mOriginalDefaultPage = mDefaultPage = a.getInt(R.styleable.Workspace_defaultScreen, 1);
a.recycle();
@@ -357,7 +318,6 @@ public class Workspace extends SmoothPagedView
// Disable multitouch across the workspace/all apps/customize tray
setMotionEventSplittingEnabled(true);
- setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES);
}
@Override
@@ -375,13 +335,12 @@ public class Workspace extends SmoothPagedView
// estimate the size of a widget with spans hSpan, vSpan. return MAX_VALUE for each
// dimension if unsuccessful
- public int[] estimateItemSize(int hSpan, int vSpan,
- ItemInfo itemInfo, boolean springLoaded) {
+ public int[] estimateItemSize(ItemInfo itemInfo, boolean springLoaded) {
int[] size = new int[2];
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, hSpan, vSpan);
+ Rect r = estimateItemPosition(cl, itemInfo, 0, 0, itemInfo.spanX, itemInfo.spanY);
size[0] = r.width();
size[1] = r.height();
if (springLoaded) {
@@ -403,32 +362,39 @@ public class Workspace extends SmoothPagedView
return r;
}
+ @Override
public void onDragStart(final DragSource source, Object info, int dragAction) {
+ if (ENFORCE_DRAG_EVENT_ORDER) {
+ enfoceDragParity("onDragStart", 0, 0);
+ }
+
mIsDragOccuring = true;
updateChildrenLayersEnabled(false);
mLauncher.lockScreenOrientation();
mLauncher.onInteractionBegin();
- setChildrenBackgroundAlphaMultipliers(1f);
// Prevent any Un/InstallShortcutReceivers from updating the db while we are dragging
InstallShortcutReceiver.enableInstallQueue();
- UninstallShortcutReceiver.enableUninstallQueue();
- post(new Runnable() {
- @Override
- public void run() {
- if (mIsDragOccuring) {
- mDeferRemoveExtraEmptyScreen = false;
- addExtraEmptyScreenOnDrag();
- }
- }
- });
+
+ if (mAddNewPageOnDrag) {
+ mDeferRemoveExtraEmptyScreen = false;
+ addExtraEmptyScreenOnDrag();
+ }
}
+ public void setAddNewPageOnDrag(boolean addPage) {
+ mAddNewPageOnDrag = addPage;
+ }
public void deferRemoveExtraEmptyScreen() {
mDeferRemoveExtraEmptyScreen = true;
}
+ @Override
public void onDragEnd() {
+ if (ENFORCE_DRAG_EVENT_ORDER) {
+ enfoceDragParity("onDragEnd", 0, 0);
+ }
+
if (!mDeferRemoveExtraEmptyScreen) {
removeExtraEmptyScreen(true, mDragSourceInternal != null);
}
@@ -439,7 +405,6 @@ public class Workspace extends SmoothPagedView
// Re-enable any Un/InstallShortcutReceiver and now process any queued items
InstallShortcutReceiver.disableAndFlushInstallQueue(getContext());
- UninstallShortcutReceiver.disableAndFlushUninstallQueue(getContext());
mDragSourceInternal = null;
mLauncher.onInteractionEnd();
@@ -450,9 +415,8 @@ public class Workspace extends SmoothPagedView
*/
protected void initWorkspace() {
mCurrentPage = mDefaultPage;
- Launcher.setScreen(mCurrentPage);
LauncherAppState app = LauncherAppState.getInstance();
- DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
+ DeviceProfile grid = mLauncher.getDeviceProfile();
mIconCache = app.getIconCache();
setWillNotDraw(false);
setClipChildren(false);
@@ -467,10 +431,11 @@ public class Workspace extends SmoothPagedView
display.getSize(mDisplaySize);
mMaxDistanceForFolderCreation = (0.55f * grid.iconSizePx);
- mFlingThresholdVelocity = (int) (FLING_THRESHOLD_VELOCITY * mDensity);
// Set the wallpaper dimensions when Launcher starts up
setWallpaperDimension();
+
+ setEdgeGlowColor(getResources().getColor(R.color.workspace_edge_effect_color));
}
private void setupLayoutTransition() {
@@ -491,11 +456,6 @@ public class Workspace extends SmoothPagedView
}
@Override
- protected int getScrollMode() {
- return SmoothPagedView.X_LARGE_MODE;
- }
-
- @Override
public void onChildViewAdded(View parent, View child) {
if (!(child instanceof CellLayout)) {
throw new IllegalArgumentException("A Workspace can only have CellLayout children.");
@@ -503,7 +463,7 @@ public class Workspace extends SmoothPagedView
CellLayout cl = ((CellLayout) child);
cl.setOnInterceptTouchListener(this);
cl.setClickable(true);
- cl.setImportantForAccessibility(ViewCompat.IMPORTANT_FOR_ACCESSIBILITY_NO);
+ cl.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_NO);
super.onChildViewAdded(parent, child);
}
@@ -518,7 +478,7 @@ public class Workspace extends SmoothPagedView
/**
* @return The open folder on the current screen, or null if there is none
*/
- Folder getOpenFolder() {
+ public Folder getOpenFolder() {
DragLayer dragLayer = mLauncher.getDragLayer();
int count = dragLayer.getChildCount();
for (int i = 0; i < count; i++) {
@@ -572,16 +532,14 @@ public class Workspace extends SmoothPagedView
}
public long insertNewWorkspaceScreen(long screenId, int insertIndex) {
- // Log to disk
- Launcher.addDumpLog(TAG, "11683562 - insertNewWorkspaceScreen(): " + screenId +
- " at index: " + insertIndex, true);
-
if (mWorkspaceScreens.containsKey(screenId)) {
throw new RuntimeException("Screen id " + screenId + " already exists!");
}
- CellLayout newScreen = (CellLayout)
- mLauncher.getLayoutInflater().inflate(R.layout.workspace_screen, null);
+ // Inflate the cell layout, but do not add it automatically so that we can get the newly
+ // created CellLayout.
+ CellLayout newScreen = (CellLayout) mLauncher.getLayoutInflater().inflate(
+ R.layout.workspace_screen, this, false /* attachToRoot */);
newScreen.setOnLongClickListener(mLongClickListener);
newScreen.setOnClickListener(mLauncher);
@@ -589,13 +547,18 @@ public class Workspace extends SmoothPagedView
mWorkspaceScreens.put(screenId, newScreen);
mScreenOrder.add(insertIndex, screenId);
addView(newScreen, insertIndex);
+
+ LauncherAccessibilityDelegate delegate =
+ LauncherAppState.getInstance().getAccessibilityDelegate();
+ if (delegate != null && delegate.isInAccessibleDrag()) {
+ newScreen.enableAccessibleDrag(true, CellLayout.WORKSPACE_ACCESSIBILITY_DRAG);
+ }
return screenId;
}
public void createCustomContentContainer() {
CellLayout customScreen = (CellLayout)
- mLauncher.getLayoutInflater().inflate(R.layout.workspace_screen, null);
- customScreen.disableBackground();
+ mLauncher.getLayoutInflater().inflate(R.layout.workspace_screen, this, false);
customScreen.disableDragTarget();
mWorkspaceScreens.put(CUSTOM_CONTENT_SCREEN_ID, customScreen);
@@ -675,9 +638,6 @@ public class Workspace extends SmoothPagedView
}
public void addExtraEmptyScreenOnDrag() {
- // Log to disk
- Launcher.addDumpLog(TAG, "11683562 - addExtraEmptyScreenOnDrag()", true);
-
boolean lastChildOnScreen = false;
boolean childOnFinalScreen = false;
@@ -704,9 +664,6 @@ public class Workspace extends SmoothPagedView
}
public boolean addExtraEmptyScreen() {
- // Log to disk
- Launcher.addDumpLog(TAG, "11683562 - addExtraEmptyScreen()", true);
-
if (!mWorkspaceScreens.containsKey(EXTRA_EMPTY_SCREEN_ID)) {
insertNewWorkspaceScreen(EXTRA_EMPTY_SCREEN_ID);
return true;
@@ -715,9 +672,6 @@ public class Workspace extends SmoothPagedView
}
private void convertFinalScreenToEmptyScreenIfNecessary() {
- // Log to disk
- Launcher.addDumpLog(TAG, "11683562 - convertFinalScreenToEmptyScreenIfNecessary()", true);
-
if (mLauncher.isWorkspaceLoading()) {
// Invalid and dangerous operation if workspace is loading
Launcher.addDumpLog(TAG, " - workspace loading, skip", true);
@@ -742,7 +696,6 @@ public class Workspace extends SmoothPagedView
// Update the model if we have changed any screens
mLauncher.getModel().updateWorkspaceScreenOrder(mLauncher, mScreenOrder);
- Launcher.addDumpLog(TAG, "11683562 - extra empty screen: " + finalScreenId, true);
}
}
@@ -752,8 +705,6 @@ public class Workspace extends SmoothPagedView
public void removeExtraEmptyScreenDelayed(final boolean animate, final Runnable onComplete,
final int delay, final boolean stripEmptyScreens) {
- // Log to disk
- Launcher.addDumpLog(TAG, "11683562 - removeExtraEmptyScreen()", true);
if (mLauncher.isWorkspaceLoading()) {
// Don't strip empty screens if the workspace is still loading
Launcher.addDumpLog(TAG, " - workspace loading, skip", true);
@@ -778,6 +729,7 @@ public class Workspace extends SmoothPagedView
fadeAndRemoveEmptyScreen(SNAP_OFF_EMPTY_SCREEN_DURATION, FADE_EMPTY_SCREEN_DURATION,
onComplete, stripEmptyScreens);
} else {
+ snapToPage(getNextPage(), 0);
fadeAndRemoveEmptyScreen(0, FADE_EMPTY_SCREEN_DURATION,
onComplete, stripEmptyScreens);
}
@@ -795,9 +747,7 @@ public class Workspace extends SmoothPagedView
private void fadeAndRemoveEmptyScreen(int delay, int duration, final Runnable onComplete,
final boolean stripEmptyScreens) {
- // Log to disk
// XXX: Do we need to update LM workspace screens below?
- Launcher.addDumpLog(TAG, "11683562 - fadeAndRemoveEmptyScreen()", true);
PropertyValuesHolder alpha = PropertyValuesHolder.ofFloat("alpha", 0f);
PropertyValuesHolder bgAlpha = PropertyValuesHolder.ofFloat("backgroundAlpha", 0f);
@@ -841,8 +791,6 @@ public class Workspace extends SmoothPagedView
}
public long commitExtraEmptyScreen() {
- // Log to disk
- Launcher.addDumpLog(TAG, "11683562 - commitExtraEmptyScreen()", true);
if (mLauncher.isWorkspaceLoading()) {
// Invalid and dangerous operation if workspace is loading
Launcher.addDumpLog(TAG, " - workspace loading, skip", true);
@@ -875,12 +823,9 @@ public class Workspace extends SmoothPagedView
}
public long getIdForScreen(CellLayout layout) {
- Iterator<Long> iter = mWorkspaceScreens.keySet().iterator();
- while (iter.hasNext()) {
- long id = iter.next();
- if (mWorkspaceScreens.get(id) == layout) {
- return id;
- }
+ int index = mWorkspaceScreens.indexOfValue(layout);
+ if (index != -1) {
+ return mWorkspaceScreens.keyAt(index);
}
return -1;
}
@@ -896,14 +841,11 @@ public class Workspace extends SmoothPagedView
return -1;
}
- ArrayList<Long> getScreenOrder() {
+ public ArrayList<Long> getScreenOrder() {
return mScreenOrder;
}
public void stripEmptyScreens() {
- // Log to disk
- Launcher.addDumpLog(TAG, "11683562 - stripEmptyScreens()", true);
-
if (mLauncher.isWorkspaceLoading()) {
// Don't strip empty screens if the workspace is still loading.
// This is dangerous and can result in data loss.
@@ -918,8 +860,10 @@ public class Workspace extends SmoothPagedView
int currentPage = getNextPage();
ArrayList<Long> removeScreens = new ArrayList<Long>();
- for (Long id: mWorkspaceScreens.keySet()) {
- CellLayout cl = mWorkspaceScreens.get(id);
+ int total = mWorkspaceScreens.size();
+ for (int i = 0; i < total; i++) {
+ long id = mWorkspaceScreens.keyAt(i);
+ CellLayout cl = mWorkspaceScreens.valueAt(i);
if (id >= 0 && cl.getShortcutsAndWidgets().getChildCount() == 0) {
removeScreens.add(id);
}
@@ -931,7 +875,6 @@ public class Workspace extends SmoothPagedView
int pageShift = 0;
for (Long id: removeScreens) {
- Launcher.addDumpLog(TAG, "11683562 - removing id: " + id, true);
CellLayout cl = mWorkspaceScreens.get(id);
mWorkspaceScreens.remove(id);
mScreenOrder.remove(id);
@@ -1075,6 +1018,7 @@ public class Workspace extends SmoothPagedView
* listener via setOnInterceptTouchEventListener(). This allows us to tell the CellLayout
* that it should intercept touch events, which is not something that is normally supported.
*/
+ @SuppressLint("ClickableViewAccessibility")
@Override
public boolean onTouch(View v, MotionEvent event) {
return (workspaceInModalState() || !isFinishedSwitchingState())
@@ -1116,7 +1060,7 @@ public class Workspace extends SmoothPagedView
case MotionEvent.ACTION_UP:
if (mTouchState == TOUCH_STATE_REST) {
final CellLayout currentPage = (CellLayout) getChildAt(mCurrentPage);
- if (currentPage != null && !currentPage.lastDownOnOccupiedCell()) {
+ if (currentPage != null) {
onWallpaperTap(ev);
}
}
@@ -1178,7 +1122,7 @@ public class Workspace extends SmoothPagedView
boolean passRightSwipesToCustomContent =
(mTouchDownTime - mCustomContentShowTime) > CUSTOM_CONTENT_GESTURE_DELAY;
- boolean swipeInIgnoreDirection = isLayoutRtl() ? deltaX < 0 : deltaX > 0;
+ boolean swipeInIgnoreDirection = mIsRtl ? deltaX < 0 : deltaX > 0;
boolean onCustomContentScreen =
getScreenIdForPageIndex(getCurrentPage()) == CUSTOM_CONTENT_SCREEN_ID;
if (swipeInIgnoreDirection && onCustomContentScreen && passRightSwipesToCustomContent) {
@@ -1285,15 +1229,14 @@ public class Workspace extends SmoothPagedView
@Override
protected void overScroll(float amount) {
- boolean isRtl = isLayoutRtl();
- boolean shouldOverScroll = (amount <= 0 && (!hasCustomContent() || isRtl)) ||
- (amount >= 0 && (!hasCustomContent() || !isRtl));
+ boolean shouldOverScroll = (amount <= 0 && (!hasCustomContent() || mIsRtl)) ||
+ (amount >= 0 && (!hasCustomContent() || !mIsRtl));
boolean shouldScrollOverlay = mLauncherOverlay != null &&
- ((amount <= 0 && !isRtl) || (amount >= 0 && isRtl));
+ ((amount <= 0 && !mIsRtl) || (amount >= 0 && mIsRtl));
boolean shouldZeroOverlay = mLauncherOverlay != null && mLastOverlaySroll != 0 &&
- ((amount >= 0 && !isRtl) || (amount <= 0 && isRtl));
+ ((amount >= 0 && !mIsRtl) || (amount <= 0 && mIsRtl));
if (shouldScrollOverlay) {
if (!mStartedSendingScrollEvents && mScrollInteractionBegan) {
@@ -1307,23 +1250,26 @@ public class Workspace extends SmoothPagedView
int progress = (int) Math.abs((f * 100));
mLastOverlaySroll = progress;
- mLauncherOverlay.onScrollChange(progress, isRtl);
+ mLauncherOverlay.onScrollChange(progress, mIsRtl);
} else if (shouldOverScroll) {
dampedOverScroll(amount);
- mOverScrollEffect = acceleratedOverFactor(amount);
- } else {
- mOverScrollEffect = 0;
}
if (shouldZeroOverlay) {
- mLauncherOverlay.onScrollChange(0, isRtl);
+ mLauncherOverlay.onScrollChange(0, mIsRtl);
}
}
@Override
+ protected void getEdgeVerticalPostion(int[] pos) {
+ View child = getChildAt(getPageCount() - 1);
+ pos[0] = child.getTop();
+ pos[1] = child.getBottom();
+ }
+
+ @Override
protected void notifyPageSwitchListener() {
super.notifyPageSwitchListener();
- Launcher.setScreen(getNextPage());
if (hasCustomContent() && getNextPage() == 0 && !mCustomContentShowing) {
mCustomContentShowing = true;
@@ -1346,10 +1292,10 @@ public class Workspace extends SmoothPagedView
protected void setWallpaperDimension() {
new AsyncTask<Void, Void, Void>() {
public Void doInBackground(Void ... args) {
- String spKey = WallpaperCropActivity.getSharedPreferencesKey();
+ String spKey = LauncherFiles.WALLPAPER_CROP_PREFERENCES_KEY;
SharedPreferences sp =
mLauncher.getSharedPreferences(spKey, Context.MODE_MULTI_PROCESS);
- LauncherWallpaperPickerActivity.suggestWallpaperDimension(mLauncher.getResources(),
+ WallpaperUtils.suggestWallpaperDimension(mLauncher.getResources(),
sp, mLauncher.getWindowManager(), mWallpaperManager,
mLauncher.overrideWallpaperDimensions());
return null;
@@ -1439,7 +1385,22 @@ public class Workspace extends SmoothPagedView
}
private float wallpaperOffsetForCurrentScroll() {
+ // TODO: do different behavior if it's a live wallpaper?
+ // Don't use up all the wallpaper parallax until you have at least
+ // MIN_PARALLAX_PAGE_SPAN pages
+ int numScrollingPages = getNumScreensExcludingEmptyAndCustom();
+ int parallaxPageSpan;
+ if (mWallpaperIsLiveWallpaper) {
+ parallaxPageSpan = numScrollingPages - 1;
+ } else {
+ parallaxPageSpan = Math.max(MIN_PARALLAX_PAGE_SPAN, numScrollingPages - 1);
+ }
+ mNumPagesForWallpaperParallax = parallaxPageSpan;
+
if (getChildCount() <= 1) {
+ if (mIsRtl) {
+ return 1 - 1.0f/mNumPagesForWallpaperParallax;
+ }
return 0;
}
@@ -1448,7 +1409,7 @@ public class Workspace extends SmoothPagedView
int firstIndex = numCustomPages();
// Exclude the last extra empty screen (if we have > MIN_PARALLAX_PAGE_SPAN pages)
int lastIndex = getChildCount() - 1 - emptyExtraPages;
- if (isLayoutRtl()) {
+ if (mIsRtl) {
int temp = firstIndex;
firstIndex = lastIndex;
lastIndex = temp;
@@ -1459,28 +1420,20 @@ public class Workspace extends SmoothPagedView
if (scrollRange == 0) {
return 0;
} else {
- // TODO: do different behavior if it's a live wallpaper?
// Sometimes the left parameter of the pages is animated during a layout transition;
// this parameter offsets it to keep the wallpaper from animating as well
int adjustedScroll =
getScrollX() - firstPageScrollX - getLayoutTransitionOffsetForPage(0);
float offset = Math.min(1, adjustedScroll / (float) scrollRange);
offset = Math.max(0, offset);
- // Don't use up all the wallpaper parallax until you have at least
- // MIN_PARALLAX_PAGE_SPAN pages
- int numScrollingPages = getNumScreensExcludingEmptyAndCustom();
- int parallaxPageSpan;
- if (mWallpaperIsLiveWallpaper) {
- parallaxPageSpan = numScrollingPages - 1;
- } else {
- parallaxPageSpan = Math.max(MIN_PARALLAX_PAGE_SPAN, numScrollingPages - 1);
- }
- mNumPagesForWallpaperParallax = parallaxPageSpan;
// On RTL devices, push the wallpaper offset to the right if we don't have enough
// pages (ie if numScrollingPages < MIN_PARALLAX_PAGE_SPAN)
- int padding = isLayoutRtl() ? parallaxPageSpan - numScrollingPages + 1 : 0;
- return offset * (padding + numScrollingPages - 1) / parallaxPageSpan;
+ if (!mWallpaperIsLiveWallpaper && numScrollingPages < MIN_PARALLAX_PAGE_SPAN
+ && mIsRtl) {
+ return offset * (parallaxPageSpan - numScrollingPages + 1) / parallaxPageSpan;
+ }
+ return offset * (numScrollingPages - 1) / parallaxPageSpan;
}
}
@@ -1560,81 +1513,17 @@ public class Workspace extends SmoothPagedView
@Override
public void announceForAccessibility(CharSequence text) {
// Don't announce if apps is on top of us.
- if (!mLauncher.isAllAppsVisible()) {
+ if (!mLauncher.isAppsViewVisible()) {
super.announceForAccessibility(text);
}
}
- void showOutlines() {
- if (!workspaceInModalState() && !mIsSwitchingState) {
- if (mChildrenOutlineFadeOutAnimation != null) mChildrenOutlineFadeOutAnimation.cancel();
- if (mChildrenOutlineFadeInAnimation != null) mChildrenOutlineFadeInAnimation.cancel();
- mChildrenOutlineFadeInAnimation = LauncherAnimUtils.ofFloat(this, "childrenOutlineAlpha", 1.0f);
- mChildrenOutlineFadeInAnimation.setDuration(CHILDREN_OUTLINE_FADE_IN_DURATION);
- mChildrenOutlineFadeInAnimation.start();
- }
- }
-
- void hideOutlines() {
- if (!workspaceInModalState() && !mIsSwitchingState) {
- if (mChildrenOutlineFadeInAnimation != null) mChildrenOutlineFadeInAnimation.cancel();
- if (mChildrenOutlineFadeOutAnimation != null) mChildrenOutlineFadeOutAnimation.cancel();
- mChildrenOutlineFadeOutAnimation = LauncherAnimUtils.ofFloat(this, "childrenOutlineAlpha", 0.0f);
- mChildrenOutlineFadeOutAnimation.setDuration(CHILDREN_OUTLINE_FADE_OUT_DURATION);
- mChildrenOutlineFadeOutAnimation.setStartDelay(CHILDREN_OUTLINE_FADE_OUT_DELAY);
- mChildrenOutlineFadeOutAnimation.start();
- }
- }
-
public void showOutlinesTemporarily() {
if (!mIsPageMoving && !isTouchActive()) {
snapToPage(mCurrentPage);
}
}
- public void setChildrenOutlineAlpha(float alpha) {
- mChildrenOutlineAlpha = alpha;
- for (int i = 0; i < getChildCount(); i++) {
- CellLayout cl = (CellLayout) getChildAt(i);
- cl.setBackgroundAlpha(alpha);
- }
- }
-
- public float getChildrenOutlineAlpha() {
- return mChildrenOutlineAlpha;
- }
-
- private void animateBackgroundGradient(float finalAlpha, boolean animated) {
- final DragLayer dragLayer = mLauncher.getDragLayer();
-
- if (mBackgroundFadeInAnimation != null) {
- mBackgroundFadeInAnimation.cancel();
- mBackgroundFadeInAnimation = null;
- }
- if (mBackgroundFadeOutAnimation != null) {
- mBackgroundFadeOutAnimation.cancel();
- mBackgroundFadeOutAnimation = null;
- }
- float startAlpha = dragLayer.getBackgroundAlpha();
- if (finalAlpha != startAlpha) {
- if (animated) {
- mBackgroundFadeOutAnimation =
- LauncherAnimUtils.ofFloat(this, startAlpha, finalAlpha);
- mBackgroundFadeOutAnimation.addUpdateListener(new AnimatorUpdateListener() {
- public void onAnimationUpdate(ValueAnimator animation) {
- dragLayer.setBackgroundAlpha(
- ((Float)animation.getAnimatedValue()).floatValue());
- }
- });
- mBackgroundFadeOutAnimation.setInterpolator(new DecelerateInterpolator(1.5f));
- mBackgroundFadeOutAnimation.setDuration(BACKGROUND_FADE_OUT_DURATION);
- mBackgroundFadeOutAnimation.start();
- } else {
- dragLayer.setBackgroundAlpha(finalAlpha);
- }
- }
- }
-
float backgroundAlphaInterpolator(float r) {
float pivotA = 0.1f;
float pivotB = 0.4f;
@@ -1648,28 +1537,38 @@ public class Workspace extends SmoothPagedView
}
private void updatePageAlphaValues(int screenCenter) {
- boolean isInOverscroll = mOverScrollX < 0 || mOverScrollX > mMaxScrollX;
if (mWorkspaceFadeInAdjacentScreens &&
!workspaceInModalState() &&
- !mIsSwitchingState &&
- !isInOverscroll) {
+ !mIsSwitchingState) {
for (int i = numCustomPages(); i < getChildCount(); i++) {
CellLayout child = (CellLayout) getChildAt(i);
if (child != null) {
float scrollProgress = getScrollProgress(screenCenter, child, i);
float alpha = 1 - Math.abs(scrollProgress);
child.getShortcutsAndWidgets().setAlpha(alpha);
- //child.setBackgroundAlphaMultiplier(1 - alpha);
}
}
}
}
- private void setChildrenBackgroundAlphaMultipliers(float a) {
+ @TargetApi(Build.VERSION_CODES.LOLLIPOP)
+ @Override
+ public void enableAccessibleDrag(boolean enable) {
for (int i = 0; i < getChildCount(); i++) {
CellLayout child = (CellLayout) getChildAt(i);
- child.setBackgroundAlphaMultiplier(a);
+ child.enableAccessibleDrag(enable, CellLayout.WORKSPACE_ACCESSIBILITY_DRAG);
+ }
+
+ if (enable) {
+ // We need to allow our individual children to become click handlers in this case
+ setOnClickListener(null);
+ } else {
+ // Reset our click listener
+ setOnClickListener(mLauncher);
}
+ mLauncher.getSearchBar().enableAccessibleDrag(enable);
+ mLauncher.getHotseat().getLayout()
+ .enableAccessibleDrag(enable, CellLayout.WORKSPACE_ACCESSIBILITY_DRAG);
}
public boolean hasCustomContent() {
@@ -1696,7 +1595,7 @@ public class Workspace extends SmoothPagedView
translationX = scrollRange - scrollDelta;
progress = (scrollRange - scrollDelta) / scrollRange;
- if (isLayoutRtl()) {
+ if (mIsRtl) {
translationX = Math.min(0, translationX);
} else {
translationX = Math.max(0, translationX);
@@ -1713,7 +1612,11 @@ public class Workspace extends SmoothPagedView
mLastCustomContentScrollProgress = progress;
- mLauncher.getDragLayer().setBackgroundAlpha(progress * 0.8f);
+ // We should only update the drag layer background alpha if we are not in all apps or the
+ // widgets tray
+ if (mState == State.NORMAL) {
+ mLauncher.getDragLayer().setBackgroundAlpha(progress == 1 ? 0 : progress * 0.8f);
+ }
if (mLauncher.getHotseat() != null) {
mLauncher.getHotseat().setTranslationX(translationX);
@@ -1738,7 +1641,7 @@ public class Workspace extends SmoothPagedView
OnClickListener listener = new OnClickListener() {
@Override
public void onClick(View arg0) {
- enterOverviewMode();
+ mLauncher.showOverviewMode(true);
}
};
return listener;
@@ -1746,35 +1649,9 @@ public class Workspace extends SmoothPagedView
@Override
protected void screenScrolled(int screenCenter) {
- final boolean isRtl = isLayoutRtl();
- super.screenScrolled(screenCenter);
-
updatePageAlphaValues(screenCenter);
updateStateForCustomContent(screenCenter);
enableHwLayersOnVisiblePages();
-
- boolean shouldOverScroll = mOverScrollX < 0 || mOverScrollX > mMaxScrollX;
-
- if (shouldOverScroll) {
- int index = 0;
- final int lowerIndex = 0;
- final int upperIndex = getChildCount() - 1;
-
- final boolean isLeftPage = mOverScrollX < 0;
- index = (!isRtl && isLeftPage) || (isRtl && !isLeftPage) ? lowerIndex : upperIndex;
-
- CellLayout cl = (CellLayout) getChildAt(index);
- float effect = Math.abs(mOverScrollEffect);
- cl.setOverScrollAmount(Math.abs(effect), isLeftPage);
-
- mOverscrollEffectSet = true;
- } else {
- if (mOverscrollEffectSet && getChildCount() > 0) {
- mOverscrollEffectSet = false;
- ((CellLayout) getChildAt(0)).setOverScrollAmount(0, false);
- ((CellLayout) getChildAt(getChildCount() - 1)).setOverScrollAmount(0, false);
- }
- }
}
protected void onAttachedToWindow() {
@@ -1798,9 +1675,6 @@ public class Workspace extends SmoothPagedView
getPageIndicator().setOnClickListener(listener);
}
}
- AccessibilityManager am = (AccessibilityManager)
- getContext().getSystemService(Context.ACCESSIBILITY_SERVICE);
- sAccessibilityEnabled = am.isEnabled();
// Update wallpaper dimensions if they were changed since last onResume
// (we also always set the wallpaper dimensions in the constructor)
@@ -1832,7 +1706,7 @@ public class Workspace extends SmoothPagedView
@Override
protected boolean onRequestFocusInDescendants(int direction, Rect previouslyFocusedRect) {
- if (!mLauncher.isAllAppsVisible()) {
+ if (!mLauncher.isAppsViewVisible()) {
final Folder openFolder = getOpenFolder();
if (openFolder != null) {
return openFolder.requestFocus(direction, previouslyFocusedRect);
@@ -1853,7 +1727,7 @@ public class Workspace extends SmoothPagedView
@Override
public void addFocusables(ArrayList<View> views, int direction, int focusableMode) {
- if (!mLauncher.isAllAppsVisible()) {
+ if (!mLauncher.isAppsViewVisible()) {
final Folder openFolder = getOpenFolder();
if (openFolder != null) {
openFolder.addFocusables(views, direction);
@@ -1898,7 +1772,7 @@ public class Workspace extends SmoothPagedView
}
}
- private void updateChildrenLayersEnabled(boolean force) {
+ @Thunk void updateChildrenLayersEnabled(boolean force) {
boolean small = mState == State.OVERVIEW || mIsSwitchingState;
boolean enableChildrenLayers = force || small || mAnimatingViewIntoPlace || isPageMoving();
@@ -1971,64 +1845,6 @@ public class Workspace extends SmoothPagedView
}
/*
- * This interpolator emulates the rate at which the perceived scale of an object changes
- * as its distance from a camera increases. When this interpolator is applied to a scale
- * animation on a view, it evokes the sense that the object is shrinking due to moving away
- * from the camera.
- */
- static class ZInterpolator implements TimeInterpolator {
- private float focalLength;
-
- public ZInterpolator(float foc) {
- focalLength = foc;
- }
-
- public float getInterpolation(float input) {
- return (1.0f - focalLength / (focalLength + input)) /
- (1.0f - focalLength / (focalLength + 1.0f));
- }
- }
-
- /*
- * The exact reverse of ZInterpolator.
- */
- static class InverseZInterpolator implements TimeInterpolator {
- private ZInterpolator zInterpolator;
- public InverseZInterpolator(float foc) {
- zInterpolator = new ZInterpolator(foc);
- }
- public float getInterpolation(float input) {
- return 1 - zInterpolator.getInterpolation(1 - input);
- }
- }
-
- /*
- * ZInterpolator compounded with an ease-out.
- */
- static class ZoomOutInterpolator implements TimeInterpolator {
- private final DecelerateInterpolator decelerate = new DecelerateInterpolator(0.75f);
- private final ZInterpolator zInterpolator = new ZInterpolator(0.13f);
-
- public float getInterpolation(float input) {
- return decelerate.getInterpolation(zInterpolator.getInterpolation(input));
- }
- }
-
- /*
- * InvereZInterpolator compounded with an ease-out.
- */
- static class ZoomInInterpolator implements TimeInterpolator {
- private final InverseZInterpolator inverseZInterpolator = new InverseZInterpolator(0.35f);
- private final DecelerateInterpolator decelerate = new DecelerateInterpolator(3.0f);
-
- public float getInterpolation(float input) {
- return decelerate.getInterpolation(inverseZInterpolator.getInterpolation(input));
- }
- }
-
- private final ZoomInInterpolator mZoomInInterpolator = new ZoomInInterpolator();
-
- /*
*
* We call these methods (onDragStartedWithItemSpans/onDragStartedWithSize) whenever we
* start a drag in Launcher, regardless of whether the drag has ever entered the Workspace
@@ -2054,16 +1870,14 @@ public class Workspace extends SmoothPagedView
public void onExternalDragStartedWithItem(View v) {
// Compose a drag bitmap with the view scaled to the icon size
- LauncherAppState app = LauncherAppState.getInstance();
- DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
+ DeviceProfile grid = mLauncher.getDeviceProfile();
int iconSize = grid.iconSizePx;
int bmpWidth = v.getMeasuredWidth();
int bmpHeight = v.getMeasuredHeight();
// If this is a text view, use its drawable instead
if (v instanceof TextView) {
- TextView tv = (TextView) v;
- Drawable d = tv.getCompoundDrawables()[1];
+ Drawable d = getTextViewIcon((TextView) v);
Rect bounds = getDrawableBounds(d);
bmpWidth = bounds.width();
bmpHeight = bounds.height();
@@ -2081,7 +1895,7 @@ public class Workspace extends SmoothPagedView
}
public void onDragStartedWithItem(PendingAddItemInfo info, Bitmap b, boolean clipAlpha) {
- int[] size = estimateItemSize(info.spanX, info.spanY, info, false);
+ int[] size = estimateItemSize(info, false);
// The outline is used to visualize where the item will land if dropped
mDragOutline = createDragOutline(b, DRAG_BITMAP_PADDING, size[0], size[1], clipAlpha);
@@ -2092,21 +1906,6 @@ public class Workspace extends SmoothPagedView
dragLayer.clearAllResizeFrames();
}
- private void initAnimationArrays() {
- final int childCount = getChildCount();
- if (mLastChildCount == childCount) return;
-
- mOldBackgroundAlphas = new float[childCount];
- mOldAlphas = new float[childCount];
- mNewBackgroundAlphas = new float[childCount];
- mNewAlphas = new float[childCount];
- }
-
- Animator getChangeStateAnimation(final State state, boolean animated,
- ArrayList<View> layerViews) {
- return getChangeStateAnimation(state, animated, 0, -1, layerViews);
- }
-
@Override
protected void getFreeScrollPageRange(int[] range) {
getOverviewModePages(range);
@@ -2120,14 +1919,13 @@ public class Workspace extends SmoothPagedView
range[1] = Math.max(0, end);
}
- protected void onStartReordering() {
+ public void onStartReordering() {
super.onStartReordering();
- showOutlines();
// Reordering handles its own animations, disable the automatic ones.
disableLayoutTransitions();
}
- protected void onEndReordering() {
+ public void onEndReordering() {
super.onEndReordering();
if (mLauncher.isWorkspaceLoading()) {
@@ -2135,7 +1933,6 @@ public class Workspace extends SmoothPagedView
return;
}
- hideOutlines();
mScreenOrder.clear();
int count = getChildCount();
for (int i = 0; i < count; i++) {
@@ -2153,44 +1950,8 @@ public class Workspace extends SmoothPagedView
return mState == State.OVERVIEW;
}
- public boolean enterOverviewMode() {
- if (mTouchState != TOUCH_STATE_REST) {
- return false;
- }
- enableOverviewMode(true, -1, true);
- return true;
- }
-
- public void exitOverviewMode(boolean animated) {
- exitOverviewMode(-1, animated);
- }
-
- public void exitOverviewMode(int snapPage, boolean animated) {
- enableOverviewMode(false, snapPage, animated);
- }
-
- private void enableOverviewMode(boolean enable, int snapPage, boolean animated) {
- State finalState = Workspace.State.OVERVIEW;
- if (!enable) {
- finalState = Workspace.State.NORMAL;
- }
-
- Animator workspaceAnim = getChangeStateAnimation(finalState, animated, 0, snapPage);
- if (workspaceAnim != null) {
- onTransitionPrepare();
- workspaceAnim.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator arg0) {
- onTransitionEnd();
- }
- });
- workspaceAnim.start();
- }
- }
-
int getOverviewModeTranslationY() {
- LauncherAppState app = LauncherAppState.getInstance();
- DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
+ DeviceProfile grid = mLauncher.getDeviceProfile();
Rect overviewBar = grid.getOverviewModeButtonBarRect();
int availableHeight = getViewportHeight();
@@ -2202,332 +1963,75 @@ public class Workspace extends SmoothPagedView
return -offsetFromTopEdge + mInsets.top + offsetToCenterInOverview;
}
- public void updateInteractionForState() {
- if (mState != State.NORMAL) {
- mLauncher.onInteractionBegin();
- } else {
- mLauncher.onInteractionEnd();
- }
- }
-
- private void setState(State state) {
- mState = state;
- updateInteractionForState();
+ /**
+ * Sets the current workspace {@link State}, returning an animation transitioning the workspace
+ * to that new state.
+ */
+ public Animator setStateWithAnimation(State toState, int toPage, boolean animated,
+ boolean hasOverlaySearchBar, HashMap<View, Integer> layerViews) {
+ // Create the animation to the new state
+ Animator workspaceAnim = mStateTransitionAnimation.getAnimationToState(mState,
+ toState, toPage, animated, hasOverlaySearchBar, layerViews);
+
+ // Update the current state
+ mState = toState;
updateAccessibilityFlags();
+
+ return workspaceAnim;
}
State getState() {
return mState;
}
- private void updateAccessibilityFlags() {
- int accessible = mState == State.NORMAL ?
- ViewCompat.IMPORTANT_FOR_ACCESSIBILITY_YES :
- ViewCompat.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS;
- setImportantForAccessibility(accessible);
- }
-
- private static final int HIDE_WORKSPACE_DURATION = 100;
-
- Animator getChangeStateAnimation(final State state, boolean animated, int delay, int snapPage) {
- return getChangeStateAnimation(state, animated, delay, snapPage, null);
- }
-
- Animator getChangeStateAnimation(final State state, boolean animated, int delay, int snapPage,
- ArrayList<View> layerViews) {
- if (mState == state) {
- return null;
- }
-
- // Initialize animation arrays for the first time if necessary
- initAnimationArrays();
-
- AnimatorSet anim = animated ? LauncherAnimUtils.createAnimatorSet() : null;
-
- // We only want a single instance of a workspace animation to be running at once, so
- // we cancel any incomplete transition.
- if (mStateAnimator != null) {
- mStateAnimator.cancel();
- }
- mStateAnimator = anim;
-
- final State oldState = mState;
- final boolean oldStateIsNormal = (oldState == State.NORMAL);
- final boolean oldStateIsSpringLoaded = (oldState == State.SPRING_LOADED);
- final boolean oldStateIsNormalHidden = (oldState == State.NORMAL_HIDDEN);
- final boolean oldStateIsOverviewHidden = (oldState == State.OVERVIEW_HIDDEN);
- final boolean oldStateIsOverview = (oldState == State.OVERVIEW);
- setState(state);
- final boolean stateIsNormal = (state == State.NORMAL);
- final boolean stateIsSpringLoaded = (state == State.SPRING_LOADED);
- final boolean stateIsNormalHidden = (state == State.NORMAL_HIDDEN);
- final boolean stateIsOverviewHidden = (state == State.OVERVIEW_HIDDEN);
- final boolean stateIsOverview = (state == State.OVERVIEW);
- float finalBackgroundAlpha = (stateIsSpringLoaded || stateIsOverview) ? 1.0f : 0f;
- float finalHotseatAndPageIndicatorAlpha = (stateIsNormal || stateIsSpringLoaded) ? 1f : 0f;
- float finalOverviewPanelAlpha = stateIsOverview ? 1f : 0f;
- float finalSearchBarAlpha = !stateIsNormal ? 0f : 1f;
- float finalWorkspaceTranslationY = stateIsOverview || stateIsOverviewHidden ?
- getOverviewModeTranslationY() : 0;
-
- boolean workspaceToAllApps = (oldStateIsNormal && stateIsNormalHidden);
- boolean overviewToAllApps = (oldStateIsOverview && stateIsOverviewHidden);
- boolean allAppsToWorkspace = (stateIsNormalHidden && stateIsNormal);
- boolean workspaceToOverview = (oldStateIsNormal && stateIsOverview);
- boolean overviewToWorkspace = (oldStateIsOverview && stateIsNormal);
-
- mNewScale = 1.0f;
-
- if (oldStateIsOverview) {
- disableFreeScroll();
- } else if (stateIsOverview) {
- enableFreeScroll();
- }
-
- if (state != State.NORMAL) {
- if (stateIsSpringLoaded) {
- mNewScale = mSpringLoadedShrinkFactor;
- } else if (stateIsOverview || stateIsOverviewHidden) {
- mNewScale = mOverviewModeShrinkFactor;
- }
- }
-
- final int duration;
- if (workspaceToAllApps || overviewToAllApps) {
- duration = HIDE_WORKSPACE_DURATION; //getResources().getInteger(R.integer.config_workspaceUnshrinkTime);
- } else if (workspaceToOverview || overviewToWorkspace) {
- duration = getResources().getInteger(R.integer.config_overviewTransitionTime);
- } else {
- duration = getResources().getInteger(R.integer.config_appsCustomizeWorkspaceShrinkTime);
- }
-
- if (snapPage == -1) {
- snapPage = getPageNearestToCenterOfScreen();
- }
- snapToPage(snapPage, duration, mZoomInInterpolator);
-
- for (int i = 0; i < getChildCount(); i++) {
- final CellLayout cl = (CellLayout) getChildAt(i);
- boolean isCurrentPage = (i == snapPage);
- float initialAlpha = cl.getShortcutsAndWidgets().getAlpha();
- float finalAlpha;
- if (stateIsNormalHidden || stateIsOverviewHidden) {
- finalAlpha = 0f;
- } else if (stateIsNormal && mWorkspaceFadeInAdjacentScreens) {
- finalAlpha = (i == snapPage || i < numCustomPages()) ? 1f : 0f;
- } else {
- finalAlpha = 1f;
- }
-
- // If we are animating to/from the small state, then hide the side pages and fade the
- // current page in
- if (!mIsSwitchingState) {
- if (workspaceToAllApps || allAppsToWorkspace) {
- if (allAppsToWorkspace && isCurrentPage) {
- initialAlpha = 0f;
- } else if (!isCurrentPage) {
- initialAlpha = finalAlpha = 0f;
- }
- cl.setShortcutAndWidgetAlpha(initialAlpha);
- }
+ public void updateAccessibilityFlags() {
+ if (Utilities.isLmpOrAbove()) {
+ int total = getPageCount();
+ for (int i = numCustomPages(); i < total; i++) {
+ updateAccessibilityFlags((CellLayout) getPageAt(i), i);
}
-
- mOldAlphas[i] = initialAlpha;
- mNewAlphas[i] = finalAlpha;
- if (animated) {
- mOldBackgroundAlphas[i] = cl.getBackgroundAlpha();
- mNewBackgroundAlphas[i] = finalBackgroundAlpha;
- } else {
- cl.setBackgroundAlpha(finalBackgroundAlpha);
- cl.setShortcutAndWidgetAlpha(finalAlpha);
- }
- }
-
- final View searchBar = mLauncher.getQsbBar();
- final View overviewPanel = mLauncher.getOverviewPanel();
- final View hotseat = mLauncher.getHotseat();
- final View pageIndicator = getPageIndicator();
- if (animated) {
- LauncherViewPropertyAnimator scale = new LauncherViewPropertyAnimator(this);
- scale.scaleX(mNewScale)
- .scaleY(mNewScale)
- .translationY(finalWorkspaceTranslationY)
- .setDuration(duration)
- .setInterpolator(mZoomInInterpolator);
- anim.play(scale);
- for (int index = 0; index < getChildCount(); index++) {
- final int i = index;
- final CellLayout cl = (CellLayout) getChildAt(i);
- float currentAlpha = cl.getShortcutsAndWidgets().getAlpha();
- if (mOldAlphas[i] == 0 && mNewAlphas[i] == 0) {
- cl.setBackgroundAlpha(mNewBackgroundAlphas[i]);
- cl.setShortcutAndWidgetAlpha(mNewAlphas[i]);
- } else {
- if (layerViews != null) {
- layerViews.add(cl);
- }
- if (mOldAlphas[i] != mNewAlphas[i] || currentAlpha != mNewAlphas[i]) {
- LauncherViewPropertyAnimator alphaAnim =
- new LauncherViewPropertyAnimator(cl.getShortcutsAndWidgets());
- alphaAnim.alpha(mNewAlphas[i])
- .setDuration(duration)
- .setInterpolator(mZoomInInterpolator);
- anim.play(alphaAnim);
- }
- if (mOldBackgroundAlphas[i] != 0 ||
- mNewBackgroundAlphas[i] != 0) {
- ValueAnimator bgAnim =
- LauncherAnimUtils.ofFloat(cl, 0f, 1f);
- bgAnim.setInterpolator(mZoomInInterpolator);
- bgAnim.setDuration(duration);
- bgAnim.addUpdateListener(new LauncherAnimatorUpdateListener() {
- public void onAnimationUpdate(float a, float b) {
- cl.setBackgroundAlpha(
- a * mOldBackgroundAlphas[i] +
- b * mNewBackgroundAlphas[i]);
- }
- });
- anim.play(bgAnim);
- }
- }
- }
- Animator pageIndicatorAlpha = null;
- if (pageIndicator != null) {
- pageIndicatorAlpha = new LauncherViewPropertyAnimator(pageIndicator)
- .alpha(finalHotseatAndPageIndicatorAlpha).withLayer();
- pageIndicatorAlpha.addListener(new AlphaUpdateListener(pageIndicator));
- } else {
- // create a dummy animation so we don't need to do null checks later
- pageIndicatorAlpha = ValueAnimator.ofFloat(0, 0);
- }
-
- Animator hotseatAlpha = new LauncherViewPropertyAnimator(hotseat)
- .alpha(finalHotseatAndPageIndicatorAlpha).withLayer();
- hotseatAlpha.addListener(new AlphaUpdateListener(hotseat));
-
- Animator overviewPanelAlpha = new LauncherViewPropertyAnimator(overviewPanel)
- .alpha(finalOverviewPanelAlpha).withLayer();
- overviewPanelAlpha.addListener(new AlphaUpdateListener(overviewPanel));
-
- // For animation optimations, we may need to provide the Launcher transition
- // with a set of views on which to force build layers in certain scenarios.
- hotseat.setLayerType(View.LAYER_TYPE_HARDWARE, null);
- overviewPanel.setLayerType(View.LAYER_TYPE_HARDWARE, null);
- if (layerViews != null) {
- layerViews.add(hotseat);
- layerViews.add(overviewPanel);
- }
-
- if (workspaceToOverview) {
- pageIndicatorAlpha.setInterpolator(new DecelerateInterpolator(2));
- hotseatAlpha.setInterpolator(new DecelerateInterpolator(2));
- overviewPanelAlpha.setInterpolator(null);
- } else if (overviewToWorkspace) {
- pageIndicatorAlpha.setInterpolator(null);
- hotseatAlpha.setInterpolator(null);
- overviewPanelAlpha.setInterpolator(new DecelerateInterpolator(2));
- }
-
- overviewPanelAlpha.setDuration(duration);
- pageIndicatorAlpha.setDuration(duration);
- hotseatAlpha.setDuration(duration);
-
- if (searchBar != null) {
- Animator searchBarAlpha = new LauncherViewPropertyAnimator(searchBar)
- .alpha(finalSearchBarAlpha).withLayer();
- searchBarAlpha.addListener(new AlphaUpdateListener(searchBar));
- searchBar.setLayerType(View.LAYER_TYPE_HARDWARE, null);
- if (layerViews != null) {
- layerViews.add(searchBar);
- }
- searchBarAlpha.setDuration(duration);
- anim.play(searchBarAlpha);
- }
-
- anim.play(overviewPanelAlpha);
- anim.play(hotseatAlpha);
- anim.play(pageIndicatorAlpha);
- anim.setStartDelay(delay);
- anim.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- mStateAnimator = null;
- }
- });
+ setImportantForAccessibility((mState == State.NORMAL || mState == State.OVERVIEW)
+ ? IMPORTANT_FOR_ACCESSIBILITY_AUTO
+ : IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS);
} else {
- overviewPanel.setAlpha(finalOverviewPanelAlpha);
- AlphaUpdateListener.updateVisibility(overviewPanel);
- hotseat.setAlpha(finalHotseatAndPageIndicatorAlpha);
- AlphaUpdateListener.updateVisibility(hotseat);
- if (pageIndicator != null) {
- pageIndicator.setAlpha(finalHotseatAndPageIndicatorAlpha);
- AlphaUpdateListener.updateVisibility(pageIndicator);
- }
- if (searchBar != null) {
- searchBar.setAlpha(finalSearchBarAlpha);
- AlphaUpdateListener.updateVisibility(searchBar);
- }
- updateCustomContentVisibility();
- setScaleX(mNewScale);
- setScaleY(mNewScale);
- setTranslationY(finalWorkspaceTranslationY);
- }
-
- if (stateIsNormal) {
- animateBackgroundGradient(0f, animated);
- } else {
- animateBackgroundGradient(getResources().getInteger(
- R.integer.config_workspaceScrimAlpha) / 100f, animated);
+ int accessible = mState == State.NORMAL ?
+ IMPORTANT_FOR_ACCESSIBILITY_AUTO :
+ IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS;
+ setImportantForAccessibility(accessible);
}
- return anim;
}
- static class AlphaUpdateListener implements AnimatorUpdateListener, AnimatorListener {
- View view;
- public AlphaUpdateListener(View v) {
- view = v;
- }
+ private void updateAccessibilityFlags(CellLayout page, int pageNo) {
+ if (mState == State.OVERVIEW) {
+ page.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
+ page.getShortcutsAndWidgets().setImportantForAccessibility(
+ IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS);
+ page.setContentDescription(getPageDescription(pageNo));
- @Override
- public void onAnimationUpdate(ValueAnimator arg0) {
- updateVisibility(view);
- }
-
- public static void updateVisibility(View view) {
- // We want to avoid the extra layout pass by setting the views to GONE unless
- // accessibility is on, in which case not setting them to GONE causes a glitch.
- int invisibleState = sAccessibilityEnabled ? GONE : INVISIBLE;
- if (view.getAlpha() < ALPHA_CUTOFF_THRESHOLD && view.getVisibility() != invisibleState) {
- view.setVisibility(invisibleState);
- } else if (view.getAlpha() > ALPHA_CUTOFF_THRESHOLD
- && view.getVisibility() != VISIBLE) {
- view.setVisibility(VISIBLE);
+ if (mPagesAccessibilityDelegate == null) {
+ mPagesAccessibilityDelegate = new OverviewScreenAccessibilityDelegate(this);
}
- }
-
- @Override
- public void onAnimationCancel(Animator arg0) {
- }
-
- @Override
- public void onAnimationEnd(Animator arg0) {
- updateVisibility(view);
- }
-
- @Override
- public void onAnimationRepeat(Animator arg0) {
- }
-
- @Override
- public void onAnimationStart(Animator arg0) {
- // We want the views to be visible for animation, so fade-in/out is visible
- view.setVisibility(VISIBLE);
+ page.setAccessibilityDelegate(mPagesAccessibilityDelegate);
+ } else {
+ int accessible = mState == State.NORMAL ?
+ IMPORTANT_FOR_ACCESSIBILITY_AUTO :
+ IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS;
+ page.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_NO);
+ page.getShortcutsAndWidgets().setImportantForAccessibility(accessible);
+ page.setContentDescription(null);
+ page.setAccessibilityDelegate(null);
}
}
@Override
public void onLauncherTransitionPrepare(Launcher l, boolean animated, boolean toWorkspace) {
- onTransitionPrepare();
+ mIsSwitchingState = true;
+
+ // Invalidate here to ensure that the pages are rendered during the state change transition.
+ invalidate();
+
+ updateChildrenLayersEnabled(false);
+ hideCustomContentIfNecessary();
}
@Override
@@ -2541,17 +2045,9 @@ public class Workspace extends SmoothPagedView
@Override
public void onLauncherTransitionEnd(Launcher l, boolean animated, boolean toWorkspace) {
- onTransitionEnd();
- }
-
- private void onTransitionPrepare() {
- mIsSwitchingState = true;
-
- // Invalidate here to ensure that the pages are rendered during the state change transition.
- invalidate();
-
+ mIsSwitchingState = false;
updateChildrenLayersEnabled(false);
- hideCustomContentIfNecessary();
+ showCustomContentIfNecessary();
}
void updateCustomContentVisibility() {
@@ -2577,15 +2073,17 @@ public class Workspace extends SmoothPagedView
}
}
- private void onTransitionEnd() {
- mIsSwitchingState = false;
- updateChildrenLayersEnabled(false);
- showCustomContentIfNecessary();
- }
-
- @Override
- public View getContent() {
- return this;
+ /**
+ * Returns the drawable for the given text view.
+ */
+ public static Drawable getTextViewIcon(TextView tv) {
+ final Drawable[] drawables = tv.getCompoundDrawables();
+ for (int i = 0; i < drawables.length; i++) {
+ if (drawables[i] != null) {
+ return drawables[i];
+ }
+ }
+ return null;
}
/**
@@ -2603,7 +2101,7 @@ public class Workspace extends SmoothPagedView
destCanvas.save();
if (v instanceof TextView) {
- Drawable d = ((TextView) v).getCompoundDrawables()[1];
+ Drawable d = getTextViewIcon((TextView) v);
Rect bounds = getDrawableBounds(d);
clipRect.set(0, 0, bounds.width() + padding, bounds.height() + padding);
destCanvas.translate(padding / 2 - bounds.left, padding / 2 - bounds.top);
@@ -2640,7 +2138,7 @@ public class Workspace extends SmoothPagedView
int padding = expectedPadding.get();
if (v instanceof TextView) {
- Drawable d = ((TextView) v).getCompoundDrawables()[1];
+ Drawable d = getTextViewIcon((TextView) v);
Rect bounds = getDrawableBounds(d);
b = Bitmap.createBitmap(bounds.width() + padding,
bounds.height() + padding, Bitmap.Config.ARGB_8888);
@@ -2701,7 +2199,12 @@ public class Workspace extends SmoothPagedView
return b;
}
- void startDrag(CellLayout.CellInfo cellInfo) {
+ public void startDrag(CellLayout.CellInfo cellInfo) {
+ startDrag(cellInfo, false);
+ }
+
+ @Override
+ public void startDrag(CellLayout.CellInfo cellInfo, boolean accessible) {
View child = cellInfo.cell;
// Make sure the drag was started by a long press as opposed to a long click.
@@ -2714,10 +2217,15 @@ public class Workspace extends SmoothPagedView
CellLayout layout = (CellLayout) child.getParent().getParent();
layout.prepareChildForDrag(child);
- beginDragShared(child, this);
+ beginDragShared(child, this, accessible);
}
- public void beginDragShared(View child, DragSource source) {
+ public void beginDragShared(View child, DragSource source, boolean accessible) {
+ beginDragShared(child, new Point(), source, accessible);
+ }
+
+ public void beginDragShared(View child, Point relativeTouchPos, DragSource source,
+ boolean accessible) {
child.clearFocus();
child.setPressed(false);
@@ -2737,16 +2245,27 @@ public class Workspace extends SmoothPagedView
int dragLayerY = Math.round(mTempXY[1] - (bmpHeight - scale * bmpHeight) / 2
- padding.get() / 2);
- LauncherAppState app = LauncherAppState.getInstance();
- DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
+ DeviceProfile grid = mLauncher.getDeviceProfile();
Point dragVisualizeOffset = null;
Rect dragRect = null;
if (child instanceof BubbleTextView) {
+ BubbleTextView icon = (BubbleTextView) child;
int iconSize = grid.iconSizePx;
int top = child.getPaddingTop();
int left = (bmpWidth - iconSize) / 2;
int right = left + iconSize;
int bottom = top + iconSize;
+ if (icon.isLayoutHorizontal()) {
+ // If the layout is horizontal, then if we are just picking up the icon, then just
+ // use the child position since the icon is top-left aligned. Otherwise, offset
+ // the drag layer position horizontally so that the icon is under the current
+ // touch position.
+ if (icon.getIcon().getBounds().contains(relativeTouchPos.x, relativeTouchPos.y)) {
+ dragLayerX = Math.round(mTempXY[0]);
+ } else {
+ dragLayerX = Math.round(mTempXY[0] + relativeTouchPos.x - (bmpWidth / 2));
+ }
+ }
dragLayerY += top;
// Note: The drag region is used to calculate drag layer offsets, but the
// dragVisualizeOffset in addition to the dragRect (the size) to position the outline.
@@ -2771,7 +2290,7 @@ public class Workspace extends SmoothPagedView
}
DragView dv = mDragController.startDrag(b, dragLayerX, dragLayerY, source, child.getTag(),
- DragController.DRAG_ACTION_MOVE, dragVisualizeOffset, dragRect, scale);
+ DragController.DRAG_ACTION_MOVE, dragVisualizeOffset, dragRect, scale, accessible);
dv.setIntrinsicIconScaleFactor(source.getIntrinsicIconScaleFactor());
if (child.getParent() instanceof ShortcutAndWidgetContainer) {
@@ -2782,8 +2301,7 @@ public class Workspace extends SmoothPagedView
}
public void beginExternalDragShared(View child, DragSource source) {
- LauncherAppState app = LauncherAppState.getInstance();
- DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
+ DeviceProfile grid = mLauncher.getDeviceProfile();
int iconSize = grid.iconSizePx;
// Notify launcher of drag start
@@ -2821,25 +2339,13 @@ public class Workspace extends SmoothPagedView
// Start the drag
DragView dv = mDragController.startDrag(b, dragLayerX, dragLayerY, source, child.getTag(),
- DragController.DRAG_ACTION_MOVE, dragVisualizeOffset, dragRect, scale);
+ DragController.DRAG_ACTION_MOVE, dragVisualizeOffset, dragRect, scale, false);
dv.setIntrinsicIconScaleFactor(source.getIntrinsicIconScaleFactor());
// Recycle temporary bitmaps
tmpB.recycle();
}
- void addApplicationShortcut(ShortcutInfo info, CellLayout target, long container, long screenId,
- int cellX, int cellY, boolean insertAtFirst, int intersectX, int intersectY) {
- View view = mLauncher.createShortcut(R.layout.application, target, (ShortcutInfo) info);
-
- final int[] cellXY = new int[2];
- target.findCellForSpanThatIntersects(cellXY, 1, 1, intersectX, intersectY);
- addInScreen(view, container, screenId, cellXY[0], cellXY[1], 1, 1, insertAtFirst);
-
- LauncherModel.addOrMoveItemInDatabase(mLauncher, info, container, screenId, cellXY[0],
- cellXY[1]);
- }
-
public boolean transitionStateShouldAllowDrop() {
return ((!isSwitchingState() || mTransitionProgress > 0.5f) &&
(mState == State.NORMAL || mState == State.SPRING_LOADED));
@@ -2858,8 +2364,7 @@ public class Workspace extends SmoothPagedView
}
if (!transitionStateShouldAllowDrop()) return false;
- mDragViewVisualCenter = getDragViewVisualCenter(d.x, d.y, d.xOffset, d.yOffset,
- d.dragView, mDragViewVisualCenter);
+ mDragViewVisualCenter = d.getVisualCenter(mDragViewVisualCenter);
// We want the point to be mapped to the dragTarget.
if (mLauncher.isHotseatLayout(dropTargetLayout)) {
@@ -3060,10 +2565,11 @@ public class Workspace extends SmoothPagedView
return false;
}
- public void onDrop(final DragObject d) {
- mDragViewVisualCenter = getDragViewVisualCenter(d.x, d.y, d.xOffset, d.yOffset, d.dragView,
- mDragViewVisualCenter);
+ @Override
+ public void prepareAccessibilityDrop() { }
+ public void onDrop(final DragObject d) {
+ mDragViewVisualCenter = d.getVisualCenter(mDragViewVisualCenter);
CellLayout dropTargetLayout = mDropToLayout;
// We want the point to be mapped to the dragTarget.
@@ -3075,7 +2581,7 @@ public class Workspace extends SmoothPagedView
}
}
- int snapScreen = -1;
+ int snapScreen = WorkspaceStateTransitionAnimation.SCROLL_TO_CURRENT_PAGE;
boolean resizeOnDrop = false;
if (d.dragSource != this) {
final int[] touchXY = new int[] { (int) mDragViewVisualCenter[0],
@@ -3178,9 +2684,9 @@ public class Workspace extends SmoothPagedView
// in its final location
final LauncherAppWidgetHostView hostView = (LauncherAppWidgetHostView) cell;
- AppWidgetProviderInfo pinfo = hostView.getAppWidgetInfo();
- if (pinfo != null &&
- pinfo.resizeMode != AppWidgetProviderInfo.RESIZE_NONE) {
+ AppWidgetProviderInfo pInfo = hostView.getAppWidgetInfo();
+ if (pInfo != null && pInfo.resizeMode != AppWidgetProviderInfo.RESIZE_NONE
+ && !d.accessibleDrag) {
final Runnable addResizeFrame = new Runnable() {
public void run() {
DragLayer dragLayer = mLauncher.getDragLayer();
@@ -3228,13 +2734,17 @@ public class Workspace extends SmoothPagedView
mAnimatingViewIntoPlace = true;
if (d.dragView.hasDrawn()) {
final ItemInfo info = (ItemInfo) cell.getTag();
- if (info.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET) {
+ boolean isWidget = info.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET
+ || info.itemType == LauncherSettings.Favorites.ITEM_TYPE_CUSTOM_APPWIDGET;
+ if (isWidget) {
int animationType = resizeOnDrop ? ANIMATE_INTO_POSITION_AND_RESIZE :
ANIMATE_INTO_POSITION_AND_DISAPPEAR;
animateWidgetDrop(info, parent, d.dragView,
onCompleteRunnable, animationType, cell, false);
} else {
- int duration = snapScreen < 0 ? -1 : ADJACENT_SCREEN_DROP_DURATION;
+ int duration = snapScreen < 0 ?
+ WorkspaceStateTransitionAnimation.SCROLL_TO_CURRENT_PAGE :
+ ADJACENT_SCREEN_DROP_DURATION;
mLauncher.getDragLayer().animateViewIntoPosition(d.dragView, cell, duration,
onCompleteRunnable, this);
}
@@ -3246,26 +2756,26 @@ public class Workspace extends SmoothPagedView
}
}
- public void setFinalScrollForPageChange(int pageIndex) {
- CellLayout cl = (CellLayout) getChildAt(pageIndex);
- if (cl != null) {
- mSavedScrollX = getScrollX();
- mSavedTranslationX = cl.getTranslationX();
- mSavedRotationY = cl.getRotationY();
- final int newX = getScrollForPage(pageIndex);
- setScrollX(newX);
- cl.setTranslationX(0f);
- cl.setRotationY(0f);
+ /**
+ * Computes the area relative to dragLayer which is used to display a page.
+ */
+ public void getPageAreaRelativeToDragLayer(Rect outArea) {
+ CellLayout child = (CellLayout) getChildAt(getNextPage());
+ if (child == null) {
+ return;
}
- }
+ ShortcutAndWidgetContainer boundingLayout = child.getShortcutsAndWidgets();
- public void resetFinalScrollForPageChange(int pageIndex) {
- if (pageIndex >= 0) {
- CellLayout cl = (CellLayout) getChildAt(pageIndex);
- setScrollX(mSavedScrollX);
- cl.setTranslationX(mSavedTranslationX);
- cl.setRotationY(mSavedRotationY);
- }
+ // Use the absolute left instead of the child left, as we want the visible area
+ // irrespective of the visible child. Since the view can only scroll horizontally, the
+ // top position is not affected.
+ mTempXY[0] = getViewportOffsetX() + getPaddingLeft() + boundingLayout.getLeft();
+ mTempXY[1] = child.getTop() + boundingLayout.getTop();
+
+ float scale = mLauncher.getDragLayer().getDescendantCoordRelativeToSelf(this, mTempXY);
+ outArea.set(mTempXY[0], mTempXY[1],
+ (int) (mTempXY[0] + scale * boundingLayout.getMeasuredWidth()),
+ (int) (mTempXY[1] + scale * boundingLayout.getMeasuredHeight()));
}
public void getViewLocationRelativeToSelf(View v, int[] location) {
@@ -3281,8 +2791,12 @@ public class Workspace extends SmoothPagedView
location[1] = vY - y;
}
+ @Override
public void onDragEnter(DragObject d) {
- mDragEnforcer.onDragEnter();
+ if (ENFORCE_DRAG_EVENT_ORDER) {
+ enfoceDragParity("onDragEnter", 1, 1);
+ }
+
mCreateUserFolderOnDrop = false;
mAddToExistingFolderOnDrop = false;
@@ -3300,42 +2814,46 @@ public class Workspace extends SmoothPagedView
* widthGap/heightGap (right, bottom) */
static Rect getCellLayoutMetrics(Launcher launcher, int orientation) {
LauncherAppState app = LauncherAppState.getInstance();
- DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
+ InvariantDeviceProfile inv = app.getInvariantDeviceProfile();
Display display = launcher.getWindowManager().getDefaultDisplay();
Point smallestSize = new Point();
Point largestSize = new Point();
display.getCurrentSizeRange(smallestSize, largestSize);
- int countX = (int) grid.numColumns;
- int countY = (int) grid.numRows;
+ int countX = (int) inv.numColumns;
+ int countY = (int) inv.numRows;
+ boolean isLayoutRtl = Utilities.isRtl(launcher.getResources());
if (orientation == CellLayout.LANDSCAPE) {
if (mLandscapeCellLayoutMetrics == null) {
- Rect padding = grid.getWorkspacePadding(CellLayout.LANDSCAPE);
+ Rect padding = inv.landscapeProfile.getWorkspacePadding(isLayoutRtl);
int width = largestSize.x - padding.left - padding.right;
int height = smallestSize.y - padding.top - padding.bottom;
mLandscapeCellLayoutMetrics = new Rect();
mLandscapeCellLayoutMetrics.set(
- grid.calculateCellWidth(width, countX),
- grid.calculateCellHeight(height, countY), 0, 0);
+ DeviceProfile.calculateCellWidth(width, countX),
+ DeviceProfile.calculateCellHeight(height, countY), 0, 0);
}
return mLandscapeCellLayoutMetrics;
} else if (orientation == CellLayout.PORTRAIT) {
if (mPortraitCellLayoutMetrics == null) {
- Rect padding = grid.getWorkspacePadding(CellLayout.PORTRAIT);
+ Rect padding = inv.portraitProfile.getWorkspacePadding(isLayoutRtl);
int width = smallestSize.x - padding.left - padding.right;
int height = largestSize.y - padding.top - padding.bottom;
mPortraitCellLayoutMetrics = new Rect();
mPortraitCellLayoutMetrics.set(
- grid.calculateCellWidth(width, countX),
- grid.calculateCellHeight(height, countY), 0, 0);
+ DeviceProfile.calculateCellWidth(width, countX),
+ DeviceProfile.calculateCellHeight(height, countY), 0, 0);
}
return mPortraitCellLayoutMetrics;
}
return null;
}
+ @Override
public void onDragExit(DragObject d) {
- mDragEnforcer.onDragExit();
+ if (ENFORCE_DRAG_EVENT_ORDER) {
+ enfoceDragParity("onDragExit", -1, 0);
+ }
// Here we store the final page that will be dropped to, if the workspace in fact
// receives the drop
@@ -3364,12 +2882,27 @@ public class Workspace extends SmoothPagedView
mSpringLoadedDragController.cancel();
- if (!mIsPageMoving) {
- hideOutlines();
- }
mLauncher.getDragLayer().hidePageHints();
}
+ private void enfoceDragParity(String event, int update, int expectedValue) {
+ enfoceDragParity(this, event, update, expectedValue);
+ for (int i = 0; i < getChildCount(); i++) {
+ enfoceDragParity(getChildAt(i), event, update, expectedValue);
+ }
+ }
+
+ private void enfoceDragParity(View v, String event, int update, int expectedValue) {
+ Object tag = v.getTag(R.id.drag_event_parity);
+ int value = tag == null ? 0 : (Integer) tag;
+ value += update;
+ v.setTag(R.id.drag_event_parity, value);
+
+ if (value != expectedValue) {
+ Log.e(TAG, event + ": Drag contract violated: " + value);
+ }
+ }
+
void setCurrentDropLayout(CellLayout layout) {
if (mDragTargetLayout != null) {
mDragTargetLayout.revertTempState();
@@ -3473,8 +3006,7 @@ public class Workspace extends SmoothPagedView
mTempPt[1] = y;
mLauncher.getDragLayer().getDescendantCoordRelativeToSelf(this, mTempPt, true);
- LauncherAppState app = LauncherAppState.getInstance();
- DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
+ DeviceProfile grid = mLauncher.getDeviceProfile();
r = grid.getHotseatRect();
if (r.contains(mTempPt[0], mTempPt[1])) {
return true;
@@ -3568,38 +3100,6 @@ public class Workspace extends SmoothPagedView
return bestMatchingScreen;
}
- // This is used to compute the visual center of the dragView. This point is then
- // used to visualize drop locations and determine where to drop an item. The idea is that
- // the visual center represents the user's interpretation of where the item is, and hence
- // is the appropriate point to use when determining drop location.
- private float[] getDragViewVisualCenter(int x, int y, int xOffset, int yOffset,
- DragView dragView, float[] recycle) {
- float res[];
- if (recycle == null) {
- res = new float[2];
- } else {
- res = recycle;
- }
-
- // First off, the drag view has been shifted in a way that is not represented in the
- // x and y values or the x/yOffsets. Here we account for that shift.
- x += getResources().getDimensionPixelSize(R.dimen.dragViewOffsetX);
- y += getResources().getDimensionPixelSize(R.dimen.dragViewOffsetY);
-
- // These represent the visual top and left of drag view if a dragRect was provided.
- // If a dragRect was not provided, then they correspond to the actual view left and
- // top, as the dragRect is in that case taken to be the entire dragView.
- // R.dimen.dragViewOffsetY.
- int left = x - xOffset;
- int top = y - yOffset;
-
- // In order to find the visual center, we shift by half the dragRect
- res[0] = left + dragView.getDragRegion().width() / 2;
- res[1] = top + dragView.getDragRegion().height() / 2;
-
- return res;
- }
-
private boolean isDragWidget(DragObject d) {
return (d.dragInfo instanceof LauncherAppWidgetInfo ||
d.dragInfo instanceof PendingAddWidgetInfo);
@@ -3624,8 +3124,7 @@ public class Workspace extends SmoothPagedView
// Ensure that we have proper spans for the item that we are dropping
if (item.spanX < 0 || item.spanY < 0) throw new RuntimeException("Improper spans found");
- mDragViewVisualCenter = getDragViewVisualCenter(d.x, d.y, d.xOffset, d.yOffset,
- d.dragView, mDragViewVisualCenter);
+ mDragViewVisualCenter = d.getVisualCenter(mDragViewVisualCenter);
final View child = (mDragInfo == null) ? null : mDragInfo.cell;
// Identify whether we have dragged over a side page
@@ -3700,7 +3199,7 @@ public class Workspace extends SmoothPagedView
mTargetCell[1]);
manageFolderFeedback(info, mDragTargetLayout, mTargetCell,
- targetCellDistance, dragOverView);
+ targetCellDistance, dragOverView, d.accessibleDrag);
boolean nearestDropOccupied = mDragTargetLayout.isNearestDropLocationOccupied((int)
mDragViewVisualCenter[0], (int) mDragViewVisualCenter[1], item.spanX,
@@ -3738,15 +3237,21 @@ public class Workspace extends SmoothPagedView
}
private void manageFolderFeedback(ItemInfo info, CellLayout targetLayout,
- int[] targetCell, float distance, View dragOverView) {
+ int[] targetCell, float distance, View dragOverView, boolean accessibleDrag) {
boolean userFolderPending = willCreateUserFolder(info, targetLayout, targetCell, distance,
false);
-
if (mDragMode == DRAG_MODE_NONE && userFolderPending &&
!mFolderCreationAlarm.alarmPending()) {
- mFolderCreationAlarm.setOnAlarmListener(new
- FolderCreationAlarmListener(targetLayout, targetCell[0], targetCell[1]));
- mFolderCreationAlarm.setAlarm(FOLDER_CREATION_TIMEOUT);
+
+ FolderCreationAlarmListener listener = new
+ FolderCreationAlarmListener(targetLayout, targetCell[0], targetCell[1]);
+
+ if (!accessibleDrag) {
+ mFolderCreationAlarm.setOnAlarmListener(listener);
+ mFolderCreationAlarm.setAlarm(FOLDER_CREATION_TIMEOUT);
+ } else {
+ listener.onAlarm(mFolderCreationAlarm);
+ }
return;
}
@@ -3950,26 +3455,14 @@ public class Workspace extends SmoothPagedView
// When dragging and dropping from customization tray, we deal with creating
// widgets/shortcuts/folders in a slightly different way
- switch (pendingInfo.itemType) {
- case LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET:
- int span[] = new int[2];
- span[0] = item.spanX;
- span[1] = item.spanY;
- mLauncher.addAppWidgetFromDrop((PendingAddWidgetInfo) pendingInfo,
- container, screenId, mTargetCell, span, null);
- break;
- case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
- mLauncher.processShortcutFromDrop(pendingInfo.componentName,
- container, screenId, mTargetCell, null);
- break;
- default:
- throw new IllegalStateException("Unknown item type: " +
- pendingInfo.itemType);
- }
+ mLauncher.addPendingItem(pendingInfo, container, screenId, mTargetCell,
+ item.spanX, item.spanY);
}
};
- View finalView = pendingInfo.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET
- ? ((PendingAddWidgetInfo) pendingInfo).boundWidget : null;
+ boolean isWidget = pendingInfo.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET
+ || pendingInfo.itemType == LauncherSettings.Favorites.ITEM_TYPE_CUSTOM_APPWIDGET;
+
+ View finalView = isWidget ? ((PendingAddWidgetInfo) pendingInfo).boundWidget : null;
if (finalView instanceof AppWidgetHostView && updateWidgetSize) {
AppWidgetHostView awhv = (AppWidgetHostView) finalView;
@@ -3978,7 +3471,7 @@ public class Workspace extends SmoothPagedView
}
int animationStyle = ANIMATE_INTO_POSITION_AND_DISAPPEAR;
- if (pendingInfo.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET &&
+ if (isWidget && ((PendingAddWidgetInfo) pendingInfo).info != null &&
((PendingAddWidgetInfo) pendingInfo).info.configure != null) {
animationStyle = ANIMATE_INTO_POSITION_AND_REMAIN;
}
@@ -3993,10 +3486,9 @@ public class Workspace extends SmoothPagedView
case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
if (info.container == NO_ID && info instanceof AppInfo) {
// Came from all apps -- make a copy
- info = new ShortcutInfo((AppInfo) info);
+ info = ((AppInfo) info).makeShortcut();
}
- view = mLauncher.createShortcut(R.layout.application, cellLayout,
- (ShortcutInfo) info);
+ view = mLauncher.createShortcut(cellLayout, (ShortcutInfo) info);
break;
case LauncherSettings.Favorites.ITEM_TYPE_FOLDER:
view = FolderIcon.fromXml(R.layout.folder_icon, mLauncher, cellLayout,
@@ -4055,8 +3547,7 @@ public class Workspace extends SmoothPagedView
}
public Bitmap createWidgetBitmap(ItemInfo widgetInfo, View layout) {
- int[] unScaledSize = mLauncher.getWorkspace().estimateItemSize(widgetInfo.spanX,
- widgetInfo.spanY, widgetInfo, false);
+ int[] unScaledSize = mLauncher.getWorkspace().estimateItemSize(widgetInfo, false);
int visibility = layout.getVisibility();
layout.setVisibility(VISIBLE);
@@ -4127,14 +3618,16 @@ public class Workspace extends SmoothPagedView
// In the case where we've prebound the widget, we remove it from the DragLayer
if (finalView instanceof AppWidgetHostView && external) {
- Log.d(TAG, "6557954 Animate widget drop, final view is appWidgetHostView");
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) {
Bitmap crossFadeBitmap = createWidgetBitmap(info, finalView);
dragView.setCrossFadeBitmap(crossFadeBitmap);
dragView.crossFade((int) (duration * 0.8f));
- } else if (info.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET && external) {
+ } else if (isWidget && external) {
scaleXY[0] = scaleXY[1] = Math.min(scaleXY[0], scaleXY[1]);
}
@@ -4170,8 +3663,8 @@ public class Workspace extends SmoothPagedView
public void setFinalTransitionTransform(CellLayout layout) {
if (isSwitchingState()) {
mCurrentScale = getScaleX();
- setScaleX(mNewScale);
- setScaleY(mNewScale);
+ setScaleX(mStateTransitionAnimation.getFinalScale());
+ setScaleY(mStateTransitionAnimation.getFinalScale());
}
}
public void resetTransitionTransform(CellLayout layout) {
@@ -4208,7 +3701,7 @@ public class Workspace extends SmoothPagedView
*
* pixelX and pixelY should be in the coordinate system of layout
*/
- private int[] findNearestArea(int pixelX, int pixelY,
+ @Thunk int[] findNearestArea(int pixelX, int pixelY,
int spanX, int spanY, CellLayout layout, int[] recycle) {
return layout.findNearestArea(
pixelX, pixelY, spanX, spanY, recycle);
@@ -4242,30 +3735,17 @@ public class Workspace extends SmoothPagedView
if (success && !(beingCalledAfterUninstall && !mUninstallSuccessful)) {
if (target != this && mDragInfo != null) {
- CellLayout parentCell = getParentCellLayoutForView(mDragInfo.cell);
- if (parentCell != null) {
- parentCell.removeView(mDragInfo.cell);
- } else if (LauncherAppState.isDogfoodBuild()) {
- throw new NullPointerException("mDragInfo.cell has null parent");
- }
- if (mDragInfo.cell instanceof DropTarget) {
- mDragController.removeDropTarget((DropTarget) mDragInfo.cell);
- }
+ removeWorkspaceItem(mDragInfo.cell);
}
} else if (mDragInfo != null) {
- CellLayout cellLayout;
- if (mLauncher.isHotseatLayout(target)) {
- cellLayout = mLauncher.getHotseat().getLayout();
- } else {
- cellLayout = getScreenWithId(mDragInfo.screenId);
- }
- if (cellLayout == null && LauncherAppState.isDogfoodBuild()) {
- throw new RuntimeException("Invalid state: cellLayout == null in "
- + "Workspace#onDropCompleted. Please file a bug. ");
- }
+ final CellLayout cellLayout = mLauncher.getCellLayout(
+ mDragInfo.container, mDragInfo.screenId);
if (cellLayout != null) {
cellLayout.onDropChild(mDragInfo.cell);
- }
+ } else if (LauncherAppState.isDogfoodBuild()) {
+ throw new RuntimeException("Invalid state: cellLayout == null in "
+ + "Workspace#onDropCompleted. Please file a bug. ");
+ };
}
if ((d.cancelled || (beingCalledAfterUninstall && !mUninstallSuccessful))
&& mDragInfo.cell != null) {
@@ -4275,11 +3755,28 @@ public class Workspace extends SmoothPagedView
mDragInfo = null;
}
+ /**
+ * For opposite operation. See {@link #addInScreen}.
+ */
+ public void removeWorkspaceItem(View v) {
+ CellLayout parentCell = getParentCellLayoutForView(v);
+ if (parentCell != null) {
+ parentCell.removeView(v);
+ } else if (LauncherAppState.isDogfoodBuild()) {
+ throw new NullPointerException("mDragInfo.cell has null parent");
+ }
+ if (v instanceof DropTarget) {
+ mDragController.removeDropTarget((DropTarget) v);
+ }
+ }
+
+ @Override
public void deferCompleteDropAfterUninstallActivity() {
mDeferDropAfterUninstall = true;
}
/// maybe move this into a smaller part
+ @Override
public void onUninstallActivityReturned(boolean success) {
mDeferDropAfterUninstall = false;
mUninstallSuccessful = success;
@@ -4311,88 +3808,6 @@ public class Workspace extends SmoothPagedView
}
}
- ArrayList<ComponentName> getUniqueComponents(boolean stripDuplicates, ArrayList<ComponentName> duplicates) {
- ArrayList<ComponentName> uniqueIntents = new ArrayList<ComponentName>();
- getUniqueIntents((CellLayout) mLauncher.getHotseat().getLayout(), uniqueIntents, duplicates, false);
- int count = getChildCount();
- for (int i = 0; i < count; i++) {
- CellLayout cl = (CellLayout) getChildAt(i);
- getUniqueIntents(cl, uniqueIntents, duplicates, false);
- }
- return uniqueIntents;
- }
-
- void getUniqueIntents(CellLayout cl, ArrayList<ComponentName> uniqueIntents,
- ArrayList<ComponentName> duplicates, boolean stripDuplicates) {
- int count = cl.getShortcutsAndWidgets().getChildCount();
-
- ArrayList<View> children = new ArrayList<View>();
- for (int i = 0; i < count; i++) {
- View v = cl.getShortcutsAndWidgets().getChildAt(i);
- children.add(v);
- }
-
- for (int i = 0; i < count; i++) {
- View v = children.get(i);
- ItemInfo info = (ItemInfo) v.getTag();
- // Null check required as the AllApps button doesn't have an item info
- if (info instanceof ShortcutInfo) {
- ShortcutInfo si = (ShortcutInfo) info;
- ComponentName cn = si.intent.getComponent();
-
- Uri dataUri = si.intent.getData();
- // If dataUri is not null / empty or if this component isn't one that would
- // have previously showed up in the AllApps list, then this is a widget-type
- // shortcut, so ignore it.
- if (dataUri != null && !dataUri.equals(Uri.EMPTY)) {
- continue;
- }
-
- if (!uniqueIntents.contains(cn)) {
- uniqueIntents.add(cn);
- } else {
- if (stripDuplicates) {
- cl.removeViewInLayout(v);
- LauncherModel.deleteItemFromDatabase(mLauncher, si);
- }
- if (duplicates != null) {
- duplicates.add(cn);
- }
- }
- }
- if (v instanceof FolderIcon) {
- FolderIcon fi = (FolderIcon) v;
- ArrayList<View> items = fi.getFolder().getItemsInReadingOrder();
- for (int j = 0; j < items.size(); j++) {
- if (items.get(j).getTag() instanceof ShortcutInfo) {
- ShortcutInfo si = (ShortcutInfo) items.get(j).getTag();
- ComponentName cn = si.intent.getComponent();
-
- Uri dataUri = si.intent.getData();
- // If dataUri is not null / empty or if this component isn't one that would
- // have previously showed up in the AllApps list, then this is a widget-type
- // shortcut, so ignore it.
- if (dataUri != null && !dataUri.equals(Uri.EMPTY)) {
- continue;
- }
-
- if (!uniqueIntents.contains(cn)) {
- uniqueIntents.add(cn);
- } else {
- if (stripDuplicates) {
- fi.getFolderInfo().remove(si);
- LauncherModel.deleteItemFromDatabase(mLauncher, si);
- }
- if (duplicates != null) {
- duplicates.add(cn);
- }
- }
- }
- }
- }
- }
- }
-
void saveWorkspaceToDb() {
saveWorkspaceScreenToDb((CellLayout) mLauncher.getHotseat().getLayout());
int count = getChildCount();
@@ -4425,8 +3840,7 @@ public class Workspace extends SmoothPagedView
cellX = hotseat.getCellXFromOrder((int) info.screenId);
cellY = hotseat.getCellYFromOrder((int) info.screenId);
}
- LauncherModel.addItemToDatabase(mLauncher, info, container, screenId, cellX,
- cellY, false);
+ LauncherModel.addItemToDatabase(mLauncher, info, container, screenId, cellX, cellY);
}
if (v instanceof FolderIcon) {
FolderIcon fi = (FolderIcon) v;
@@ -4456,7 +3870,7 @@ public class Workspace extends SmoothPagedView
}
@Override
- public void onFlingToDelete(DragObject d, int x, int y, PointF vec) {
+ public void onFlingToDelete(DragObject d, PointF vec) {
// Do nothing
}
@@ -4470,12 +3884,6 @@ public class Workspace extends SmoothPagedView
}
@Override
- protected void onRestoreInstanceState(Parcelable state) {
- super.onRestoreInstanceState(state);
- Launcher.setScreen(mCurrentPage);
- }
-
- @Override
protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) {
// We don't dispatch restoreInstanceState to our children using this code path.
// Some pages will be restored immediately as their items are bound immediately, and
@@ -4529,7 +3937,7 @@ public class Workspace extends SmoothPagedView
@Override
public boolean onEnterScrollArea(int x, int y, int direction) {
// Ignore the scroll area if we are dragging over the hot seat
- boolean isPortrait = !LauncherAppState.isScreenLandscape(getContext());
+ boolean isPortrait = !mLauncher.getDeviceProfile().isLandscape;
if (mLauncher.getHotseat() != null && isPortrait) {
Rect r = new Rect();
mLauncher.getHotseat().getHitRect(r);
@@ -4706,7 +4114,7 @@ public class Workspace extends SmoothPagedView
&& packageNames.contains(cn.getPackageName())) {
shortcutInfo.isDisabled |= reason;
BubbleTextView shortcut = (BubbleTextView) v;
- shortcut.applyFromShortcutInfo(shortcutInfo, mIconCache, true, false);
+ shortcut.applyFromShortcutInfo(shortcutInfo, mIconCache);
if (parent != null) {
parent.invalidate();
@@ -4890,9 +4298,9 @@ public class Workspace extends SmoothPagedView
updates.contains(info)) {
ShortcutInfo si = (ShortcutInfo) info;
BubbleTextView shortcut = (BubbleTextView) v;
- boolean oldPromiseState = shortcut.getCompoundDrawables()[1]
+ boolean oldPromiseState = getTextViewIcon(shortcut)
instanceof PreloadIconDrawable;
- shortcut.applyFromShortcutInfo(si, mIconCache, true,
+ shortcut.applyFromShortcutInfo(si, mIconCache,
si.isPromise() != oldPromiseState);
if (parent != null) {
@@ -4912,31 +4320,17 @@ public class Workspace extends SmoothPagedView
removeItemsByPackageName(packages, user);
}
- public void updatePackageBadge(final String packageName, final UserHandleCompat user) {
+ public void updateRestoreItems(final HashSet<ItemInfo> updates) {
mapOverItems(MAP_RECURSE, new ItemOperator() {
@Override
public boolean evaluate(ItemInfo info, View v, View parent) {
- if (info instanceof ShortcutInfo && v instanceof BubbleTextView) {
- ShortcutInfo shortcutInfo = (ShortcutInfo) info;
- ComponentName cn = shortcutInfo.getTargetComponent();
- if (user.equals(shortcutInfo.user) && cn != null
- && shortcutInfo.isPromise()
- && packageName.equals(cn.getPackageName())) {
- if (shortcutInfo.hasStatusFlag(ShortcutInfo.FLAG_AUTOINTALL_ICON)) {
- // For auto install apps update the icon as well as label.
- mIconCache.getTitleAndIcon(shortcutInfo,
- shortcutInfo.promisedIntent, user, true);
- } else {
- // Only update the icon for restored apps.
- shortcutInfo.updateIcon(mIconCache);
- }
- BubbleTextView shortcut = (BubbleTextView) v;
- shortcut.applyFromShortcutInfo(shortcutInfo, mIconCache, true, false);
-
- if (parent != null) {
- parent.invalidate();
- }
- }
+ if (info instanceof ShortcutInfo && v instanceof BubbleTextView
+ && updates.contains(info)) {
+ ((BubbleTextView) v).applyState(false);
+ } else if (v instanceof PendingAppWidgetHostView
+ && info instanceof LauncherAppWidgetInfo
+ && updates.contains(info)) {
+ ((PendingAppWidgetHostView) v).applyState();
}
// process all the shortcuts
return false;
@@ -4944,48 +4338,13 @@ public class Workspace extends SmoothPagedView
});
}
- public void updatePackageState(ArrayList<PackageInstallInfo> installInfos) {
- for (final PackageInstallInfo installInfo : installInfos) {
- if (installInfo.state == PackageInstallerCompat.STATUS_INSTALLED) {
- continue;
- }
-
- mapOverItems(MAP_RECURSE, new ItemOperator() {
- @Override
- public boolean evaluate(ItemInfo info, View v, View parent) {
- if (info instanceof ShortcutInfo && v instanceof BubbleTextView) {
- ShortcutInfo si = (ShortcutInfo) info;
- ComponentName cn = si.getTargetComponent();
- if (si.isPromise() && (cn != null)
- && installInfo.packageName.equals(cn.getPackageName())) {
- si.setInstallProgress(installInfo.progress);
- if (installInfo.state == PackageInstallerCompat.STATUS_FAILED) {
- // Mark this info as broken.
- si.status &= ~ShortcutInfo.FLAG_INSTALL_SESSION_ACTIVE;
- }
- ((BubbleTextView)v).applyState(false);
- }
- } else if (v instanceof PendingAppWidgetHostView
- && info instanceof LauncherAppWidgetInfo
- && ((LauncherAppWidgetInfo) info).providerName.getPackageName()
- .equals(installInfo.packageName)) {
- ((LauncherAppWidgetInfo) info).installProgress = installInfo.progress;
- ((PendingAppWidgetHostView) v).applyState();
- }
-
- // process all the shortcuts
- return false;
- }
- });
- }
- }
-
void widgetsRestored(ArrayList<LauncherAppWidgetInfo> changedInfo) {
if (!changedInfo.isEmpty()) {
DeferredWidgetRefresh widgetRefresh = new DeferredWidgetRefresh(changedInfo,
mLauncher.getAppWidgetHost());
- if (LauncherModel.findAppWidgetProviderInfoWithComponent(getContext(),
- changedInfo.get(0).providerName) != null) {
+ if (LauncherModel.getProviderInfo(getContext(),
+ changedInfo.get(0).providerName,
+ changedInfo.get(0).user) != null) {
// Re-inflate the widgets which have changed status
widgetRefresh.run();
} else {
@@ -5049,25 +4408,21 @@ public class Workspace extends SmoothPagedView
return super.getPageIndicatorMarker(pageIndex);
}
- @Override
- public void syncPages() {
- }
-
- @Override
- public void syncPageItems(int page, boolean immediate) {
- }
-
protected String getPageIndicatorDescription() {
String settings = getResources().getString(R.string.settings_button_text);
return getCurrentPageDescription() + ", " + settings;
}
protected String getCurrentPageDescription() {
- int page = (mNextPage != INVALID_PAGE) ? mNextPage : mCurrentPage;
- int delta = numCustomPages();
if (hasCustomContent() && getNextPage() == 0) {
return mCustomContentDescription;
}
+ int page = (mNextPage != INVALID_PAGE) ? mNextPage : mCurrentPage;
+ return getPageDescription(page);
+ }
+
+ private String getPageDescription(int page) {
+ int delta = numCustomPages();
return String.format(getContext().getString(R.string.workspace_scroll_format),
page + 1 - delta, getChildCount() - delta);
}
@@ -5076,6 +4431,12 @@ public class Workspace extends SmoothPagedView
mLauncher.getDragLayer().getLocationInDragLayer(this, loc);
}
+ @Override
+ public void fillInLaunchSourceData(Bundle sourceData) {
+ sourceData.putString(Stats.SOURCE_EXTRA_CONTAINER, Stats.CONTAINER_HOMESCREEN);
+ sourceData.putInt(Stats.SOURCE_EXTRA_CONTAINER_PAGE, getCurrentPage());
+ }
+
/**
* Used as a workaround to ensure that the AppWidgetService receives the
* PACKAGE_ADDED broadcast before updating widgets.
diff --git a/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java b/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java
new file mode 100644
index 000000000..b8916a72b
--- /dev/null
+++ b/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java
@@ -0,0 +1,587 @@
+/*
+ * 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;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.AnimatorSet;
+import android.animation.ObjectAnimator;
+import android.animation.TimeInterpolator;
+import android.animation.ValueAnimator;
+import android.content.Context;
+import android.content.res.Resources;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.accessibility.AccessibilityManager;
+import android.view.accessibility.AccessibilityNodeInfo;
+import android.view.animation.DecelerateInterpolator;
+
+import com.android.launcher3.util.Thunk;
+
+import java.util.HashMap;
+
+/**
+ * A convenience class to update a view's visibility state after an alpha animation.
+ */
+class AlphaUpdateListener extends AnimatorListenerAdapter implements ValueAnimator.AnimatorUpdateListener {
+ private static final float ALPHA_CUTOFF_THRESHOLD = 0.01f;
+
+ private View mView;
+ private boolean mAccessibilityEnabled;
+
+ public AlphaUpdateListener(View v, boolean accessibilityEnabled) {
+ mView = v;
+ mAccessibilityEnabled = accessibilityEnabled;
+ }
+
+ @Override
+ public void onAnimationUpdate(ValueAnimator arg0) {
+ updateVisibility(mView, mAccessibilityEnabled);
+ }
+
+ public static void updateVisibility(View view, boolean accessibilityEnabled) {
+ // We want to avoid the extra layout pass by setting the views to GONE unless
+ // accessibility is on, in which case not setting them to GONE causes a glitch.
+ int invisibleState = accessibilityEnabled ? View.GONE : View.INVISIBLE;
+ if (view.getAlpha() < ALPHA_CUTOFF_THRESHOLD && view.getVisibility() != invisibleState) {
+ view.setVisibility(invisibleState);
+ } else if (view.getAlpha() > ALPHA_CUTOFF_THRESHOLD
+ && view.getVisibility() != View.VISIBLE) {
+ view.setVisibility(View.VISIBLE);
+ }
+ }
+
+ @Override
+ public void onAnimationEnd(Animator arg0) {
+ updateVisibility(mView, mAccessibilityEnabled);
+ }
+
+ @Override
+ public void onAnimationStart(Animator arg0) {
+ // We want the views to be visible for animation, so fade-in/out is visible
+ mView.setVisibility(View.VISIBLE);
+ }
+}
+
+/**
+ * This interpolator emulates the rate at which the perceived scale of an object changes
+ * as its distance from a camera increases. When this interpolator is applied to a scale
+ * animation on a view, it evokes the sense that the object is shrinking due to moving away
+ * from the camera.
+ */
+class ZInterpolator implements TimeInterpolator {
+ private float focalLength;
+
+ public ZInterpolator(float foc) {
+ focalLength = foc;
+ }
+
+ public float getInterpolation(float input) {
+ return (1.0f - focalLength / (focalLength + input)) /
+ (1.0f - focalLength / (focalLength + 1.0f));
+ }
+}
+
+/**
+ * The exact reverse of ZInterpolator.
+ */
+class InverseZInterpolator implements TimeInterpolator {
+ private ZInterpolator zInterpolator;
+ public InverseZInterpolator(float foc) {
+ zInterpolator = new ZInterpolator(foc);
+ }
+ public float getInterpolation(float input) {
+ return 1 - zInterpolator.getInterpolation(1 - input);
+ }
+}
+
+/**
+ * InverseZInterpolator compounded with an ease-out.
+ */
+class ZoomInInterpolator implements TimeInterpolator {
+ private final InverseZInterpolator inverseZInterpolator = new InverseZInterpolator(0.35f);
+ private final DecelerateInterpolator decelerate = new DecelerateInterpolator(3.0f);
+
+ public float getInterpolation(float input) {
+ return decelerate.getInterpolation(inverseZInterpolator.getInterpolation(input));
+ }
+}
+
+/**
+ * Stores the transition states for convenience.
+ */
+class TransitionStates {
+
+ // Raw states
+ final boolean oldStateIsNormal;
+ final boolean oldStateIsSpringLoaded;
+ final boolean oldStateIsNormalHidden;
+ final boolean oldStateIsOverviewHidden;
+ final boolean oldStateIsOverview;
+
+ final boolean stateIsNormal;
+ final boolean stateIsSpringLoaded;
+ final boolean stateIsNormalHidden;
+ final boolean stateIsOverviewHidden;
+ final boolean stateIsOverview;
+
+ // Convenience members
+ final boolean workspaceToAllApps;
+ final boolean overviewToAllApps;
+ final boolean allAppsToWorkspace;
+ final boolean workspaceToOverview;
+ final boolean overviewToWorkspace;
+
+ public TransitionStates(final Workspace.State fromState, final Workspace.State toState) {
+ oldStateIsNormal = (fromState == Workspace.State.NORMAL);
+ oldStateIsSpringLoaded = (fromState == Workspace.State.SPRING_LOADED);
+ oldStateIsNormalHidden = (fromState == Workspace.State.NORMAL_HIDDEN);
+ oldStateIsOverviewHidden = (fromState == Workspace.State.OVERVIEW_HIDDEN);
+ oldStateIsOverview = (fromState == Workspace.State.OVERVIEW);
+
+ stateIsNormal = (toState == Workspace.State.NORMAL);
+ stateIsSpringLoaded = (toState == Workspace.State.SPRING_LOADED);
+ stateIsNormalHidden = (toState == Workspace.State.NORMAL_HIDDEN);
+ stateIsOverviewHidden = (toState == Workspace.State.OVERVIEW_HIDDEN);
+ stateIsOverview = (toState == Workspace.State.OVERVIEW);
+
+ workspaceToOverview = (oldStateIsNormal && stateIsOverview);
+ workspaceToAllApps = (oldStateIsNormal && stateIsNormalHidden);
+ overviewToWorkspace = (oldStateIsOverview && stateIsNormal);
+ overviewToAllApps = (oldStateIsOverview && stateIsOverviewHidden);
+ allAppsToWorkspace = (stateIsNormalHidden && stateIsNormal);
+ }
+}
+
+/**
+ * Manages the animations between each of the workspace states.
+ */
+public class WorkspaceStateTransitionAnimation {
+
+ public static final String TAG = "WorkspaceStateTransitionAnimation";
+
+ public static final int SCROLL_TO_CURRENT_PAGE = -1;
+ @Thunk static final int BACKGROUND_FADE_OUT_DURATION = 350;
+
+ final @Thunk Launcher mLauncher;
+ final @Thunk Workspace mWorkspace;
+
+ @Thunk AnimatorSet mStateAnimator;
+ @Thunk float[] mOldBackgroundAlphas;
+ @Thunk float[] mOldAlphas;
+ @Thunk float[] mNewBackgroundAlphas;
+ @Thunk float[] mNewAlphas;
+ @Thunk int mLastChildCount = -1;
+
+ @Thunk float mCurrentScale;
+ @Thunk float mNewScale;
+
+ @Thunk final ZoomInInterpolator mZoomInInterpolator = new ZoomInInterpolator();
+
+ @Thunk float mSpringLoadedShrinkFactor;
+ @Thunk float mOverviewModeShrinkFactor;
+ @Thunk float mWorkspaceScrimAlpha;
+ @Thunk int mAllAppsTransitionTime;
+ @Thunk int mOverviewTransitionTime;
+ @Thunk int mOverlayTransitionTime;
+ @Thunk boolean mWorkspaceFadeInAdjacentScreens;
+
+ public WorkspaceStateTransitionAnimation(Launcher launcher, Workspace workspace) {
+ mLauncher = launcher;
+ mWorkspace = workspace;
+
+ DeviceProfile grid = mLauncher.getDeviceProfile();
+ Resources res = launcher.getResources();
+ mAllAppsTransitionTime = res.getInteger(R.integer.config_allAppsTransitionTime);
+ mOverviewTransitionTime = res.getInteger(R.integer.config_overviewTransitionTime);
+ mOverlayTransitionTime = res.getInteger(R.integer.config_overlayTransitionTime);
+ mSpringLoadedShrinkFactor =
+ res.getInteger(R.integer.config_workspaceSpringLoadShrinkPercentage) / 100f;
+ mWorkspaceScrimAlpha = res.getInteger(R.integer.config_workspaceScrimAlpha) / 100f;
+ mOverviewModeShrinkFactor = grid.getOverviewModeScale(Utilities.isRtl(res));
+ mWorkspaceFadeInAdjacentScreens = grid.shouldFadeAdjacentWorkspaceScreens();
+ }
+
+ public AnimatorSet getAnimationToState(Workspace.State fromState, Workspace.State toState,
+ int toPage, boolean animated, boolean hasOverlaySearchBar,
+ HashMap<View, Integer> layerViews) {
+ AccessibilityManager am = (AccessibilityManager)
+ mLauncher.getSystemService(Context.ACCESSIBILITY_SERVICE);
+ final boolean accessibilityEnabled = am.isEnabled();
+ TransitionStates states = new TransitionStates(fromState, toState);
+ int duration = getAnimationDuration(states);
+ animateWorkspace(states, toPage, animated, duration, layerViews,
+ accessibilityEnabled);
+ animateSearchBar(states, animated, duration, hasOverlaySearchBar, layerViews,
+ accessibilityEnabled);
+ animateBackgroundGradient(states, animated, BACKGROUND_FADE_OUT_DURATION);
+ return mStateAnimator;
+ }
+
+ public float getFinalScale() {
+ return mNewScale;
+ }
+
+ /**
+ * Reinitializes the arrays that we need for the animations on each page.
+ */
+ private void reinitializeAnimationArrays() {
+ final int childCount = mWorkspace.getChildCount();
+ if (mLastChildCount == childCount) return;
+
+ mOldBackgroundAlphas = new float[childCount];
+ mOldAlphas = new float[childCount];
+ mNewBackgroundAlphas = new float[childCount];
+ mNewAlphas = new float[childCount];
+ }
+
+ /**
+ * Returns the proper animation duration for a transition.
+ */
+ private int getAnimationDuration(TransitionStates states) {
+ if (states.workspaceToAllApps || states.overviewToAllApps) {
+ return mAllAppsTransitionTime;
+ } else if (states.workspaceToOverview || states.overviewToWorkspace) {
+ return mOverviewTransitionTime;
+ } else {
+ return mOverlayTransitionTime;
+ }
+ }
+
+ /**
+ * Starts a transition animation for the workspace.
+ */
+ private void animateWorkspace(final TransitionStates states, int toPage, final boolean animated,
+ final int duration, final HashMap<View, Integer> layerViews,
+ final boolean accessibilityEnabled) {
+ // Reinitialize animation arrays for the current workspace state
+ reinitializeAnimationArrays();
+
+ // Cancel existing workspace animations and create a new animator set if requested
+ cancelAnimation();
+ if (animated) {
+ mStateAnimator = LauncherAnimUtils.createAnimatorSet();
+ }
+
+ // Update the workspace state
+ float finalBackgroundAlpha = (states.stateIsSpringLoaded || states.stateIsOverview) ?
+ 1.0f : 0f;
+ float finalHotseatAndPageIndicatorAlpha = (states.stateIsNormal || states.stateIsSpringLoaded) ?
+ 1f : 0f;
+ float finalOverviewPanelAlpha = states.stateIsOverview ? 1f : 0f;
+ float finalWorkspaceTranslationY = states.stateIsOverview || states.stateIsOverviewHidden ?
+ mWorkspace.getOverviewModeTranslationY() : 0;
+
+ final int childCount = mWorkspace.getChildCount();
+ final int customPageCount = mWorkspace.numCustomPages();
+
+ mNewScale = 1.0f;
+
+ if (states.oldStateIsOverview) {
+ mWorkspace.disableFreeScroll();
+ } else if (states.stateIsOverview) {
+ mWorkspace.enableFreeScroll();
+ }
+
+ if (!states.stateIsNormal) {
+ if (states.stateIsSpringLoaded) {
+ mNewScale = mSpringLoadedShrinkFactor;
+ } else if (states.stateIsOverview || states.stateIsOverviewHidden) {
+ mNewScale = mOverviewModeShrinkFactor;
+ }
+ }
+
+ if (toPage == SCROLL_TO_CURRENT_PAGE) {
+ toPage = mWorkspace.getPageNearestToCenterOfScreen();
+ }
+ mWorkspace.snapToPage(toPage, duration, mZoomInInterpolator);
+
+ for (int i = 0; i < childCount; i++) {
+ final CellLayout cl = (CellLayout) mWorkspace.getChildAt(i);
+ boolean isCurrentPage = (i == toPage);
+ float initialAlpha = cl.getShortcutsAndWidgets().getAlpha();
+ float finalAlpha;
+ if (states.stateIsNormalHidden || states.stateIsOverviewHidden) {
+ finalAlpha = 0f;
+ } else if (states.stateIsNormal && mWorkspaceFadeInAdjacentScreens) {
+ finalAlpha = (i == toPage || i < customPageCount) ? 1f : 0f;
+ } else {
+ finalAlpha = 1f;
+ }
+
+ // If we are animating to/from the small state, then hide the side pages and fade the
+ // current page in
+ if (!mWorkspace.isSwitchingState()) {
+ if (states.workspaceToAllApps || states.allAppsToWorkspace) {
+ if (states.allAppsToWorkspace && isCurrentPage) {
+ initialAlpha = 0f;
+ } else if (!isCurrentPage) {
+ initialAlpha = finalAlpha = 0f;
+ }
+ cl.setShortcutAndWidgetAlpha(initialAlpha);
+ }
+ }
+
+ mOldAlphas[i] = initialAlpha;
+ mNewAlphas[i] = finalAlpha;
+ if (animated) {
+ mOldBackgroundAlphas[i] = cl.getBackgroundAlpha();
+ mNewBackgroundAlphas[i] = finalBackgroundAlpha;
+ } else {
+ cl.setBackgroundAlpha(finalBackgroundAlpha);
+ cl.setShortcutAndWidgetAlpha(finalAlpha);
+ }
+ }
+
+ final ViewGroup overviewPanel = mLauncher.getOverviewPanel();
+ final View hotseat = mLauncher.getHotseat();
+ final View pageIndicator = mWorkspace.getPageIndicator();
+ if (animated) {
+ LauncherViewPropertyAnimator scale = new LauncherViewPropertyAnimator(mWorkspace);
+ scale.scaleX(mNewScale)
+ .scaleY(mNewScale)
+ .translationY(finalWorkspaceTranslationY)
+ .setDuration(duration)
+ .setInterpolator(mZoomInInterpolator);
+ mStateAnimator.play(scale);
+ for (int index = 0; index < childCount; index++) {
+ final int i = index;
+ final CellLayout cl = (CellLayout) mWorkspace.getChildAt(i);
+ float currentAlpha = cl.getShortcutsAndWidgets().getAlpha();
+ if (mOldAlphas[i] == 0 && mNewAlphas[i] == 0) {
+ cl.setBackgroundAlpha(mNewBackgroundAlphas[i]);
+ cl.setShortcutAndWidgetAlpha(mNewAlphas[i]);
+ } else {
+ if (layerViews != null) {
+ layerViews.put(cl, LauncherStateTransitionAnimation.BUILD_LAYER);
+ }
+ if (mOldAlphas[i] != mNewAlphas[i] || currentAlpha != mNewAlphas[i]) {
+ LauncherViewPropertyAnimator alphaAnim =
+ new LauncherViewPropertyAnimator(cl.getShortcutsAndWidgets());
+ alphaAnim.alpha(mNewAlphas[i])
+ .setDuration(duration)
+ .setInterpolator(mZoomInInterpolator);
+ mStateAnimator.play(alphaAnim);
+ }
+ if (mOldBackgroundAlphas[i] != 0 ||
+ mNewBackgroundAlphas[i] != 0) {
+ ValueAnimator bgAnim = ObjectAnimator.ofFloat(cl, "backgroundAlpha",
+ mOldBackgroundAlphas[i], mNewBackgroundAlphas[i]);
+ LauncherAnimUtils.ofFloat(cl, 0f, 1f);
+ bgAnim.setInterpolator(mZoomInInterpolator);
+ bgAnim.setDuration(duration);
+ mStateAnimator.play(bgAnim);
+ }
+ }
+ }
+ Animator pageIndicatorAlpha;
+ if (pageIndicator != null) {
+ pageIndicatorAlpha = new LauncherViewPropertyAnimator(pageIndicator)
+ .alpha(finalHotseatAndPageIndicatorAlpha).withLayer();
+ pageIndicatorAlpha.addListener(new AlphaUpdateListener(pageIndicator,
+ accessibilityEnabled));
+ } else {
+ // create a dummy animation so we don't need to do null checks later
+ pageIndicatorAlpha = ValueAnimator.ofFloat(0, 0);
+ }
+
+ LauncherViewPropertyAnimator hotseatAlpha = new LauncherViewPropertyAnimator(hotseat)
+ .alpha(finalHotseatAndPageIndicatorAlpha);
+ hotseatAlpha.addListener(new AlphaUpdateListener(hotseat, accessibilityEnabled));
+
+ LauncherViewPropertyAnimator overviewPanelAlpha =
+ new LauncherViewPropertyAnimator(overviewPanel).alpha(finalOverviewPanelAlpha);
+ overviewPanelAlpha.addListener(new AlphaUpdateListener(overviewPanel,
+ accessibilityEnabled));
+
+ // For animation optimations, we may need to provide the Launcher transition
+ // with a set of views on which to force build layers in certain scenarios.
+ hotseat.setLayerType(View.LAYER_TYPE_HARDWARE, null);
+ overviewPanel.setLayerType(View.LAYER_TYPE_HARDWARE, null);
+ if (layerViews != null) {
+ // If layerViews is not null, we add these views, and indicate that
+ // the caller can manage layer state.
+ layerViews.put(hotseat, LauncherStateTransitionAnimation.BUILD_AND_SET_LAYER);
+ layerViews.put(overviewPanel, LauncherStateTransitionAnimation.BUILD_AND_SET_LAYER);
+ } else {
+ // Otherwise let the animator handle layer management.
+ hotseatAlpha.withLayer();
+ overviewPanelAlpha.withLayer();
+ }
+
+ if (states.workspaceToOverview) {
+ pageIndicatorAlpha.setInterpolator(new DecelerateInterpolator(2));
+ hotseatAlpha.setInterpolator(new DecelerateInterpolator(2));
+ overviewPanelAlpha.setInterpolator(null);
+ } else if (states.overviewToWorkspace) {
+ pageIndicatorAlpha.setInterpolator(null);
+ hotseatAlpha.setInterpolator(null);
+ overviewPanelAlpha.setInterpolator(new DecelerateInterpolator(2));
+ }
+
+ overviewPanelAlpha.setDuration(duration);
+ pageIndicatorAlpha.setDuration(duration);
+ hotseatAlpha.setDuration(duration);
+
+ mStateAnimator.play(overviewPanelAlpha);
+ mStateAnimator.play(hotseatAlpha);
+ mStateAnimator.play(pageIndicatorAlpha);
+ mStateAnimator.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ mStateAnimator = null;
+
+ if (accessibilityEnabled && overviewPanel.getVisibility() == View.VISIBLE) {
+ overviewPanel.getChildAt(0).performAccessibilityAction(
+ AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS, null);
+ }
+ }
+ });
+ } else {
+ overviewPanel.setAlpha(finalOverviewPanelAlpha);
+ AlphaUpdateListener.updateVisibility(overviewPanel, accessibilityEnabled);
+ hotseat.setAlpha(finalHotseatAndPageIndicatorAlpha);
+ AlphaUpdateListener.updateVisibility(hotseat, accessibilityEnabled);
+ if (pageIndicator != null) {
+ pageIndicator.setAlpha(finalHotseatAndPageIndicatorAlpha);
+ AlphaUpdateListener.updateVisibility(pageIndicator, accessibilityEnabled);
+ }
+ mWorkspace.updateCustomContentVisibility();
+ mWorkspace.setScaleX(mNewScale);
+ mWorkspace.setScaleY(mNewScale);
+ mWorkspace.setTranslationY(finalWorkspaceTranslationY);
+
+ if (accessibilityEnabled && overviewPanel.getVisibility() == View.VISIBLE) {
+ overviewPanel.getChildAt(0).performAccessibilityAction(
+ AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS, null);
+ }
+ }
+ }
+
+ /**
+ * Coordinates with the workspace animation to animate the search bar.
+ *
+ * TODO: This should really be coordinated with the SearchDropTargetBar, otherwise the
+ * bar has no idea that it is hidden, and this has no idea what state the bar is
+ * actually in.
+ */
+ private void animateSearchBar(TransitionStates states, boolean animated, int duration,
+ boolean hasOverlaySearchBar, final HashMap<View, Integer> layerViews,
+ final boolean accessibilityEnabled) {
+
+ // The search bar is only visible in the workspace
+ final View searchBar = mLauncher.getOrCreateQsbBar();
+ if (searchBar != null) {
+ final boolean searchBarWillBeShown = states.stateIsNormal;
+ final float finalSearchBarAlpha = searchBarWillBeShown ? 1f : 0f;
+ if (animated) {
+ if (hasOverlaySearchBar) {
+ // If there is an overlay search bar, then we will coordinate with it.
+ mStateAnimator.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationStart(Animator animation) {
+ // If we are transitioning to a visible search bar, show it immediately
+ // and let the overlay search bar has faded out
+ if (searchBarWillBeShown) {
+ searchBar.setAlpha(finalSearchBarAlpha);
+ AlphaUpdateListener.updateVisibility(searchBar, accessibilityEnabled);
+ }
+ }
+
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ // If we are transitioning to a hidden search bar, hide it only after
+ // the overlay search bar has faded in
+ if (!searchBarWillBeShown) {
+ searchBar.setAlpha(finalSearchBarAlpha);
+ AlphaUpdateListener.updateVisibility(searchBar, accessibilityEnabled);
+ }
+ }
+ });
+ } else {
+ // Otherwise, we can just do the normal animation
+ LauncherViewPropertyAnimator searchBarAlpha =
+ new LauncherViewPropertyAnimator(searchBar).alpha(finalSearchBarAlpha);
+ searchBarAlpha.addListener(new AlphaUpdateListener(searchBar,
+ accessibilityEnabled));
+ searchBar.setLayerType(View.LAYER_TYPE_HARDWARE, null);
+ if (layerViews != null) {
+ // If layerViews is not null, we add these views, and indicate that
+ // the caller can manage layer state.
+ layerViews.put(searchBar, LauncherStateTransitionAnimation.BUILD_AND_SET_LAYER);
+ } else {
+ // Otherwise let the animator handle layer management.
+ searchBarAlpha.withLayer();
+ }
+ searchBarAlpha.setDuration(duration);
+ mStateAnimator.play(searchBarAlpha);
+ }
+ } else {
+ // Set the search bar state immediately
+ searchBar.setAlpha(finalSearchBarAlpha);
+ AlphaUpdateListener.updateVisibility(searchBar, accessibilityEnabled);
+ }
+ }
+ }
+
+ /**
+ * Animates the background scrim. Add to the state animator to prevent jankiness.
+ *
+ * @param finalAlpha the final alpha for the background scrim
+ * @param animated whether or not to set the background alpha immediately
+ * @duration duration of the animation
+ */
+ private void animateBackgroundGradient(TransitionStates states,
+ boolean animated, int duration) {
+
+ final DragLayer dragLayer = mLauncher.getDragLayer();
+ final float startAlpha = dragLayer.getBackgroundAlpha();
+ float finalAlpha = states.stateIsNormal ? 0 : mWorkspaceScrimAlpha;
+
+ if (finalAlpha != startAlpha) {
+ if (animated) {
+ // These properties refer to the background protection gradient used for AllApps
+ // and Widget tray.
+ ValueAnimator bgFadeOutAnimation =
+ LauncherAnimUtils.ofFloat(mWorkspace, startAlpha, finalAlpha);
+ bgFadeOutAnimation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+ @Override
+ public void onAnimationUpdate(ValueAnimator animation) {
+ dragLayer.setBackgroundAlpha(
+ ((Float)animation.getAnimatedValue()).floatValue());
+ }
+ });
+ bgFadeOutAnimation.setInterpolator(new DecelerateInterpolator(1.5f));
+ bgFadeOutAnimation.setDuration(duration);
+ mStateAnimator.play(bgFadeOutAnimation);
+ } else {
+ dragLayer.setBackgroundAlpha(finalAlpha);
+ }
+ }
+ }
+
+ /**
+ * Cancels the current animation.
+ */
+ private void cancelAnimation() {
+ if (mStateAnimator != null) {
+ mStateAnimator.setDuration(0);
+ mStateAnimator.cancel();
+ }
+ mStateAnimator = null;
+ }
+} \ No newline at end of file
diff --git a/src/com/android/launcher3/accessibility/DragAndDropAccessibilityDelegate.java b/src/com/android/launcher3/accessibility/DragAndDropAccessibilityDelegate.java
new file mode 100644
index 000000000..78accf720
--- /dev/null
+++ b/src/com/android/launcher3/accessibility/DragAndDropAccessibilityDelegate.java
@@ -0,0 +1,136 @@
+/*
+ * 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.graphics.Rect;
+import android.os.Bundle;
+import android.support.v4.view.accessibility.AccessibilityNodeInfoCompat;
+import android.support.v4.widget.ExploreByTouchHelper;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.accessibility.AccessibilityEvent;
+
+import com.android.launcher3.CellLayout;
+import com.android.launcher3.LauncherAppState;
+import com.android.launcher3.R;
+
+import java.util.List;
+
+/**
+ * Helper class to make drag-and-drop in a {@link CellLayout} accessible.
+ */
+public abstract class DragAndDropAccessibilityDelegate extends ExploreByTouchHelper
+ implements OnClickListener {
+ protected static final int INVALID_POSITION = -1;
+
+ private static final int[] sTempArray = new int[2];
+
+ protected final CellLayout mView;
+ protected final Context mContext;
+ protected final LauncherAccessibilityDelegate mDelegate;
+
+ private final Rect mTempRect = new Rect();
+
+ public DragAndDropAccessibilityDelegate(CellLayout forView) {
+ super(forView);
+ mView = forView;
+ mContext = mView.getContext();
+ mDelegate = LauncherAppState.getInstance().getAccessibilityDelegate();
+ }
+
+ @Override
+ protected int getVirtualViewAt(float x, float y) {
+ if (x < 0 || y < 0 || x > mView.getMeasuredWidth() || y > mView.getMeasuredHeight()) {
+ return INVALID_ID;
+ }
+ mView.pointToCellExact((int) x, (int) y, sTempArray);
+
+ // Map cell to id
+ int id = sTempArray[0] + sTempArray[1] * mView.getCountX();
+ return intersectsValidDropTarget(id);
+ }
+
+ /**
+ * @return the view id of the top left corner of a valid drop region or
+ * {@link #INVALID_POSITION} if there is no such valid region.
+ */
+ protected abstract int intersectsValidDropTarget(int id);
+
+ @Override
+ protected void getVisibleVirtualViews(List<Integer> virtualViews) {
+ // We create a virtual view for each cell of the grid
+ // The cell ids correspond to cells in reading order.
+ int nCells = mView.getCountX() * mView.getCountY();
+
+ for (int i = 0; i < nCells; i++) {
+ if (intersectsValidDropTarget(i) == i) {
+ virtualViews.add(i);
+ }
+ }
+ }
+
+ @Override
+ protected boolean onPerformActionForVirtualView(int viewId, int action, Bundle args) {
+ if (action == AccessibilityNodeInfoCompat.ACTION_CLICK && viewId != INVALID_ID) {
+ String confirmation = getConfirmationForIconDrop(viewId);
+ mDelegate.handleAccessibleDrop(mView, getItemBounds(viewId), confirmation);
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public void onClick(View v) {
+ onPerformActionForVirtualView(getFocusedVirtualView(),
+ AccessibilityNodeInfoCompat.ACTION_CLICK, null);
+ }
+
+ @Override
+ protected void onPopulateEventForVirtualView(int id, AccessibilityEvent event) {
+ if (id == INVALID_ID) {
+ throw new IllegalArgumentException("Invalid virtual view id");
+ }
+ event.setContentDescription(mContext.getString(R.string.action_move_here));
+ }
+
+ @Override
+ protected void onPopulateNodeForVirtualView(int id, AccessibilityNodeInfoCompat node) {
+ if (id == INVALID_ID) {
+ throw new IllegalArgumentException("Invalid virtual view id");
+ }
+
+ node.setContentDescription(getLocationDescriptionForIconDrop(id));
+ node.setBoundsInParent(getItemBounds(id));
+
+ node.addAction(AccessibilityNodeInfoCompat.ACTION_CLICK);
+ node.setClickable(true);
+ node.setFocusable(true);
+ }
+
+ protected abstract String getLocationDescriptionForIconDrop(int id);
+
+ protected abstract String getConfirmationForIconDrop(int id);
+
+ private Rect getItemBounds(int id) {
+ int cellX = id % mView.getCountX();
+ int cellY = id / mView.getCountX();
+ LauncherAccessibilityDelegate.DragInfo dragInfo = mDelegate.getDragInfo();
+ mView.cellToRect(cellX, cellY, dragInfo.info.spanX, dragInfo.info.spanY, mTempRect);
+ return mTempRect;
+ }
+} \ No newline at end of file
diff --git a/src/com/android/launcher3/accessibility/FolderAccessibilityHelper.java b/src/com/android/launcher3/accessibility/FolderAccessibilityHelper.java
new file mode 100644
index 000000000..ff9989036
--- /dev/null
+++ b/src/com/android/launcher3/accessibility/FolderAccessibilityHelper.java
@@ -0,0 +1,56 @@
+/*
+ * 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 com.android.launcher3.CellLayout;
+import com.android.launcher3.FolderPagedView;
+import com.android.launcher3.R;
+
+/**
+ * Implementation of {@link DragAndDropAccessibilityDelegate} to support DnD in a folder.
+ */
+public class FolderAccessibilityHelper extends DragAndDropAccessibilityDelegate {
+
+ /**
+ * 0-index position for the first cell in {@link #mView} in {@link #mParent}.
+ */
+ private final int mStartPosition;
+
+ private final FolderPagedView mParent;
+
+ public FolderAccessibilityHelper(CellLayout layout) {
+ super(layout);
+ mParent = (FolderPagedView) layout.getParent();
+
+ int index = mParent.indexOfChild(layout);
+ mStartPosition = index * layout.getCountX() * layout.getCountY();
+ }
+ @Override
+ protected int intersectsValidDropTarget(int id) {
+ return Math.min(id, mParent.getAllocatedContentSize() - mStartPosition - 1);
+ }
+
+ @Override
+ protected String getLocationDescriptionForIconDrop(int id) {
+ return mContext.getString(R.string.move_to_position, id + mStartPosition + 1);
+ }
+
+ @Override
+ protected String getConfirmationForIconDrop(int id) {
+ return mContext.getString(R.string.item_moved);
+ }
+}
diff --git a/src/com/android/launcher3/accessibility/LauncherAccessibilityDelegate.java b/src/com/android/launcher3/accessibility/LauncherAccessibilityDelegate.java
new file mode 100644
index 000000000..fe7b25edd
--- /dev/null
+++ b/src/com/android/launcher3/accessibility/LauncherAccessibilityDelegate.java
@@ -0,0 +1,434 @@
+package com.android.launcher3.accessibility;
+
+import android.annotation.TargetApi;
+import android.app.AlertDialog;
+import android.appwidget.AppWidgetProviderInfo;
+import android.content.DialogInterface;
+import android.graphics.Rect;
+import android.os.Build;
+import android.os.Bundle;
+import android.os.Handler;
+import android.text.TextUtils;
+import android.util.Log;
+import android.util.SparseArray;
+import android.view.View;
+import android.view.View.AccessibilityDelegate;
+import android.view.accessibility.AccessibilityNodeInfo;
+import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
+
+import com.android.launcher3.AppInfo;
+import com.android.launcher3.AppWidgetResizeFrame;
+import com.android.launcher3.CellLayout;
+import com.android.launcher3.DeleteDropTarget;
+import com.android.launcher3.DragController.DragListener;
+import com.android.launcher3.DragSource;
+import com.android.launcher3.Folder;
+import com.android.launcher3.FolderInfo;
+import com.android.launcher3.InfoDropTarget;
+import com.android.launcher3.ItemInfo;
+import com.android.launcher3.Launcher;
+import com.android.launcher3.LauncherAppWidgetHostView;
+import com.android.launcher3.LauncherAppWidgetInfo;
+import com.android.launcher3.LauncherModel;
+import com.android.launcher3.LauncherSettings;
+import com.android.launcher3.PendingAddItemInfo;
+import com.android.launcher3.R;
+import com.android.launcher3.ShortcutInfo;
+import com.android.launcher3.UninstallDropTarget;
+import com.android.launcher3.Workspace;
+import com.android.launcher3.util.Thunk;
+
+import java.util.ArrayList;
+
+@TargetApi(Build.VERSION_CODES.LOLLIPOP)
+public class LauncherAccessibilityDelegate extends AccessibilityDelegate implements DragListener {
+
+ private static final String TAG = "LauncherAccessibilityDelegate";
+
+ private static final int REMOVE = R.id.action_remove;
+ private static final int INFO = R.id.action_info;
+ private static final int UNINSTALL = R.id.action_uninstall;
+ private static final int ADD_TO_WORKSPACE = R.id.action_add_to_workspace;
+ private static final int MOVE = R.id.action_move;
+ private static final int MOVE_TO_WORKSPACE = R.id.action_move_to_workspace;
+ private static final int RESIZE = R.id.action_resize;
+
+ public enum DragType {
+ ICON,
+ FOLDER,
+ WIDGET
+ }
+
+ public static class DragInfo {
+ public DragType dragType;
+ public ItemInfo info;
+ public View item;
+ }
+
+ private final SparseArray<AccessibilityAction> mActions = new SparseArray<>();
+ @Thunk final Launcher mLauncher;
+
+ private DragInfo mDragInfo = null;
+ private AccessibilityDragSource mDragSource = null;
+
+ public LauncherAccessibilityDelegate(Launcher launcher) {
+ mLauncher = launcher;
+
+ mActions.put(REMOVE, new AccessibilityAction(REMOVE,
+ launcher.getText(R.string.delete_target_label)));
+ mActions.put(INFO, new AccessibilityAction(INFO,
+ launcher.getText(R.string.info_target_label)));
+ mActions.put(UNINSTALL, new AccessibilityAction(UNINSTALL,
+ launcher.getText(R.string.delete_target_uninstall_label)));
+ mActions.put(ADD_TO_WORKSPACE, new AccessibilityAction(ADD_TO_WORKSPACE,
+ launcher.getText(R.string.action_add_to_workspace)));
+ mActions.put(MOVE, new AccessibilityAction(MOVE,
+ launcher.getText(R.string.action_move)));
+ mActions.put(MOVE_TO_WORKSPACE, new AccessibilityAction(MOVE_TO_WORKSPACE,
+ launcher.getText(R.string.action_move_to_workspace)));
+ mActions.put(RESIZE, new AccessibilityAction(RESIZE,
+ launcher.getText(R.string.action_resize)));
+ }
+
+ @Override
+ public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
+ super.onInitializeAccessibilityNodeInfo(host, info);
+ if (!(host.getTag() instanceof ItemInfo)) return;
+ ItemInfo item = (ItemInfo) host.getTag();
+
+ if (DeleteDropTarget.supportsDrop(item)) {
+ info.addAction(mActions.get(REMOVE));
+ }
+ if (UninstallDropTarget.supportsDrop(host.getContext(), item)) {
+ info.addAction(mActions.get(UNINSTALL));
+ }
+ if (InfoDropTarget.supportsDrop(host.getContext(), item)) {
+ info.addAction(mActions.get(INFO));
+ }
+
+ if ((item instanceof ShortcutInfo)
+ || (item instanceof LauncherAppWidgetInfo)
+ || (item instanceof FolderInfo)) {
+ info.addAction(mActions.get(MOVE));
+
+ if (item.container >= 0) {
+ info.addAction(mActions.get(MOVE_TO_WORKSPACE));
+ } else if (item instanceof LauncherAppWidgetInfo) {
+ if (!getSupportedResizeActions(host, (LauncherAppWidgetInfo) item).isEmpty()) {
+ info.addAction(mActions.get(RESIZE));
+ }
+ }
+ } if ((item instanceof AppInfo) || (item instanceof PendingAddItemInfo)) {
+ info.addAction(mActions.get(ADD_TO_WORKSPACE));
+ }
+ }
+
+ @Override
+ public boolean performAccessibilityAction(View host, int action, Bundle args) {
+ if ((host.getTag() instanceof ItemInfo)
+ && performAction(host, (ItemInfo) host.getTag(), action)) {
+ return true;
+ }
+ return super.performAccessibilityAction(host, action, args);
+ }
+
+ 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;
+ } else if (action == INFO) {
+ InfoDropTarget.startDetailsActivityForInfo(item, mLauncher);
+ return true;
+ } else if (action == UNINSTALL) {
+ return UninstallDropTarget.startUninstallActivity(mLauncher, item);
+ } else if (action == MOVE) {
+ beginAccessibleDrag(host, item);
+ } else if (action == ADD_TO_WORKSPACE) {
+ final int[] coordinates = new int[2];
+ final long screenId = findSpaceOnWorkspace(item, coordinates);
+ mLauncher.showWorkspace(true, new Runnable() {
+
+ @Override
+ public void run() {
+ if (item instanceof AppInfo) {
+ ShortcutInfo info = ((AppInfo) item).makeShortcut();
+ LauncherModel.addItemToDatabase(mLauncher, info,
+ LauncherSettings.Favorites.CONTAINER_DESKTOP,
+ screenId, coordinates[0], coordinates[1]);
+
+ ArrayList<ItemInfo> itemList = new ArrayList<>();
+ itemList.add(info);
+ mLauncher.bindItems(itemList, 0, itemList.size(), true);
+ } else if (item instanceof PendingAddItemInfo) {
+ PendingAddItemInfo info = (PendingAddItemInfo) item;
+ Workspace workspace = mLauncher.getWorkspace();
+ workspace.snapToPage(workspace.getPageIndexForScreenId(screenId));
+ mLauncher.addPendingItem(info, LauncherSettings.Favorites.CONTAINER_DESKTOP,
+ screenId, coordinates, info.spanX, info.spanY);
+ }
+ announceConfirmation(R.string.item_added_to_workspace);
+ }
+ });
+ return true;
+ } else if (action == MOVE_TO_WORKSPACE) {
+ Folder folder = mLauncher.getWorkspace().getOpenFolder();
+ mLauncher.closeFolder(folder);
+ ShortcutInfo info = (ShortcutInfo) item;
+ folder.getInfo().remove(info);
+
+ final int[] coordinates = new int[2];
+ final long screenId = findSpaceOnWorkspace(item, coordinates);
+ LauncherModel.moveItemInDatabase(mLauncher, info,
+ LauncherSettings.Favorites.CONTAINER_DESKTOP,
+ screenId, coordinates[0], coordinates[1]);
+
+ // Bind the item in next frame so that if a new workspace page was created,
+ // it will get laid out.
+ new Handler().post(new Runnable() {
+
+ @Override
+ public void run() {
+ ArrayList<ItemInfo> itemList = new ArrayList<>();
+ itemList.add(item);
+ mLauncher.bindItems(itemList, 0, itemList.size(), true);
+ announceConfirmation(R.string.item_moved);
+ }
+ });
+ } else if (action == RESIZE) {
+ final LauncherAppWidgetInfo info = (LauncherAppWidgetInfo) item;
+ final ArrayList<Integer> actions = getSupportedResizeActions(host, info);
+ CharSequence[] labels = new CharSequence[actions.size()];
+ for (int i = 0; i < actions.size(); i++) {
+ labels[i] = mLauncher.getText(actions.get(i));
+ }
+
+ new AlertDialog.Builder(mLauncher)
+ .setTitle(R.string.action_resize)
+ .setItems(labels, new DialogInterface.OnClickListener() {
+
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ performResizeAction(actions.get(which), host, info);
+ dialog.dismiss();
+ }
+ })
+ .show();
+ }
+ return false;
+ }
+
+ private ArrayList<Integer> getSupportedResizeActions(View host, LauncherAppWidgetInfo info) {
+ ArrayList<Integer> actions = new ArrayList<>();
+
+ AppWidgetProviderInfo providerInfo = ((LauncherAppWidgetHostView) host).getAppWidgetInfo();
+ if (providerInfo == null) {
+ return actions;
+ }
+
+ CellLayout layout = (CellLayout) host.getParent().getParent();
+ if ((providerInfo.resizeMode & AppWidgetProviderInfo.RESIZE_HORIZONTAL) != 0) {
+ if (layout.isRegionVacant(info.cellX + info.spanX, info.cellY, 1, info.spanY) ||
+ layout.isRegionVacant(info.cellX - 1, info.cellY, 1, info.spanY)) {
+ actions.add(R.string.action_increase_width);
+ }
+
+ if (info.spanX > info.minSpanX && info.spanX > 1) {
+ actions.add(R.string.action_decrease_width);
+ }
+ }
+
+ if ((providerInfo.resizeMode & AppWidgetProviderInfo.RESIZE_VERTICAL) != 0) {
+ if (layout.isRegionVacant(info.cellX, info.cellY + info.spanY, info.spanX, 1) ||
+ layout.isRegionVacant(info.cellX, info.cellY - 1, info.spanX, 1)) {
+ actions.add(R.string.action_increase_height);
+ }
+
+ if (info.spanY > info.minSpanY && info.spanY > 1) {
+ actions.add(R.string.action_decrease_height);
+ }
+ }
+ return actions;
+ }
+
+ @Thunk void performResizeAction(int action, View host, LauncherAppWidgetInfo info) {
+ CellLayout.LayoutParams lp = (CellLayout.LayoutParams) host.getLayoutParams();
+ CellLayout layout = (CellLayout) host.getParent().getParent();
+ layout.markCellsAsUnoccupiedForView(host);
+
+ if (action == R.string.action_increase_width) {
+ if (((host.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL)
+ && layout.isRegionVacant(info.cellX - 1, info.cellY, 1, info.spanY))
+ || !layout.isRegionVacant(info.cellX + info.spanX, info.cellY, 1, info.spanY)) {
+ lp.cellX --;
+ info.cellX --;
+ }
+ lp.cellHSpan ++;
+ info.spanX ++;
+ } else if (action == R.string.action_decrease_width) {
+ lp.cellHSpan --;
+ info.spanX --;
+ } else if (action == R.string.action_increase_height) {
+ if (!layout.isRegionVacant(info.cellX, info.cellY + info.spanY, info.spanX, 1)) {
+ lp.cellY --;
+ info.cellY --;
+ }
+ lp.cellVSpan ++;
+ info.spanY ++;
+ } else if (action == R.string.action_decrease_height) {
+ lp.cellVSpan --;
+ info.spanY --;
+ }
+
+ layout.markCellsAsOccupiedForView(host);
+ Rect sizeRange = new Rect();
+ AppWidgetResizeFrame.getWidgetSizeRanges(mLauncher, info.spanX, info.spanY, sizeRange);
+ ((LauncherAppWidgetHostView) host).updateAppWidgetSize(null,
+ sizeRange.left, sizeRange.top, sizeRange.right, sizeRange.bottom);
+ host.requestLayout();
+ LauncherModel.updateItemInDatabase(mLauncher, info);
+ announceConfirmation(mLauncher.getString(R.string.widget_resized, info.spanX, info.spanY));
+ }
+
+ @Thunk void announceConfirmation(int resId) {
+ announceConfirmation(mLauncher.getResources().getString(resId));
+ }
+
+ @Thunk void announceConfirmation(String confirmation) {
+ mLauncher.getDragLayer().announceForAccessibility(confirmation);
+
+ }
+
+ public boolean isInAccessibleDrag() {
+ return mDragInfo != null;
+ }
+
+ public DragInfo getDragInfo() {
+ return mDragInfo;
+ }
+
+ /**
+ * @param clickedTarget the actual view that was clicked
+ * @param dropLocation relative to {@param clickedTarget}. If provided, its center is used
+ * as the actual drop location otherwise the views center is used.
+ */
+ public void handleAccessibleDrop(View clickedTarget, Rect dropLocation,
+ String confirmation) {
+ if (!isInAccessibleDrag()) return;
+
+ int[] loc = new int[2];
+ if (dropLocation == null) {
+ loc[0] = clickedTarget.getWidth() / 2;
+ loc[1] = clickedTarget.getHeight() / 2;
+ } else {
+ loc[0] = dropLocation.centerX();
+ loc[1] = dropLocation.centerY();
+ }
+
+ mLauncher.getDragLayer().getDescendantCoordRelativeToSelf(clickedTarget, loc);
+ mLauncher.getDragController().completeAccessibleDrag(loc);
+
+ if (!TextUtils.isEmpty(confirmation)) {
+ announceConfirmation(confirmation);
+ }
+ }
+
+ public void beginAccessibleDrag(View item, ItemInfo info) {
+ mDragInfo = new DragInfo();
+ mDragInfo.info = info;
+ mDragInfo.item = item;
+ mDragInfo.dragType = DragType.ICON;
+ if (info instanceof FolderInfo) {
+ mDragInfo.dragType = DragType.FOLDER;
+ } else if (info instanceof LauncherAppWidgetInfo) {
+ mDragInfo.dragType = DragType.WIDGET;
+ }
+
+ CellLayout.CellInfo cellInfo = new CellLayout.CellInfo(item, info);
+
+ Rect pos = new Rect();
+ mLauncher.getDragLayer().getDescendantRectRelativeToSelf(item, pos);
+ mLauncher.getDragController().prepareAccessibleDrag(pos.centerX(), pos.centerY());
+
+ Workspace workspace = mLauncher.getWorkspace();
+
+ Folder folder = workspace.getOpenFolder();
+ if (folder != null) {
+ if (folder.getItemsInReadingOrder().contains(item)) {
+ mDragSource = folder;
+ } else {
+ mLauncher.closeFolder();
+ }
+ }
+ if (mDragSource == null) {
+ mDragSource = workspace;
+ }
+ mDragSource.enableAccessibleDrag(true);
+ mDragSource.startDrag(cellInfo, true);
+
+ if (mLauncher.getDragController().isDragging()) {
+ mLauncher.getDragController().addDragListener(this);
+ }
+ }
+
+
+ @Override
+ public void onDragStart(DragSource source, Object info, int dragAction) {
+ // No-op
+ }
+
+ @Override
+ public void onDragEnd() {
+ mLauncher.getDragController().removeDragListener(this);
+ mDragInfo = null;
+ if (mDragSource != null) {
+ mDragSource.enableAccessibleDrag(false);
+ mDragSource = null;
+ }
+ }
+
+ public static interface AccessibilityDragSource {
+ void startDrag(CellLayout.CellInfo cellInfo, boolean accessible);
+
+ void enableAccessibleDrag(boolean enable);
+ }
+
+ /**
+ * Find empty space on the workspace and returns the screenId.
+ */
+ private long findSpaceOnWorkspace(ItemInfo info, int[] outCoordinates) {
+ Workspace workspace = mLauncher.getWorkspace();
+ ArrayList<Long> workspaceScreens = workspace.getScreenOrder();
+ long screenId;
+
+ // First check if there is space on the current screen.
+ int screenIndex = workspace.getCurrentPage();
+ screenId = workspaceScreens.get(screenIndex);
+ CellLayout layout = (CellLayout) workspace.getPageAt(screenIndex);
+
+ boolean found = layout.findCellForSpan(outCoordinates, info.spanX, info.spanY);
+ screenIndex = workspace.hasCustomContent() ? 1 : 0;
+ while (!found && screenIndex < workspaceScreens.size()) {
+ screenId = workspaceScreens.get(screenIndex);
+ layout = (CellLayout) workspace.getPageAt(screenIndex);
+ found = layout.findCellForSpan(outCoordinates, info.spanX, info.spanY);
+ screenIndex++;
+ }
+
+ if (found) {
+ return screenId;
+ }
+
+ workspace.addExtraEmptyScreen();
+ screenId = workspace.commitExtraEmptyScreen();
+ layout = workspace.getScreenWithId(screenId);
+ found = layout.findCellForSpan(outCoordinates, info.spanX, info.spanY);
+
+ if (!found) {
+ Log.wtf(TAG, "Not enough space on an empty screen");
+ }
+ return screenId;
+ }
+}
diff --git a/src/com/android/launcher3/accessibility/OverviewScreenAccessibilityDelegate.java b/src/com/android/launcher3/accessibility/OverviewScreenAccessibilityDelegate.java
new file mode 100644
index 000000000..c5b52de72
--- /dev/null
+++ b/src/com/android/launcher3/accessibility/OverviewScreenAccessibilityDelegate.java
@@ -0,0 +1,95 @@
+/*
+ * 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.annotation.TargetApi;
+import android.content.Context;
+import android.os.Build;
+import android.os.Bundle;
+import android.util.SparseArray;
+import android.view.View;
+import android.view.View.AccessibilityDelegate;
+import android.view.accessibility.AccessibilityNodeInfo;
+import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
+import com.android.launcher3.R;
+import com.android.launcher3.Utilities;
+import com.android.launcher3.Workspace;
+
+@TargetApi(Build.VERSION_CODES.LOLLIPOP)
+public class OverviewScreenAccessibilityDelegate extends AccessibilityDelegate {
+
+ private static final int MOVE_BACKWARD = R.id.action_move_screen_backwards;
+ private static final int MOVE_FORWARD = R.id.action_move_screen_forwards;
+
+ private final SparseArray<AccessibilityAction> mActions = new SparseArray<>();
+ private final Workspace mWorkspace;
+
+ public OverviewScreenAccessibilityDelegate(Workspace workspace) {
+ mWorkspace = workspace;
+
+ Context context = mWorkspace.getContext();
+ boolean isRtl = Utilities.isRtl(context.getResources());
+ mActions.put(MOVE_BACKWARD, new AccessibilityAction(MOVE_BACKWARD,
+ context.getText(isRtl ? R.string.action_move_screen_right :
+ R.string.action_move_screen_left)));
+ mActions.put(MOVE_FORWARD, new AccessibilityAction(MOVE_FORWARD,
+ context.getText(isRtl ? R.string.action_move_screen_left :
+ R.string.action_move_screen_right)));
+ }
+
+ @Override
+ public boolean performAccessibilityAction(View host, int action, Bundle args) {
+ if (host != null) {
+ if (action == AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS ) {
+ int index = mWorkspace.indexOfChild(host);
+ mWorkspace.setCurrentPage(index);
+ } else if (action == MOVE_FORWARD) {
+ movePage(mWorkspace.indexOfChild(host) + 1, host);
+ return true;
+ } else if (action == MOVE_BACKWARD) {
+ movePage(mWorkspace.indexOfChild(host) - 1, host);
+ return true;
+ }
+ }
+
+ return super.performAccessibilityAction(host, action, args);
+ }
+
+ private void movePage(int finalIndex, View view) {
+ mWorkspace.onStartReordering();
+ mWorkspace.removeView(view);
+ mWorkspace.addView(view, finalIndex);
+ mWorkspace.onEndReordering();
+ mWorkspace.announceForAccessibility(mWorkspace.getContext().getText(R.string.screen_moved));
+
+ mWorkspace.updateAccessibilityFlags();
+ view.performAccessibilityAction(AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS, null);
+ }
+
+ @Override
+ public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
+ super.onInitializeAccessibilityNodeInfo(host, info);
+
+ int index = mWorkspace.indexOfChild(host);
+ if (index < mWorkspace.getChildCount() - 1) {
+ info.addAction(mActions.get(MOVE_FORWARD));
+ }
+ if (index > mWorkspace.numCustomPages()) {
+ info.addAction(mActions.get(MOVE_BACKWARD));
+ }
+ }
+}
diff --git a/src/com/android/launcher3/accessibility/WorkspaceAccessibilityHelper.java b/src/com/android/launcher3/accessibility/WorkspaceAccessibilityHelper.java
new file mode 100644
index 000000000..80ddc13b7
--- /dev/null
+++ b/src/com/android/launcher3/accessibility/WorkspaceAccessibilityHelper.java
@@ -0,0 +1,166 @@
+/*
+ * 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.text.TextUtils;
+import android.view.View;
+
+import com.android.launcher3.AppInfo;
+import com.android.launcher3.CellLayout;
+import com.android.launcher3.FolderInfo;
+import com.android.launcher3.ItemInfo;
+import com.android.launcher3.accessibility.LauncherAccessibilityDelegate.DragType;
+import com.android.launcher3.R;
+import com.android.launcher3.ShortcutInfo;
+
+/**
+ * Implementation of {@link DragAndDropAccessibilityDelegate} to support DnD on workspace.
+ */
+public class WorkspaceAccessibilityHelper extends DragAndDropAccessibilityDelegate {
+
+ public WorkspaceAccessibilityHelper(CellLayout layout) {
+ super(layout);
+ }
+
+ /**
+ * Find the virtual view id corresponding to the top left corner of any drop region by which
+ * the passed id is contained. For an icon, this is simply
+ */
+ @Override
+ protected int intersectsValidDropTarget(int id) {
+ int mCountX = mView.getCountX();
+ int mCountY = mView.getCountY();
+
+ int x = id % mCountX;
+ int y = id / mCountX;
+ LauncherAccessibilityDelegate.DragInfo dragInfo = mDelegate.getDragInfo();
+
+ if (dragInfo.dragType == DragType.WIDGET && mView.isHotseat()) {
+ return INVALID_POSITION;
+ }
+
+ if (dragInfo.dragType == DragType.WIDGET) {
+ // For a widget, every cell must be vacant. In addition, we will return any valid
+ // drop target by which the passed id is contained.
+ boolean fits = false;
+
+ // These represent the amount that we can back off if we hit a problem. They
+ // get consumed as we move up and to the right, trying new regions.
+ int spanX = dragInfo.info.spanX;
+ int spanY = dragInfo.info.spanY;
+
+ for (int m = 0; m < spanX; m++) {
+ for (int n = 0; n < spanY; n++) {
+
+ fits = true;
+ int x0 = x - m;
+ int y0 = y - n;
+
+ if (x0 < 0 || y0 < 0) continue;
+
+ for (int i = x0; i < x0 + spanX; i++) {
+ if (!fits) break;
+ for (int j = y0; j < y0 + spanY; j++) {
+ if (i >= mCountX || j >= mCountY || mView.isOccupied(i, j)) {
+ fits = false;
+ break;
+ }
+ }
+ }
+ if (fits) {
+ return x0 + mCountX * y0;
+ }
+ }
+ }
+ return INVALID_POSITION;
+ } else {
+ // For an icon, we simply check the view directly below
+ View child = mView.getChildAt(x, y);
+ if (child == null || child == dragInfo.item) {
+ // Empty cell. Good for an icon or folder.
+ return id;
+ } else if (dragInfo.dragType != DragType.FOLDER) {
+ // For icons, we can consider cells that have another icon or a folder.
+ ItemInfo info = (ItemInfo) child.getTag();
+ if (info instanceof AppInfo || info instanceof FolderInfo ||
+ info instanceof ShortcutInfo) {
+ return id;
+ }
+ }
+ return INVALID_POSITION;
+ }
+ }
+
+ @Override
+ protected String getConfirmationForIconDrop(int id) {
+ int x = id % mView.getCountX();
+ int y = id / mView.getCountX();
+ LauncherAccessibilityDelegate.DragInfo dragInfo = mDelegate.getDragInfo();
+
+ View child = mView.getChildAt(x, y);
+ if (child == null || child == dragInfo.item) {
+ return mContext.getString(R.string.item_moved);
+ } else {
+ ItemInfo info = (ItemInfo) child.getTag();
+ if (info instanceof AppInfo || info instanceof ShortcutInfo) {
+ return mContext.getString(R.string.folder_created);
+
+ } else if (info instanceof FolderInfo) {
+ return mContext.getString(R.string.added_to_folder);
+ }
+ }
+ return "";
+ }
+
+ @Override
+ protected String getLocationDescriptionForIconDrop(int id) {
+ int x = id % mView.getCountX();
+ int y = id / mView.getCountX();
+ LauncherAccessibilityDelegate.DragInfo dragInfo = mDelegate.getDragInfo();
+
+ View child = mView.getChildAt(x, y);
+ if (child == null || child == dragInfo.item) {
+ if (mView.isHotseat()) {
+ return mContext.getString(R.string.move_to_hotseat_position, id + 1);
+ } else {
+ 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;
+ }
+ }
+
+ if (firstItem != null) {
+ return mContext.getString(R.string.add_to_folder_with_app, firstItem.title);
+ }
+ }
+ return mContext.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
new file mode 100644
index 000000000..67d572819
--- /dev/null
+++ b/src/com/android/launcher3/allapps/AllAppsContainerView.java
@@ -0,0 +1,638 @@
+/*
+ * 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.annotation.SuppressLint;
+import android.annotation.TargetApi;
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Point;
+import android.graphics.Rect;
+import android.graphics.drawable.InsetDrawable;
+import android.os.Build;
+import android.os.Bundle;
+import android.support.v7.widget.RecyclerView;
+import android.text.Selection;
+import android.text.SpannableStringBuilder;
+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;
+import android.view.ViewGroup;
+import android.view.ViewTreeObserver;
+import android.widget.FrameLayout;
+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.CheckLongPressHelper;
+import com.android.launcher3.DeleteDropTarget;
+import com.android.launcher3.DeviceProfile;
+import com.android.launcher3.DragSource;
+import com.android.launcher3.DropTarget;
+import com.android.launcher3.Folder;
+import com.android.launcher3.ItemInfo;
+import com.android.launcher3.Launcher;
+import com.android.launcher3.LauncherTransitionable;
+import com.android.launcher3.R;
+import com.android.launcher3.Stats;
+import com.android.launcher3.Utilities;
+import com.android.launcher3.Workspace;
+import com.android.launcher3.util.ComponentKey;
+import com.android.launcher3.util.Thunk;
+
+import java.nio.charset.Charset;
+import java.nio.charset.CharsetEncoder;
+import java.util.ArrayList;
+import java.util.List;
+
+
+
+/**
+ * A merge algorithm that merges every section indiscriminately.
+ */
+final class FullMergeAlgorithm implements AlphabeticalAppsList.MergeAlgorithm {
+
+ @Override
+ public boolean continueMerging(AlphabeticalAppsList.SectionInfo section,
+ AlphabeticalAppsList.SectionInfo withSection,
+ int sectionAppCount, int numAppsPerRow, int mergeCount) {
+ // Don't merge the predicted apps
+ if (section.firstAppItem.viewType != AllAppsGridAdapter.ICON_VIEW_TYPE) {
+ return false;
+ }
+ // Otherwise, merge every other section
+ return true;
+ }
+}
+
+/**
+ * The logic we use to merge multiple sections. We only merge sections when their final row
+ * contains less than a certain number of icons, and stop at a specified max number of merges.
+ * In addition, we will try and not merge sections that identify apps from different scripts.
+ */
+final class SimpleSectionMergeAlgorithm implements AlphabeticalAppsList.MergeAlgorithm {
+
+ private int mMinAppsPerRow;
+ private int mMinRowsInMergedSection;
+ private int mMaxAllowableMerges;
+ private CharsetEncoder mAsciiEncoder;
+
+ public SimpleSectionMergeAlgorithm(int minAppsPerRow, int minRowsInMergedSection, int maxNumMerges) {
+ mMinAppsPerRow = minAppsPerRow;
+ mMinRowsInMergedSection = minRowsInMergedSection;
+ mMaxAllowableMerges = maxNumMerges;
+ mAsciiEncoder = Charset.forName("US-ASCII").newEncoder();
+ }
+
+ @Override
+ public boolean continueMerging(AlphabeticalAppsList.SectionInfo section,
+ AlphabeticalAppsList.SectionInfo withSection,
+ int sectionAppCount, int numAppsPerRow, int mergeCount) {
+ // Don't merge the predicted apps
+ if (section.firstAppItem.viewType != AllAppsGridAdapter.ICON_VIEW_TYPE) {
+ return false;
+ }
+
+ // Continue merging if the number of hanging apps on the final row is less than some
+ // fixed number (ragged), the merged rows has yet to exceed some minimum row count,
+ // and while the number of merged sections is less than some fixed number of merges
+ int rows = sectionAppCount / numAppsPerRow;
+ int cols = sectionAppCount % numAppsPerRow;
+
+ // Ensure that we do not merge across scripts, currently we only allow for english and
+ // native scripts so we can test if both can just be ascii encoded
+ boolean isCrossScript = false;
+ if (section.firstAppItem != null && withSection.firstAppItem != null) {
+ isCrossScript = mAsciiEncoder.canEncode(section.firstAppItem.sectionName) !=
+ mAsciiEncoder.canEncode(withSection.firstAppItem.sectionName);
+ }
+ return (0 < cols && cols < mMinAppsPerRow) &&
+ rows < mMinRowsInMergedSection &&
+ mergeCount < mMaxAllowableMerges &&
+ !isCrossScript;
+ }
+}
+
+/**
+ * The all apps view container.
+ */
+public class AllAppsContainerView extends BaseContainerView implements DragSource,
+ LauncherTransitionable, View.OnTouchListener, View.OnLongClickListener,
+ AllAppsSearchBarController.Callbacks {
+
+ private static final int MIN_ROWS_IN_MERGED_SECTION_PHONE = 3;
+ private static final int MAX_NUM_MERGES_PHONE = 2;
+
+ @Thunk Launcher mLauncher;
+ @Thunk AlphabeticalAppsList mApps;
+ private AllAppsGridAdapter mAdapter;
+ private RecyclerView.LayoutManager mLayoutManager;
+ private RecyclerView.ItemDecoration mItemDecoration;
+
+ @Thunk View mContent;
+ @Thunk View mContainerView;
+ @Thunk View mRevealView;
+ @Thunk AllAppsRecyclerView mAppsRecyclerView;
+ @Thunk AllAppsSearchBarController mSearchBarController;
+ private ViewGroup mSearchBarContainerView;
+ private View mSearchBarView;
+
+ private int mSectionNamesMargin;
+ private int mNumAppsPerRow;
+ private int mNumPredictedAppsPerRow;
+ private int mRecyclerViewTopBottomPadding;
+ // This coordinate is relative to this container view
+ private final Point mBoundsCheckLastTouchDownPos = new Point(-1, -1);
+ // This coordinate is relative to its parent
+ private final Point mIconLastTouchPos = new Point();
+
+ private SpannableStringBuilder mSearchQueryBuilder = null;
+
+ public AllAppsContainerView(Context context) {
+ this(context, null);
+ }
+
+ public AllAppsContainerView(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public AllAppsContainerView(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ Resources res = context.getResources();
+
+ mLauncher = (Launcher) context;
+ mSectionNamesMargin = res.getDimensionPixelSize(R.dimen.all_apps_grid_view_start_margin);
+ mApps = new AlphabeticalAppsList(context);
+ mAdapter = new AllAppsGridAdapter(context, mApps, this, mLauncher, this);
+ mAdapter.setEmptySearchText(res.getString(R.string.all_apps_loading_message));
+ mApps.setAdapter(mAdapter);
+ mLayoutManager = mAdapter.getLayoutManager();
+ mItemDecoration = mAdapter.getItemDecoration();
+ mRecyclerViewTopBottomPadding =
+ res.getDimensionPixelSize(R.dimen.all_apps_list_top_bottom_padding);
+
+ mSearchQueryBuilder = new SpannableStringBuilder();
+ Selection.setSelection(mSearchQueryBuilder, 0);
+ }
+
+ /**
+ * Sets the current set of predicted apps.
+ */
+ public void setPredictedApps(List<ComponentKey> apps) {
+ mApps.setPredictedApps(apps);
+ }
+
+ /**
+ * Sets the current set of apps.
+ */
+ public void setApps(List<AppInfo> apps) {
+ mApps.setApps(apps);
+ }
+
+ /**
+ * Adds new apps to the list.
+ */
+ public void addApps(List<AppInfo> apps) {
+ mApps.addApps(apps);
+ }
+
+ /**
+ * Updates existing apps in the list
+ */
+ public void updateApps(List<AppInfo> apps) {
+ mApps.updateApps(apps);
+ }
+
+ /**
+ * Removes some apps from the list.
+ */
+ public void removeApps(List<AppInfo> apps) {
+ mApps.removeApps(apps);
+ }
+
+ /**
+ * Sets the search bar that shows above the a-z list.
+ */
+ public void setSearchBarController(AllAppsSearchBarController searchController) {
+ if (mSearchBarController != null) {
+ throw new RuntimeException("Expected search bar controller to only be set once");
+ }
+ mSearchBarController = searchController;
+ mSearchBarController.initialize(mApps, this);
+
+ // Add the new search view to the layout
+ View searchBarView = searchController.getView(mSearchBarContainerView);
+ mSearchBarContainerView.addView(searchBarView);
+ mSearchBarContainerView.setVisibility(View.VISIBLE);
+ mSearchBarView = searchBarView;
+ setHasSearchBar();
+
+ updateBackgroundAndPaddings();
+ }
+
+ /**
+ * Scrolls this list view to the top.
+ */
+ public void scrollToTop() {
+ mAppsRecyclerView.scrollToTop();
+ }
+
+ /**
+ * Returns the content view used for the launcher transitions.
+ */
+ public View getContentView() {
+ return mContainerView;
+ }
+
+ /**
+ * Returns the all apps search view.
+ */
+ public View getSearchBarView() {
+ return mSearchBarView;
+ }
+
+ /**
+ * Returns the reveal view used for the launcher transitions.
+ */
+ public View getRevealView() {
+ return mRevealView;
+ }
+
+ /**
+ * Returns an new instance of the default app search controller.
+ */
+ public AllAppsSearchBarController newDefaultAppSearchController() {
+ return new DefaultAppSearchController(getContext(), this, mAppsRecyclerView);
+ }
+
+ /**
+ * Focuses the search field and begins an app search.
+ */
+ public void startAppsSearch() {
+ if (mSearchBarController != null) {
+ mSearchBarController.focusSearchField();
+ }
+ }
+
+ @Override
+ protected void onFinishInflate() {
+ super.onFinishInflate();
+ boolean isRtl = Utilities.isRtl(getResources());
+ mAdapter.setRtl(isRtl);
+ mContent = findViewById(R.id.content);
+
+ // This is a focus listener that proxies focus from a view into the list view. This is to
+ // work around the search box from getting first focus and showing the cursor.
+ View.OnFocusChangeListener focusProxyListener = new View.OnFocusChangeListener() {
+ @Override
+ public void onFocusChange(View v, boolean hasFocus) {
+ if (hasFocus) {
+ mAppsRecyclerView.requestFocus();
+ }
+ }
+ };
+ mSearchBarContainerView = (ViewGroup) findViewById(R.id.search_box_container);
+ mSearchBarContainerView.setOnFocusChangeListener(focusProxyListener);
+ mContainerView = findViewById(R.id.all_apps_container);
+ mContainerView.setOnFocusChangeListener(focusProxyListener);
+ mRevealView = findViewById(R.id.all_apps_reveal);
+
+ // Load the all apps recycler view
+ mAppsRecyclerView = (AllAppsRecyclerView) findViewById(R.id.apps_list_view);
+ mAppsRecyclerView.setApps(mApps);
+ mAppsRecyclerView.setLayoutManager(mLayoutManager);
+ mAppsRecyclerView.setAdapter(mAdapter);
+ mAppsRecyclerView.setHasFixedSize(true);
+ if (mItemDecoration != null) {
+ mAppsRecyclerView.addItemDecoration(mItemDecoration);
+ }
+
+ updateBackgroundAndPaddings();
+ }
+
+ @Override
+ public void onBoundsChanged(Rect newBounds) {
+ mLauncher.updateOverlayBounds(newBounds);
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ // Update the number of items in the grid before we measure the view
+ int availableWidth = !mContentBounds.isEmpty() ? mContentBounds.width() :
+ MeasureSpec.getSize(widthMeasureSpec);
+ DeviceProfile grid = mLauncher.getDeviceProfile();
+ grid.updateAppsViewNumCols(getResources(), availableWidth);
+ if (mNumAppsPerRow != grid.allAppsNumCols ||
+ mNumPredictedAppsPerRow != grid.allAppsNumPredictiveCols) {
+ mNumAppsPerRow = grid.allAppsNumCols;
+ mNumPredictedAppsPerRow = grid.allAppsNumPredictiveCols;
+
+ // If there is a start margin to draw section names, determine how we are going to merge
+ // app sections
+ boolean mergeSectionsFully = mSectionNamesMargin == 0 || !grid.isPhone;
+ AlphabeticalAppsList.MergeAlgorithm mergeAlgorithm = mergeSectionsFully ?
+ new FullMergeAlgorithm() :
+ new SimpleSectionMergeAlgorithm((int) Math.ceil(mNumAppsPerRow / 2f),
+ MIN_ROWS_IN_MERGED_SECTION_PHONE, MAX_NUM_MERGES_PHONE);
+
+ mAppsRecyclerView.setNumAppsPerRow(grid, mNumAppsPerRow);
+ mAdapter.setNumAppsPerRow(mNumAppsPerRow);
+ mApps.setNumAppsPerRow(mNumAppsPerRow, mNumPredictedAppsPerRow, mergeAlgorithm);
+ }
+
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+ }
+
+ /**
+ * Update the background and padding of the Apps view and children. Instead of insetting the
+ * container view, we inset the background and padding of the recycler view to allow for the
+ * recycler view to handle touch events (for fast scrolling) all the way to the edge.
+ */
+ @Override
+ protected void onUpdateBackgroundAndPaddings(Rect searchBarBounds, Rect padding) {
+ boolean isRtl = Utilities.isRtl(getResources());
+
+ // TODO: Use quantum_panel instead of quantum_panel_shape
+ InsetDrawable background = new InsetDrawable(
+ getResources().getDrawable(R.drawable.quantum_panel_shape), padding.left, 0,
+ padding.right, 0);
+ Rect bgPadding = new Rect();
+ background.getPadding(bgPadding);
+ mContainerView.setBackground(background);
+ mRevealView.setBackground(background.getConstantState().newDrawable());
+ mAppsRecyclerView.updateBackgroundPadding(bgPadding);
+ mAdapter.updateBackgroundPadding(bgPadding);
+
+ // Hack: We are going to let the recycler view take the full width, so reset the padding on
+ // the container to zero after setting the background and apply the top-bottom padding to
+ // the content view instead so that the launcher transition clips correctly.
+ mContent.setPadding(0, padding.top, 0, padding.bottom);
+ mContainerView.setPadding(0, 0, 0, 0);
+
+ // Pad the recycler view by the background padding plus the start margin (for the section
+ // names)
+ int startInset = Math.max(mSectionNamesMargin, mAppsRecyclerView.getMaxScrollbarWidth());
+ int topBottomPadding = mRecyclerViewTopBottomPadding;
+ if (isRtl) {
+ mAppsRecyclerView.setPadding(padding.left + mAppsRecyclerView.getMaxScrollbarWidth(),
+ topBottomPadding, padding.right + startInset, topBottomPadding);
+ } else {
+ mAppsRecyclerView.setPadding(padding.left + startInset, topBottomPadding,
+ padding.right + mAppsRecyclerView.getMaxScrollbarWidth(), topBottomPadding);
+ }
+
+ // Inset the search bar to fit its bounds above the container
+ if (mSearchBarView != null) {
+ Rect backgroundPadding = new Rect();
+ if (mSearchBarView.getBackground() != null) {
+ mSearchBarView.getBackground().getPadding(backgroundPadding);
+ }
+ LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams)
+ mSearchBarContainerView.getLayoutParams();
+ lp.leftMargin = searchBarBounds.left - backgroundPadding.left;
+ lp.topMargin = searchBarBounds.top - backgroundPadding.top;
+ lp.rightMargin = (getMeasuredWidth() - searchBarBounds.right) - backgroundPadding.right;
+ mSearchBarContainerView.requestLayout();
+ }
+ }
+
+ @Override
+ public boolean dispatchKeyEvent(KeyEvent event) {
+ // Determine if the key event was actual text, if so, focus the search bar and then dispatch
+ // the key normally so that it can process this key event
+ if (!mSearchBarController.isSearchFieldFocused() &&
+ event.getAction() == KeyEvent.ACTION_DOWN) {
+ final int unicodeChar = event.getUnicodeChar();
+ final boolean isKeyNotWhitespace = unicodeChar > 0 &&
+ !Character.isWhitespace(unicodeChar) && !Character.isSpaceChar(unicodeChar);
+ if (isKeyNotWhitespace) {
+ boolean gotKey = TextKeyListener.getInstance().onKeyDown(this, mSearchQueryBuilder,
+ event.getKeyCode(), event);
+ if (gotKey && mSearchQueryBuilder.length() > 0) {
+ mSearchBarController.focusSearchField();
+ }
+ }
+ }
+
+ return super.dispatchKeyEvent(event);
+ }
+
+ @Override
+ public boolean onInterceptTouchEvent(MotionEvent ev) {
+ return handleTouchEvent(ev);
+ }
+
+ @SuppressLint("ClickableViewAccessibility")
+ @Override
+ public boolean onTouchEvent(MotionEvent ev) {
+ return handleTouchEvent(ev);
+ }
+
+ @SuppressLint("ClickableViewAccessibility")
+ @Override
+ public boolean onTouch(View v, MotionEvent ev) {
+ switch (ev.getAction()) {
+ case MotionEvent.ACTION_DOWN:
+ case MotionEvent.ACTION_MOVE:
+ mIconLastTouchPos.set((int) ev.getX(), (int) ev.getY());
+ break;
+ }
+ return false;
+ }
+
+ @Override
+ public boolean onLongClick(View v) {
+ // Return early if this is not initiated from a touch
+ if (!v.isInTouchMode()) return false;
+ // When we have exited all apps or are in transition, disregard long clicks
+ if (!mLauncher.isAppsViewVisible() ||
+ mLauncher.getWorkspace().isSwitchingState()) return false;
+ // Return if global dragging is not enabled
+ if (!mLauncher.isDraggingEnabled()) return false;
+
+ // Start the drag
+ mLauncher.getWorkspace().beginDragShared(v, mIconLastTouchPos, this, false);
+ // Enter spring loaded mode
+ mLauncher.enterSpringLoadedDragMode();
+
+ return false;
+ }
+
+ @Override
+ public boolean supportsFlingToDelete() {
+ return true;
+ }
+
+ @Override
+ public boolean supportsAppInfoDropTarget() {
+ return true;
+ }
+
+ @Override
+ public boolean supportsDeleteDropTarget() {
+ return false;
+ }
+
+ @Override
+ public float getIntrinsicIconScaleFactor() {
+ DeviceProfile grid = mLauncher.getDeviceProfile();
+ return (float) grid.allAppsIconSizePx / grid.iconSizePx;
+ }
+
+ @Override
+ public void onFlingToDeleteCompleted() {
+ // We just dismiss the drag when we fling, so cleanup here
+ mLauncher.exitSpringLoadedDragModeDelayed(true,
+ Launcher.EXIT_SPRINGLOADED_MODE_SHORT_TIMEOUT, null);
+ mLauncher.unlockScreenOrientation(false);
+ }
+
+ @Override
+ public void onDropCompleted(View target, DropTarget.DragObject d, boolean isFlingToDelete,
+ boolean success) {
+ 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
+ // drop in Workspace
+ mLauncher.exitSpringLoadedDragModeDelayed(true,
+ Launcher.EXIT_SPRINGLOADED_MODE_SHORT_TIMEOUT, null);
+ }
+ mLauncher.unlockScreenOrientation(false);
+
+ // Display an error message if the drag failed due to there not being enough space on the
+ // target layout we were dropping on.
+ if (!success) {
+ boolean showOutOfSpaceMessage = false;
+ if (target instanceof Workspace) {
+ int currentScreen = mLauncher.getCurrentWorkspaceScreen();
+ Workspace workspace = (Workspace) target;
+ CellLayout layout = (CellLayout) workspace.getChildAt(currentScreen);
+ ItemInfo itemInfo = (ItemInfo) d.dragInfo;
+ if (layout != null) {
+ layout.calculateSpans(itemInfo);
+ showOutOfSpaceMessage =
+ !layout.findCellForSpan(null, itemInfo.spanX, itemInfo.spanY);
+ }
+ }
+ if (showOutOfSpaceMessage) {
+ mLauncher.showOutOfSpaceMessage(false);
+ }
+
+ d.deferDragViewCleanupPostAnimation = false;
+ }
+ }
+
+ @Override
+ public void onLauncherTransitionPrepare(Launcher l, boolean animated, boolean toWorkspace) {
+ // Do nothing
+ }
+
+ @Override
+ public void onLauncherTransitionStart(Launcher l, boolean animated, boolean toWorkspace) {
+ // Do nothing
+ }
+
+ @Override
+ public void onLauncherTransitionStep(Launcher l, float t) {
+ // Do nothing
+ }
+
+ @Override
+ public void onLauncherTransitionEnd(Launcher l, boolean animated, boolean toWorkspace) {
+ if (toWorkspace) {
+ // Reset the search bar after transitioning home
+ mSearchBarController.reset();
+ }
+ }
+
+ /**
+ * Handles the touch events to dismiss all apps when clicking outside the bounds of the
+ * recycler view.
+ */
+ private boolean handleTouchEvent(MotionEvent ev) {
+ DeviceProfile grid = mLauncher.getDeviceProfile();
+ int x = (int) ev.getX();
+ int y = (int) ev.getY();
+
+ switch (ev.getAction()) {
+ case MotionEvent.ACTION_DOWN:
+ if (!mContentBounds.isEmpty()) {
+ // Outset the fixed bounds and check if the touch is outside all apps
+ Rect tmpRect = new Rect(mContentBounds);
+ tmpRect.inset(-grid.allAppsIconSizePx / 2, 0);
+ if (ev.getX() < tmpRect.left || ev.getX() > tmpRect.right) {
+ mBoundsCheckLastTouchDownPos.set(x, y);
+ return true;
+ }
+ } else {
+ // Check if the touch is outside all apps
+ if (ev.getX() < getPaddingLeft() ||
+ ev.getX() > (getWidth() - getPaddingRight())) {
+ mBoundsCheckLastTouchDownPos.set(x, y);
+ return true;
+ }
+ }
+ break;
+ case MotionEvent.ACTION_UP:
+ if (mBoundsCheckLastTouchDownPos.x > -1) {
+ ViewConfiguration viewConfig = ViewConfiguration.get(getContext());
+ float dx = ev.getX() - mBoundsCheckLastTouchDownPos.x;
+ float dy = ev.getY() - mBoundsCheckLastTouchDownPos.y;
+ float distance = (float) Math.hypot(dx, dy);
+ if (distance < viewConfig.getScaledTouchSlop()) {
+ // The background was clicked, so just go home
+ Launcher launcher = (Launcher) getContext();
+ launcher.showWorkspace(true);
+ return true;
+ }
+ }
+ // Fall through
+ case MotionEvent.ACTION_CANCEL:
+ mBoundsCheckLastTouchDownPos.set(-1, -1);
+ break;
+ }
+ return false;
+ }
+
+ @Override
+ public void onSearchResult(String query, ArrayList<ComponentKey> apps) {
+ if (apps != null) {
+ if (apps.isEmpty()) {
+ String formatStr = getResources().getString(R.string.all_apps_no_search_results);
+ mAdapter.setEmptySearchText(String.format(formatStr, query));
+ } else {
+ mAppsRecyclerView.scrollToTop();
+ }
+ mApps.setOrderedFilter(apps);
+ }
+ }
+
+ @Override
+ public void clearSearchResult() {
+ mApps.setOrderedFilter(null);
+
+ // Clear the search query
+ mSearchQueryBuilder.clear();
+ mSearchQueryBuilder.clearSpans();
+ Selection.setSelection(mSearchQueryBuilder, 0);
+ }
+}
diff --git a/src/com/android/launcher3/allapps/AllAppsGridAdapter.java b/src/com/android/launcher3/allapps/AllAppsGridAdapter.java
new file mode 100644
index 000000000..057883cab
--- /dev/null
+++ b/src/com/android/launcher3/allapps/AllAppsGridAdapter.java
@@ -0,0 +1,453 @@
+/*
+ * 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.content.Context;
+import android.content.res.Resources;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.PointF;
+import android.graphics.Rect;
+import android.os.Handler;
+import android.support.v7.widget.GridLayoutManager;
+import android.support.v7.widget.RecyclerView;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewConfiguration;
+import android.view.ViewGroup;
+import android.widget.TextView;
+import com.android.launcher3.AppInfo;
+import com.android.launcher3.BubbleTextView;
+import com.android.launcher3.R;
+import com.android.launcher3.Utilities;
+import com.android.launcher3.util.Thunk;
+
+import java.util.HashMap;
+import java.util.List;
+
+
+/**
+ * The grid view adapter of all the apps.
+ */
+class AllAppsGridAdapter extends RecyclerView.Adapter<AllAppsGridAdapter.ViewHolder> {
+
+ public static final String TAG = "AppsGridAdapter";
+ private static final boolean DEBUG = false;
+
+ // A section break in the grid
+ public static final int SECTION_BREAK_VIEW_TYPE = 0;
+ // A normal icon
+ public static final int ICON_VIEW_TYPE = 1;
+ // A prediction icon
+ public static final int PREDICTION_ICON_VIEW_TYPE = 2;
+ // The message shown when there are no filtered results
+ public static final int EMPTY_SEARCH_VIEW_TYPE = 3;
+
+ /**
+ * ViewHolder for each icon.
+ */
+ public static class ViewHolder extends RecyclerView.ViewHolder {
+ public View mContent;
+
+ public ViewHolder(View v) {
+ super(v);
+ mContent = v;
+ }
+ }
+
+ /**
+ * Helper class to size the grid items.
+ */
+ public class GridSpanSizer extends GridLayoutManager.SpanSizeLookup {
+
+ public GridSpanSizer() {
+ super();
+ setSpanIndexCacheEnabled(true);
+ }
+
+ @Override
+ public int getSpanSize(int position) {
+ if (mApps.hasNoFilteredResults()) {
+ // Empty view spans full width
+ return mAppsPerRow;
+ }
+
+ switch (mApps.getAdapterItems().get(position).viewType) {
+ case AllAppsGridAdapter.ICON_VIEW_TYPE:
+ case AllAppsGridAdapter.PREDICTION_ICON_VIEW_TYPE:
+ return 1;
+ default:
+ // Section breaks span the full width
+ return mAppsPerRow;
+ }
+ }
+ }
+
+ /**
+ * Helper class to draw the section headers
+ */
+ public class GridItemDecoration extends RecyclerView.ItemDecoration {
+
+ private static final boolean DEBUG_SECTION_MARGIN = false;
+ private static final boolean FADE_OUT_SECTIONS = false;
+
+ private HashMap<String, PointF> mCachedSectionBounds = new HashMap<>();
+ private Rect mTmpBounds = new Rect();
+
+ @Override
+ public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
+ if (mApps.hasFilter() || mAppsPerRow == 0) {
+ return;
+ }
+
+ if (DEBUG_SECTION_MARGIN) {
+ Paint p = new Paint();
+ p.setColor(0x33ff0000);
+ c.drawRect(mBackgroundPadding.left, 0, mBackgroundPadding.left + mSectionNamesMargin,
+ parent.getMeasuredHeight(), p);
+ }
+
+ List<AlphabeticalAppsList.AdapterItem> items = mApps.getAdapterItems();
+ boolean hasDrawnPredictedAppsDivider = false;
+ boolean showSectionNames = mSectionNamesMargin > 0;
+ int childCount = parent.getChildCount();
+ int lastSectionTop = 0;
+ int lastSectionHeight = 0;
+ for (int i = 0; i < childCount; i++) {
+ View child = parent.getChildAt(i);
+ ViewHolder holder = (ViewHolder) parent.getChildViewHolder(child);
+ if (!isValidHolderAndChild(holder, child, items)) {
+ continue;
+ }
+
+ if (shouldDrawItemDivider(holder, items) && !hasDrawnPredictedAppsDivider) {
+ // Draw the divider under the predicted apps
+ int top = child.getTop() + child.getHeight() + mPredictionBarDividerOffset;
+ c.drawLine(mBackgroundPadding.left, top,
+ parent.getWidth() - mBackgroundPadding.right, top,
+ mPredictedAppsDividerPaint);
+ hasDrawnPredictedAppsDivider = true;
+
+ } else if (showSectionNames && shouldDrawItemSection(holder, i, items)) {
+ // At this point, we only draw sections for each section break;
+ int viewTopOffset = (2 * child.getPaddingTop());
+ int pos = holder.getPosition();
+ AlphabeticalAppsList.AdapterItem item = items.get(pos);
+ AlphabeticalAppsList.SectionInfo sectionInfo = item.sectionInfo;
+
+ // Draw all the sections for this index
+ String lastSectionName = item.sectionName;
+ for (int j = item.sectionAppIndex; j < sectionInfo.numApps; j++, pos++) {
+ AlphabeticalAppsList.AdapterItem nextItem = items.get(pos);
+ String sectionName = nextItem.sectionName;
+ if (nextItem.sectionInfo != sectionInfo) {
+ break;
+ }
+ if (j > item.sectionAppIndex && sectionName.equals(lastSectionName)) {
+ continue;
+ }
+
+
+ // Find the section name bounds
+ PointF sectionBounds = getAndCacheSectionBounds(sectionName);
+
+ // Calculate where to draw the section
+ int sectionBaseline = (int) (viewTopOffset + sectionBounds.y);
+ int x = mIsRtl ?
+ parent.getWidth() - mBackgroundPadding.left - mSectionNamesMargin :
+ mBackgroundPadding.left;
+ x += (int) ((mSectionNamesMargin - sectionBounds.x) / 2f);
+ int y = child.getTop() + sectionBaseline;
+
+ // Determine whether this is the last row with apps in that section, if
+ // so, then fix the section to the row allowing it to scroll past the
+ // baseline, otherwise, bound it to the baseline so it's in the viewport
+ int appIndexInSection = items.get(pos).sectionAppIndex;
+ int nextRowPos = Math.min(items.size() - 1,
+ pos + mAppsPerRow - (appIndexInSection % mAppsPerRow));
+ AlphabeticalAppsList.AdapterItem nextRowItem = items.get(nextRowPos);
+ boolean fixedToRow = !sectionName.equals(nextRowItem.sectionName);
+ if (!fixedToRow) {
+ y = Math.max(sectionBaseline, y);
+ }
+
+ // In addition, if it overlaps with the last section that was drawn, then
+ // offset it so that it does not overlap
+ if (lastSectionHeight > 0 && y <= (lastSectionTop + lastSectionHeight)) {
+ y += lastSectionTop - y + lastSectionHeight;
+ }
+
+ // Draw the section header
+ if (FADE_OUT_SECTIONS) {
+ int alpha = 255;
+ if (fixedToRow) {
+ alpha = Math.min(255,
+ (int) (255 * (Math.max(0, y) / (float) sectionBaseline)));
+ }
+ mSectionTextPaint.setAlpha(alpha);
+ }
+ c.drawText(sectionName, x, y, mSectionTextPaint);
+
+ lastSectionTop = y;
+ lastSectionHeight = (int) (sectionBounds.y + mSectionHeaderOffset);
+ lastSectionName = sectionName;
+ }
+ i += (sectionInfo.numApps - item.sectionAppIndex);
+ }
+ }
+ }
+
+ @Override
+ public void getItemOffsets(Rect outRect, View view, RecyclerView parent,
+ RecyclerView.State state) {
+ // Do nothing
+ }
+
+ /**
+ * Given a section name, return the bounds of the given section name.
+ */
+ private PointF getAndCacheSectionBounds(String sectionName) {
+ PointF bounds = mCachedSectionBounds.get(sectionName);
+ if (bounds == null) {
+ mSectionTextPaint.getTextBounds(sectionName, 0, sectionName.length(), mTmpBounds);
+ bounds = new PointF(mSectionTextPaint.measureText(sectionName), mTmpBounds.height());
+ mCachedSectionBounds.put(sectionName, bounds);
+ }
+ return bounds;
+ }
+
+ /**
+ * Returns whether we consider this a valid view holder for us to draw a divider or section for.
+ */
+ private boolean isValidHolderAndChild(ViewHolder holder, View child,
+ List<AlphabeticalAppsList.AdapterItem> items) {
+ // Ensure item is not already removed
+ GridLayoutManager.LayoutParams lp = (GridLayoutManager.LayoutParams)
+ child.getLayoutParams();
+ if (lp.isItemRemoved()) {
+ return false;
+ }
+ // Ensure we have a valid holder
+ if (holder == null) {
+ return false;
+ }
+ // Ensure we have a holder position
+ int pos = holder.getPosition();
+ if (pos < 0 || pos >= items.size()) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Returns whether to draw the divider for a given child.
+ */
+ private boolean shouldDrawItemDivider(ViewHolder holder,
+ List<AlphabeticalAppsList.AdapterItem> items) {
+ int pos = holder.getPosition();
+ return items.get(pos).viewType == AllAppsGridAdapter.PREDICTION_ICON_VIEW_TYPE;
+ }
+
+ /**
+ * Returns whether to draw the section for the given child.
+ */
+ private boolean shouldDrawItemSection(ViewHolder holder, int childIndex,
+ List<AlphabeticalAppsList.AdapterItem> items) {
+ int pos = holder.getPosition();
+ AlphabeticalAppsList.AdapterItem item = items.get(pos);
+
+ // Ensure it's an icon
+ if (item.viewType != AllAppsGridAdapter.ICON_VIEW_TYPE) {
+ return false;
+ }
+ // Draw the section header for the first item in each section
+ return (childIndex == 0) ||
+ (items.get(pos - 1).viewType == AllAppsGridAdapter.SECTION_BREAK_VIEW_TYPE);
+ }
+ }
+
+ private LayoutInflater mLayoutInflater;
+ @Thunk AlphabeticalAppsList mApps;
+ private GridLayoutManager mGridLayoutMgr;
+ private GridSpanSizer mGridSizer;
+ private GridItemDecoration mItemDecoration;
+ private View.OnTouchListener mTouchListener;
+ private View.OnClickListener mIconClickListener;
+ private View.OnLongClickListener mIconLongClickListener;
+ @Thunk final Rect mBackgroundPadding = new Rect();
+ @Thunk int mPredictionBarDividerOffset;
+ @Thunk int mAppsPerRow;
+ @Thunk boolean mIsRtl;
+ private String mEmptySearchText;
+
+ // Section drawing
+ @Thunk int mSectionNamesMargin;
+ @Thunk int mSectionHeaderOffset;
+ @Thunk Paint mSectionTextPaint;
+ @Thunk Paint mPredictedAppsDividerPaint;
+
+ public AllAppsGridAdapter(Context context, AlphabeticalAppsList apps,
+ View.OnTouchListener touchListener, View.OnClickListener iconClickListener,
+ View.OnLongClickListener iconLongClickListener) {
+ Resources res = context.getResources();
+ mApps = apps;
+ mGridSizer = new GridSpanSizer();
+ mGridLayoutMgr = new GridLayoutManager(context, 1, GridLayoutManager.VERTICAL, false);
+ mGridLayoutMgr.setSpanSizeLookup(mGridSizer);
+ mItemDecoration = new GridItemDecoration();
+ mLayoutInflater = LayoutInflater.from(context);
+ mTouchListener = touchListener;
+ mIconClickListener = iconClickListener;
+ mIconLongClickListener = iconLongClickListener;
+ mSectionNamesMargin = res.getDimensionPixelSize(R.dimen.all_apps_grid_view_start_margin);
+ mSectionHeaderOffset = res.getDimensionPixelSize(R.dimen.all_apps_grid_section_y_offset);
+
+ mSectionTextPaint = new Paint();
+ mSectionTextPaint.setTextSize(res.getDimensionPixelSize(
+ R.dimen.all_apps_grid_section_text_size));
+ mSectionTextPaint.setColor(res.getColor(R.color.all_apps_grid_section_text_color));
+ mSectionTextPaint.setAntiAlias(true);
+
+ mPredictedAppsDividerPaint = new Paint();
+ mPredictedAppsDividerPaint.setStrokeWidth(Utilities.pxFromDp(1f, res.getDisplayMetrics()));
+ mPredictedAppsDividerPaint.setColor(0x1E000000);
+ mPredictedAppsDividerPaint.setAntiAlias(true);
+ mPredictionBarDividerOffset =
+ (-res.getDimensionPixelSize(R.dimen.all_apps_prediction_icon_bottom_padding) +
+ res.getDimensionPixelSize(R.dimen.all_apps_icon_top_bottom_padding)) / 2;
+ }
+
+ /**
+ * Sets the number of apps per row.
+ */
+ public void setNumAppsPerRow(int appsPerRow) {
+ mAppsPerRow = appsPerRow;
+ mGridLayoutMgr.setSpanCount(appsPerRow);
+ }
+
+ /**
+ * Sets whether we are in RTL mode.
+ */
+ public void setRtl(boolean rtl) {
+ mIsRtl = rtl;
+ }
+
+ /**
+ * Sets the text to show when there are no apps.
+ */
+ public void setEmptySearchText(String query) {
+ mEmptySearchText = query;
+ }
+
+ /**
+ * Notifies the adapter of the background padding so that it can draw things correctly in the
+ * item decorator.
+ */
+ public void updateBackgroundPadding(Rect padding) {
+ mBackgroundPadding.set(padding);
+ }
+
+ /**
+ * Returns the grid layout manager.
+ */
+ public GridLayoutManager getLayoutManager() {
+ return mGridLayoutMgr;
+ }
+
+ /**
+ * Returns the item decoration for the recycler view.
+ */
+ public RecyclerView.ItemDecoration getItemDecoration() {
+ // We don't draw any headers when we are uncomfortably dense
+ return mItemDecoration;
+ }
+
+ @Override
+ public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
+ switch (viewType) {
+ case EMPTY_SEARCH_VIEW_TYPE:
+ return new ViewHolder(mLayoutInflater.inflate(R.layout.all_apps_empty_search, parent,
+ false));
+ case SECTION_BREAK_VIEW_TYPE:
+ return new ViewHolder(new View(parent.getContext()));
+ case ICON_VIEW_TYPE: {
+ BubbleTextView icon = (BubbleTextView) mLayoutInflater.inflate(
+ R.layout.all_apps_icon, parent, false);
+ icon.setOnTouchListener(mTouchListener);
+ icon.setOnClickListener(mIconClickListener);
+ icon.setOnLongClickListener(mIconLongClickListener);
+ icon.setLongPressTimeout(ViewConfiguration.get(parent.getContext())
+ .getLongPressTimeout());
+ icon.setFocusable(true);
+ return new ViewHolder(icon);
+ }
+ case PREDICTION_ICON_VIEW_TYPE: {
+ BubbleTextView icon = (BubbleTextView) mLayoutInflater.inflate(
+ R.layout.all_apps_prediction_bar_icon, parent, false);
+ icon.setOnTouchListener(mTouchListener);
+ icon.setOnClickListener(mIconClickListener);
+ icon.setOnLongClickListener(mIconLongClickListener);
+ icon.setLongPressTimeout(ViewConfiguration.get(parent.getContext())
+ .getLongPressTimeout());
+ icon.setFocusable(true);
+ return new ViewHolder(icon);
+ }
+ default:
+ throw new RuntimeException("Unexpected view type");
+ }
+ }
+
+ @Override
+ public void onBindViewHolder(ViewHolder holder, int position) {
+ switch (holder.getItemViewType()) {
+ case ICON_VIEW_TYPE: {
+ AppInfo info = mApps.getAdapterItems().get(position).appInfo;
+ BubbleTextView icon = (BubbleTextView) holder.mContent;
+ icon.applyFromApplicationInfo(info);
+ break;
+ }
+ case PREDICTION_ICON_VIEW_TYPE: {
+ AppInfo info = mApps.getAdapterItems().get(position).appInfo;
+ BubbleTextView icon = (BubbleTextView) holder.mContent;
+ icon.applyFromApplicationInfo(info);
+ break;
+ }
+ case EMPTY_SEARCH_VIEW_TYPE:
+ TextView emptyViewText = (TextView) holder.mContent.findViewById(R.id.empty_text);
+ emptyViewText.setText(mEmptySearchText);
+ break;
+ }
+ }
+
+ @Override
+ public int getItemCount() {
+ if (mApps.hasNoFilteredResults()) {
+ // For the empty view
+ return 1;
+ }
+ return mApps.getAdapterItems().size();
+ }
+
+ @Override
+ public int getItemViewType(int position) {
+ if (mApps.hasNoFilteredResults()) {
+ return EMPTY_SEARCH_VIEW_TYPE;
+ }
+
+ AlphabeticalAppsList.AdapterItem item = mApps.getAdapterItems().get(position);
+ return item.viewType;
+ }
+}
diff --git a/src/com/android/launcher3/allapps/AllAppsRecyclerView.java b/src/com/android/launcher3/allapps/AllAppsRecyclerView.java
new file mode 100644
index 000000000..730c8d15a
--- /dev/null
+++ b/src/com/android/launcher3/allapps/AllAppsRecyclerView.java
@@ -0,0 +1,327 @@
+/*
+ * 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.content.Context;
+import android.graphics.Canvas;
+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.DeviceProfile;
+import com.android.launcher3.Stats;
+import com.android.launcher3.Utilities;
+import com.android.launcher3.util.Thunk;
+
+import java.util.List;
+
+/**
+ * A RecyclerView with custom fast scroll support for the all apps view.
+ */
+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 int mNumAppsPerRow;
+
+ @Thunk BaseRecyclerViewFastScrollBar.FastScrollFocusableView mLastFastScrollFocusedView;
+ @Thunk int mPrevFastScrollFocusedPosition;
+ @Thunk int mFastScrollFrameIndex;
+ @Thunk final int[] mFastScrollFrames = new int[10];
+
+ 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();
+
+ public AllAppsRecyclerView(Context context) {
+ this(context, null);
+ }
+
+ public AllAppsRecyclerView(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public AllAppsRecyclerView(Context context, AttributeSet attrs, int defStyleAttr) {
+ this(context, attrs, defStyleAttr, 0);
+ }
+
+ public AllAppsRecyclerView(Context context, AttributeSet attrs, int defStyleAttr,
+ int defStyleRes) {
+ super(context, attrs, defStyleAttr);
+ }
+
+ /**
+ * Sets the list of apps in this view, used to determine the fastscroll position.
+ */
+ public void setApps(AlphabeticalAppsList apps) {
+ mApps = apps;
+ }
+
+ /**
+ * Sets the number of apps per row in this recycler view.
+ */
+ public void setNumAppsPerRow(DeviceProfile grid, int numAppsPerRow) {
+ mNumAppsPerRow = numAppsPerRow;
+
+ RecyclerView.RecycledViewPool pool = getRecycledViewPool();
+ int approxRows = (int) Math.ceil(grid.availableHeightPx / grid.allAppsIconSizePx);
+ pool.setMaxRecycledViews(AllAppsGridAdapter.EMPTY_SEARCH_VIEW_TYPE, 1);
+ pool.setMaxRecycledViews(AllAppsGridAdapter.ICON_VIEW_TYPE, approxRows * mNumAppsPerRow);
+ pool.setMaxRecycledViews(AllAppsGridAdapter.PREDICTION_ICON_VIEW_TYPE, mNumAppsPerRow);
+ pool.setMaxRecycledViews(AllAppsGridAdapter.SECTION_BREAK_VIEW_TYPE, approxRows);
+ }
+
+ /**
+ * Scrolls this recycler view to the top.
+ */
+ public void scrollToTop() {
+ scrollToPosition(0);
+ }
+
+ /**
+ * We need to override the draw to ensure that we don't draw the overscroll effect beyond the
+ * background bounds.
+ */
+ @Override
+ protected void dispatchDraw(Canvas canvas) {
+ canvas.clipRect(mBackgroundPadding.left, mBackgroundPadding.top,
+ getWidth() - mBackgroundPadding.right,
+ getHeight() - mBackgroundPadding.bottom);
+ super.dispatchDraw(canvas);
+ }
+
+ @Override
+ protected void onFinishInflate() {
+ super.onFinishInflate();
+
+ // Bind event handlers
+ addOnItemTouchListener(this);
+ }
+
+ @Override
+ public void fillInLaunchSourceData(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 {
+ sourceData.putString(Stats.SOURCE_EXTRA_SUB_CONTAINER,
+ Stats.SUB_CONTAINER_ALL_APPS_A_Z);
+ }
+ }
+
+ /**
+ * Maps the touch (from 0..1) to the adapter position that should be visible.
+ */
+ @Override
+ public String scrollToPositionAtProgress(float touchFraction) {
+ int rowCount = mApps.getNumAppRows();
+ if (rowCount == 0) {
+ return "";
+ }
+
+ // Stop the scroller if it is scrolling
+ stopScroll();
+
+ // Find the fastscroll section that maps to this touch fraction
+ 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;
+ }
+ } 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");
+ }
+
+ // Map the touch position back to the scroll of the recycler view
+ getCurScrollState(mScrollPosState, mApps.getAdapterItems());
+ int availableScrollHeight = getAvailableScrollHeight(rowCount, mScrollPosState.rowHeight, 0);
+ 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");
+ }
+ }
+ 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;
+ }
+
+ /**
+ * Updates the bounds for the scrollbar.
+ */
+ @Override
+ public void onUpdateScrollbar() {
+ List<AlphabeticalAppsList.AdapterItem> items = mApps.getAdapterItems();
+
+ // Skip early if there are no items or we haven't been measured
+ if (items.isEmpty() || mNumAppsPerRow == 0) {
+ mScrollbar.setScrollbarThumbOffset(-1, -1);
+ return;
+ }
+
+ // Find the index and height of the first visible row (all rows have the same height)
+ int rowCount = mApps.getNumAppRows();
+ getCurScrollState(mScrollPosState, items);
+ if (mScrollPosState.rowIndex < 0) {
+ mScrollbar.setScrollbarThumbOffset(-1, -1);
+ return;
+ }
+
+ synchronizeScrollBarThumbOffsetToViewScroll(mScrollPosState, rowCount, 0);
+ }
+
+ /**
+ * 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.
+ */
+ private void getCurScrollState(ScrollPositionState stateOut,
+ List<AlphabeticalAppsList.AdapterItem> items) {
+ stateOut.rowIndex = -1;
+ stateOut.rowTopOffset = -1;
+ stateOut.rowHeight = -1;
+
+ // Return early if there are no items or we haven't been measured
+ if (items.isEmpty() || mNumAppsPerRow == 0) {
+ return;
+ }
+
+ int childCount = getChildCount();
+ for (int i = 0; i < childCount; i++) {
+ View child = getChildAt(i);
+ 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) {
+ stateOut.rowIndex = item.rowIndex;
+ stateOut.rowTopOffset = getLayoutManager().getDecoratedTop(child);
+ stateOut.rowHeight = child.getHeight();
+ break;
+ }
+ }
+ }
+ }
+
+ /**
+ * 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 {
+ return 0;
+ }
+ }
+}
diff --git a/src/com/android/launcher3/allapps/AllAppsRecyclerViewContainerView.java b/src/com/android/launcher3/allapps/AllAppsRecyclerViewContainerView.java
new file mode 100644
index 000000000..14e2a1863
--- /dev/null
+++ b/src/com/android/launcher3/allapps/AllAppsRecyclerViewContainerView.java
@@ -0,0 +1,72 @@
+/*
+ * 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.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.FrameLayout;
+import com.android.launcher3.BubbleTextView;
+import com.android.launcher3.BubbleTextView.BubbleTextShadowHandler;
+import com.android.launcher3.ClickShadowView;
+import com.android.launcher3.DeviceProfile;
+import com.android.launcher3.Launcher;
+import com.android.launcher3.R;
+
+/**
+ * A container for RecyclerView to allow for the click shadow view to be shown behind an icon that
+ * is launching.
+ */
+public class AllAppsRecyclerViewContainerView extends FrameLayout
+ implements BubbleTextShadowHandler {
+
+ private final ClickShadowView mTouchFeedbackView;
+
+ public AllAppsRecyclerViewContainerView(Context context) {
+ this(context, null);
+ }
+
+ public AllAppsRecyclerViewContainerView(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public AllAppsRecyclerViewContainerView(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+
+ Launcher launcher = (Launcher) context;
+ DeviceProfile grid = launcher.getDeviceProfile();
+
+ mTouchFeedbackView = new ClickShadowView(context);
+
+ // Make the feedback view large enough to hold the blur bitmap.
+ int size = grid.allAppsIconSizePx + mTouchFeedbackView.getExtraSize();
+ addView(mTouchFeedbackView, size, size);
+ }
+
+ @Override
+ public void setPressedIcon(BubbleTextView icon, Bitmap background) {
+ if (icon == null || background == null) {
+ mTouchFeedbackView.setBitmap(null);
+ mTouchFeedbackView.animate().cancel();
+ } else if (mTouchFeedbackView.setBitmap(background)) {
+ mTouchFeedbackView.alignWithIconView(icon, (ViewGroup) icon.getParent());
+ mTouchFeedbackView.animateShadow();
+ }
+ }
+}
diff --git a/src/com/android/launcher3/allapps/AllAppsSearchBarController.java b/src/com/android/launcher3/allapps/AllAppsSearchBarController.java
new file mode 100644
index 000000000..2b363c0cb
--- /dev/null
+++ b/src/com/android/launcher3/allapps/AllAppsSearchBarController.java
@@ -0,0 +1,100 @@
+/*
+ * 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.content.ComponentName;
+import android.graphics.Rect;
+import android.view.View;
+import android.view.ViewGroup;
+
+import com.android.launcher3.util.ComponentKey;
+
+import java.util.ArrayList;
+
+/**
+ * An interface to a search box that AllApps can command.
+ */
+public abstract class AllAppsSearchBarController {
+
+ protected AlphabeticalAppsList mApps;
+ protected Callbacks mCb;
+
+ /**
+ * Sets the references to the apps model and the search result callback.
+ */
+ public final void initialize(AlphabeticalAppsList apps, Callbacks cb) {
+ mApps = apps;
+ mCb = cb;
+ onInitialize();
+ }
+
+ /**
+ * To be overridden by subclasses. This method will get called when the controller is set,
+ * before getView().
+ */
+ protected abstract void onInitialize();
+
+ /**
+ * Returns the search bar view.
+ * @param parent the parent to attach the search bar view to.
+ */
+ public abstract View getView(ViewGroup parent);
+
+ /**
+ * Focuses the search field to handle key events.
+ */
+ public abstract void focusSearchField();
+
+ /**
+ * Returns whether the search field is focused.
+ */
+ public abstract boolean isSearchFieldFocused();
+
+ /**
+ * Resets the search bar state.
+ */
+ public abstract void reset();
+
+ /**
+ * Returns whether the prediction bar should currently be visible depending on the state of
+ * the search bar.
+ */
+ @Deprecated
+ public abstract boolean shouldShowPredictionBar();
+
+ /**
+ * Callback for getting search results.
+ */
+ public interface Callbacks {
+
+ /**
+ * Called when the bounds of the search bar has changed.
+ */
+ void onBoundsChanged(Rect newBounds);
+
+ /**
+ * Called when the search is complete.
+ *
+ * @param apps sorted list of matching components or null if in case of failure.
+ */
+ void onSearchResult(String query, ArrayList<ComponentKey> apps);
+
+ /**
+ * Called when the search results should be cleared.
+ */
+ void clearSearchResult();
+ }
+} \ No newline at end of file
diff --git a/src/com/android/launcher3/allapps/AllAppsSearchEditView.java b/src/com/android/launcher3/allapps/AllAppsSearchEditView.java
new file mode 100644
index 000000000..b7dcd66ed
--- /dev/null
+++ b/src/com/android/launcher3/allapps/AllAppsSearchEditView.java
@@ -0,0 +1,65 @@
+/*
+ * 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.content.Context;
+import android.util.AttributeSet;
+import android.view.KeyEvent;
+import android.widget.EditText;
+
+
+/**
+ * The edit text for the search container
+ */
+public class AllAppsSearchEditView extends EditText {
+
+ /**
+ * Implemented by listeners of the back key.
+ */
+ public interface OnBackKeyListener {
+ public void onBackKey();
+ }
+
+ private OnBackKeyListener mBackKeyListener;
+
+ public AllAppsSearchEditView(Context context) {
+ this(context, null);
+ }
+
+ public AllAppsSearchEditView(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public AllAppsSearchEditView(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ }
+
+ public void setOnBackKeyListener(OnBackKeyListener listener) {
+ mBackKeyListener = listener;
+ }
+
+ @Override
+ public boolean onKeyPreIme(int keyCode, KeyEvent event) {
+ // If this is a back key, propagate the key back to the listener
+ if (keyCode == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_UP) {
+ if (mBackKeyListener != null) {
+ mBackKeyListener.onBackKey();
+ }
+ return false;
+ }
+ return super.onKeyPreIme(keyCode, event);
+ }
+}
diff --git a/src/com/android/launcher3/allapps/AlphabeticalAppsList.java b/src/com/android/launcher3/allapps/AlphabeticalAppsList.java
new file mode 100644
index 000000000..47241ce5d
--- /dev/null
+++ b/src/com/android/launcher3/allapps/AlphabeticalAppsList.java
@@ -0,0 +1,590 @@
+/*
+ * 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.content.Context;
+import android.support.v7.widget.RecyclerView;
+import android.util.Log;
+import com.android.launcher3.AppInfo;
+import com.android.launcher3.Launcher;
+import com.android.launcher3.LauncherAppState;
+import com.android.launcher3.compat.AlphabeticIndexCompat;
+import com.android.launcher3.compat.UserHandleCompat;
+import com.android.launcher3.model.AppNameComparator;
+import com.android.launcher3.util.ComponentKey;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.TreeMap;
+
+/**
+ * The alphabetically sorted list of applications.
+ */
+public class AlphabeticalAppsList {
+
+ public static final String TAG = "AlphabeticalAppsList";
+ private static final boolean DEBUG = false;
+ private static final boolean DEBUG_PREDICTIONS = false;
+
+ /**
+ * Info about a section in the alphabetic list
+ */
+ public static class SectionInfo {
+ // The number of applications in this section
+ public int numApps;
+ // The section break AdapterItem for this section
+ public AdapterItem sectionBreakItem;
+ // The first app AdapterItem for this section
+ public AdapterItem firstAppItem;
+ }
+
+ /**
+ * Info about a fast scroller section, depending if sections are merged, the fast scroller
+ * sections will not be the same set as the section headers.
+ */
+ public static class FastScrollSectionInfo {
+ // The section name
+ public String sectionName;
+ // The AdapterItem to scroll to for this section
+ public AdapterItem fastScrollToItem;
+ // The touch fraction that should map to this fast scroll section info
+ public float touchFraction;
+
+ public FastScrollSectionInfo(String sectionName) {
+ this.sectionName = sectionName;
+ }
+ }
+
+ /**
+ * Info about a particular adapter item (can be either section or app)
+ */
+ public static class AdapterItem {
+ /** Common properties */
+ // The index of this adapter item in the list
+ public int position;
+ // The type of this item
+ public int viewType;
+ // The row that this item shows up on
+ public int rowIndex;
+
+ /** Section & App properties */
+ // The section for this item
+ public SectionInfo sectionInfo;
+
+ /** App-only properties */
+ // The section name of this app. Note that there can be multiple items with different
+ // sectionNames in the same section
+ public String sectionName = null;
+ // The index of this app in the section
+ public int sectionAppIndex = -1;
+ // The index of this app in the row
+ public int rowAppIndex;
+ // The associated AppInfo for the app
+ public AppInfo appInfo = null;
+ // The index of this app not including sections
+ public int appIndex = -1;
+
+ public static AdapterItem asSectionBreak(int pos, SectionInfo section) {
+ AdapterItem item = new AdapterItem();
+ item.viewType = AllAppsGridAdapter.SECTION_BREAK_VIEW_TYPE;
+ item.position = pos;
+ item.sectionInfo = section;
+ section.sectionBreakItem = item;
+ return item;
+ }
+
+ public static AdapterItem asPredictedApp(int pos, SectionInfo section, String sectionName,
+ int sectionAppIndex, AppInfo appInfo, int appIndex) {
+ AdapterItem item = asApp(pos, section, sectionName, sectionAppIndex, appInfo, appIndex);
+ item.viewType = AllAppsGridAdapter.PREDICTION_ICON_VIEW_TYPE;
+ return item;
+ }
+
+ public static AdapterItem asApp(int pos, SectionInfo section, String sectionName,
+ int sectionAppIndex, AppInfo appInfo, int appIndex) {
+ AdapterItem item = new AdapterItem();
+ item.viewType = AllAppsGridAdapter.ICON_VIEW_TYPE;
+ item.position = pos;
+ item.sectionInfo = section;
+ item.sectionName = sectionName;
+ item.sectionAppIndex = sectionAppIndex;
+ item.appInfo = appInfo;
+ item.appIndex = appIndex;
+ return item;
+ }
+ }
+
+ /**
+ * Common interface for different merging strategies.
+ */
+ public interface MergeAlgorithm {
+ boolean continueMerging(SectionInfo section, SectionInfo withSection,
+ int sectionAppCount, int numAppsPerRow, int mergeCount);
+ }
+
+ private Launcher mLauncher;
+
+ // The set of apps from the system not including predictions
+ private final List<AppInfo> mApps = new ArrayList<>();
+ private final HashMap<ComponentKey, AppInfo> mComponentToAppMap = new HashMap<>();
+
+ // The set of filtered apps with the current filter
+ private List<AppInfo> mFilteredApps = new ArrayList<>();
+ // The current set of adapter items
+ private List<AdapterItem> mAdapterItems = new ArrayList<>();
+ // The set of sections for the apps with the current filter
+ private List<SectionInfo> mSections = new ArrayList<>();
+ // The set of sections that we allow fast-scrolling to (includes non-merged sections)
+ private List<FastScrollSectionInfo> mFastScrollerSections = new ArrayList<>();
+ // The set of predicted app component names
+ private List<ComponentKey> mPredictedAppComponents = new ArrayList<>();
+ // The set of predicted apps resolved from the component names and the current set of apps
+ private List<AppInfo> mPredictedApps = new ArrayList<>();
+ // The of ordered component names as a result of a search query
+ private ArrayList<ComponentKey> mSearchResults;
+ private HashMap<CharSequence, String> mCachedSectionNames = new HashMap<>();
+ private RecyclerView.Adapter mAdapter;
+ private AlphabeticIndexCompat mIndexer;
+ private AppNameComparator mAppNameComparator;
+ private MergeAlgorithm mMergeAlgorithm;
+ private int mNumAppsPerRow;
+ private int mNumPredictedAppsPerRow;
+ private int mNumAppRowsInAdapter;
+
+ public AlphabeticalAppsList(Context context) {
+ mLauncher = (Launcher) context;
+ mIndexer = new AlphabeticIndexCompat(context);
+ mAppNameComparator = new AppNameComparator(context);
+ }
+
+ /**
+ * Sets the number of apps per row.
+ */
+ public void setNumAppsPerRow(int numAppsPerRow, int numPredictedAppsPerRow,
+ MergeAlgorithm mergeAlgorithm) {
+ mNumAppsPerRow = numAppsPerRow;
+ mNumPredictedAppsPerRow = numPredictedAppsPerRow;
+ mMergeAlgorithm = mergeAlgorithm;
+
+ updateAdapterItems();
+ }
+
+ /**
+ * Sets the adapter to notify when this dataset changes.
+ */
+ public void setAdapter(RecyclerView.Adapter adapter) {
+ mAdapter = adapter;
+ }
+
+ /**
+ * Returns all the apps.
+ */
+ public List<AppInfo> getApps() {
+ return mApps;
+ }
+
+ /**
+ * Returns sections of all the current filtered applications.
+ */
+ public List<SectionInfo> getSections() {
+ return mSections;
+ }
+
+ /**
+ * Returns fast scroller sections of all the current filtered applications.
+ */
+ public List<FastScrollSectionInfo> getFastScrollerSections() {
+ return mFastScrollerSections;
+ }
+
+ /**
+ * Returns the current filtered list of applications broken down into their sections.
+ */
+ public List<AdapterItem> getAdapterItems() {
+ return mAdapterItems;
+ }
+
+ /**
+ * Returns the number of applications in this list.
+ */
+ public int getSize() {
+ return mFilteredApps.size();
+ }
+
+ /**
+ * Returns the number of rows of applications (not including predictions)
+ */
+ public int getNumAppRows() {
+ return mNumAppRowsInAdapter;
+ }
+
+ /**
+ * Returns whether there are is a filter set.
+ */
+ public boolean hasFilter() {
+ return (mSearchResults != null);
+ }
+
+ /**
+ * Returns whether there are no filtered results.
+ */
+ public boolean hasNoFilteredResults() {
+ return (mSearchResults != null) && mFilteredApps.isEmpty();
+ }
+
+ /**
+ * Sets the sorted list of filtered components.
+ */
+ public void setOrderedFilter(ArrayList<ComponentKey> f) {
+ if (mSearchResults != f) {
+ mSearchResults = f;
+ updateAdapterItems();
+ }
+ }
+
+ /**
+ * Sets the current set of predicted apps. Since this can be called before we get the full set
+ * of applications, we should merge the results only in onAppsUpdated() which is idempotent.
+ */
+ public void setPredictedApps(List<ComponentKey> apps) {
+ mPredictedAppComponents.clear();
+ mPredictedAppComponents.addAll(apps);
+ onAppsUpdated();
+ }
+
+ /**
+ * Sets the current set of apps.
+ */
+ public void setApps(List<AppInfo> apps) {
+ mComponentToAppMap.clear();
+ addApps(apps);
+ }
+
+ /**
+ * Adds new apps to the list.
+ */
+ public void addApps(List<AppInfo> apps) {
+ updateApps(apps);
+ }
+
+ /**
+ * Updates existing apps in the list
+ */
+ public void updateApps(List<AppInfo> apps) {
+ for (AppInfo app : apps) {
+ mComponentToAppMap.put(app.toComponentKey(), app);
+ }
+ onAppsUpdated();
+ }
+
+ /**
+ * Removes some apps from the list.
+ */
+ public void removeApps(List<AppInfo> apps) {
+ for (AppInfo app : apps) {
+ mComponentToAppMap.remove(app.toComponentKey());
+ }
+ onAppsUpdated();
+ }
+
+ /**
+ * Updates internals when the set of apps are updated.
+ */
+ private void onAppsUpdated() {
+ // Sort the list of apps
+ mApps.clear();
+ mApps.addAll(mComponentToAppMap.values());
+ Collections.sort(mApps, mAppNameComparator.getAppInfoComparator());
+
+ // As a special case for some languages (currently only Simplified Chinese), we may need to
+ // coalesce sections
+ Locale curLocale = mLauncher.getResources().getConfiguration().locale;
+ TreeMap<String, ArrayList<AppInfo>> sectionMap = null;
+ boolean localeRequiresSectionSorting = curLocale.equals(Locale.SIMPLIFIED_CHINESE);
+ if (localeRequiresSectionSorting) {
+ // Compute the section headers. We use a TreeMap with the section name comparator to
+ // ensure that the sections are ordered when we iterate over it later
+ sectionMap = new TreeMap<>(mAppNameComparator.getSectionNameComparator());
+ for (AppInfo info : mApps) {
+ // Add the section to the cache
+ String sectionName = getAndUpdateCachedSectionName(info.title);
+
+ // Add it to the mapping
+ ArrayList<AppInfo> sectionApps = sectionMap.get(sectionName);
+ if (sectionApps == null) {
+ sectionApps = new ArrayList<>();
+ sectionMap.put(sectionName, sectionApps);
+ }
+ sectionApps.add(info);
+ }
+
+ // Add each of the section apps to the list in order
+ List<AppInfo> allApps = new ArrayList<>(mApps.size());
+ for (Map.Entry<String, ArrayList<AppInfo>> entry : sectionMap.entrySet()) {
+ allApps.addAll(entry.getValue());
+ }
+
+ mApps.clear();
+ mApps.addAll(allApps);
+ } else {
+ // Just compute the section headers for use below
+ for (AppInfo info : mApps) {
+ // Add the section to the cache
+ getAndUpdateCachedSectionName(info.title);
+ }
+ }
+
+ // Recompose the set of adapter items from the current set of apps
+ updateAdapterItems();
+ }
+
+ /**
+ * Updates the set of filtered apps with the current filter. At this point, we expect
+ * mCachedSectionNames to have been calculated for the set of all apps in mApps.
+ */
+ private void updateAdapterItems() {
+ SectionInfo lastSectionInfo = null;
+ String lastSectionName = null;
+ FastScrollSectionInfo lastFastScrollerSectionInfo = null;
+ int position = 0;
+ int appIndex = 0;
+
+ // Prepare to update the list of sections, filtered apps, etc.
+ mFilteredApps.clear();
+ mFastScrollerSections.clear();
+ mAdapterItems.clear();
+ mSections.clear();
+
+ if (DEBUG_PREDICTIONS) {
+ if (mPredictedAppComponents.isEmpty() && !mApps.isEmpty()) {
+ mPredictedAppComponents.add(new ComponentKey(mApps.get(0).componentName,
+ UserHandleCompat.myUserHandle()));
+ mPredictedAppComponents.add(new ComponentKey(mApps.get(0).componentName,
+ UserHandleCompat.myUserHandle()));
+ mPredictedAppComponents.add(new ComponentKey(mApps.get(0).componentName,
+ UserHandleCompat.myUserHandle()));
+ mPredictedAppComponents.add(new ComponentKey(mApps.get(0).componentName,
+ UserHandleCompat.myUserHandle()));
+ }
+ }
+
+ // Process the predicted app components
+ mPredictedApps.clear();
+ if (mPredictedAppComponents != null && !mPredictedAppComponents.isEmpty() && !hasFilter()) {
+ for (ComponentKey ck : mPredictedAppComponents) {
+ AppInfo info = mComponentToAppMap.get(ck);
+ if (info != null) {
+ mPredictedApps.add(info);
+ } else {
+ if (LauncherAppState.isDogfoodBuild()) {
+ Log.e(TAG, "Predicted app not found: " + ck.flattenToString(mLauncher));
+ }
+ }
+ // Stop at the number of predicted apps
+ if (mPredictedApps.size() == mNumPredictedAppsPerRow) {
+ break;
+ }
+ }
+
+ if (!mPredictedApps.isEmpty()) {
+ // Add a section for the predictions
+ lastSectionInfo = new SectionInfo();
+ lastFastScrollerSectionInfo = new FastScrollSectionInfo("");
+ AdapterItem sectionItem = AdapterItem.asSectionBreak(position++, lastSectionInfo);
+ mSections.add(lastSectionInfo);
+ mFastScrollerSections.add(lastFastScrollerSectionInfo);
+ mAdapterItems.add(sectionItem);
+
+ // Add the predicted app items
+ for (AppInfo info : mPredictedApps) {
+ AdapterItem appItem = AdapterItem.asPredictedApp(position++, lastSectionInfo,
+ "", lastSectionInfo.numApps++, info, appIndex++);
+ if (lastSectionInfo.firstAppItem == null) {
+ lastSectionInfo.firstAppItem = appItem;
+ lastFastScrollerSectionInfo.fastScrollToItem = appItem;
+ }
+ mAdapterItems.add(appItem);
+ mFilteredApps.add(info);
+ }
+ }
+ }
+
+ // Recreate the filtered and sectioned apps (for convenience for the grid layout) from the
+ // ordered set of sections
+ for (AppInfo info : getFiltersAppInfos()) {
+ String sectionName = getAndUpdateCachedSectionName(info.title);
+
+ // Create a new section if the section names do not match
+ if (lastSectionInfo == null || !sectionName.equals(lastSectionName)) {
+ lastSectionName = sectionName;
+ lastSectionInfo = new SectionInfo();
+ lastFastScrollerSectionInfo = new FastScrollSectionInfo(sectionName);
+ mSections.add(lastSectionInfo);
+ mFastScrollerSections.add(lastFastScrollerSectionInfo);
+
+ // Create a new section item to break the flow of items in the list
+ if (!hasFilter()) {
+ AdapterItem sectionItem = AdapterItem.asSectionBreak(position++, lastSectionInfo);
+ mAdapterItems.add(sectionItem);
+ }
+ }
+
+ // Create an app item
+ AdapterItem appItem = AdapterItem.asApp(position++, lastSectionInfo, sectionName,
+ lastSectionInfo.numApps++, info, appIndex++);
+ if (lastSectionInfo.firstAppItem == null) {
+ lastSectionInfo.firstAppItem = appItem;
+ lastFastScrollerSectionInfo.fastScrollToItem = appItem;
+ }
+ mAdapterItems.add(appItem);
+ mFilteredApps.add(info);
+ }
+
+ // Merge multiple sections together as requested by the merge strategy for this device
+ mergeSections();
+
+ if (mNumAppsPerRow != 0) {
+ // Update the number of rows in the adapter after we do all the merging (otherwise, we
+ // would have to shift the values again)
+ int numAppsInSection = 0;
+ int numAppsInRow = 0;
+ int rowIndex = -1;
+ for (AdapterItem item : mAdapterItems) {
+ item.rowIndex = 0;
+ if (item.viewType == AllAppsGridAdapter.SECTION_BREAK_VIEW_TYPE) {
+ numAppsInSection = 0;
+ } else if (item.viewType == AllAppsGridAdapter.ICON_VIEW_TYPE ||
+ item.viewType == AllAppsGridAdapter.PREDICTION_ICON_VIEW_TYPE) {
+ if (numAppsInSection % mNumAppsPerRow == 0) {
+ numAppsInRow = 0;
+ rowIndex++;
+ }
+ item.rowIndex = rowIndex;
+ item.rowAppIndex = numAppsInRow;
+ numAppsInSection++;
+ numAppsInRow++;
+ }
+ }
+ mNumAppRowsInAdapter = rowIndex + 1;
+
+ // Pre-calculate all the fast scroller fractions based on the number of rows
+ float rowFraction = 1f / mNumAppRowsInAdapter;
+ for (FastScrollSectionInfo info : mFastScrollerSections) {
+ AdapterItem item = info.fastScrollToItem;
+ if (item.viewType != AllAppsGridAdapter.ICON_VIEW_TYPE &&
+ item.viewType != AllAppsGridAdapter.PREDICTION_ICON_VIEW_TYPE) {
+ info.touchFraction = 0f;
+ continue;
+ }
+
+ float subRowFraction = item.rowAppIndex * (rowFraction / mNumAppsPerRow);
+ info.touchFraction = item.rowIndex * rowFraction + subRowFraction;
+ }
+ }
+
+ // Refresh the recycler view
+ if (mAdapter != null) {
+ mAdapter.notifyDataSetChanged();
+ }
+ }
+
+ private List<AppInfo> getFiltersAppInfos() {
+ if (mSearchResults == null) {
+ return mApps;
+ }
+
+ ArrayList<AppInfo> result = new ArrayList<>();
+ for (ComponentKey key : mSearchResults) {
+ AppInfo match = mComponentToAppMap.get(key);
+ if (match != null) {
+ result.add(match);
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Merges multiple sections to reduce visual raggedness.
+ */
+ private void mergeSections() {
+ // Ignore merging until we have an algorithm and a valid row size
+ if (mMergeAlgorithm == null || mNumAppsPerRow == 0) {
+ return;
+ }
+
+ // Go through each section and try and merge some of the sections
+ if (!hasFilter()) {
+ int sectionAppCount = 0;
+ for (int i = 0; i < mSections.size() - 1; i++) {
+ SectionInfo section = mSections.get(i);
+ sectionAppCount = section.numApps;
+ int mergeCount = 1;
+
+ // Merge rows based on the current strategy
+ while (i < (mSections.size() - 1) &&
+ mMergeAlgorithm.continueMerging(section, mSections.get(i + 1),
+ sectionAppCount, mNumAppsPerRow, mergeCount)) {
+ SectionInfo nextSection = mSections.remove(i + 1);
+
+ // Remove the next section break
+ mAdapterItems.remove(nextSection.sectionBreakItem);
+ int pos = mAdapterItems.indexOf(section.firstAppItem);
+
+ // Point the section for these new apps to the merged section
+ int nextPos = pos + section.numApps;
+ for (int j = nextPos; j < (nextPos + nextSection.numApps); j++) {
+ AdapterItem item = mAdapterItems.get(j);
+ item.sectionInfo = section;
+ item.sectionAppIndex += section.numApps;
+ }
+
+ // Update the following adapter items of the removed section item
+ pos = mAdapterItems.indexOf(nextSection.firstAppItem);
+ for (int j = pos; j < mAdapterItems.size(); j++) {
+ AdapterItem item = mAdapterItems.get(j);
+ item.position--;
+ }
+ section.numApps += nextSection.numApps;
+ sectionAppCount += nextSection.numApps;
+
+ if (DEBUG) {
+ Log.d(TAG, "Merging: " + nextSection.firstAppItem.sectionName +
+ " to " + section.firstAppItem.sectionName +
+ " mergedNumRows: " + (sectionAppCount / mNumAppsPerRow));
+ }
+ mergeCount++;
+ }
+ }
+ }
+ }
+
+ /**
+ * Returns the cached section name for the given title, recomputing and updating the cache if
+ * the title has no cached section name.
+ */
+ private String getAndUpdateCachedSectionName(CharSequence title) {
+ String sectionName = mCachedSectionNames.get(title);
+ if (sectionName == null) {
+ sectionName = mIndexer.computeSectionName(title);
+ mCachedSectionNames.put(title, sectionName);
+ }
+ return sectionName;
+ }
+}
diff --git a/src/com/android/launcher3/allapps/DefaultAppSearchAlgorithm.java b/src/com/android/launcher3/allapps/DefaultAppSearchAlgorithm.java
new file mode 100644
index 000000000..10740ec77
--- /dev/null
+++ b/src/com/android/launcher3/allapps/DefaultAppSearchAlgorithm.java
@@ -0,0 +1,94 @@
+/*
+ * 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.os.Handler;
+
+import com.android.launcher3.AppInfo;
+import com.android.launcher3.util.ComponentKey;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.regex.Pattern;
+
+/**
+ * The default search implementation.
+ */
+public class DefaultAppSearchAlgorithm {
+
+ private static final Pattern SPLIT_PATTERN = Pattern.compile("[\\s|\\p{javaSpaceChar}]+");
+
+ private final List<AppInfo> mApps;
+ protected final Handler mResultHandler;
+
+ public DefaultAppSearchAlgorithm(List<AppInfo> apps) {
+ mApps = apps;
+ mResultHandler = new Handler();
+ }
+
+ public void cancel(boolean interruptActiveRequests) {
+ if (interruptActiveRequests) {
+ mResultHandler.removeCallbacksAndMessages(null);
+ }
+ }
+
+ public void doSearch(final String query,
+ final AllAppsSearchBarController.Callbacks callback) {
+ final ArrayList<ComponentKey> result = getTitleMatchResult(query);
+ mResultHandler.post(new Runnable() {
+
+ @Override
+ public void run() {
+ callback.onSearchResult(query, result);
+ }
+ });
+ }
+
+ protected ArrayList<ComponentKey> getTitleMatchResult(String query) {
+ // Do an intersection of the words in the query and each title, and filter out all the
+ // apps that don't match all of the words in the query.
+ final String queryTextLower = query.toLowerCase();
+ final String[] queryWords = SPLIT_PATTERN.split(queryTextLower);
+
+ final ArrayList<ComponentKey> result = new ArrayList<>();
+ for (AppInfo info : mApps) {
+ if (matches(info, queryWords)) {
+ result.add(info.toComponentKey());
+ }
+ }
+ return result;
+ }
+
+ protected boolean matches(AppInfo info, String[] queryWords) {
+ String title = info.title.toString();
+ String[] words = SPLIT_PATTERN.split(title.toLowerCase());
+ for (int qi = 0; qi < queryWords.length; qi++) {
+ boolean foundMatch = false;
+ for (int i = 0; i < words.length; i++) {
+ if (words[i].startsWith(queryWords[qi])) {
+ foundMatch = true;
+ break;
+ }
+ }
+ if (!foundMatch) {
+ // If there is a word in the query that does not match any words in this
+ // title, so skip it.
+ return false;
+ }
+ }
+ return true;
+ }
+}
diff --git a/src/com/android/launcher3/allapps/DefaultAppSearchController.java b/src/com/android/launcher3/allapps/DefaultAppSearchController.java
new file mode 100644
index 000000000..83b920589
--- /dev/null
+++ b/src/com/android/launcher3/allapps/DefaultAppSearchController.java
@@ -0,0 +1,269 @@
+/*
+ * 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.content.Context;
+import android.text.Editable;
+import android.text.TextWatcher;
+import android.view.KeyEvent;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.inputmethod.EditorInfo;
+import android.view.inputmethod.InputMethodManager;
+import android.widget.TextView;
+import com.android.launcher3.R;
+import com.android.launcher3.Utilities;
+import com.android.launcher3.util.Thunk;
+
+import java.util.List;
+
+
+/**
+ * The default search controller.
+ */
+final class DefaultAppSearchController extends AllAppsSearchBarController
+ implements TextWatcher, TextView.OnEditorActionListener, View.OnClickListener {
+
+ private static final boolean ALLOW_SINGLE_APP_LAUNCH = true;
+
+ private static final int FADE_IN_DURATION = 175;
+ private static final int FADE_OUT_DURATION = 100;
+ private static final int SEARCH_TRANSLATION_X_DP = 18;
+
+ private final Context mContext;
+ @Thunk final InputMethodManager mInputMethodManager;
+
+ private DefaultAppSearchAlgorithm mSearchManager;
+
+ private ViewGroup mContainerView;
+ private View mSearchView;
+ @Thunk View mSearchBarContainerView;
+ private View mSearchButtonView;
+ private View mDismissSearchButtonView;
+ @Thunk AllAppsSearchEditView mSearchBarEditView;
+ @Thunk AllAppsRecyclerView mAppsRecyclerView;
+ @Thunk Runnable mFocusRecyclerViewRunnable = new Runnable() {
+ @Override
+ public void run() {
+ mAppsRecyclerView.requestFocus();
+ }
+ };
+
+ public DefaultAppSearchController(Context context, ViewGroup containerView,
+ AllAppsRecyclerView appsRecyclerView) {
+ mContext = context;
+ mInputMethodManager = (InputMethodManager)
+ mContext.getSystemService(Context.INPUT_METHOD_SERVICE);
+ mContainerView = containerView;
+ mAppsRecyclerView = appsRecyclerView;
+ }
+
+ @Override
+ public View getView(ViewGroup parent) {
+ LayoutInflater inflater = LayoutInflater.from(parent.getContext());
+ mSearchView = inflater.inflate(R.layout.all_apps_search_bar, parent, false);
+ mSearchView.setOnClickListener(this);
+
+ mSearchButtonView = mSearchView.findViewById(R.id.search_button);
+ mSearchBarContainerView = mSearchView.findViewById(R.id.search_container);
+ mDismissSearchButtonView = mSearchBarContainerView.findViewById(R.id.dismiss_search_button);
+ mDismissSearchButtonView.setOnClickListener(this);
+ mSearchBarEditView = (AllAppsSearchEditView)
+ mSearchBarContainerView.findViewById(R.id.search_box_input);
+ mSearchBarEditView.addTextChangedListener(this);
+ mSearchBarEditView.setOnEditorActionListener(this);
+ mSearchBarEditView.setOnBackKeyListener(
+ new AllAppsSearchEditView.OnBackKeyListener() {
+ @Override
+ public void onBackKey() {
+ // Only hide the search field if there is no query, or if there
+ // are no filtered results
+ String query = Utilities.trim(
+ mSearchBarEditView.getEditableText().toString());
+ if (query.isEmpty() || mApps.hasNoFilteredResults()) {
+ hideSearchField(true, mFocusRecyclerViewRunnable);
+ }
+ }
+ });
+ return mSearchView;
+ }
+
+ @Override
+ public void focusSearchField() {
+ mSearchBarEditView.requestFocus();
+ showSearchField();
+ }
+
+ @Override
+ public boolean isSearchFieldFocused() {
+ return mSearchBarEditView.isFocused();
+ }
+
+ @Override
+ protected void onInitialize() {
+ mSearchManager = new DefaultAppSearchAlgorithm(mApps.getApps());
+ }
+
+ @Override
+ public void reset() {
+ hideSearchField(false, null);
+ }
+
+ @Override
+ public boolean shouldShowPredictionBar() {
+ return false;
+ }
+
+ @Override
+ public void onClick(View v) {
+ if (v == mSearchView) {
+ showSearchField();
+ } else if (v == mDismissSearchButtonView) {
+ hideSearchField(true, mFocusRecyclerViewRunnable);
+ }
+ }
+
+ @Override
+ public void beforeTextChanged(CharSequence s, int start, int count, int after) {
+ // Do nothing
+ }
+
+ @Override
+ public void onTextChanged(CharSequence s, int start, int before, int count) {
+ // Do nothing
+ }
+
+ @Override
+ public void afterTextChanged(final Editable s) {
+ String query = s.toString();
+ if (query.isEmpty()) {
+ mSearchManager.cancel(true);
+ mCb.clearSearchResult();
+ } else {
+ mSearchManager.cancel(false);
+ mSearchManager.doSearch(query, mCb);
+ }
+ }
+
+ @Override
+ public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
+ // Skip if we disallow app-launch-on-enter
+ if (!ALLOW_SINGLE_APP_LAUNCH) {
+ return false;
+ }
+ // Skip if it's not the right action
+ if (actionId != EditorInfo.IME_ACTION_DONE) {
+ return false;
+ }
+ // Skip if there isn't exactly one item
+ if (mApps.getSize() != 1) {
+ return false;
+ }
+ // If there is exactly one icon, then quick-launch it
+ List<AlphabeticalAppsList.AdapterItem> items = mApps.getAdapterItems();
+ for (int i = 0; i < items.size(); i++) {
+ AlphabeticalAppsList.AdapterItem item = items.get(i);
+ if (item.viewType == AllAppsGridAdapter.ICON_VIEW_TYPE) {
+ mAppsRecyclerView.getChildAt(i).performClick();
+ mInputMethodManager.hideSoftInputFromWindow(
+ mContainerView.getWindowToken(), 0);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Focuses the search field.
+ */
+ private void showSearchField() {
+ // Show the search bar and focus the search
+ final int translationX = Utilities.pxFromDp(SEARCH_TRANSLATION_X_DP,
+ mContext.getResources().getDisplayMetrics());
+ mSearchBarContainerView.setVisibility(View.VISIBLE);
+ mSearchBarContainerView.setAlpha(0f);
+ mSearchBarContainerView.setTranslationX(translationX);
+ mSearchBarContainerView.animate()
+ .alpha(1f)
+ .translationX(0)
+ .setDuration(FADE_IN_DURATION)
+ .withLayer()
+ .withEndAction(new Runnable() {
+ @Override
+ public void run() {
+ mSearchBarEditView.requestFocus();
+ mInputMethodManager.showSoftInput(mSearchBarEditView,
+ InputMethodManager.SHOW_IMPLICIT);
+ }
+ });
+ mSearchButtonView.animate()
+ .alpha(0f)
+ .translationX(-translationX)
+ .setDuration(FADE_OUT_DURATION)
+ .withLayer();
+ }
+
+ /**
+ * Unfocuses the search field.
+ */
+ @Thunk void hideSearchField(boolean animated, final Runnable postAnimationRunnable) {
+ mSearchManager.cancel(true);
+
+ final boolean resetTextField = mSearchBarEditView.getText().toString().length() > 0;
+ final int translationX = Utilities.pxFromDp(SEARCH_TRANSLATION_X_DP,
+ mContext.getResources().getDisplayMetrics());
+ if (animated) {
+ // Hide the search bar and focus the recycler view
+ mSearchBarContainerView.animate()
+ .alpha(0f)
+ .translationX(0)
+ .setDuration(FADE_IN_DURATION)
+ .withLayer()
+ .withEndAction(new Runnable() {
+ @Override
+ public void run() {
+ mSearchBarContainerView.setVisibility(View.INVISIBLE);
+ if (resetTextField) {
+ mSearchBarEditView.setText("");
+ }
+ mCb.clearSearchResult();
+ if (postAnimationRunnable != null) {
+ postAnimationRunnable.run();
+ }
+ }
+ });
+ mSearchButtonView.setTranslationX(-translationX);
+ mSearchButtonView.animate()
+ .alpha(1f)
+ .translationX(0)
+ .setDuration(FADE_OUT_DURATION)
+ .withLayer();
+ } else {
+ mSearchBarContainerView.setVisibility(View.INVISIBLE);
+ if (resetTextField) {
+ mSearchBarEditView.setText("");
+ }
+ mCb.clearSearchResult();
+ mSearchButtonView.setAlpha(1f);
+ mSearchButtonView.setTranslationX(0f);
+ if (postAnimationRunnable != null) {
+ postAnimationRunnable.run();
+ }
+ }
+ mInputMethodManager.hideSoftInputFromWindow(mContainerView.getWindowToken(), 0);
+ }
+}
diff --git a/src/com/android/launcher3/compat/AlphabeticIndexCompat.java b/src/com/android/launcher3/compat/AlphabeticIndexCompat.java
new file mode 100644
index 000000000..ec1fb669f
--- /dev/null
+++ b/src/com/android/launcher3/compat/AlphabeticIndexCompat.java
@@ -0,0 +1,170 @@
+package com.android.launcher3.compat;
+
+import android.content.Context;
+import com.android.launcher3.Utilities;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+import java.util.Locale;
+
+/**
+ * Fallback class to support Alphabetic indexing if not supported by the framework.
+ * TODO(winsonc): disable for non-english locales
+ */
+class BaseAlphabeticIndex {
+
+ private static final String BUCKETS = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-";
+ private static final int UNKNOWN_BUCKET_INDEX = BUCKETS.length() - 1;
+
+ public BaseAlphabeticIndex() {}
+
+ /**
+ * Sets the max number of the label buckets in this index.
+ */
+ public void setMaxLabelCount(int count) {
+ // Not currently supported
+ }
+
+ /**
+ * Returns the index of the bucket in which the given string should appear.
+ */
+ protected int getBucketIndex(String s) {
+ if (s.isEmpty()) {
+ return UNKNOWN_BUCKET_INDEX;
+ }
+ int index = BUCKETS.indexOf(s.substring(0, 1).toUpperCase());
+ if (index != -1) {
+ return index;
+ }
+ return UNKNOWN_BUCKET_INDEX;
+ }
+
+ /**
+ * Returns the label for the bucket at the given index (as returned by getBucketIndex).
+ */
+ protected String getBucketLabel(int index) {
+ return BUCKETS.substring(index, index + 1);
+ }
+}
+
+/**
+ * Reflected libcore.icu.AlphabeticIndex implementation, falls back to the base alphabetic index.
+ */
+public class AlphabeticIndexCompat extends BaseAlphabeticIndex {
+
+ private static final String MID_DOT = "\u2219";
+
+ private Object mAlphabeticIndex;
+ private Method mAddLabelsMethod;
+ private Method mSetMaxLabelCountMethod;
+ private Method mGetBucketIndexMethod;
+ private Method mGetBucketLabelMethod;
+ private boolean mHasValidAlphabeticIndex;
+ private String mDefaultMiscLabel;
+
+ public AlphabeticIndexCompat(Context context) {
+ super();
+ try {
+ Locale curLocale = context.getResources().getConfiguration().locale;
+ Class clazz = Class.forName("libcore.icu.AlphabeticIndex");
+ Constructor ctor = clazz.getConstructor(Locale.class);
+ mAddLabelsMethod = clazz.getDeclaredMethod("addLabels", Locale.class);
+ mSetMaxLabelCountMethod = clazz.getDeclaredMethod("setMaxLabelCount", int.class);
+ mGetBucketIndexMethod = clazz.getDeclaredMethod("getBucketIndex", String.class);
+ mGetBucketLabelMethod = clazz.getDeclaredMethod("getBucketLabel", int.class);
+ mAlphabeticIndex = ctor.newInstance(curLocale);
+ try {
+ // Ensure we always have some base English locale buckets
+ if (!curLocale.getLanguage().equals(Locale.ENGLISH.getLanguage())) {
+ mAddLabelsMethod.invoke(mAlphabeticIndex, Locale.ENGLISH);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ if (curLocale.getLanguage().equals(Locale.JAPANESE.getLanguage())) {
+ // Japanese character 他 ("misc")
+ mDefaultMiscLabel = "\u4ed6";
+ // TODO(winsonc, omakoto): We need to handle Japanese sections better, especially the kanji
+ } else {
+ // Dot
+ mDefaultMiscLabel = MID_DOT;
+ }
+ mHasValidAlphabeticIndex = true;
+ } catch (Exception e) {
+ mHasValidAlphabeticIndex = false;
+ }
+ }
+
+ /**
+ * Sets the max number of the label buckets in this index.
+ * (ICU 51 default is 99)
+ */
+ public void setMaxLabelCount(int count) {
+ if (mHasValidAlphabeticIndex) {
+ try {
+ mSetMaxLabelCountMethod.invoke(mAlphabeticIndex, count);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ } else {
+ super.setMaxLabelCount(count);
+ }
+ }
+
+ /**
+ * Computes the section name for an given string {@param s}.
+ */
+ public String computeSectionName(CharSequence cs) {
+ String s = Utilities.trim(cs);
+ String sectionName = getBucketLabel(getBucketIndex(s));
+ if (Utilities.trim(sectionName).isEmpty() && s.length() > 0) {
+ int c = s.codePointAt(0);
+ boolean startsWithDigit = Character.isDigit(c);
+ if (startsWithDigit) {
+ // Digit section
+ return "#";
+ } else {
+ boolean startsWithLetter = Character.isLetter(c);
+ if (startsWithLetter) {
+ return mDefaultMiscLabel;
+ } else {
+ // In languages where these differ, this ensures that we differentiate
+ // between the misc section in the native language and a misc section
+ // for everything else.
+ return MID_DOT;
+ }
+ }
+ }
+ return sectionName;
+ }
+
+ /**
+ * Returns the index of the bucket in which {@param s} should appear.
+ * Function is synchronized because underlying routine walks an iterator
+ * whose state is maintained inside the index object.
+ */
+ protected int getBucketIndex(String s) {
+ if (mHasValidAlphabeticIndex) {
+ try {
+ return (Integer) mGetBucketIndexMethod.invoke(mAlphabeticIndex, s);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ return super.getBucketIndex(s);
+ }
+
+ /**
+ * Returns the label for the bucket at the given index (as returned by getBucketIndex).
+ */
+ protected String getBucketLabel(int index) {
+ if (mHasValidAlphabeticIndex) {
+ try {
+ return (String) mGetBucketLabelMethod.invoke(mAlphabeticIndex, index);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ return super.getBucketLabel(index);
+ }
+}
diff --git a/src/com/android/launcher3/compat/AppWidgetManagerCompat.java b/src/com/android/launcher3/compat/AppWidgetManagerCompat.java
index 6512d427e..7aa36d447 100644
--- a/src/com/android/launcher3/compat/AppWidgetManagerCompat.java
+++ b/src/com/android/launcher3/compat/AppWidgetManagerCompat.java
@@ -26,6 +26,7 @@ import android.graphics.drawable.Drawable;
import android.os.Bundle;
import com.android.launcher3.IconCache;
+import com.android.launcher3.LauncherAppWidgetProviderInfo;
import com.android.launcher3.Utilities;
import java.util.List;
@@ -63,20 +64,21 @@ public abstract class AppWidgetManagerCompat {
public abstract List<AppWidgetProviderInfo> getAllProviders();
- public abstract String loadLabel(AppWidgetProviderInfo info);
+ public abstract String loadLabel(LauncherAppWidgetProviderInfo info);
public abstract boolean bindAppWidgetIdIfAllowed(
int appWidgetId, AppWidgetProviderInfo info, Bundle options);
- public abstract UserHandleCompat getUser(AppWidgetProviderInfo info);
+ public abstract UserHandleCompat getUser(LauncherAppWidgetProviderInfo info);
public abstract void startConfigActivity(AppWidgetProviderInfo info, int widgetId,
Activity activity, AppWidgetHost host, int requestCode);
public abstract Drawable loadPreview(AppWidgetProviderInfo info);
- public abstract Drawable loadIcon(AppWidgetProviderInfo info, IconCache cache);
+ public abstract Drawable loadIcon(LauncherAppWidgetProviderInfo info, IconCache cache);
- public abstract Bitmap getBadgeBitmap(AppWidgetProviderInfo info, Bitmap bitmap);
+ public abstract Bitmap getBadgeBitmap(LauncherAppWidgetProviderInfo info, Bitmap bitmap,
+ int imageHeight);
}
diff --git a/src/com/android/launcher3/compat/AppWidgetManagerCompatV16.java b/src/com/android/launcher3/compat/AppWidgetManagerCompatV16.java
index f599f4303..f7f4b7e4f 100644
--- a/src/com/android/launcher3/compat/AppWidgetManagerCompatV16.java
+++ b/src/com/android/launcher3/compat/AppWidgetManagerCompatV16.java
@@ -16,6 +16,7 @@
package com.android.launcher3.compat;
+import android.annotation.TargetApi;
import android.app.Activity;
import android.appwidget.AppWidgetHost;
import android.appwidget.AppWidgetManager;
@@ -28,6 +29,7 @@ import android.os.Build;
import android.os.Bundle;
import com.android.launcher3.IconCache;
+import com.android.launcher3.LauncherAppWidgetProviderInfo;
import com.android.launcher3.Utilities;
import java.util.List;
@@ -44,10 +46,11 @@ class AppWidgetManagerCompatV16 extends AppWidgetManagerCompat {
}
@Override
- public String loadLabel(AppWidgetProviderInfo info) {
- return info.label.trim();
+ public String loadLabel(LauncherAppWidgetProviderInfo info) {
+ return Utilities.trim(info.label);
}
+ @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
@Override
public boolean bindAppWidgetIdIfAllowed(int appWidgetId, AppWidgetProviderInfo info,
Bundle options) {
@@ -59,7 +62,7 @@ class AppWidgetManagerCompatV16 extends AppWidgetManagerCompat {
}
@Override
- public UserHandleCompat getUser(AppWidgetProviderInfo info) {
+ public UserHandleCompat getUser(LauncherAppWidgetProviderInfo info) {
return UserHandleCompat.myUserHandle();
}
@@ -79,12 +82,13 @@ class AppWidgetManagerCompatV16 extends AppWidgetManagerCompat {
}
@Override
- public Drawable loadIcon(AppWidgetProviderInfo info, IconCache cache) {
+ public Drawable loadIcon(LauncherAppWidgetProviderInfo info, IconCache cache) {
return cache.getFullResIcon(info.provider.getPackageName(), info.icon);
}
@Override
- public Bitmap getBadgeBitmap(AppWidgetProviderInfo info, Bitmap bitmap) {
+ public Bitmap getBadgeBitmap(LauncherAppWidgetProviderInfo info, Bitmap bitmap,
+ int imageHeight) {
return bitmap;
}
}
diff --git a/src/com/android/launcher3/compat/AppWidgetManagerCompatVL.java b/src/com/android/launcher3/compat/AppWidgetManagerCompatVL.java
index 03d43a6f2..13712d8c7 100644
--- a/src/com/android/launcher3/compat/AppWidgetManagerCompatVL.java
+++ b/src/com/android/launcher3/compat/AppWidgetManagerCompatVL.java
@@ -38,6 +38,7 @@ import android.view.View;
import android.widget.Toast;
import com.android.launcher3.IconCache;
+import com.android.launcher3.LauncherAppWidgetProviderInfo;
import com.android.launcher3.R;
import java.util.ArrayList;
@@ -65,8 +66,8 @@ class AppWidgetManagerCompatVL extends AppWidgetManagerCompat {
}
@Override
- public String loadLabel(AppWidgetProviderInfo info) {
- return info.loadLabel(mPm);
+ public String loadLabel(LauncherAppWidgetProviderInfo info) {
+ return info.getLabel(mPm);
}
@Override
@@ -77,7 +78,10 @@ class AppWidgetManagerCompatVL extends AppWidgetManagerCompat {
}
@Override
- public UserHandleCompat getUser(AppWidgetProviderInfo info) {
+ public UserHandleCompat getUser(LauncherAppWidgetProviderInfo info) {
+ if (info.isCustomWidget) {
+ return UserHandleCompat.myUserHandle();
+ }
return UserHandleCompat.fromUser(info.getProfile());
}
@@ -99,27 +103,28 @@ class AppWidgetManagerCompatVL extends AppWidgetManagerCompat {
}
@Override
- public Drawable loadIcon(AppWidgetProviderInfo info, IconCache cache) {
- return info.loadIcon(mContext, cache.getFullResIconDpi());
+ public Drawable loadIcon(LauncherAppWidgetProviderInfo info, IconCache cache) {
+ return info.getIcon(mContext, cache);
}
@Override
- public Bitmap getBadgeBitmap(AppWidgetProviderInfo info, Bitmap bitmap) {
- if (info.getProfile().equals(android.os.Process.myUserHandle())) {
+ public Bitmap getBadgeBitmap(LauncherAppWidgetProviderInfo info, Bitmap bitmap,
+ int imageHeight) {
+ if (info.isCustomWidget || info.getProfile().equals(android.os.Process.myUserHandle())) {
return bitmap;
}
// Add a user badge in the bottom right of the image.
final Resources res = mContext.getResources();
final int badgeSize = res.getDimensionPixelSize(R.dimen.profile_badge_size);
- final int badgeMargin = res.getDimensionPixelSize(R.dimen.profile_badge_margin);
+ final int badgeMinTop = res.getDimensionPixelSize(R.dimen.profile_badge_minimum_top);
final Rect badgeLocation = new Rect(0, 0, badgeSize, badgeSize);
- final int top = bitmap.getHeight() - badgeSize - badgeMargin;
+ final int top = Math.max(imageHeight - badgeSize, badgeMinTop);
if (res.getConfiguration().getLayoutDirection() == View.LAYOUT_DIRECTION_RTL) {
- badgeLocation.offset(badgeMargin, top);
+ badgeLocation.offset(0, top);
} else {
- badgeLocation.offset(bitmap.getWidth() - badgeSize - badgeMargin, top);
+ badgeLocation.offset(bitmap.getWidth() - badgeSize, top);
}
Drawable drawable = mPm.getUserBadgedDrawableForDensity(
diff --git a/src/com/android/launcher3/compat/LauncherActivityInfoCompat.java b/src/com/android/launcher3/compat/LauncherActivityInfoCompat.java
index 90a4d1a1f..07ef0efb7 100644
--- a/src/com/android/launcher3/compat/LauncherActivityInfoCompat.java
+++ b/src/com/android/launcher3/compat/LauncherActivityInfoCompat.java
@@ -17,7 +17,9 @@
package com.android.launcher3.compat;
import android.content.ComponentName;
+import android.content.Context;
import android.content.pm.ApplicationInfo;
+import android.content.pm.ResolveInfo;
import android.graphics.drawable.Drawable;
public abstract class LauncherActivityInfoCompat {
@@ -32,4 +34,11 @@ public abstract class LauncherActivityInfoCompat {
public abstract ApplicationInfo getApplicationInfo();
public abstract long getFirstInstallTime();
public abstract Drawable getBadgedIcon(int density);
+
+ /**
+ * Creates a LauncherActivityInfoCompat for the primary user.
+ */
+ public static LauncherActivityInfoCompat fromResolveInfo(ResolveInfo info, Context context) {
+ return new LauncherActivityInfoCompatV16(context, info);
+ }
}
diff --git a/src/com/android/launcher3/compat/LauncherActivityInfoCompatV16.java b/src/com/android/launcher3/compat/LauncherActivityInfoCompatV16.java
index 1d41a6ff6..ea51aace8 100644
--- a/src/com/android/launcher3/compat/LauncherActivityInfoCompatV16.java
+++ b/src/com/android/launcher3/compat/LauncherActivityInfoCompatV16.java
@@ -29,13 +29,15 @@ import android.graphics.drawable.Drawable;
public class LauncherActivityInfoCompatV16 extends LauncherActivityInfoCompat {
- private ActivityInfo mActivityInfo;
- private ComponentName mComponentName;
- private PackageManager mPm;
+ private final ResolveInfo mResolveInfo;
+ private final ActivityInfo mActivityInfo;
+ private final ComponentName mComponentName;
+ private final PackageManager mPm;
LauncherActivityInfoCompatV16(Context context, ResolveInfo info) {
super();
- this.mActivityInfo = info.activityInfo;
+ mResolveInfo = info;
+ mActivityInfo = info.activityInfo;
mComponentName = new ComponentName(mActivityInfo.packageName, mActivityInfo.name);
mPm = context.getPackageManager();
}
@@ -49,31 +51,30 @@ public class LauncherActivityInfoCompatV16 extends LauncherActivityInfoCompat {
}
public CharSequence getLabel() {
- return mActivityInfo.loadLabel(mPm);
+ return mResolveInfo.loadLabel(mPm);
}
public Drawable getIcon(int density) {
- Drawable d = null;
- if (mActivityInfo.getIconResource() != 0) {
- Resources resources;
+ int iconRes = mResolveInfo.getIconResource();
+ Resources resources = null;
+ Drawable icon = null;
+ // Get the preferred density icon from the app's resources
+ if (density != 0 && iconRes != 0) {
try {
- resources = mPm.getResourcesForApplication(mActivityInfo.packageName);
- } catch (PackageManager.NameNotFoundException e) {
- resources = null;
- }
- if (resources != null) {
- try {
- d = resources.getDrawableForDensity(mActivityInfo.getIconResource(), density);
- } catch (Resources.NotFoundException e) {
- // Return default icon below.
- }
+ resources = mPm.getResourcesForApplication(mActivityInfo.applicationInfo);
+ icon = resources.getDrawableForDensity(iconRes, density);
+ } catch (NameNotFoundException | Resources.NotFoundException exc) {
}
}
- if (d == null) {
- Resources resources = Resources.getSystem();
- d = resources.getDrawableForDensity(android.R.mipmap.sym_def_app_icon, density);
+ // Get the default density icon
+ if (icon == null) {
+ icon = mResolveInfo.loadIcon(mPm);
+ }
+ if (icon == null) {
+ resources = Resources.getSystem();
+ icon = resources.getDrawableForDensity(android.R.mipmap.sym_def_app_icon, density);
}
- return d;
+ return icon;
}
public ApplicationInfo getApplicationInfo() {
diff --git a/src/com/android/launcher3/compat/LauncherActivityInfoCompatVL.java b/src/com/android/launcher3/compat/LauncherActivityInfoCompatVL.java
index b52cf1de2..4448758e7 100644
--- a/src/com/android/launcher3/compat/LauncherActivityInfoCompatVL.java
+++ b/src/com/android/launcher3/compat/LauncherActivityInfoCompatVL.java
@@ -16,12 +16,14 @@
package com.android.launcher3.compat;
+import android.annotation.TargetApi;
import android.content.ComponentName;
import android.content.pm.ApplicationInfo;
import android.content.pm.LauncherActivityInfo;
import android.graphics.drawable.Drawable;
-import android.os.UserHandle;
+import android.os.Build;
+@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public class LauncherActivityInfoCompatVL extends LauncherActivityInfoCompat {
private LauncherActivityInfo mLauncherActivityInfo;
diff --git a/src/com/android/launcher3/compat/LauncherAppsCompatV16.java b/src/com/android/launcher3/compat/LauncherAppsCompatV16.java
index e47b9a58d..ac3d252f5 100644
--- a/src/com/android/launcher3/compat/LauncherAppsCompatV16.java
+++ b/src/com/android/launcher3/compat/LauncherAppsCompatV16.java
@@ -31,6 +31,8 @@ import android.os.Build;
import android.os.Bundle;
import android.provider.Settings;
+import com.android.launcher3.util.Thunk;
+
import java.util.ArrayList;
import java.util.List;
@@ -139,11 +141,11 @@ public class LauncherAppsCompatV16 extends LauncherAppsCompat {
mContext.registerReceiver(mPackageMonitor, filter);
}
- private synchronized List<OnAppsChangedCallbackCompat> getCallbacks() {
+ @Thunk synchronized List<OnAppsChangedCallbackCompat> getCallbacks() {
return new ArrayList<OnAppsChangedCallbackCompat>(mCallbacks);
}
- private class PackageMonitor extends BroadcastReceiver {
+ @Thunk class PackageMonitor extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
final UserHandleCompat user = UserHandleCompat.myUserHandle();
diff --git a/src/com/android/launcher3/compat/LauncherAppsCompatVL.java b/src/com/android/launcher3/compat/LauncherAppsCompatVL.java
index e0d28b566..fbf91b548 100644
--- a/src/com/android/launcher3/compat/LauncherAppsCompatVL.java
+++ b/src/com/android/launcher3/compat/LauncherAppsCompatVL.java
@@ -16,6 +16,7 @@
package com.android.launcher3.compat;
+import android.annotation.TargetApi;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -32,6 +33,7 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
+@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public class LauncherAppsCompatVL extends LauncherAppsCompat {
private LauncherApps mLauncherApps;
@@ -49,7 +51,7 @@ public class LauncherAppsCompatVL extends LauncherAppsCompat {
List<LauncherActivityInfo> list = mLauncherApps.getActivityList(packageName,
user.getUser());
if (list.size() == 0) {
- return Collections.EMPTY_LIST;
+ return Collections.emptyList();
}
ArrayList<LauncherActivityInfoCompat> compatList =
new ArrayList<LauncherActivityInfoCompat>(list.size());
diff --git a/src/com/android/launcher3/compat/PackageInstallerCompat.java b/src/com/android/launcher3/compat/PackageInstallerCompat.java
index 0eb8754e8..c49908328 100644
--- a/src/com/android/launcher3/compat/PackageInstallerCompat.java
+++ b/src/com/android/launcher3/compat/PackageInstallerCompat.java
@@ -20,7 +20,7 @@ import android.content.Context;
import com.android.launcher3.Utilities;
-import java.util.HashSet;
+import java.util.HashMap;
public abstract class PackageInstallerCompat {
@@ -37,25 +37,20 @@ public abstract class PackageInstallerCompat {
if (Utilities.isLmpOrAbove()) {
sInstance = new PackageInstallerCompatVL(context);
} else {
- sInstance = new PackageInstallerCompatV16(context) { };
+ sInstance = new PackageInstallerCompatV16();
}
}
return sInstance;
}
}
- public abstract HashSet<String> updateAndGetActiveSessionCache();
-
- public abstract void onPause();
-
- public abstract void onResume();
-
- public abstract void onFinishBind();
+ /**
+ * @return a map of active installs to their progress
+ */
+ public abstract HashMap<String, Integer> updateAndGetActiveSessionCache();
public abstract void onStop();
- public abstract void recordPackageUpdate(String packageName, int state, int progress);
-
public static final class PackageInstallInfo {
public final String packageName;
diff --git a/src/com/android/launcher3/compat/PackageInstallerCompatV16.java b/src/com/android/launcher3/compat/PackageInstallerCompatV16.java
index 1910d22ae..654e34968 100644
--- a/src/com/android/launcher3/compat/PackageInstallerCompatV16.java
+++ b/src/com/android/launcher3/compat/PackageInstallerCompatV16.java
@@ -16,160 +16,17 @@
package com.android.launcher3.compat;
-import android.content.Context;
-import android.content.SharedPreferences;
-import android.text.TextUtils;
-import android.util.Log;
-
-import com.android.launcher3.LauncherAppState;
-
-import org.json.JSONException;
-import org.json.JSONObject;
-import org.json.JSONStringer;
-import org.json.JSONTokener;
-
-import java.util.ArrayList;
-import java.util.HashSet;
+import java.util.HashMap;
public class PackageInstallerCompatV16 extends PackageInstallerCompat {
- private static final String TAG = "PackageInstallerCompatV16";
- private static final boolean DEBUG = false;
-
- private static final String KEY_PROGRESS = "progress";
- private static final String KEY_STATE = "state";
-
- private static final String PREFS =
- "com.android.launcher3.compat.PackageInstallerCompatV16.queue";
-
- protected final SharedPreferences mPrefs;
-
- boolean mUseQueue;
- boolean mFinishedBind;
- boolean mReplayPending;
-
- PackageInstallerCompatV16(Context context) {
- mPrefs = context.getSharedPreferences(PREFS, Context.MODE_PRIVATE);
- }
-
- @Override
- public void onPause() {
- mUseQueue = true;
- if (DEBUG) Log.d(TAG, "updates paused");
- }
-
- @Override
- public void onResume() {
- mUseQueue = false;
- if (mFinishedBind) {
- replayUpdates();
- }
- }
-
- @Override
- public void onFinishBind() {
- mFinishedBind = true;
- if (!mUseQueue) {
- replayUpdates();
- }
- }
+ PackageInstallerCompatV16() { }
@Override
public void onStop() { }
- private void replayUpdates() {
- if (DEBUG) Log.d(TAG, "updates resumed");
- LauncherAppState app = LauncherAppState.getInstanceNoCreate();
- if (app == null) {
- mReplayPending = true; // try again later
- if (DEBUG) Log.d(TAG, "app is null, delaying send");
- return;
- }
- mReplayPending = false;
- ArrayList<PackageInstallInfo> updates = new ArrayList<PackageInstallInfo>();
- for (String packageName: mPrefs.getAll().keySet()) {
- final String json = mPrefs.getString(packageName, null);
- if (!TextUtils.isEmpty(json)) {
- updates.add(infoFromJson(packageName, json));
- }
- }
- if (!updates.isEmpty()) {
- sendUpdate(app, updates);
- }
- }
-
- /**
- * This should be called by the implementations to register a package update.
- */
- @Override
- public synchronized void recordPackageUpdate(String packageName, int state, int progress) {
- SharedPreferences.Editor editor = mPrefs.edit();
- PackageInstallInfo installInfo = new PackageInstallInfo(packageName);
- installInfo.progress = progress;
- installInfo.state = state;
- if (state == STATUS_INSTALLED) {
- // no longer necessary to track this package
- editor.remove(packageName);
- if (DEBUG) Log.d(TAG, "no longer tracking " + packageName);
- } else {
- editor.putString(packageName, infoToJson(installInfo));
- if (DEBUG)
- Log.d(TAG, "saved state: " + infoToJson(installInfo)
- + " for package: " + packageName);
-
- }
- editor.commit();
-
- if (!mUseQueue) {
- if (mReplayPending) {
- replayUpdates();
- } else if (state != STATUS_INSTALLED) {
- LauncherAppState app = LauncherAppState.getInstanceNoCreate();
- ArrayList<PackageInstallInfo> update = new ArrayList<PackageInstallInfo>();
- update.add(installInfo);
- sendUpdate(app, update);
- }
- }
- }
-
- private void sendUpdate(LauncherAppState app, ArrayList<PackageInstallInfo> updates) {
- if (app == null) {
- mReplayPending = true; // try again later
- if (DEBUG) Log.d(TAG, "app is null, delaying send");
- } else {
- app.setPackageState(updates);
- }
- }
-
- private static PackageInstallInfo infoFromJson(String packageName, String json) {
- PackageInstallInfo info = new PackageInstallInfo(packageName);
- try {
- JSONObject object = (JSONObject) new JSONTokener(json).nextValue();
- info.state = object.getInt(KEY_STATE);
- info.progress = object.getInt(KEY_PROGRESS);
- } catch (JSONException e) {
- Log.e(TAG, "failed to deserialize app state update", e);
- }
- return info;
- }
-
- private static String infoToJson(PackageInstallInfo info) {
- String value = null;
- try {
- JSONStringer json = new JSONStringer()
- .object()
- .key(KEY_STATE).value(info.state)
- .key(KEY_PROGRESS).value(info.progress)
- .endObject();
- value = json.toString();
- } catch (JSONException e) {
- Log.e(TAG, "failed to serialize app state update", e);
- }
- return value;
- }
-
@Override
- public HashSet<String> updateAndGetActiveSessionCache() {
- return new HashSet<String>();
+ public HashMap<String, Integer> updateAndGetActiveSessionCache() {
+ return new HashMap<>();
}
}
diff --git a/src/com/android/launcher3/compat/PackageInstallerCompatVL.java b/src/com/android/launcher3/compat/PackageInstallerCompatVL.java
index 601f04cea..3ad51017d 100644
--- a/src/com/android/launcher3/compat/PackageInstallerCompatVL.java
+++ b/src/com/android/launcher3/compat/PackageInstallerCompatVL.java
@@ -16,73 +16,55 @@
package com.android.launcher3.compat;
+import android.annotation.TargetApi;
import android.content.Context;
import android.content.pm.PackageInstaller;
import android.content.pm.PackageInstaller.SessionCallback;
import android.content.pm.PackageInstaller.SessionInfo;
+import android.os.Build;
import android.os.Handler;
-import android.util.Log;
import android.util.SparseArray;
import com.android.launcher3.IconCache;
import com.android.launcher3.LauncherAppState;
+import com.android.launcher3.LauncherModel;
+import com.android.launcher3.util.Thunk;
-import java.util.ArrayList;
-import java.util.HashSet;
+import java.util.HashMap;
-public class PackageInstallerCompatVL extends PackageInstallerCompat implements Runnable {
+@TargetApi(Build.VERSION_CODES.LOLLIPOP)
+public class PackageInstallerCompatVL extends PackageInstallerCompat {
- private static final String TAG = "PackageInstallerCompatVL";
- private static final boolean DEBUG = false;
+ @Thunk final SparseArray<String> mActiveSessions = new SparseArray<>();
- // All updates to these sets must happen on the {@link #mWorker} thread.
- private final SparseArray<SessionInfo> mPendingReplays = new SparseArray<SessionInfo>();
- private final HashSet<String> mPendingBadgeUpdates = new HashSet<String>();
-
- private final PackageInstaller mInstaller;
+ @Thunk final PackageInstaller mInstaller;
private final IconCache mCache;
private final Handler mWorker;
- private boolean mResumed;
- private boolean mBound;
-
PackageInstallerCompatVL(Context context) {
mInstaller = context.getPackageManager().getPackageInstaller();
LauncherAppState.setApplicationContext(context.getApplicationContext());
mCache = LauncherAppState.getInstance().getIconCache();
- mWorker = new Handler();
-
- mResumed = false;
- mBound = false;
+ mWorker = new Handler(LauncherModel.getWorkerLooper());
mInstaller.registerSessionCallback(mCallback, mWorker);
-
- // On start, send updates for all active sessions
- mWorker.post(new Runnable() {
-
- @Override
- public void run() {
- for (SessionInfo info : mInstaller.getAllSessions()) {
- mPendingReplays.append(info.getSessionId(), info);
- }
- }
- });
}
@Override
- public HashSet<String> updateAndGetActiveSessionCache() {
- HashSet<String> activePackages = new HashSet<String>();
+ public HashMap<String, Integer> updateAndGetActiveSessionCache() {
+ HashMap<String, Integer> activePackages = new HashMap<>();
UserHandleCompat user = UserHandleCompat.myUserHandle();
for (SessionInfo info : mInstaller.getAllSessions()) {
addSessionInfoToCahce(info, user);
if (info.getAppPackageName() != null) {
- activePackages.add(info.getAppPackageName());
+ activePackages.put(info.getAppPackageName(), (int) (info.getProgress() * 100));
+ mActiveSessions.put(info.getSessionId(), info.getAppPackageName());
}
}
return activePackages;
}
- private void addSessionInfoToCahce(SessionInfo info, UserHandleCompat user) {
+ @Thunk void addSessionInfoToCahce(SessionInfo info, UserHandleCompat user) {
String packageName = info.getAppPackageName();
if (packageName != null) {
mCache.cachePackageInstallInfo(packageName, user, info.getAppIcon(),
@@ -95,74 +77,10 @@ public class PackageInstallerCompatVL extends PackageInstallerCompat implements
mInstaller.unregisterSessionCallback(mCallback);
}
- @Override
- public void onFinishBind() {
- mBound = true;
- mWorker.post(this);
- }
-
- @Override
- public void onPause() {
- mResumed = false;
- }
-
- @Override
- public void onResume() {
- mResumed = true;
- mWorker.post(this);
- }
-
- @Override
- public void recordPackageUpdate(String packageName, int state, int progress) {
- // No op
- }
-
- @Override
- public void run() {
- // Called on mWorker thread.
- replayUpdates(null);
- }
-
- private void replayUpdates(PackageInstallInfo newInfo) {
- if (DEBUG) Log.d(TAG, "updates resumed");
- if (!mResumed || !mBound) {
- // Not yet ready
- return;
- }
- if ((mPendingReplays.size() == 0) && (newInfo == null)) {
- // Nothing to update
- return;
- }
-
+ @Thunk void sendUpdate(PackageInstallInfo info) {
LauncherAppState app = LauncherAppState.getInstanceNoCreate();
- if (app == null) {
- // Try again later
- if (DEBUG) Log.d(TAG, "app is null, delaying send");
- return;
- }
-
- ArrayList<PackageInstallInfo> updates = new ArrayList<PackageInstallInfo>();
- if ((newInfo != null) && (newInfo.state != STATUS_INSTALLED)) {
- updates.add(newInfo);
- }
- for (int i = mPendingReplays.size() - 1; i >= 0; i--) {
- SessionInfo session = mPendingReplays.valueAt(i);
- if (session.getAppPackageName() != null) {
- updates.add(new PackageInstallInfo(session.getAppPackageName(),
- STATUS_INSTALLING,
- (int) (session.getProgress() * 100)));
- }
- }
- mPendingReplays.clear();
- if (!updates.isEmpty()) {
- app.setPackageState(updates);
- }
-
- if (!mPendingBadgeUpdates.isEmpty()) {
- for (String pkg : mPendingBadgeUpdates) {
- app.updatePackageBadge(pkg);
- }
- mPendingBadgeUpdates.clear();
+ if (app != null) {
+ app.getModel().setPackageState(info);
}
}
@@ -170,19 +88,18 @@ public class PackageInstallerCompatVL extends PackageInstallerCompat implements
@Override
public void onCreated(int sessionId) {
- pushSessionBadgeToLauncher(sessionId);
+ pushSessionDisplayToLauncher(sessionId);
}
@Override
public void onFinished(int sessionId, boolean success) {
- mPendingReplays.remove(sessionId);
- SessionInfo session = mInstaller.getSessionInfo(sessionId);
- if ((session != null) && (session.getAppPackageName() != null)) {
- mPendingBadgeUpdates.remove(session.getAppPackageName());
- // Replay all updates with a one time update for this installed package. No
- // need to store this record for future updates, as the app list will get
- // refreshed on resume.
- replayUpdates(new PackageInstallInfo(session.getAppPackageName(),
+ // For a finished session, we can't get the session info. So use the
+ // packageName from our local cache.
+ String packageName = mActiveSessions.get(sessionId);
+ mActiveSessions.remove(sessionId);
+
+ if (packageName != null) {
+ sendUpdate(new PackageInstallInfo(packageName,
success ? STATUS_INSTALLED : STATUS_FAILED, 0));
}
}
@@ -191,8 +108,9 @@ public class PackageInstallerCompatVL extends PackageInstallerCompat implements
public void onProgressChanged(int sessionId, float progress) {
SessionInfo session = mInstaller.getSessionInfo(sessionId);
if (session != null) {
- mPendingReplays.put(sessionId, session);
- replayUpdates(null);
+ sendUpdate(new PackageInstallInfo(session.getAppPackageName(),
+ STATUS_INSTALLING,
+ (int) (session.getProgress() * 100)));
}
}
@@ -201,18 +119,18 @@ public class PackageInstallerCompatVL extends PackageInstallerCompat implements
@Override
public void onBadgingChanged(int sessionId) {
- pushSessionBadgeToLauncher(sessionId);
+ pushSessionDisplayToLauncher(sessionId);
}
- private void pushSessionBadgeToLauncher(int sessionId) {
+ private void pushSessionDisplayToLauncher(int sessionId) {
SessionInfo session = mInstaller.getSessionInfo(sessionId);
if (session != null) {
addSessionInfoToCahce(session, UserHandleCompat.myUserHandle());
- if (session.getAppPackageName() != null) {
- mPendingBadgeUpdates.add(session.getAppPackageName());
+ LauncherAppState app = LauncherAppState.getInstanceNoCreate();
+
+ if (app != null) {
+ app.getModel().updateSessionDisplayInfo(session.getAppPackageName());
}
- mPendingReplays.put(sessionId, session);
- replayUpdates(null);
}
}
};
diff --git a/src/com/android/launcher3/compat/UserHandleCompat.java b/src/com/android/launcher3/compat/UserHandleCompat.java
index 2ae673171..ab4b7216b 100644
--- a/src/com/android/launcher3/compat/UserHandleCompat.java
+++ b/src/com/android/launcher3/compat/UserHandleCompat.java
@@ -16,10 +16,10 @@
package com.android.launcher3.compat;
+import android.annotation.TargetApi;
import android.content.Intent;
import android.os.Build;
import android.os.UserHandle;
-
import com.android.launcher3.Utilities;
public class UserHandleCompat {
@@ -32,6 +32,7 @@ public class UserHandleCompat {
private UserHandleCompat() {
}
+ @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
public static UserHandleCompat myUserHandle() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
return new UserHandleCompat(android.os.Process.myUserHandle());
@@ -40,7 +41,7 @@ public class UserHandleCompat {
}
}
- static UserHandleCompat fromUser(UserHandle user) {
+ public static UserHandleCompat fromUser(UserHandle user) {
if (user == null) {
return null;
} else {
diff --git a/src/com/android/launcher3/compat/UserManagerCompat.java b/src/com/android/launcher3/compat/UserManagerCompat.java
index 1374b4e49..a79d94646 100644
--- a/src/com/android/launcher3/compat/UserManagerCompat.java
+++ b/src/com/android/launcher3/compat/UserManagerCompat.java
@@ -43,4 +43,5 @@ public abstract class UserManagerCompat {
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 32f972e85..ffe698c8b 100644
--- a/src/com/android/launcher3/compat/UserManagerCompatV16.java
+++ b/src/com/android/launcher3/compat/UserManagerCompatV16.java
@@ -48,4 +48,9 @@ public class UserManagerCompatV16 extends UserManagerCompat {
public CharSequence getBadgedLabelForUser(CharSequence label, UserHandleCompat user) {
return label;
}
+
+ @Override
+ public long getUserCreationTime(UserHandleCompat user) {
+ return 0;
+ }
}
diff --git a/src/com/android/launcher3/compat/UserManagerCompatV17.java b/src/com/android/launcher3/compat/UserManagerCompatV17.java
index 055359afe..c42c00c7d 100644
--- a/src/com/android/launcher3/compat/UserManagerCompatV17.java
+++ b/src/com/android/launcher3/compat/UserManagerCompatV17.java
@@ -16,14 +16,12 @@
package com.android.launcher3.compat;
+import android.annotation.TargetApi;
import android.content.Context;
-import android.graphics.drawable.Drawable;
-import android.os.UserHandle;
+import android.os.Build;
import android.os.UserManager;
-import java.util.ArrayList;
-import java.util.List;
-
+@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
public class UserManagerCompatV17 extends UserManagerCompatV16 {
protected UserManager mUserManager;
diff --git a/src/com/android/launcher3/compat/UserManagerCompatVL.java b/src/com/android/launcher3/compat/UserManagerCompatVL.java
index 19eeabdcf..dd7a72617 100644
--- a/src/com/android/launcher3/compat/UserManagerCompatVL.java
+++ b/src/com/android/launcher3/compat/UserManagerCompatVL.java
@@ -17,29 +17,36 @@
package com.android.launcher3.compat;
+import android.annotation.TargetApi;
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 android.os.UserManager;
-
+import com.android.launcher3.LauncherAppState;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
+@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public class UserManagerCompatVL extends UserManagerCompatV17 {
+ private static final String USER_CREATION_TIME_KEY = "user_creation_time_";
+
private final PackageManager mPm;
+ private final Context mContext;
UserManagerCompatVL(Context context) {
super(context);
mPm = context.getPackageManager();
+ mContext = context;
}
@Override
public List<UserHandleCompat> getUserProfiles() {
List<UserHandle> users = mUserManager.getUserProfiles();
if (users == null) {
- return Collections.EMPTY_LIST;
+ return Collections.emptyList();
}
ArrayList<UserHandleCompat> compatUsers = new ArrayList<UserHandleCompat>(
users.size());
@@ -61,5 +68,17 @@ public class UserManagerCompatVL extends UserManagerCompatV17 {
}
return mPm.getUserBadgedLabel(label, user.getUser());
}
+
+ @Override
+ public long getUserCreationTime(UserHandleCompat user) {
+ // TODO: Use system API once available.
+ SharedPreferences prefs = mContext.getSharedPreferences(
+ LauncherAppState.getSharedPreferencesKey(), Context.MODE_PRIVATE);
+ String key = USER_CREATION_TIME_KEY + getSerialNumberForUser(user);
+ if (!prefs.contains(key)) {
+ prefs.edit().putLong(key, System.currentTimeMillis()).apply();
+ }
+ return prefs.getLong(key, 0);
+ }
}
diff --git a/src/com/android/launcher3/config/ProviderConfig.java b/src/com/android/launcher3/config/ProviderConfig.java
index db25076ea..e8930d063 100644
--- a/src/com/android/launcher3/config/ProviderConfig.java
+++ b/src/com/android/launcher3/config/ProviderConfig.java
@@ -18,5 +18,5 @@ package com.android.launcher3.config;
public class ProviderConfig {
- public static final String AUTHORITY = "com.android.launcher3.settings";
+ public static final String AUTHORITY = "com.android.launcher3.settings".intern();
}
diff --git a/src/com/android/launcher3/model/AbstractUserComparator.java b/src/com/android/launcher3/model/AbstractUserComparator.java
new file mode 100644
index 000000000..cf47ce648
--- /dev/null
+++ b/src/com/android/launcher3/model/AbstractUserComparator.java
@@ -0,0 +1,67 @@
+/*
+ * 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.model;
+
+import android.content.Context;
+
+import com.android.launcher3.ItemInfo;
+import com.android.launcher3.compat.UserHandleCompat;
+import com.android.launcher3.compat.UserManagerCompat;
+
+import java.util.Comparator;
+import java.util.HashMap;
+
+/**
+ * A comparator to arrange items based on user profiles.
+ */
+public abstract class AbstractUserComparator<T extends ItemInfo> implements Comparator<T> {
+
+ private HashMap<UserHandleCompat, Long> mUserSerialCache = new HashMap<>();
+ private final UserManagerCompat mUserManager;
+ private final UserHandleCompat mMyUser;
+
+ public AbstractUserComparator(Context context) {
+ mUserManager = UserManagerCompat.getInstance(context);
+ mMyUser = UserHandleCompat.myUserHandle();
+ }
+
+ @Override
+ public int compare(T lhs, T rhs) {
+ if (mMyUser.equals(lhs.user)) {
+ return -1;
+ } else {
+ Long aUserSerial = getAndCacheUserSerial(lhs.user);
+ Long bUserSerial = getAndCacheUserSerial(rhs.user);
+ return aUserSerial.compareTo(bUserSerial);
+ }
+ }
+
+ /**
+ * Returns the user serial for this user, using a cached serial if possible.
+ */
+ private Long getAndCacheUserSerial(UserHandleCompat user) {
+ Long userSerial = mUserSerialCache.get(user);
+ if (userSerial == null) {
+ userSerial = mUserManager.getSerialNumberForUser(user);
+ mUserSerialCache.put(user, userSerial);
+ }
+ return userSerial;
+ }
+
+ public void clearUserCache() {
+ mUserSerialCache.clear();
+ }
+}
diff --git a/src/com/android/launcher3/model/AppNameComparator.java b/src/com/android/launcher3/model/AppNameComparator.java
new file mode 100644
index 000000000..c4b74d4dc
--- /dev/null
+++ b/src/com/android/launcher3/model/AppNameComparator.java
@@ -0,0 +1,101 @@
+/*
+ * 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.model;
+
+import android.content.Context;
+
+import com.android.launcher3.AppInfo;
+import com.android.launcher3.ItemInfo;
+import com.android.launcher3.util.Thunk;
+
+import java.text.Collator;
+import java.util.Comparator;
+
+/**
+ * Class to manage access to an app name comparator.
+ * <p>
+ * Used to sort application name in all apps view and widget tray view.
+ */
+public class AppNameComparator {
+ private final Collator mCollator;
+ private final AbstractUserComparator<ItemInfo> mAppInfoComparator;
+ private final Comparator<String> mSectionNameComparator;
+
+ public AppNameComparator(Context context) {
+ mCollator = Collator.getInstance();
+ mAppInfoComparator = new AbstractUserComparator<ItemInfo>(context) {
+
+ @Override
+ public final int compare(ItemInfo a, ItemInfo b) {
+ // Order by the title in the current locale
+ int result = compareTitles(a.title.toString(), b.title.toString());
+ if (result == 0 && a instanceof AppInfo && b instanceof AppInfo) {
+ AppInfo aAppInfo = (AppInfo) a;
+ AppInfo bAppInfo = (AppInfo) b;
+ // If two apps have the same title, then order by the component name
+ result = aAppInfo.componentName.compareTo(bAppInfo.componentName);
+ if (result == 0) {
+ // If the two apps are the same component, then prioritize by the order that
+ // the app user was created (prioritizing the main user's apps)
+ return super.compare(a, b);
+ }
+ }
+ return result;
+ }
+ };
+ mSectionNameComparator = new Comparator<String>() {
+ @Override
+ public int compare(String o1, String o2) {
+ return compareTitles(o1, o2);
+ }
+ };
+ }
+
+ /**
+ * Returns a locale-aware comparator that will alphabetically order a list of applications.
+ */
+ public Comparator<ItemInfo> getAppInfoComparator() {
+ // Clear the user serial cache so that we get serials as needed in the comparator
+ mAppInfoComparator.clearUserCache();
+ return mAppInfoComparator;
+ }
+
+ /**
+ * Returns a locale-aware comparator that will alphabetically order a list of section names.
+ */
+ public Comparator<String> getSectionNameComparator() {
+ return mSectionNameComparator;
+ }
+
+ /**
+ * Compares two titles with the same return value semantics as Comparator.
+ */
+ @Thunk int compareTitles(String titleA, String titleB) {
+ // Ensure that we de-prioritize any titles that don't start with a linguistic letter or digit
+ boolean aStartsWithLetter = (titleA.length() > 0) &&
+ Character.isLetterOrDigit(titleA.codePointAt(0));
+ boolean bStartsWithLetter = (titleB.length() > 0) &&
+ Character.isLetterOrDigit(titleB.codePointAt(0));
+ if (aStartsWithLetter && !bStartsWithLetter) {
+ return -1;
+ } else if (!aStartsWithLetter && bStartsWithLetter) {
+ return 1;
+ }
+
+ // Order by the title in the current locale
+ return mCollator.compare(titleA, titleB);
+ }
+}
diff --git a/src/com/android/launcher3/model/PackageItemInfo.java b/src/com/android/launcher3/model/PackageItemInfo.java
new file mode 100644
index 000000000..30f228c68
--- /dev/null
+++ b/src/com/android/launcher3/model/PackageItemInfo.java
@@ -0,0 +1,65 @@
+/*
+ * 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.model;
+
+import android.graphics.Bitmap;
+
+import com.android.launcher3.ItemInfo;
+
+import java.util.Arrays;
+
+/**
+ * Represents a {@link Package} in the widget tray section.
+ */
+public class PackageItemInfo extends ItemInfo {
+
+ /**
+ * A bitmap version of the application icon.
+ */
+ public Bitmap iconBitmap;
+
+ /**
+ * Indicates whether we're using a low res icon.
+ */
+ public boolean usingLowResIcon;
+
+ /**
+ * Package name of the {@link ItemInfo}.
+ */
+ public String packageName;
+
+ /**
+ * Character that is used as a section name for the {@link ItemInfo#title}.
+ * (e.g., "G" will be stored if title is "Google")
+ */
+ public String titleSectionName;
+
+ int flags = 0;
+
+ PackageItemInfo(String packageName) {
+ this.packageName = packageName;
+ }
+
+ @Override
+ public String toString() {
+ return "PackageItemInfo(title=" + title + " id=" + this.id
+ + " type=" + this.itemType + " container=" + this.container
+ + " screen=" + screenId + " cellX=" + cellX + " cellY=" + cellY
+ + " spanX=" + spanX + " spanY=" + spanY + " dropPos=" + Arrays.toString(dropPos)
+ + " user=" + user + ")";
+ }
+}
diff --git a/src/com/android/launcher3/model/WidgetsAndShortcutNameComparator.java b/src/com/android/launcher3/model/WidgetsAndShortcutNameComparator.java
new file mode 100644
index 000000000..61e895283
--- /dev/null
+++ b/src/com/android/launcher3/model/WidgetsAndShortcutNameComparator.java
@@ -0,0 +1,68 @@
+package com.android.launcher3.model;
+
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+
+import com.android.launcher3.LauncherAppWidgetProviderInfo;
+import com.android.launcher3.Utilities;
+import com.android.launcher3.compat.AppWidgetManagerCompat;
+import com.android.launcher3.compat.UserHandleCompat;
+
+import java.text.Collator;
+import java.util.Comparator;
+import java.util.HashMap;
+
+public class WidgetsAndShortcutNameComparator implements Comparator<Object> {
+ private final AppWidgetManagerCompat mManager;
+ private final PackageManager mPackageManager;
+ private final HashMap<Object, String> mLabelCache;
+ private final Collator mCollator;
+ private final UserHandleCompat mMainHandle;
+
+ public WidgetsAndShortcutNameComparator(Context context) {
+ mManager = AppWidgetManagerCompat.getInstance(context);
+ mPackageManager = context.getPackageManager();
+ mLabelCache = new HashMap<Object, String>();
+ mCollator = Collator.getInstance();
+ mMainHandle = UserHandleCompat.myUserHandle();
+ }
+
+ @Override
+ public final int compare(Object a, Object b) {
+ String labelA, labelB;
+ if (mLabelCache.containsKey(a)) {
+ labelA = mLabelCache.get(a);
+ } else {
+ labelA = (a instanceof LauncherAppWidgetProviderInfo)
+ ? Utilities.trim(mManager.loadLabel((LauncherAppWidgetProviderInfo) a))
+ : Utilities.trim(((ResolveInfo) a).loadLabel(mPackageManager));
+ mLabelCache.put(a, labelA);
+ }
+ if (mLabelCache.containsKey(b)) {
+ labelB = mLabelCache.get(b);
+ } else {
+ labelB = (b instanceof LauncherAppWidgetProviderInfo)
+ ? Utilities.trim(mManager.loadLabel((LauncherAppWidgetProviderInfo) b))
+ : Utilities.trim(((ResolveInfo) b).loadLabel(mPackageManager));
+ mLabelCache.put(b, labelB);
+ }
+
+ // Currently, there is no work profile shortcuts, hence only considering the widget cases.
+
+ boolean aWorkProfile = (a instanceof LauncherAppWidgetProviderInfo) &&
+ !mMainHandle.equals(mManager.getUser((LauncherAppWidgetProviderInfo) a));
+ boolean bWorkProfile = (b instanceof LauncherAppWidgetProviderInfo) &&
+ !mMainHandle.equals(mManager.getUser((LauncherAppWidgetProviderInfo) b));
+
+ // Independent of how the labels compare, if only one of the two widget info belongs to
+ // work profile, put that one in the back.
+ if (aWorkProfile && !bWorkProfile) {
+ return 1;
+ }
+ if (!aWorkProfile && bWorkProfile) {
+ return -1;
+ }
+ return mCollator.compare(labelA, labelB);
+ }
+};
diff --git a/src/com/android/launcher3/model/WidgetsModel.java b/src/com/android/launcher3/model/WidgetsModel.java
new file mode 100644
index 000000000..185dfcae3
--- /dev/null
+++ b/src/com/android/launcher3/model/WidgetsModel.java
@@ -0,0 +1,170 @@
+
+package com.android.launcher3.model;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.pm.ResolveInfo;
+import android.util.Log;
+
+import com.android.launcher3.AppFilter;
+import com.android.launcher3.IconCache;
+import com.android.launcher3.LauncherAppWidgetProviderInfo;
+import com.android.launcher3.Utilities;
+import com.android.launcher3.compat.AlphabeticIndexCompat;
+import com.android.launcher3.compat.AppWidgetManagerCompat;
+import com.android.launcher3.compat.UserHandleCompat;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.List;
+
+/**
+ * Widgets data model that is used by the adapters of the widget views and controllers.
+ *
+ * <p> The widgets and shortcuts are organized using package name as its index.
+ */
+public class WidgetsModel {
+
+ private static final String TAG = "WidgetsModel";
+ private static final boolean DEBUG = false;
+
+ /* List of packages that is tracked by this model. */
+ private ArrayList<PackageItemInfo> mPackageItemInfos = new ArrayList<>();
+
+ /* Map of widgets and shortcuts that are tracked per package. */
+ private HashMap<PackageItemInfo, ArrayList<Object>> mWidgetsList = new HashMap<>();
+
+ private ArrayList<Object> mRawList;
+
+ private final AppWidgetManagerCompat mAppWidgetMgr;
+ private final Comparator mWidgetAndShortcutNameComparator;
+ private final Comparator mAppNameComparator;
+ private final IconCache mIconCache;
+ private final AppFilter mAppFilter;
+ private AlphabeticIndexCompat mIndexer;
+
+ public WidgetsModel(Context context, IconCache iconCache, AppFilter appFilter) {
+ mAppWidgetMgr = AppWidgetManagerCompat.getInstance(context);
+ mWidgetAndShortcutNameComparator = new WidgetsAndShortcutNameComparator(context);
+ mAppNameComparator = (new AppNameComparator(context)).getAppInfoComparator();
+ mIconCache = iconCache;
+ mAppFilter = appFilter;
+ mIndexer = new AlphabeticIndexCompat(context);
+ }
+
+ private WidgetsModel(WidgetsModel model) {
+ mAppWidgetMgr = model.mAppWidgetMgr;
+ mPackageItemInfos = (ArrayList<PackageItemInfo>) model.mPackageItemInfos.clone();
+ mWidgetsList = (HashMap<PackageItemInfo, ArrayList<Object>>) model.mWidgetsList.clone();
+ mRawList = (ArrayList<Object>) model.mRawList.clone();
+ mWidgetAndShortcutNameComparator = model.mWidgetAndShortcutNameComparator;
+ mAppNameComparator = model.mAppNameComparator;
+ mIconCache = model.mIconCache;
+ mAppFilter = model.mAppFilter;
+ }
+
+ // Access methods that may be deleted if the private fields are made package-private.
+ public int getPackageSize() {
+ if (mPackageItemInfos == null) {
+ return 0;
+ }
+ return mPackageItemInfos.size();
+ }
+
+ // Access methods that may be deleted if the private fields are made package-private.
+ public PackageItemInfo getPackageItemInfo(int pos) {
+ if (pos >= mPackageItemInfos.size() || pos < 0) {
+ return null;
+ }
+ return mPackageItemInfos.get(pos);
+ }
+
+ public List<Object> getSortedWidgets(int pos) {
+ return mWidgetsList.get(mPackageItemInfos.get(pos));
+ }
+
+ public ArrayList<Object> getRawList() {
+ return mRawList;
+ }
+
+ public void setWidgetsAndShortcuts(ArrayList<Object> rawWidgetsShortcuts) {
+ Utilities.assertWorkerThread();
+ mRawList = rawWidgetsShortcuts;
+ if (DEBUG) {
+ Log.d(TAG, "addWidgetsAndShortcuts, widgetsShortcuts#=" + rawWidgetsShortcuts.size());
+ }
+
+ // Temporary list for {@link PackageItemInfos} to avoid having to go through
+ // {@link mPackageItemInfos} to locate the key to be used for {@link #mWidgetsList}
+ HashMap<String, PackageItemInfo> tmpPackageItemInfos = new HashMap<>();
+
+ // clear the lists.
+ mWidgetsList.clear();
+ mPackageItemInfos.clear();
+
+ // add and update.
+ for (Object o: rawWidgetsShortcuts) {
+ String packageName = "";
+ UserHandleCompat userHandle = null;
+ ComponentName componentName = null;
+ if (o instanceof LauncherAppWidgetProviderInfo) {
+ LauncherAppWidgetProviderInfo widgetInfo = (LauncherAppWidgetProviderInfo) o;
+ componentName = widgetInfo.provider;
+ packageName = widgetInfo.provider.getPackageName();
+ userHandle = mAppWidgetMgr.getUser(widgetInfo);
+ } else if (o instanceof ResolveInfo) {
+ ResolveInfo resolveInfo = (ResolveInfo) o;
+ componentName = new ComponentName(resolveInfo.activityInfo.packageName,
+ resolveInfo.activityInfo.name);
+ packageName = resolveInfo.activityInfo.packageName;
+ userHandle = UserHandleCompat.myUserHandle();
+ }
+
+ if (componentName == null || userHandle == null) {
+ Log.e(TAG, String.format("Widget cannot be set for %s.", o.getClass().toString()));
+ continue;
+ }
+ if (mAppFilter != null && !mAppFilter.shouldShowApp(componentName)) {
+ if (DEBUG) {
+ Log.d(TAG, String.format("%s is filtered and not added to the widget tray.",
+ packageName));
+ }
+ continue;
+ }
+
+ PackageItemInfo pInfo = tmpPackageItemInfos.get(packageName);
+ ArrayList<Object> widgetsShortcutsList = mWidgetsList.get(pInfo);
+ if (widgetsShortcutsList != null) {
+ widgetsShortcutsList.add(o);
+ } else {
+ widgetsShortcutsList = new ArrayList<Object>();
+ widgetsShortcutsList.add(o);
+ pInfo = new PackageItemInfo(packageName);
+ mIconCache.getTitleAndIconForApp(packageName, userHandle,
+ true /* userLowResIcon */, pInfo);
+ pInfo.titleSectionName = mIndexer.computeSectionName(pInfo.title);
+ mWidgetsList.put(pInfo, widgetsShortcutsList);
+ tmpPackageItemInfos.put(packageName, pInfo);
+ mPackageItemInfos.add(pInfo);
+ }
+ }
+
+ // sort.
+ Collections.sort(mPackageItemInfos, mAppNameComparator);
+ for (PackageItemInfo p: mPackageItemInfos) {
+ Collections.sort(mWidgetsList.get(p), mWidgetAndShortcutNameComparator);
+ }
+ }
+
+ /**
+ * Create a snapshot of the widgets model.
+ * <p>
+ * Usage case: view binding without being modified from package updates.
+ */
+ @Override
+ public WidgetsModel clone(){
+ return new WidgetsModel(this);
+ }
+} \ No newline at end of file
diff --git a/src/com/android/launcher3/LauncherExtension.java b/src/com/android/launcher3/testing/LauncherExtension.java
index b264042cf..34492e4ca 100644
--- a/src/com/android/launcher3/LauncherExtension.java
+++ b/src/com/android/launcher3/testing/LauncherExtension.java
@@ -1,7 +1,6 @@
-package com.android.launcher3;
+package com.android.launcher3.testing;
import android.animation.Animator;
-import android.animation.Animator.AnimatorListener;
import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
import android.content.ComponentName;
@@ -12,9 +11,19 @@ import android.view.Menu;
import android.view.View;
import android.view.ViewGroup;
+import com.android.launcher3.AppInfo;
+import com.android.launcher3.InsettableFrameLayout;
+import com.android.launcher3.Launcher;
+import com.android.launcher3.LauncherAnimUtils;
+import com.android.launcher3.LauncherCallbacks;
+import com.android.launcher3.R;
+import com.android.launcher3.allapps.AllAppsSearchBarController;
+import com.android.launcher3.util.ComponentKey;
+
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
+import java.util.List;
/**
* This class represents a very trivial LauncherExtension. It primarily serves as a simple
@@ -82,6 +91,11 @@ public class LauncherExtension extends Launcher {
}
@Override
+ public void onRequestPermissionsResult(int requestCode, String[] permissions,
+ int[] grantResults) {
+ }
+
+ @Override
public void onWindowFocusChanged(boolean hasFocus) {
}
@@ -108,6 +122,10 @@ public class LauncherExtension extends Launcher {
}
@Override
+ public void onTrimMemory(int level) {
+ }
+
+ @Override
public void onLauncherProviderChange() {
}
@@ -242,6 +260,16 @@ public class LauncherExtension extends Launcher {
}
@Override
+ public AllAppsSearchBarController getAllAppsSearchBarController() {
+ return null;
+ }
+
+ @Override
+ public List<ComponentKey> getPredictedApps() {
+ return new ArrayList<>();
+ }
+
+ @Override
public boolean isLauncherPreinstalled() {
return false;
}
@@ -261,6 +289,11 @@ public class LauncherExtension extends Launcher {
return mLauncherOverlay;
}
+ @Override
+ public void setLauncherSearchCallback(Object callbacks) {
+ // Do nothing
+ }
+
class LauncherExtensionOverlay implements LauncherOverlay {
LauncherOverlayCallbacks mLauncherOverlayCallbacks;
ViewGroup mOverlayView;
diff --git a/src/com/android/launcher3/util/ComponentKey.java b/src/com/android/launcher3/util/ComponentKey.java
new file mode 100644
index 000000000..6a7df4318
--- /dev/null
+++ b/src/com/android/launcher3/util/ComponentKey.java
@@ -0,0 +1,81 @@
+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.ComponentName;
+import android.content.Context;
+import com.android.launcher3.compat.UserHandleCompat;
+import com.android.launcher3.compat.UserManagerCompat;
+
+import java.util.Arrays;
+
+public class ComponentKey {
+
+ public final ComponentName componentName;
+ public final UserHandleCompat user;
+
+ private final int mHashCode;
+
+ public ComponentKey(ComponentName componentName, UserHandleCompat user) {
+ assert (componentName != null);
+ assert (user != null);
+ this.componentName = componentName;
+ this.user = user;
+ mHashCode = Arrays.hashCode(new Object[] {componentName, user});
+
+ }
+
+ /**
+ * Creates a new component key from an encoded component key string in the form of
+ * [flattenedComponentString#userId]. If the userId is not present, then it defaults
+ * to the current user.
+ */
+ public ComponentKey(Context context, String componentKeyStr) {
+ int userDelimiterIndex = componentKeyStr.indexOf("#");
+ if (userDelimiterIndex != -1) {
+ String componentStr = componentKeyStr.substring(0, userDelimiterIndex);
+ Long componentUser = Long.valueOf(componentKeyStr.substring(userDelimiterIndex + 1));
+ componentName = ComponentName.unflattenFromString(componentStr);
+ user = UserManagerCompat.getInstance(context)
+ .getUserForSerialNumber(componentUser.longValue());
+ } else {
+ // No user provided, default to the current user
+ componentName = ComponentName.unflattenFromString(componentKeyStr);
+ user = UserHandleCompat.myUserHandle();
+ }
+ mHashCode = Arrays.hashCode(new Object[] {componentName, user});
+ }
+
+ /**
+ * Encodes a component key as a string of the form [flattenedComponentString#userId].
+ */
+ public String flattenToString(Context context) {
+ return componentName.flattenToString() + "#" +
+ UserManagerCompat.getInstance(context).getSerialNumberForUser(user);
+ }
+
+ @Override
+ public int hashCode() {
+ return mHashCode;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ ComponentKey other = (ComponentKey) o;
+ return other.componentName.equals(componentName) && other.user.equals(user);
+ }
+} \ No newline at end of file
diff --git a/src/com/android/launcher3/util/CursorIconInfo.java b/src/com/android/launcher3/util/CursorIconInfo.java
new file mode 100644
index 000000000..cdf9e3c60
--- /dev/null
+++ b/src/com/android/launcher3/util/CursorIconInfo.java
@@ -0,0 +1,70 @@
+/*
+ * 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.content.Context;
+import android.content.Intent.ShortcutIconResource;
+import android.database.Cursor;
+import android.graphics.Bitmap;
+import android.text.TextUtils;
+
+import com.android.launcher3.LauncherSettings;
+import com.android.launcher3.ShortcutInfo;
+import com.android.launcher3.Utilities;
+
+/**
+ * Utility class to load icon from a cursor.
+ */
+public class CursorIconInfo {
+ public final int iconTypeIndex;
+ public final int iconPackageIndex;
+ public final int iconResourceIndex;
+ public final int iconIndex;
+
+ public CursorIconInfo(Cursor c) {
+ iconTypeIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ICON_TYPE);
+ iconIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ICON);
+ iconPackageIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ICON_PACKAGE);
+ iconResourceIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ICON_RESOURCE);
+ }
+
+ public Bitmap loadIcon(Cursor c, ShortcutInfo info, Context context) {
+ Bitmap icon = null;
+ int iconType = c.getInt(iconTypeIndex);
+ switch (iconType) {
+ case LauncherSettings.Favorites.ICON_TYPE_RESOURCE:
+ String packageName = c.getString(iconPackageIndex);
+ String resourceName = c.getString(iconResourceIndex);
+ if (!TextUtils.isEmpty(packageName) || !TextUtils.isEmpty(resourceName)) {
+ info.iconResource = new ShortcutIconResource();
+ info.iconResource.packageName = packageName;
+ info.iconResource.resourceName = resourceName;
+ icon = Utilities.createIconBitmap(packageName, resourceName, context);
+ }
+ if (icon == null) {
+ // Failed to load from resource, try loading from DB.
+ icon = Utilities.createIconBitmap(c, iconIndex, context);
+ }
+ break;
+ case LauncherSettings.Favorites.ICON_TYPE_BITMAP:
+ icon = Utilities.createIconBitmap(c, iconIndex, context);
+ info.customIcon = icon != null;
+ break;
+ }
+ return icon;
+ }
+}
diff --git a/src/com/android/launcher3/util/FlingAnimation.java b/src/com/android/launcher3/util/FlingAnimation.java
new file mode 100644
index 000000000..55c5d7dc2
--- /dev/null
+++ b/src/com/android/launcher3/util/FlingAnimation.java
@@ -0,0 +1,104 @@
+package com.android.launcher3.util;
+
+import android.animation.TimeInterpolator;
+import android.animation.ValueAnimator;
+import android.animation.ValueAnimator.AnimatorUpdateListener;
+import android.graphics.PointF;
+import android.graphics.Rect;
+import android.view.animation.DecelerateInterpolator;
+
+import com.android.launcher3.DragLayer;
+import com.android.launcher3.DragView;
+import com.android.launcher3.DropTarget.DragObject;
+
+public class FlingAnimation implements AnimatorUpdateListener {
+
+ /**
+ * Maximum acceleration in one dimension (pixels per milliseconds)
+ */
+ private static final float MAX_ACCELERATION = 0.5f;
+ private static final int DRAG_END_DELAY = 300;
+
+ protected final DragObject mDragObject;
+ protected final Rect mIconRect;
+ protected final DragLayer mDragLayer;
+ protected final Rect mFrom;
+ protected final int mDuration;
+ protected final float mUX, mUY;
+ protected final float mAnimationTimeFraction;
+ protected final TimeInterpolator mAlphaInterpolator = new DecelerateInterpolator(0.75f);
+
+ protected float mAX, mAY;
+
+ /**
+ * @param vel initial fling velocity in pixels per second.
+ */
+ public FlingAnimation(DragObject d, PointF vel, Rect iconRect, DragLayer dragLayer) {
+ mDragObject = d;
+ mUX = vel.x / 1000;
+ mUY = vel.y / 1000;
+ mIconRect = iconRect;
+
+ mDragLayer = dragLayer;
+ mFrom = new Rect();
+ dragLayer.getViewRectRelativeToSelf(d.dragView, mFrom);
+
+ float scale = d.dragView.getScaleX();
+ float xOffset = ((scale - 1f) * d.dragView.getMeasuredWidth()) / 2f;
+ float yOffset = ((scale - 1f) * d.dragView.getMeasuredHeight()) / 2f;
+ mFrom.left += xOffset;
+ mFrom.right -= xOffset;
+ mFrom.top += yOffset;
+ mFrom.bottom -= yOffset;
+
+ mDuration = initDuration();
+ mAnimationTimeFraction = ((float) mDuration) / (mDuration + DRAG_END_DELAY);
+ }
+
+ /**
+ * The fling animation is based on the following system
+ * - Apply a constant force in the y direction to causing the fling to decelerate.
+ * - The animation runs for the time taken by the object to go out of the screen.
+ * - Calculate a constant acceleration in x direction such that the object reaches
+ * {@link #mIconRect} in the given time.
+ */
+ protected int initDuration() {
+ float sY = -mFrom.bottom;
+
+ float d = mUY * mUY + 2 * sY * MAX_ACCELERATION;
+ if (d >= 0) {
+ // sY can be reached under the MAX_ACCELERATION. Use MAX_ACCELERATION for y direction.
+ mAY = MAX_ACCELERATION;
+ } else {
+ // sY is not reachable, decrease the acceleration so that sY is almost reached.
+ d = 0;
+ mAY = mUY * mUY / (2 * -sY);
+ }
+ double t = (-mUY - Math.sqrt(d)) / mAY;
+
+ float sX = -mFrom.exactCenterX() + mIconRect.exactCenterX();
+
+ // Find horizontal acceleration such that: u*t + a*t*t/2 = s
+ mAX = (float) ((sX - t * mUX) * 2 / (t * t));
+ return (int) Math.round(t);
+ }
+
+ public final int getDuration() {
+ return mDuration + DRAG_END_DELAY;
+ }
+
+ @Override
+ public void onAnimationUpdate(ValueAnimator animation) {
+ float t = animation.getAnimatedFraction();
+ if (t > mAnimationTimeFraction) {
+ t = 1;
+ } else {
+ t = t / mAnimationTimeFraction;
+ }
+ final DragView dragView = (DragView) mDragLayer.getAnimatedView();
+ final float time = t * mDuration;
+ dragView.setTranslationX(time * mUX + mFrom.left + mAX * time * time / 2);
+ dragView.setTranslationY(time * mUY + mFrom.top + mAY * time * time / 2);
+ dragView.setAlpha(1f - mAlphaInterpolator.getInterpolation(t));
+ }
+}
diff --git a/src/com/android/launcher3/util/FocusLogic.java b/src/com/android/launcher3/util/FocusLogic.java
new file mode 100644
index 000000000..696eabe00
--- /dev/null
+++ b/src/com/android/launcher3/util/FocusLogic.java
@@ -0,0 +1,507 @@
+/*
+ * 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.util.Log;
+import android.view.KeyEvent;
+import android.view.View;
+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;
+
+/**
+ * Calculates the next item that a {@link KeyEvent} should change the focus to.
+ *<p>
+ * Note, this utility class calculates everything regards to icon index and its (x,y) coordinates.
+ * Currently supports:
+ * <ul>
+ * <li> full matrix of cells that are 1x1
+ * <li> sparse matrix of cells that are 1x1
+ * [ 1][ ][ 2][ ]
+ * [ ][ ][ 3][ ]
+ * [ ][ 4][ ][ ]
+ * [ ][ 5][ 6][ 7]
+ * </ul>
+ * *<p>
+ * For testing, one can use a BT keyboard, or use following adb command.
+ * ex. $ adb shell input keyevent 20 // KEYCODE_DPAD_LEFT
+ */
+public class FocusLogic {
+
+ private static final String TAG = "FocusLogic";
+ private static final boolean DEBUG = false;
+
+ // 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;
+ public static final int PREVIOUS_PAGE_FIRST_ITEM = -3;
+ public static final int PREVIOUS_PAGE_LAST_ITEM = -4;
+ public static final int PREVIOUS_PAGE_LEFT_COLUMN = -5;
+
+ public static final int CURRENT_PAGE_FIRST_ITEM = -6;
+ public static final int CURRENT_PAGE_LAST_ITEM = -7;
+
+ public static final int NEXT_PAGE_FIRST_ITEM = -8;
+ public static final int NEXT_PAGE_LEFT_COLUMN = -9;
+ public static final int NEXT_PAGE_RIGHT_COLUMN = -10;
+
+ // Matrix related constant.
+ public static final int EMPTY = -1;
+ public static final int PIVOT = 100;
+
+ /**
+ * Returns true only if this utility class handles the key code.
+ */
+ public static boolean shouldConsume(int keyCode) {
+ return (keyCode == KeyEvent.KEYCODE_DPAD_LEFT || keyCode == KeyEvent.KEYCODE_DPAD_RIGHT ||
+ keyCode == KeyEvent.KEYCODE_DPAD_UP || keyCode == KeyEvent.KEYCODE_DPAD_DOWN ||
+ keyCode == KeyEvent.KEYCODE_MOVE_HOME || keyCode == KeyEvent.KEYCODE_MOVE_END ||
+ keyCode == KeyEvent.KEYCODE_PAGE_UP || keyCode == KeyEvent.KEYCODE_PAGE_DOWN ||
+ 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) {
+
+ if (DEBUG) {
+ Log.v(TAG, String.format(
+ "handleKeyEvent START: cntX=%d, cntY=%d, iconIdx=%d, pageIdx=%d, pageCnt=%d",
+ cntX, cntY, iconIdx, pageIndex, pageCount));
+ }
+
+ 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 = 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 = NEXT_PAGE_LEFT_COLUMN;
+ } else if (isRtl && newIndex == NOOP && pageIndex > 0) {
+ newIndex = PREVIOUS_PAGE_LEFT_COLUMN;
+ }
+ break;
+ case KeyEvent.KEYCODE_DPAD_DOWN:
+ newIndex = handleDpadVertical(iconIdx, cntX, cntY, map, 1 /*increment*/);
+ break;
+ case KeyEvent.KEYCODE_DPAD_UP:
+ newIndex = handleDpadVertical(iconIdx, cntX, cntY, map, -1 /*increment*/);
+ break;
+ case KeyEvent.KEYCODE_MOVE_HOME:
+ newIndex = handleMoveHome();
+ break;
+ case KeyEvent.KEYCODE_MOVE_END:
+ newIndex = handleMoveEnd();
+ break;
+ case KeyEvent.KEYCODE_PAGE_DOWN:
+ newIndex = handlePageDown(pageIndex, pageCount);
+ break;
+ case KeyEvent.KEYCODE_PAGE_UP:
+ newIndex = handlePageUp(pageIndex);
+ break;
+ default:
+ break;
+ }
+
+ if (DEBUG) {
+ Log.v(TAG, String.format("handleKeyEvent FINISH: index [%d -> %s]",
+ iconIdx, getStringIndex(newIndex)));
+ }
+ return newIndex;
+ }
+
+ /**
+ * Returns a matrix of size (m x n) that has been initialized with {@link #EMPTY}.
+ *
+ * @param m number of columns in the matrix
+ * @param n number of rows in the matrix
+ */
+ // TODO: get rid of dynamic matrix creation.
+ private static int[][] createFullMatrix(int m, int n) {
+ int[][] matrix = new int [m][n];
+
+ for (int i=0; i < m;i++) {
+ Arrays.fill(matrix[i], EMPTY);
+ }
+ return matrix;
+ }
+
+ /**
+ * Returns a matrix of size same as the {@link CellLayout} dimension that is initialized with the
+ * index of the child view.
+ */
+ // TODO: get rid of the dynamic matrix creation
+ public static int[][] createSparseMatrix(CellLayout layout) {
+ ShortcutAndWidgetContainer parent = layout.getShortcutsAndWidgets();
+ final int m = layout.getCountX();
+ final int n = layout.getCountY();
+ final boolean invert = parent.invertLayoutHorizontally();
+
+ int[][] matrix = createFullMatrix(m, n);
+
+ // 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;
+ matrix[invert ? (m - cx - 1) : cx][cy] = i;
+ }
+ if (DEBUG) {
+ printMatrix(matrix);
+ }
+ return matrix;
+ }
+
+ /**
+ * Creates a sparse matrix that merges the icon and hotseat view group using the cell layout.
+ * The size of the returning matrix is [icon column count x (icon + hotseat row count)]
+ * 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) {
+
+ ViewGroup iconParent = iconLayout.getShortcutsAndWidgets();
+ ViewGroup hotseatParent = hotseatLayout.getShortcutsAndWidgets();
+
+ int m, n;
+ if (isHorizontal) {
+ m = iconLayout.getCountX();
+ n = iconLayout.getCountY() + hotseatLayout.getCountY();
+ } else {
+ m = iconLayout.getCountX() + hotseatLayout.getCountX();
+ n = iconLayout.getCountY();
+ }
+ int[][] matrix = createFullMatrix(m, n);
+
+ // 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;
+ 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) {
+ 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;
+ } 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;
+ }
+ }
+ if (DEBUG) {
+ printMatrix(matrix);
+ }
+ return matrix;
+ }
+
+ /**
+ * Creates a sparse matrix that merges the icon of previous/next page and last column of
+ * current page. When left key is triggered on the leftmost column, sparse matrix is created
+ * that combines previous page matrix and an extra column on the right. Likewise, when right
+ * key is triggered on the rightmost column, sparse matrix is created that combines this column
+ * on the 0th column and the next page matrix.
+ *
+ * @param pivotX x coordinate of the focused item in the current page
+ * @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) {
+
+ ViewGroup iconParent = iconLayout.getShortcutsAndWidgets();
+
+ int[][] matrix = createFullMatrix(iconLayout.getCountX() + 1, iconLayout.getCountY());
+
+ // 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;
+ if (pivotX < 0) {
+ matrix[cx - pivotX][cy] = i;
+ } else {
+ matrix[cx][cy] = i;
+ }
+ }
+
+ if (pivotX < 0) {
+ matrix[0][pivotY] = PIVOT;
+ } else {
+ matrix[pivotX][pivotY] = PIVOT;
+ }
+ if (DEBUG) {
+ printMatrix(matrix);
+ }
+ return matrix;
+ }
+
+ //
+ // key event handling methods.
+ //
+
+ /**
+ * Calculates icon that has is closest to the horizontal axis in reference to the cur icon.
+ *
+ * Example of the check order for KEYCODE_DPAD_RIGHT:
+ * [ ][ ][13][14][15]
+ * [ ][ 6][ 8][10][12]
+ * [ X][ 1][ 2][ 3][ 4]
+ * [ ][ 5][ 7][ 9][11]
+ */
+ // TODO: add unit tests to verify all permutation.
+ private static int handleDpadHorizontal(int iconIdx, int cntX, int cntY,
+ int[][] matrix, int increment) {
+ if(matrix == null) {
+ throw new IllegalStateException("Dpad navigation requires a matrix.");
+ }
+ int newIconIndex = NOOP;
+
+ int xPos = -1;
+ int yPos = -1;
+ // Figure out the location of the icon.
+ for (int i = 0; i < cntX; i++) {
+ for (int j = 0; j < cntY; j++) {
+ if (matrix[i][j] == iconIdx) {
+ xPos = i;
+ yPos = j;
+ }
+ }
+ }
+ if (DEBUG) {
+ Log.v(TAG, String.format("\thandleDpadHorizontal: \t[x, y]=[%d, %d] iconIndex=%d",
+ xPos, yPos, iconIdx));
+ }
+
+ // 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) {
+ return newIconIndex;
+ }
+ }
+
+ // Rule2: check (x1-n, yPos + increment), (x1-n, yPos - increment)
+ // (x2-n, yPos + 2*increment), (x2-n, yPos - 2*increment)
+ int nextYPos1;
+ int nextYPos2;
+ int i = -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) {
+ return newIconIndex;
+ }
+ if ((newIconIndex = inspectMatrix(i, nextYPos2, cntX, cntY, matrix)) != NOOP) {
+ return newIconIndex;
+ }
+ }
+ }
+ return newIconIndex;
+ }
+
+ /**
+ * Calculates icon that is closest to the vertical axis in reference to the current icon.
+ *
+ * Example of the check order for KEYCODE_DPAD_DOWN:
+ * [ ][ ][ ][ X][ ][ ][ ]
+ * [ ][ ][ 5][ 1][ 4][ ][ ]
+ * [ ][10][ 7][ 2][ 6][ 9][ ]
+ * [14][12][ 9][ 3][ 8][11][13]
+ */
+ // TODO: add unit tests to verify all permutation.
+ private static int handleDpadVertical(int iconIndex, int cntX, int cntY,
+ int [][] matrix, int increment) {
+ int newIconIndex = NOOP;
+ if(matrix == null) {
+ throw new IllegalStateException("Dpad navigation requires a matrix.");
+ }
+
+ int xPos = -1;
+ int yPos = -1;
+ // Figure out the location of the icon.
+ for (int i = 0; i< cntX; i++) {
+ for (int j = 0; j < cntY; j++) {
+ if (matrix[i][j] == iconIndex) {
+ xPos = i;
+ yPos = j;
+ }
+ }
+ }
+
+ if (DEBUG) {
+ Log.v(TAG, String.format("\thandleDpadVertical: \t[x, y]=[%d, %d] iconIndex=%d",
+ xPos, yPos, iconIndex));
+ }
+
+ // 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) {
+ return newIconIndex;
+ }
+ }
+
+ // Rule2: check (xPos + increment, y_(1-n)), (xPos - increment, y_(1-n))
+ // (xPos + 2*increment, y_(2-n))), (xPos - 2*increment, y_(2-n))
+ int nextXPos1;
+ int nextXPos2;
+ int j = -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) {
+ return newIconIndex;
+ }
+ if ((newIconIndex = inspectMatrix(nextXPos2, j, cntX, cntY, matrix)) != NOOP) {
+ return newIconIndex;
+ }
+ }
+ }
+ return newIconIndex;
+ }
+
+ private static int handleMoveHome() {
+ return CURRENT_PAGE_FIRST_ITEM;
+ }
+
+ private static int handleMoveEnd() {
+ return CURRENT_PAGE_LAST_ITEM;
+ }
+
+ private static int handlePageDown(int pageIndex, int pageCount) {
+ if (pageIndex < pageCount -1) {
+ return NEXT_PAGE_FIRST_ITEM;
+ }
+ return CURRENT_PAGE_LAST_ITEM;
+ }
+
+ private static int handlePageUp(int pageIndex) {
+ if (pageIndex > 0) {
+ return PREVIOUS_PAGE_FIRST_ITEM;
+ } else {
+ return CURRENT_PAGE_FIRST_ITEM;
+ }
+ }
+
+ //
+ // Helper methods.
+ //
+
+ private static boolean isValid(int xPos, int yPos, int countX, int countY) {
+ return (0 <= xPos && xPos < countX && 0 <= yPos && yPos < countY);
+ }
+
+ private static int inspectMatrix(int x, int y, int cntX, int cntY, int[][] matrix) {
+ int newIconIndex = NOOP;
+ if (isValid(x, y, cntX, cntY)) {
+ if (matrix[x][y] != -1) {
+ newIconIndex = matrix[x][y];
+ if (DEBUG) {
+ Log.v(TAG, String.format("\t\tinspect: \t[x, y]=[%d, %d] %d",
+ x, y, matrix[x][y]));
+ }
+ return newIconIndex;
+ }
+ }
+ return newIconIndex;
+ }
+
+ /**
+ * Only used for debugging.
+ */
+ private static String getStringIndex(int index) {
+ switch(index) {
+ case NOOP: return "NOOP";
+ case PREVIOUS_PAGE_FIRST_ITEM: return "PREVIOUS_PAGE_FIRST";
+ case PREVIOUS_PAGE_LAST_ITEM: return "PREVIOUS_PAGE_LAST";
+ case PREVIOUS_PAGE_RIGHT_COLUMN:return "PREVIOUS_PAGE_RIGHT_COLUMN";
+ case CURRENT_PAGE_FIRST_ITEM: return "CURRENT_PAGE_FIRST";
+ 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";
+ default:
+ return Integer.toString(index);
+ }
+ }
+
+ /**
+ * Only used for debugging.
+ */
+ private static void printMatrix(int[][] matrix) {
+ Log.v(TAG, "\tprintMap:");
+ int m = matrix.length;
+ int n = matrix[0].length;
+
+ for (int j=0; j < n; j++) {
+ String colY = "\t\t";
+ for (int i=0; i < m; i++) {
+ colY += String.format("%3d",matrix[i][j]);
+ }
+ Log.v(TAG, colY);
+ }
+ }
+
+ /**
+ * @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}.
+ */
+ public static View getAdjacentChildInNextPage(
+ ShortcutAndWidgetContainer nextPage, View oldView, int edgeColumn) {
+ final int newRow = ((CellLayout.LayoutParams) oldView.getLayoutParams()).cellY;
+
+ int column = (edgeColumn == NEXT_PAGE_LEFT_COLUMN) ^ nextPage.invertLayoutHorizontally()
+ ? 0 : (((CellLayout) nextPage.getParent()).getCountX() - 1);
+
+ for (; column >= 0; column--) {
+ for (int row = newRow; row >= 0; row--) {
+ View newView = nextPage.getChildAt(column, row);
+ if (newView != null) {
+ return newView;
+ }
+ }
+ }
+ return null;
+ }
+}
diff --git a/src/com/android/launcher3/util/LauncherEdgeEffect.java b/src/com/android/launcher3/util/LauncherEdgeEffect.java
new file mode 100644
index 000000000..3e3b255ad
--- /dev/null
+++ b/src/com/android/launcher3/util/LauncherEdgeEffect.java
@@ -0,0 +1,365 @@
+/*
+ * 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.Canvas;
+import android.graphics.Paint;
+import android.graphics.Rect;
+import android.view.animation.AnimationUtils;
+import android.view.animation.DecelerateInterpolator;
+import android.view.animation.Interpolator;
+
+/**
+ * This class differs from the framework {@link android.widget.EdgeEffect}:
+ * 1) It does not use PorterDuffXfermode
+ * 2) The width to radius factor is smaller (0.5 instead of 0.75)
+ */
+public class LauncherEdgeEffect {
+
+ // Time it will take the effect to fully recede in ms
+ private static final int RECEDE_TIME = 600;
+
+ // Time it will take before a pulled glow begins receding in ms
+ private static final int PULL_TIME = 167;
+
+ // Time it will take in ms for a pulled glow to decay to partial strength before release
+ private static final int PULL_DECAY_TIME = 2000;
+
+ private static final float MAX_ALPHA = 0.5f;
+
+ private static final float MAX_GLOW_SCALE = 2.f;
+
+ private static final float PULL_GLOW_BEGIN = 0.f;
+
+ // Minimum velocity that will be absorbed
+ private static final int MIN_VELOCITY = 100;
+ // Maximum velocity, clamps at this value
+ private static final int MAX_VELOCITY = 10000;
+
+ private static final float EPSILON = 0.001f;
+
+ private static final double ANGLE = Math.PI / 6;
+ private static final float SIN = (float) Math.sin(ANGLE);
+ private static final float COS = (float) Math.cos(ANGLE);
+
+ private float mGlowAlpha;
+ private float mGlowScaleY;
+
+ private float mGlowAlphaStart;
+ private float mGlowAlphaFinish;
+ private float mGlowScaleYStart;
+ private float mGlowScaleYFinish;
+
+ private long mStartTime;
+ private float mDuration;
+
+ private final Interpolator mInterpolator;
+
+ private static final int STATE_IDLE = 0;
+ private static final int STATE_PULL = 1;
+ private static final int STATE_ABSORB = 2;
+ private static final int STATE_RECEDE = 3;
+ private static final int STATE_PULL_DECAY = 4;
+
+ private static final float PULL_DISTANCE_ALPHA_GLOW_FACTOR = 0.8f;
+
+ private static final int VELOCITY_GLOW_FACTOR = 6;
+
+ private int mState = STATE_IDLE;
+
+ private float mPullDistance;
+
+ private final Rect mBounds = new Rect();
+ private final Paint mPaint = new Paint();
+ private float mRadius;
+ private float mBaseGlowScale;
+ private float mDisplacement = 0.5f;
+ private float mTargetDisplacement = 0.5f;
+
+ /**
+ * Construct a new EdgeEffect with a theme appropriate for the provided context.
+ */
+ public LauncherEdgeEffect() {
+ mPaint.setAntiAlias(true);
+ mPaint.setStyle(Paint.Style.FILL);
+ mInterpolator = new DecelerateInterpolator();
+ }
+
+ /**
+ * Set the size of this edge effect in pixels.
+ *
+ * @param width Effect width in pixels
+ * @param height Effect height in pixels
+ */
+ public void setSize(int width, int height) {
+ final float r = width * 0.5f / SIN;
+ final float y = COS * r;
+ final float h = r - y;
+ final float or = height * 0.75f / SIN;
+ final float oy = COS * or;
+ final float oh = or - oy;
+
+ mRadius = r;
+ mBaseGlowScale = h > 0 ? Math.min(oh / h, 1.f) : 1.f;
+
+ mBounds.set(mBounds.left, mBounds.top, width, (int) Math.min(height, h));
+ }
+
+ /**
+ * Reports if this EdgeEffect's animation is finished. If this method returns false
+ * after a call to {@link #draw(Canvas)} the host widget should schedule another
+ * drawing pass to continue the animation.
+ *
+ * @return true if animation is finished, false if drawing should continue on the next frame.
+ */
+ public boolean isFinished() {
+ return mState == STATE_IDLE;
+ }
+
+ /**
+ * Immediately finish the current animation.
+ * After this call {@link #isFinished()} will return true.
+ */
+ public void finish() {
+ mState = STATE_IDLE;
+ }
+
+ /**
+ * A view should call this when content is pulled away from an edge by the user.
+ * This will update the state of the current visual effect and its associated animation.
+ * The host view should always {@link android.view.View#invalidate()} after this
+ * and draw the results accordingly.
+ *
+ * <p>Views using EdgeEffect should favor {@link #onPull(float, float)} when the displacement
+ * of the pull point is known.</p>
+ *
+ * @param deltaDistance Change in distance since the last call. Values may be 0 (no change) to
+ * 1.f (full length of the view) or negative values to express change
+ * back toward the edge reached to initiate the effect.
+ */
+ public void onPull(float deltaDistance) {
+ onPull(deltaDistance, 0.5f);
+ }
+
+ /**
+ * A view should call this when content is pulled away from an edge by the user.
+ * This will update the state of the current visual effect and its associated animation.
+ * The host view should always {@link android.view.View#invalidate()} after this
+ * and draw the results accordingly.
+ *
+ * @param deltaDistance Change in distance since the last call. Values may be 0 (no change) to
+ * 1.f (full length of the view) or negative values to express change
+ * back toward the edge reached to initiate the effect.
+ * @param displacement The displacement from the starting side of the effect of the point
+ * initiating the pull. In the case of touch this is the finger position.
+ * Values may be from 0-1.
+ */
+ public void onPull(float deltaDistance, float displacement) {
+ final long now = AnimationUtils.currentAnimationTimeMillis();
+ mTargetDisplacement = displacement;
+ if (mState == STATE_PULL_DECAY && now - mStartTime < mDuration) {
+ return;
+ }
+ if (mState != STATE_PULL) {
+ mGlowScaleY = Math.max(PULL_GLOW_BEGIN, mGlowScaleY);
+ }
+ mState = STATE_PULL;
+
+ mStartTime = now;
+ mDuration = PULL_TIME;
+
+ mPullDistance += deltaDistance;
+
+ final float absdd = Math.abs(deltaDistance);
+ mGlowAlpha = mGlowAlphaStart = Math.min(MAX_ALPHA,
+ mGlowAlpha + (absdd * PULL_DISTANCE_ALPHA_GLOW_FACTOR));
+
+ if (mPullDistance == 0) {
+ mGlowScaleY = mGlowScaleYStart = 0;
+ } else {
+ final float scale = (float) (Math.max(0, 1 - 1 /
+ Math.sqrt(Math.abs(mPullDistance) * mBounds.height()) - 0.3d) / 0.7d);
+
+ mGlowScaleY = mGlowScaleYStart = scale;
+ }
+
+ mGlowAlphaFinish = mGlowAlpha;
+ mGlowScaleYFinish = mGlowScaleY;
+ }
+
+ /**
+ * Call when the object is released after being pulled.
+ * This will begin the "decay" phase of the effect. After calling this method
+ * the host view should {@link android.view.View#invalidate()} and thereby
+ * draw the results accordingly.
+ */
+ public void onRelease() {
+ mPullDistance = 0;
+
+ if (mState != STATE_PULL && mState != STATE_PULL_DECAY) {
+ return;
+ }
+
+ mState = STATE_RECEDE;
+ mGlowAlphaStart = mGlowAlpha;
+ mGlowScaleYStart = mGlowScaleY;
+
+ mGlowAlphaFinish = 0.f;
+ mGlowScaleYFinish = 0.f;
+
+ mStartTime = AnimationUtils.currentAnimationTimeMillis();
+ mDuration = RECEDE_TIME;
+ }
+
+ /**
+ * Call when the effect absorbs an impact at the given velocity.
+ * Used when a fling reaches the scroll boundary.
+ *
+ * <p>When using a {@link android.widget.Scroller} or {@link android.widget.OverScroller},
+ * the method <code>getCurrVelocity</code> will provide a reasonable approximation
+ * to use here.</p>
+ *
+ * @param velocity Velocity at impact in pixels per second.
+ */
+ public void onAbsorb(int velocity) {
+ mState = STATE_ABSORB;
+ velocity = Math.min(Math.max(MIN_VELOCITY, Math.abs(velocity)), MAX_VELOCITY);
+
+ mStartTime = AnimationUtils.currentAnimationTimeMillis();
+ mDuration = 0.15f + (velocity * 0.02f);
+
+ // The glow depends more on the velocity, and therefore starts out
+ // nearly invisible.
+ mGlowAlphaStart = 0.3f;
+ mGlowScaleYStart = Math.max(mGlowScaleY, 0.f);
+
+
+ // Growth for the size of the glow should be quadratic to properly
+ // respond
+ // to a user's scrolling speed. The faster the scrolling speed, the more
+ // intense the effect should be for both the size and the saturation.
+ mGlowScaleYFinish = Math.min(0.025f + (velocity * (velocity / 100) * 0.00015f) / 2, 1.f);
+ // Alpha should change for the glow as well as size.
+ mGlowAlphaFinish = Math.max(
+ mGlowAlphaStart, Math.min(velocity * VELOCITY_GLOW_FACTOR * .00001f, MAX_ALPHA));
+ mTargetDisplacement = 0.5f;
+ }
+
+ /**
+ * Set the color of this edge effect in argb.
+ *
+ * @param color Color in argb
+ */
+ public void setColor(int color) {
+ mPaint.setColor(color);
+ }
+
+ /**
+ * Return the color of this edge effect in argb.
+ * @return The color of this edge effect in argb
+ */
+ public int getColor() {
+ return mPaint.getColor();
+ }
+
+ /**
+ * Draw into the provided canvas. Assumes that the canvas has been rotated
+ * accordingly and the size has been set. The effect will be drawn the full
+ * width of X=0 to X=width, beginning from Y=0 and extending to some factor <
+ * 1.f of height.
+ *
+ * @param canvas Canvas to draw into
+ * @return true if drawing should continue beyond this frame to continue the
+ * animation
+ */
+ public boolean draw(Canvas canvas) {
+ update();
+
+ final float centerX = mBounds.centerX();
+ final float centerY = mBounds.height() - mRadius;
+
+ canvas.scale(1.f, Math.min(mGlowScaleY, 1.f) * mBaseGlowScale, centerX, 0);
+
+ final float displacement = Math.max(0, Math.min(mDisplacement, 1.f)) - 0.5f;
+ float translateX = mBounds.width() * displacement / 2;
+ mPaint.setAlpha((int) (0xff * mGlowAlpha));
+ canvas.drawCircle(centerX + translateX, centerY, mRadius, mPaint);
+
+ boolean oneLastFrame = false;
+ if (mState == STATE_RECEDE && mGlowScaleY == 0) {
+ mState = STATE_IDLE;
+ oneLastFrame = true;
+ }
+
+ return mState != STATE_IDLE || oneLastFrame;
+ }
+
+ /**
+ * Return the maximum height that the edge effect will be drawn at given the original
+ * {@link #setSize(int, int) input size}.
+ * @return The maximum height of the edge effect
+ */
+ public int getMaxHeight() {
+ return (int) (mBounds.height() * MAX_GLOW_SCALE + 0.5f);
+ }
+
+ private void update() {
+ final long time = AnimationUtils.currentAnimationTimeMillis();
+ final float t = Math.min((time - mStartTime) / mDuration, 1.f);
+
+ final float interp = mInterpolator.getInterpolation(t);
+
+ mGlowAlpha = mGlowAlphaStart + (mGlowAlphaFinish - mGlowAlphaStart) * interp;
+ mGlowScaleY = mGlowScaleYStart + (mGlowScaleYFinish - mGlowScaleYStart) * interp;
+ mDisplacement = (mDisplacement + mTargetDisplacement) / 2;
+
+ if (t >= 1.f - EPSILON) {
+ switch (mState) {
+ case STATE_ABSORB:
+ mState = STATE_RECEDE;
+ mStartTime = AnimationUtils.currentAnimationTimeMillis();
+ mDuration = RECEDE_TIME;
+
+ mGlowAlphaStart = mGlowAlpha;
+ mGlowScaleYStart = mGlowScaleY;
+
+ // After absorb, the glow should fade to nothing.
+ mGlowAlphaFinish = 0.f;
+ mGlowScaleYFinish = 0.f;
+ break;
+ case STATE_PULL:
+ mState = STATE_PULL_DECAY;
+ mStartTime = AnimationUtils.currentAnimationTimeMillis();
+ mDuration = PULL_DECAY_TIME;
+
+ mGlowAlphaStart = mGlowAlpha;
+ mGlowScaleYStart = mGlowScaleY;
+
+ // After pull, the glow should fade to nothing.
+ mGlowAlphaFinish = 0.f;
+ mGlowScaleYFinish = 0.f;
+ break;
+ case STATE_PULL_DECAY:
+ mState = STATE_RECEDE;
+ break;
+ case STATE_RECEDE:
+ mState = STATE_IDLE;
+ break;
+ }
+ }
+ }
+}
diff --git a/src/com/android/launcher3/util/LongArrayMap.java b/src/com/android/launcher3/util/LongArrayMap.java
new file mode 100644
index 000000000..a337e85bd
--- /dev/null
+++ b/src/com/android/launcher3/util/LongArrayMap.java
@@ -0,0 +1,65 @@
+/*
+ * 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.util.LongSparseArray;
+
+import java.util.Iterator;
+
+/**
+ * Extension of {@link LongSparseArray} with some utility methods.
+ */
+public class LongArrayMap<E> extends LongSparseArray<E> implements Iterable<E> {
+
+ public boolean containsKey(long key) {
+ return indexOfKey(key) >= 0;
+ }
+
+ public boolean isEmpty() {
+ return size() <= 0;
+ }
+
+ @Override
+ public LongArrayMap<E> clone() {
+ return (LongArrayMap<E>) super.clone();
+ }
+
+ @Override
+ public Iterator<E> iterator() {
+ return new ValueIterator();
+ }
+
+ @Thunk class ValueIterator implements Iterator<E> {
+
+ private int mNextIndex = 0;
+
+ @Override
+ public boolean hasNext() {
+ return mNextIndex < size();
+ }
+
+ @Override
+ public E next() {
+ return valueAt(mNextIndex ++);
+ }
+
+ @Override
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+ }
+}
diff --git a/src/com/android/launcher3/util/ManagedProfileHeuristic.java b/src/com/android/launcher3/util/ManagedProfileHeuristic.java
new file mode 100644
index 000000000..b37f44719
--- /dev/null
+++ b/src/com/android/launcher3/util/ManagedProfileHeuristic.java
@@ -0,0 +1,350 @@
+/*
+ * 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.annotation.TargetApi;
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.os.Build;
+import android.util.Log;
+
+import com.android.launcher3.FolderInfo;
+import com.android.launcher3.ItemInfo;
+import com.android.launcher3.LauncherAppState;
+import com.android.launcher3.LauncherFiles;
+import com.android.launcher3.LauncherModel;
+import com.android.launcher3.MainThreadExecutor;
+import com.android.launcher3.R;
+import com.android.launcher3.ShortcutInfo;
+import com.android.launcher3.Utilities;
+import com.android.launcher3.compat.LauncherActivityInfoCompat;
+import com.android.launcher3.compat.LauncherAppsCompat;
+import com.android.launcher3.compat.UserHandleCompat;
+import com.android.launcher3.compat.UserManagerCompat;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Handles addition of app shortcuts for managed profiles.
+ * Methods of class should only be called on {@link LauncherModel#sWorkerThread}.
+ */
+@TargetApi(Build.VERSION_CODES.LOLLIPOP)
+public class ManagedProfileHeuristic {
+
+ private static final String TAG = "ManagedProfileHeuristic";
+
+ /**
+ * Maintain a set of packages installed per user.
+ */
+ private static final String INSTALLED_PACKAGES_PREFIX = "installed_packages_for_user_";
+
+ private static final String USER_FOLDER_ID_PREFIX = "user_folder_";
+
+ /**
+ * Duration (in milliseconds) for which app shortcuts will be added to work folder.
+ */
+ private static final long AUTO_ADD_TO_FOLDER_DURATION = 8 * 60 * 60 * 1000;
+
+ public static ManagedProfileHeuristic get(Context context, UserHandleCompat user) {
+ if (Utilities.isLmpOrAbove() && !UserHandleCompat.myUserHandle().equals(user)) {
+ return new ManagedProfileHeuristic(context, user);
+ }
+ return null;
+ }
+
+ private final Context mContext;
+ private final UserHandleCompat mUser;
+ private final LauncherModel mModel;
+
+ private final SharedPreferences mPrefs;
+ private final long mUserSerial;
+ private final long mUserCreationTime;
+ private final String mPackageSetKey;
+
+ private ArrayList<ShortcutInfo> mHomescreenApps;
+ private ArrayList<ShortcutInfo> mWorkFolderApps;
+
+ private ManagedProfileHeuristic(Context context, UserHandleCompat user) {
+ mContext = context;
+ mUser = user;
+ mModel = LauncherAppState.getInstance().getModel();
+
+ UserManagerCompat userManager = UserManagerCompat.getInstance(context);
+ mUserSerial = userManager.getSerialNumberForUser(user);
+ mUserCreationTime = userManager.getUserCreationTime(user);
+ mPackageSetKey = INSTALLED_PACKAGES_PREFIX + mUserSerial;
+
+ mPrefs = mContext.getSharedPreferences(LauncherFiles.MANAGED_USER_PREFERENCES_KEY,
+ Context.MODE_PRIVATE);
+ }
+
+ /**
+ * 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<>();
+
+ 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);
+ }
+ }
+ }
+
+ if (newPackageAdded) {
+ mPrefs.edit().putStringSet(mPackageSetKey, packageSet).apply();
+ // Do not add shortcuts on the homescreen for the first time. This prevents the launcher
+ // getting filled with the managed user apps, when it start with a fresh DB (or after
+ // a very long time).
+ finalizeAdditions(userAppsExisted);
+ }
+ }
+
+ private void markForAddition(LauncherActivityInfoCompat info, long installTime) {
+ ArrayList<ShortcutInfo> targetList =
+ (installTime <= mUserCreationTime + AUTO_ADD_TO_FOLDER_DURATION) ?
+ mWorkFolderApps : mHomescreenApps;
+ targetList.add(ShortcutInfo.fromActivityInfo(info, mContext));
+ }
+
+ /**
+ * Adds and binds shortcuts marked to be added to the work folder.
+ */
+ private void finalizeWorkFolder() {
+ 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);
+ }
+ });
+
+ // Try to get a work folder.
+ String folderIdKey = USER_FOLDER_ID_PREFIX + mUserSerial;
+ if (mPrefs.contains(folderIdKey)) {
+ long folderId = mPrefs.getLong(folderIdKey, 0);
+ final FolderInfo workFolder = mModel.findFolderById(folderId);
+
+ if (workFolder == null || !workFolder.hasOption(FolderInfo.FLAG_WORK_FOLDER)) {
+ // Could not get a work folder. Add all the icons to homescreen.
+ mHomescreenApps.addAll(mWorkFolderApps);
+ return;
+ }
+ saveWorkFolderShortcuts(folderId, workFolder.contents.size());
+
+ final ArrayList<ShortcutInfo> shortcuts = mWorkFolderApps;
+ // FolderInfo could already be bound. We need to add shortcuts on the UI thread.
+ new MainThreadExecutor().execute(new Runnable() {
+
+ @Override
+ public void run() {
+ for (ShortcutInfo info : shortcuts) {
+ workFolder.add(info);
+ }
+ }
+ });
+ } else {
+ // Create a new folder.
+ final FolderInfo workFolder = new FolderInfo();
+ workFolder.title = mContext.getText(R.string.work_folder_name);
+ workFolder.setOption(FolderInfo.FLAG_WORK_FOLDER, true, null);
+
+ // Add all shortcuts before adding it to the UI, as an empty folder might get deleted.
+ for (ShortcutInfo info : mWorkFolderApps) {
+ workFolder.add(info);
+ }
+
+ // Add the item to home screen and DB. This also generates an item id synchronously.
+ ArrayList<ItemInfo> itemList = new ArrayList<ItemInfo>(1);
+ itemList.add(workFolder);
+ mModel.addAndBindAddedWorkspaceItems(mContext, itemList);
+ mPrefs.edit().putLong(USER_FOLDER_ID_PREFIX + mUserSerial, workFolder.id).apply();
+
+ saveWorkFolderShortcuts(workFolder.id, 0);
+ }
+ }
+
+ /**
+ * Add work folder shortcuts to the DB.
+ */
+ private void saveWorkFolderShortcuts(long workFolderId, int startingRank) {
+ for (ItemInfo info : mWorkFolderApps) {
+ info.rank = startingRank++;
+ LauncherModel.addItemToDatabase(mContext, info, workFolderId, 0, 0, 0);
+ }
+ }
+
+ /**
+ * Adds and binds all shortcuts marked for addition.
+ */
+ private void finalizeAdditions(boolean addHomeScreenShortcuts) {
+ finalizeWorkFolder();
+
+ if (addHomeScreenShortcuts && !mHomescreenApps.isEmpty()) {
+ mModel.addAndBindAddedWorkspaceItems(mContext, mHomescreenApps);
+ }
+ }
+
+ /**
+ * 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<>();
+
+ HashSet<String> packageSet = new HashSet<>();
+ final boolean userAppsExisted = getUserApps(packageSet);
+
+ boolean newPackageAdded = false;
+ long installTime = System.currentTimeMillis();
+ LauncherAppsCompat launcherApps = LauncherAppsCompat.getInstance(mContext);
+
+ for (String packageName : packages) {
+ if (!packageSet.contains(packageName)) {
+ packageSet.add(packageName);
+ newPackageAdded = true;
+
+ List<LauncherActivityInfoCompat> activities =
+ launcherApps.getActivityList(packageName, mUser);
+ if (!activities.isEmpty()) {
+ markForAddition(activities.get(0), installTime);
+ }
+ }
+ }
+
+ if (newPackageAdded) {
+ mPrefs.edit().putStringSet(mPackageSetKey, packageSet).apply();
+ finalizeAdditions(userAppsExisted);
+ }
+ }
+
+ /**
+ * Updates the list of installed packages for the user.
+ */
+ public void processPackageRemoved(String[] packages) {
+ HashSet<String> packageSet = new HashSet<String>();
+ getUserApps(packageSet);
+ boolean packageRemoved = false;
+
+ for (String packageName : packages) {
+ if (packageSet.remove(packageName)) {
+ packageRemoved = true;
+ }
+ }
+
+ if (packageRemoved) {
+ mPrefs.edit().putStringSet(mPackageSetKey, packageSet).apply();
+ }
+ }
+
+ /**
+ * Reads the list of user apps which have already been processed.
+ * @return false if the list didn't exist, true otherwise
+ */
+ private boolean getUserApps(HashSet<String> outExistingApps) {
+ Set<String> userApps = mPrefs.getStringSet(mPackageSetKey, null);
+ if (userApps == null) {
+ return false;
+ } else {
+ outExistingApps.addAll(userApps);
+ return true;
+ }
+ }
+
+ /**
+ * Verifies that entries corresponding to {@param users} exist and removes all invalid entries.
+ */
+ public static void processAllUsers(List<UserHandleCompat> users, Context context) {
+ if (!Utilities.isLmpOrAbove()) {
+ return;
+ }
+ UserManagerCompat userManager = UserManagerCompat.getInstance(context);
+ HashSet<String> validKeys = new HashSet<String>();
+ for (UserHandleCompat user : users) {
+ addAllUserKeys(userManager.getSerialNumberForUser(user), validKeys);
+ }
+
+ SharedPreferences prefs = context.getSharedPreferences(
+ LauncherFiles.MANAGED_USER_PREFERENCES_KEY,
+ Context.MODE_PRIVATE);
+ SharedPreferences.Editor editor = prefs.edit();
+ for (String key : prefs.getAll().keySet()) {
+ if (!validKeys.contains(key)) {
+ editor.remove(key);
+ }
+ }
+ editor.apply();
+ }
+
+ private static void addAllUserKeys(long userSerial, HashSet<String> keysOut) {
+ keysOut.add(INSTALLED_PACKAGES_PREFIX + userSerial);
+ keysOut.add(USER_FOLDER_ID_PREFIX + userSerial);
+ }
+
+ /**
+ * For each user, if a work folder has not been created, mark it such that the folder will
+ * never get created.
+ */
+ public static void markExistingUsersForNoFolderCreation(Context context) {
+ UserManagerCompat userManager = UserManagerCompat.getInstance(context);
+ UserHandleCompat myUser = UserHandleCompat.myUserHandle();
+
+ SharedPreferences prefs = null;
+ for (UserHandleCompat user : userManager.getUserProfiles()) {
+ if (myUser.equals(user)) {
+ continue;
+ }
+
+ if (prefs == null) {
+ prefs = context.getSharedPreferences(
+ LauncherFiles.MANAGED_USER_PREFERENCES_KEY,
+ Context.MODE_PRIVATE);
+ }
+ String folderIdKey = USER_FOLDER_ID_PREFIX + userManager.getSerialNumberForUser(user);
+ if (!prefs.contains(folderIdKey)) {
+ prefs.edit().putLong(folderIdKey, ItemInfo.NO_ID).apply();
+ }
+ }
+ }
+}
diff --git a/src/com/android/launcher3/util/RevealOutlineProvider.java b/src/com/android/launcher3/util/RevealOutlineProvider.java
new file mode 100644
index 000000000..0db3984f8
--- /dev/null
+++ b/src/com/android/launcher3/util/RevealOutlineProvider.java
@@ -0,0 +1,49 @@
+package com.android.launcher3.util;
+
+import android.annotation.TargetApi;
+import android.graphics.Outline;
+import android.graphics.Rect;
+import android.os.Build;
+import android.view.View;
+import android.view.ViewOutlineProvider;
+
+@TargetApi(Build.VERSION_CODES.LOLLIPOP)
+public class RevealOutlineProvider extends ViewOutlineProvider {
+
+ private int mCenterX;
+ private int mCenterY;
+ private float mRadius0;
+ private float mRadius1;
+ private int mCurrentRadius;
+
+ private final Rect mOval;
+
+ /**
+ * @param x reveal center x
+ * @param y reveal center y
+ * @param r0 initial radius
+ * @param r1 final radius
+ */
+ public RevealOutlineProvider(int x, int y, float r0, float r1) {
+ mCenterX = x;
+ mCenterY = y;
+ mRadius0 = r0;
+ mRadius1 = r1;
+
+ mOval = new Rect();
+ }
+
+ public void setProgress(float progress) {
+ mCurrentRadius = (int) ((1 - progress) * mRadius0 + progress * mRadius1);
+
+ mOval.left = mCenterX - mCurrentRadius;
+ mOval.top = mCenterY - mCurrentRadius;
+ mOval.right = mCenterX + mCurrentRadius;
+ mOval.bottom = mCenterY + mCurrentRadius;
+ }
+
+ @Override
+ public void getOutline(View v, Outline outline) {
+ outline.setRoundRect(mOval, mCurrentRadius);
+ }
+}
diff --git a/src/com/android/launcher3/util/Thunk.java b/src/com/android/launcher3/util/Thunk.java
new file mode 100644
index 000000000..de350b068
--- /dev/null
+++ b/src/com/android/launcher3/util/Thunk.java
@@ -0,0 +1,43 @@
+/*
+ * 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 java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Indicates that the given field or method has package visibility solely to prevent the creation
+ * of a synthetic method. In practice, you should treat this field/method as if it were private.
+ * <p>
+ *
+ * When a private method is called from an inner class, the Java compiler generates a simple
+ * package private shim method that the class generated from the inner class can call. This results
+ * in unnecessary bloat and runtime method call overhead. It also gets us closer to the dex method
+ * count limit.
+ * <p>
+ *
+ * If you'd like to see warnings for these synthetic methods in eclipse, turn on:
+ * Window > Preferences > Java > Compiler > Errors/Warnings > "Access to a non-accessible member
+ * of an enclosing type".
+ * <p>
+ *
+ */
+@Retention(RetentionPolicy.SOURCE)
+@Target({ElementType.METHOD, ElementType.FIELD, ElementType.CONSTRUCTOR, ElementType.TYPE})
+public @interface Thunk { } \ No newline at end of file
diff --git a/src/com/android/launcher3/util/UiThreadCircularReveal.java b/src/com/android/launcher3/util/UiThreadCircularReveal.java
new file mode 100644
index 000000000..3ca3aeeee
--- /dev/null
+++ b/src/com/android/launcher3/util/UiThreadCircularReveal.java
@@ -0,0 +1,57 @@
+package com.android.launcher3.util;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ValueAnimator;
+import android.animation.ValueAnimator.AnimatorUpdateListener;
+import android.annotation.TargetApi;
+import android.os.Build;
+import android.view.View;
+import android.view.ViewOutlineProvider;
+
+import com.android.launcher3.Utilities;
+
+@TargetApi(Build.VERSION_CODES.LOLLIPOP)
+public class UiThreadCircularReveal {
+
+ public static ValueAnimator createCircularReveal(View v, int x, int y, float r0, float r1) {
+ return createCircularReveal(v, x, y, r0, r1, ViewOutlineProvider.BACKGROUND);
+ }
+
+ public static ValueAnimator createCircularReveal(View v, int x, int y, float r0, float r1,
+ final ViewOutlineProvider originalProvider) {
+ ValueAnimator va = ValueAnimator.ofFloat(0f, 1f);
+
+ final View revealView = v;
+ final RevealOutlineProvider outlineProvider = new RevealOutlineProvider(x, y, r0, r1);
+ final float elevation = v.getElevation();
+
+ va.addListener(new AnimatorListenerAdapter() {
+ public void onAnimationStart(Animator animation) {
+ revealView.setOutlineProvider(outlineProvider);
+ revealView.setClipToOutline(true);
+ revealView.setTranslationZ(-elevation);
+ }
+
+ public void onAnimationEnd(Animator animation) {
+ revealView.setOutlineProvider(originalProvider);
+ revealView.setClipToOutline(false);
+ revealView.setTranslationZ(0);
+ }
+
+ });
+
+ va.addUpdateListener(new AnimatorUpdateListener() {
+ @Override
+ public void onAnimationUpdate(ValueAnimator arg0) {
+ float progress = arg0.getAnimatedFraction();
+ outlineProvider.setProgress(progress);
+ revealView.invalidateOutline();
+ if (!Utilities.isLmpMR1OrAbove()) {
+ revealView.invalidate();
+ }
+ }
+ });
+ return va;
+ }
+}
diff --git a/src/com/android/launcher3/util/WallpaperUtils.java b/src/com/android/launcher3/util/WallpaperUtils.java
new file mode 100644
index 000000000..53b2acd84
--- /dev/null
+++ b/src/com/android/launcher3/util/WallpaperUtils.java
@@ -0,0 +1,123 @@
+/*
+ * 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.annotation.TargetApi;
+import android.app.WallpaperManager;
+import android.content.SharedPreferences;
+import android.content.res.Resources;
+import android.graphics.Point;
+import android.os.Build;
+import android.view.WindowManager;
+
+/**
+ * Utility methods for wallpaper management.
+ */
+public final class WallpaperUtils {
+
+ public static final String WALLPAPER_WIDTH_KEY = "wallpaper.width";
+ public static final String WALLPAPER_HEIGHT_KEY = "wallpaper.height";
+ public static final float WALLPAPER_SCREENS_SPAN = 2f;
+
+ public static void suggestWallpaperDimension(Resources res,
+ final SharedPreferences sharedPrefs,
+ WindowManager windowManager,
+ final WallpaperManager wallpaperManager, boolean fallBackToDefaults) {
+ final Point defaultWallpaperSize = WallpaperUtils.getDefaultWallpaperSize(res, windowManager);
+ // If we have saved a wallpaper width/height, use that instead
+
+ int savedWidth = sharedPrefs.getInt(WALLPAPER_WIDTH_KEY, -1);
+ int savedHeight = sharedPrefs.getInt(WALLPAPER_HEIGHT_KEY, -1);
+
+ if (savedWidth == -1 || savedHeight == -1) {
+ if (!fallBackToDefaults) {
+ return;
+ } else {
+ savedWidth = defaultWallpaperSize.x;
+ savedHeight = defaultWallpaperSize.y;
+ }
+ }
+
+ if (savedWidth != wallpaperManager.getDesiredMinimumWidth() ||
+ savedHeight != wallpaperManager.getDesiredMinimumHeight()) {
+ wallpaperManager.suggestDesiredDimensions(savedWidth, savedHeight);
+ }
+ }
+
+ /**
+ * As a ratio of screen height, the total distance we want the parallax effect to span
+ * horizontally
+ */
+ public static float wallpaperTravelToScreenWidthRatio(int width, int height) {
+ float aspectRatio = width / (float) height;
+
+ // At an aspect ratio of 16/10, the wallpaper parallax effect should span 1.5 * screen width
+ // At an aspect ratio of 10/16, the wallpaper parallax effect should span 1.2 * screen width
+ // We will use these two data points to extrapolate how much the wallpaper parallax effect
+ // to span (ie travel) at any aspect ratio:
+
+ final float ASPECT_RATIO_LANDSCAPE = 16/10f;
+ final float ASPECT_RATIO_PORTRAIT = 10/16f;
+ final float WALLPAPER_WIDTH_TO_SCREEN_RATIO_LANDSCAPE = 1.5f;
+ final float WALLPAPER_WIDTH_TO_SCREEN_RATIO_PORTRAIT = 1.2f;
+
+ // To find out the desired width at different aspect ratios, we use the following two
+ // formulas, where the coefficient on x is the aspect ratio (width/height):
+ // (16/10)x + y = 1.5
+ // (10/16)x + y = 1.2
+ // We solve for x and y and end up with a final formula:
+ final float x =
+ (WALLPAPER_WIDTH_TO_SCREEN_RATIO_LANDSCAPE - WALLPAPER_WIDTH_TO_SCREEN_RATIO_PORTRAIT) /
+ (ASPECT_RATIO_LANDSCAPE - ASPECT_RATIO_PORTRAIT);
+ final float y = WALLPAPER_WIDTH_TO_SCREEN_RATIO_PORTRAIT - x * ASPECT_RATIO_PORTRAIT;
+ return x * aspectRatio + y;
+ }
+
+ private static Point sDefaultWallpaperSize;
+
+ @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
+ public static Point getDefaultWallpaperSize(Resources res, WindowManager windowManager) {
+ if (sDefaultWallpaperSize == null) {
+ Point minDims = new Point();
+ Point maxDims = new Point();
+ windowManager.getDefaultDisplay().getCurrentSizeRange(minDims, maxDims);
+
+ int maxDim = Math.max(maxDims.x, maxDims.y);
+ int minDim = Math.max(minDims.x, minDims.y);
+
+ if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR1) {
+ Point realSize = new Point();
+ windowManager.getDefaultDisplay().getRealSize(realSize);
+ maxDim = Math.max(realSize.x, realSize.y);
+ minDim = Math.min(realSize.x, realSize.y);
+ }
+
+ // We need to ensure that there is enough extra space in the wallpaper
+ // for the intended parallax effects
+ final int defaultWidth, defaultHeight;
+ if (res.getConfiguration().smallestScreenWidthDp >= 720) {
+ defaultWidth = (int) (maxDim * wallpaperTravelToScreenWidthRatio(maxDim, minDim));
+ defaultHeight = maxDim;
+ } else {
+ defaultWidth = Math.max((int) (minDim * WALLPAPER_SCREENS_SPAN), maxDim);
+ defaultHeight = maxDim;
+ }
+ sDefaultWallpaperSize = new Point(defaultWidth, defaultHeight);
+ }
+ return sDefaultWallpaperSize;
+ }
+}
diff --git a/src/com/android/launcher3/widget/PendingAddShortcutInfo.java b/src/com/android/launcher3/widget/PendingAddShortcutInfo.java
new file mode 100644
index 000000000..a56985083
--- /dev/null
+++ b/src/com/android/launcher3/widget/PendingAddShortcutInfo.java
@@ -0,0 +1,44 @@
+/*
+ * 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.widget;
+
+import android.content.ComponentName;
+import android.content.pm.ActivityInfo;
+
+import com.android.launcher3.LauncherSettings;
+import com.android.launcher3.PendingAddItemInfo;
+
+/**
+ * Meta data used for late binding of the short cuts.
+ *
+ * @see {@link PendingAddItemInfo}
+ */
+public class PendingAddShortcutInfo extends PendingAddItemInfo {
+
+ ActivityInfo activityInfo;
+
+ public PendingAddShortcutInfo(ActivityInfo activityInfo) {
+ this.activityInfo = activityInfo;
+ componentName = new ComponentName(activityInfo.packageName, activityInfo.name);
+ itemType = LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT;
+ }
+
+ @Override
+ public String toString() {
+ return String.format("PendingAddShortcutInfo package=%s, name=%s",
+ activityInfo.packageName, activityInfo.name);
+ }
+}
diff --git a/src/com/android/launcher3/widget/PendingAddWidgetInfo.java b/src/com/android/launcher3/widget/PendingAddWidgetInfo.java
new file mode 100644
index 000000000..758287af3
--- /dev/null
+++ b/src/com/android/launcher3/widget/PendingAddWidgetInfo.java
@@ -0,0 +1,75 @@
+/*
+ * 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.widget;
+
+import android.appwidget.AppWidgetHostView;
+import android.os.Bundle;
+import android.os.Parcelable;
+
+import com.android.launcher3.Launcher;
+import com.android.launcher3.LauncherAppWidgetProviderInfo;
+import com.android.launcher3.LauncherSettings;
+import com.android.launcher3.PendingAddItemInfo;
+import com.android.launcher3.compat.AppWidgetManagerCompat;
+
+/**
+ * Meta data used for late binding of {@link LauncherAppWidgetProviderInfo}.
+ *
+ * @see {@link PendingAddItemInfo}
+ */
+public class PendingAddWidgetInfo extends PendingAddItemInfo {
+ public int minWidth;
+ public int minHeight;
+ public int minResizeWidth;
+ public int minResizeHeight;
+ public int previewImage;
+ public int icon;
+ public LauncherAppWidgetProviderInfo info;
+ public AppWidgetHostView boundWidget;
+ public Bundle bindOptions = null;
+
+ public PendingAddWidgetInfo(Launcher launcher, LauncherAppWidgetProviderInfo i, Parcelable data) {
+ if (i.isCustomWidget) {
+ itemType = LauncherSettings.Favorites.ITEM_TYPE_CUSTOM_APPWIDGET;
+ } else {
+ itemType = LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET;
+ }
+ this.info = i;
+ user = AppWidgetManagerCompat.getInstance(launcher).getUser(i);
+ componentName = i.provider;
+ minWidth = i.minWidth;
+ minHeight = i.minHeight;
+ minResizeWidth = i.minResizeWidth;
+ minResizeHeight = i.minResizeHeight;
+ previewImage = i.previewImage;
+ icon = i.icon;
+
+ spanX = i.getSpanX(launcher);
+ spanY = i.getSpanY(launcher);
+ minSpanX = i.getMinSpanX(launcher);
+ minSpanY = i.getMinSpanY(launcher);
+ }
+
+ public boolean isCustomWidget() {
+ return itemType == LauncherSettings.Favorites.ITEM_TYPE_CUSTOM_APPWIDGET;
+ }
+
+ @Override
+ public String toString() {
+ return String.format("PendingAddWidgetInfo package=%s, name=%s",
+ componentName.getPackageName(), componentName.getShortClassName());
+ }
+}
diff --git a/src/com/android/launcher3/widget/WidgetCell.java b/src/com/android/launcher3/widget/WidgetCell.java
new file mode 100644
index 000000000..7496ea2ef
--- /dev/null
+++ b/src/com/android/launcher3/widget/WidgetCell.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.widget;
+
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.View.OnLayoutChangeListener;
+import android.view.ViewPropertyAnimator;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import com.android.launcher3.DeviceProfile;
+import com.android.launcher3.InvariantDeviceProfile;
+import com.android.launcher3.ItemInfo;
+import com.android.launcher3.Launcher;
+import com.android.launcher3.LauncherAppState;
+import com.android.launcher3.LauncherAppWidgetProviderInfo;
+import com.android.launcher3.R;
+import com.android.launcher3.StylusEventHelper;
+import com.android.launcher3.WidgetPreviewLoader;
+import com.android.launcher3.WidgetPreviewLoader.PreviewLoadRequest;
+import com.android.launcher3.compat.AppWidgetManagerCompat;
+
+/**
+ * Represents the individual cell of the widget inside the widget tray. The preview is drawn
+ * horizontally centered, and scaled down if needed.
+ *
+ * This view does not support padding. Since the image is scaled down to fit the view, padding will
+ * further decrease the scaling factor. Drag-n-drop uses the view bounds for showing a smooth
+ * transition from the view to drag view, so when adding padding support, DnD would need to
+ * consider the appropriate scaling factor.
+ */
+public class WidgetCell extends LinearLayout implements OnLayoutChangeListener {
+
+ private static final String TAG = "WidgetCell";
+ private static final boolean DEBUG = false;
+
+ private static final int FADE_IN_DURATION_MS = 90;
+
+ /** Widget cell width is calculated by multiplying this factor to grid cell width. */
+ private static final float WIDTH_SCALE = 2.6f;
+
+ /** Widget preview width is calculated by multiplying this factor to the widget cell width. */
+ private static final float PREVIEW_SCALE = 0.8f;
+
+ private int mPresetPreviewSize;
+ int cellSize;
+
+ private WidgetImageView mWidgetImage;
+ private TextView mWidgetName;
+ private TextView mWidgetDims;
+
+ private String mDimensionsFormatString;
+ private Object mInfo;
+
+ private WidgetPreviewLoader mWidgetPreviewLoader;
+ private PreviewLoadRequest mActiveRequest;
+ private StylusEventHelper mStylusEventHelper;
+
+ private Launcher mLauncher;
+
+ public WidgetCell(Context context) {
+ this(context, null);
+ }
+
+ public WidgetCell(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public WidgetCell(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+
+ final Resources r = context.getResources();
+ mLauncher = (Launcher) context;
+ mStylusEventHelper = new StylusEventHelper(this);
+
+ mDimensionsFormatString = r.getString(R.string.widget_dims_format);
+ setContainerWidth();
+ setWillNotDraw(false);
+ setClipToPadding(false);
+ setAccessibilityDelegate(LauncherAppState.getInstance().getAccessibilityDelegate());
+ }
+
+ private void setContainerWidth() {
+ DeviceProfile profile = mLauncher.getDeviceProfile();
+ cellSize = (int) (profile.cellWidthPx * WIDTH_SCALE);
+ mPresetPreviewSize = (int) (cellSize * PREVIEW_SCALE);
+ }
+
+ @Override
+ protected void onFinishInflate() {
+ super.onFinishInflate();
+
+ mWidgetImage = (WidgetImageView) findViewById(R.id.widget_preview);
+ mWidgetName = ((TextView) findViewById(R.id.widget_name));
+ mWidgetDims = ((TextView) findViewById(R.id.widget_dims));
+ }
+
+ /**
+ * Called to clear the view and free attached resources. (e.g., {@link Bitmap}
+ */
+ public void clear() {
+ if (DEBUG) {
+ Log.d(TAG, "reset called on:" + mWidgetName.getText());
+ }
+ mWidgetImage.animate().cancel();
+ mWidgetImage.setBitmap(null);
+ mWidgetName.setText(null);
+ mWidgetDims.setText(null);
+
+ if (mActiveRequest != null) {
+ mActiveRequest.cleanup();
+ mActiveRequest = null;
+ }
+ }
+
+ /**
+ * Apply the widget provider info to the view.
+ */
+ public void applyFromAppWidgetProviderInfo(LauncherAppWidgetProviderInfo info,
+ WidgetPreviewLoader loader) {
+
+ InvariantDeviceProfile profile =
+ LauncherAppState.getInstance().getInvariantDeviceProfile();
+ mInfo = info;
+ // TODO(hyunyoungs): setup a cache for these labels.
+ mWidgetName.setText(AppWidgetManagerCompat.getInstance(getContext()).loadLabel(info));
+ int hSpan = Math.min(info.getSpanX(mLauncher), profile.numColumns);
+ int vSpan = Math.min(info.getSpanY(mLauncher), profile.numRows);
+ mWidgetDims.setText(String.format(mDimensionsFormatString, hSpan, vSpan));
+ mWidgetPreviewLoader = loader;
+ }
+
+ /**
+ * Apply the resolve info to the view.
+ */
+ public void applyFromResolveInfo(
+ PackageManager pm, ResolveInfo info, WidgetPreviewLoader loader) {
+ mInfo = info;
+ CharSequence label = info.loadLabel(pm);
+ mWidgetName.setText(label);
+ mWidgetDims.setText(String.format(mDimensionsFormatString, 1, 1));
+ mWidgetPreviewLoader = loader;
+ }
+
+ public int[] getPreviewSize() {
+ int[] maxSize = new int[2];
+
+ maxSize[0] = mPresetPreviewSize;
+ maxSize[1] = mPresetPreviewSize;
+ return maxSize;
+ }
+
+ public void applyPreview(Bitmap bitmap) {
+ if (bitmap != null) {
+ mWidgetImage.setBitmap(bitmap);
+ mWidgetImage.setAlpha(0f);
+ ViewPropertyAnimator anim = mWidgetImage.animate();
+ anim.alpha(1.0f).setDuration(FADE_IN_DURATION_MS);
+ }
+ }
+
+ public void ensurePreview() {
+ if (mActiveRequest != null) {
+ return;
+ }
+ int[] size = getPreviewSize();
+ if (DEBUG) {
+ Log.d(TAG, String.format("[tag=%s] ensurePreview (%d, %d):",
+ getTagToString(), size[0], size[1]));
+ }
+ mActiveRequest = mWidgetPreviewLoader.getPreview(mInfo, size[0], size[1], this);
+ }
+
+ @Override
+ public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft,
+ int oldTop, int oldRight, int oldBottom) {
+ removeOnLayoutChangeListener(this);
+ ensurePreview();
+ }
+
+ public int getActualItemWidth() {
+ ItemInfo info = (ItemInfo) getTag();
+ int[] size = getPreviewSize();
+ int cellWidth = mLauncher.getDeviceProfile().cellWidthPx;
+
+ return Math.min(size[0], info.spanX * cellWidth);
+ }
+
+ @Override
+ public boolean onTouchEvent(MotionEvent ev) {
+ boolean handled = super.onTouchEvent(ev);
+ if (mStylusEventHelper.checkAndPerformStylusEvent(ev)) {
+ return true;
+ }
+ return handled;
+ }
+
+ /**
+ * Helper method to get the string info of the tag.
+ */
+ private String getTagToString() {
+ if (getTag() instanceof PendingAddWidgetInfo ||
+ getTag() instanceof PendingAddShortcutInfo) {
+ return getTag().toString();
+ }
+ return "";
+ }
+}
diff --git a/src/com/android/launcher3/widget/WidgetHostViewLoader.java b/src/com/android/launcher3/widget/WidgetHostViewLoader.java
new file mode 100644
index 000000000..30b3d581a
--- /dev/null
+++ b/src/com/android/launcher3/widget/WidgetHostViewLoader.java
@@ -0,0 +1,155 @@
+package com.android.launcher3.widget;
+
+import android.appwidget.AppWidgetHostView;
+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.view.View;
+
+import com.android.launcher3.AppWidgetResizeFrame;
+import com.android.launcher3.DragController.DragListener;
+import com.android.launcher3.DragLayer;
+import com.android.launcher3.DragSource;
+import com.android.launcher3.Launcher;
+import com.android.launcher3.LauncherAppWidgetProviderInfo;
+import com.android.launcher3.compat.AppWidgetManagerCompat;
+import com.android.launcher3.util.Thunk;
+
+public class WidgetHostViewLoader implements DragListener {
+
+ /* Runnables to handle inflation and binding. */
+ @Thunk Runnable mInflateWidgetRunnable = null;
+ private Runnable mBindWidgetRunnable = null;
+
+ // TODO: technically, this class should not have to know the existence of the launcher.
+ @Thunk Launcher mLauncher;
+ @Thunk Handler mHandler;
+ @Thunk final View mView;
+ @Thunk final PendingAddWidgetInfo mInfo;
+
+ // Widget id generated for binding a widget host view or -1 for invalid id. The id is
+ // not is use as long as it is stored here and can be deleted safely. Once its used, this value
+ // to be set back to -1.
+ @Thunk int mWidgetLoadingId = -1;
+
+ public WidgetHostViewLoader(Launcher launcher, View view) {
+ mLauncher = launcher;
+ mHandler = new Handler();
+ mView = view;
+ mInfo = (PendingAddWidgetInfo) view.getTag();
+ }
+
+ @Override
+ public void onDragStart(DragSource source, Object info, int dragAction) { }
+
+ @Override
+ public void onDragEnd() {
+ // Cleanup up preloading state.
+ mLauncher.getDragController().removeDragListener(this);
+
+ mHandler.removeCallbacks(mBindWidgetRunnable);
+ mHandler.removeCallbacks(mInflateWidgetRunnable);
+
+ // Cleanup widget id
+ if (mWidgetLoadingId != -1) {
+ mLauncher.getAppWidgetHost().deleteAppWidgetId(mWidgetLoadingId);
+ mWidgetLoadingId = -1;
+ }
+
+ // The widget was inflated and added to the DragLayer -- remove it.
+ if (mInfo.boundWidget != null) {
+ mLauncher.getDragLayer().removeView(mInfo.boundWidget);
+ mLauncher.getAppWidgetHost().deleteAppWidgetId(mInfo.boundWidget.getAppWidgetId());
+ mInfo.boundWidget = null;
+ }
+ }
+
+ /**
+ * Start preloading the widget.
+ */
+ public boolean preloadWidget() {
+ final LauncherAppWidgetProviderInfo pInfo = mInfo.info;
+
+ if (pInfo.isCustomWidget) {
+ return false;
+ }
+ final Bundle options = getDefaultOptionsForWidget(mLauncher, mInfo);
+
+ // If there is a configuration activity, do not follow thru bound and inflate.
+ if (pInfo.configure != null) {
+ mInfo.bindOptions = options;
+ return false;
+ }
+
+ mBindWidgetRunnable = new Runnable() {
+ @Override
+ public void run() {
+ mWidgetLoadingId = mLauncher.getAppWidgetHost().allocateAppWidgetId();
+ if(AppWidgetManagerCompat.getInstance(mLauncher).bindAppWidgetIdIfAllowed(
+ mWidgetLoadingId, pInfo, options)) {
+
+ // Widget id bound. Inflate the widget.
+ mHandler.post(mInflateWidgetRunnable);
+ }
+ }
+ };
+
+ mInflateWidgetRunnable = new Runnable() {
+ @Override
+ public void run() {
+ if (mWidgetLoadingId == -1) {
+ return;
+ }
+ AppWidgetHostView hostView = mLauncher.getAppWidgetHost().createView(
+ (Context) mLauncher, mWidgetLoadingId, pInfo);
+ mInfo.boundWidget = hostView;
+
+ // We used up the widget Id in binding the above view.
+ mWidgetLoadingId = -1;
+
+ hostView.setVisibility(View.INVISIBLE);
+ int[] unScaledSize = mLauncher.getWorkspace().estimateItemSize(mInfo, false);
+ // We want the first widget layout to be the correct size. This will be important
+ // for width size reporting to the AppWidgetManager.
+ DragLayer.LayoutParams lp = new DragLayer.LayoutParams(unScaledSize[0],
+ unScaledSize[1]);
+ lp.x = lp.y = 0;
+ lp.customPosition = true;
+ hostView.setLayoutParams(lp);
+ mLauncher.getDragLayer().addView(hostView);
+ mView.setTag(mInfo);
+ }
+ };
+
+ mHandler.post(mBindWidgetRunnable);
+ return true;
+ }
+
+ public static Bundle getDefaultOptionsForWidget(Launcher launcher, PendingAddWidgetInfo info) {
+ Bundle options = null;
+ Rect rect = new Rect();
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
+ AppWidgetResizeFrame.getWidgetSizeRanges(launcher, info.spanX, info.spanY, rect);
+ Rect padding = AppWidgetHostView.getDefaultPaddingForWidget(launcher,
+ info.componentName, null);
+
+ float density = launcher.getResources().getDisplayMetrics().density;
+ int xPaddingDips = (int) ((padding.left + padding.right) / density);
+ int yPaddingDips = (int) ((padding.top + padding.bottom) / density);
+
+ options = new Bundle();
+ options.putInt(AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH,
+ rect.left - xPaddingDips);
+ options.putInt(AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT,
+ rect.top - yPaddingDips);
+ options.putInt(AppWidgetManager.OPTION_APPWIDGET_MAX_WIDTH,
+ rect.right - xPaddingDips);
+ options.putInt(AppWidgetManager.OPTION_APPWIDGET_MAX_HEIGHT,
+ rect.bottom - yPaddingDips);
+ }
+ return options;
+ }
+}
diff --git a/src/com/android/launcher3/widget/WidgetImageView.java b/src/com/android/launcher3/widget/WidgetImageView.java
new file mode 100644
index 000000000..b0fbe1ed9
--- /dev/null
+++ b/src/com/android/launcher3/widget/WidgetImageView.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.widget;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Rect;
+import android.graphics.RectF;
+import android.util.AttributeSet;
+import android.view.View;
+
+/**
+ * View that draws a bitmap horizontally centered. If the image width is greater than the view
+ * width, the image is scaled down appropriately.
+ */
+public class WidgetImageView extends View {
+
+ private final Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG);
+ private final RectF mDstRectF = new RectF();
+ private Bitmap mBitmap;
+
+ public WidgetImageView(Context context) {
+ super(context);
+ }
+
+ public WidgetImageView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public WidgetImageView(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ }
+
+ public void setBitmap(Bitmap bitmap) {
+ mBitmap = bitmap;
+ invalidate();
+ }
+
+ public Bitmap getBitmap() {
+ return mBitmap;
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ if (mBitmap != null) {
+ updateDstRectF();
+ canvas.drawBitmap(mBitmap, null, mDstRectF, mPaint);
+ }
+ }
+
+ /**
+ * Prevents the inefficient alpha view rendering.
+ */
+ @Override
+ public boolean hasOverlappingRendering() {
+ return false;
+ }
+
+ private void updateDstRectF() {
+ if (mBitmap.getWidth() > getWidth()) {
+ float scale = ((float) getWidth()) / mBitmap.getWidth();
+ mDstRectF.set(0, 0, getWidth(), scale * mBitmap.getHeight());
+ } else {
+ mDstRectF.set(
+ (getWidth() - mBitmap.getWidth()) * 0.5f,
+ 0,
+ (getWidth() + mBitmap.getWidth()) * 0.5f,
+ mBitmap.getHeight());
+ }
+ }
+
+ /**
+ * @return the bounds where the image was drawn.
+ */
+ public Rect getBitmapBounds() {
+ updateDstRectF();
+ Rect rect = new Rect();
+ mDstRectF.round(rect);
+ return rect;
+ }
+}
diff --git a/src/com/android/launcher3/widget/WidgetsContainerView.java b/src/com/android/launcher3/widget/WidgetsContainerView.java
new file mode 100644
index 000000000..5afd7c493
--- /dev/null
+++ b/src/com/android/launcher3/widget/WidgetsContainerView.java
@@ -0,0 +1,370 @@
+/*
+ * 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.widget;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.InsetDrawable;
+import android.support.v7.widget.LinearLayoutManager;
+import android.support.v7.widget.RecyclerView.State;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.View;
+import android.widget.Toast;
+
+import com.android.launcher3.BaseContainerView;
+import com.android.launcher3.CellLayout;
+import com.android.launcher3.DeleteDropTarget;
+import com.android.launcher3.DeviceProfile;
+import com.android.launcher3.DragController;
+import com.android.launcher3.DragSource;
+import com.android.launcher3.DropTarget.DragObject;
+import com.android.launcher3.Folder;
+import com.android.launcher3.IconCache;
+import com.android.launcher3.ItemInfo;
+import com.android.launcher3.Launcher;
+import com.android.launcher3.LauncherAppState;
+import com.android.launcher3.PendingAddItemInfo;
+import com.android.launcher3.R;
+import com.android.launcher3.Utilities;
+import com.android.launcher3.WidgetPreviewLoader;
+import com.android.launcher3.Workspace;
+import com.android.launcher3.model.WidgetsModel;
+import com.android.launcher3.util.Thunk;
+
+/**
+ * The widgets list view container.
+ */
+public class WidgetsContainerView extends BaseContainerView
+ implements View.OnLongClickListener, View.OnClickListener, DragSource{
+
+ private static final String TAG = "WidgetsContainerView";
+ private static final boolean DEBUG = false;
+
+ /* Coefficient multiplied to the screen height for preloading widgets. */
+ private static final int PRELOAD_SCREEN_HEIGHT_MULTIPLE = 1;
+
+ /* Global instances that are used inside this container. */
+ @Thunk Launcher mLauncher;
+ private DragController mDragController;
+ private IconCache mIconCache;
+
+ /* Recycler view related member variables */
+ private View mContent;
+ private WidgetsRecyclerView mView;
+ private WidgetsListAdapter mAdapter;
+
+ /* Touch handling related member variables. */
+ private Toast mWidgetInstructionToast;
+
+ /* Rendering related. */
+ private WidgetPreviewLoader mWidgetPreviewLoader;
+
+ private Rect mPadding = new Rect();
+
+ public WidgetsContainerView(Context context) {
+ this(context, null);
+ }
+
+ public WidgetsContainerView(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public WidgetsContainerView(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ mLauncher = (Launcher) context;
+ mDragController = mLauncher.getDragController();
+ mAdapter = new WidgetsListAdapter(context, this, this, mLauncher);
+ mIconCache = (LauncherAppState.getInstance()).getIconCache();
+ if (DEBUG) {
+ Log.d(TAG, "WidgetsContainerView constructor");
+ }
+ }
+
+ @Override
+ protected void onFinishInflate() {
+ mContent = findViewById(R.id.content);
+ mView = (WidgetsRecyclerView) findViewById(R.id.widgets_list_view);
+ mView.setAdapter(mAdapter);
+
+ // This extends the layout space so that preloading happen for the {@link RecyclerView}
+ mView.setLayoutManager(new LinearLayoutManager(getContext()) {
+ @Override
+ protected int getExtraLayoutSpace(State state) {
+ DeviceProfile grid = mLauncher.getDeviceProfile();
+ return super.getExtraLayoutSpace(state)
+ + grid.availableHeightPx * PRELOAD_SCREEN_HEIGHT_MULTIPLE;
+ }
+ });
+ mPadding.set(getPaddingLeft(), getPaddingTop(), getPaddingRight(),
+ getPaddingBottom());
+ }
+
+ //
+ // Returns views used for launcher transitions.
+ //
+
+ public View getContentView() {
+ return mView;
+ }
+
+ public View getRevealView() {
+ // TODO(hyunyoungs): temporarily use apps view transition.
+ return findViewById(R.id.widgets_reveal_view);
+ }
+
+ public void scrollToTop() {
+ mView.scrollToPosition(0);
+ }
+
+ //
+ // Touch related handling.
+ //
+
+ @Override
+ public void onClick(View v) {
+ // When we have exited widget tray or are in transition, disregard clicks
+ if (!mLauncher.isWidgetsViewVisible()
+ || mLauncher.getWorkspace().isSwitchingState()
+ || !(v instanceof WidgetCell)) return;
+
+ // Let the user know that they have to long press to add a widget
+ if (mWidgetInstructionToast != null) {
+ mWidgetInstructionToast.cancel();
+ }
+ mWidgetInstructionToast = Toast.makeText(getContext(),R.string.long_press_widget_to_add,
+ Toast.LENGTH_SHORT);
+ mWidgetInstructionToast.show();
+ }
+
+ @Override
+ public boolean onLongClick(View v) {
+ if (DEBUG) {
+ Log.d(TAG, String.format("onLonglick [v=%s]", v));
+ }
+ // Return early if this is not initiated from a touch
+ if (!v.isInTouchMode()) return false;
+ // When we have exited all apps or are in transition, disregard long clicks
+ 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) {
+ Log.d(TAG, String.format("preloading widget [status=%s]", preloadStatus));
+ }
+ mLauncher.getDragController().addDragListener(hostLoader);
+ }
+ return status;
+ }
+
+ private boolean beginDragging(View v) {
+ if (v instanceof WidgetCell) {
+ if (!beginDraggingWidget((WidgetCell) v)) {
+ return false;
+ }
+ } else {
+ Log.e(TAG, "Unexpected dragging view: " + v);
+ }
+
+ // We don't enter spring-loaded mode if the drag has been cancelled
+ if (mLauncher.getDragController().isDragging()) {
+ // Go into spring loaded mode (must happen before we startDrag())
+ mLauncher.enterSpringLoadedDragMode();
+ }
+
+ return true;
+ }
+
+ private boolean beginDraggingWidget(WidgetCell v) {
+ // Get the widget preview as the drag representation
+ WidgetImageView image = (WidgetImageView) v.findViewById(R.id.widget_preview);
+ PendingAddItemInfo createItemInfo = (PendingAddItemInfo) v.getTag();
+
+ // If the ImageView doesn't have a drawable yet, the widget preview hasn't been loaded and
+ // we abort the drag.
+ if (image.getBitmap() == null) {
+ return false;
+ }
+
+ // Compose the drag image
+ Bitmap preview;
+ float scale = 1f;
+ final Rect bounds = image.getBitmapBounds();
+
+ if (createItemInfo instanceof PendingAddWidgetInfo) {
+ // This can happen in some weird cases involving multi-touch. We can't start dragging
+ // the widget if this is null, so we break out.
+
+ PendingAddWidgetInfo createWidgetInfo = (PendingAddWidgetInfo) createItemInfo;
+ int[] size = mLauncher.getWorkspace().estimateItemSize(createWidgetInfo, true);
+
+ Bitmap icon = image.getBitmap();
+ float minScale = 1.25f;
+ int maxWidth = Math.min((int) (icon.getWidth() * minScale), size[0]);
+
+ int[] previewSizeBeforeScale = new int[1];
+ preview = getWidgetPreviewLoader().generateWidgetPreview(mLauncher,
+ createWidgetInfo.info, maxWidth, null, previewSizeBeforeScale);
+
+ if (previewSizeBeforeScale[0] < icon.getWidth()) {
+ // The icon has extra padding around it.
+ int padding = (icon.getWidth() - previewSizeBeforeScale[0]) / 2;
+ if (icon.getWidth() > image.getWidth()) {
+ padding = padding * image.getWidth() / icon.getWidth();
+ }
+
+ bounds.left += padding;
+ bounds.right -= padding;
+ }
+ scale = bounds.width() / (float) preview.getWidth();
+ } else {
+ PendingAddShortcutInfo createShortcutInfo = (PendingAddShortcutInfo) v.getTag();
+ Drawable icon = mIconCache.getFullResIcon(createShortcutInfo.activityInfo);
+ preview = Utilities.createIconBitmap(icon, mLauncher);
+ createItemInfo.spanX = createItemInfo.spanY = 1;
+ scale = ((float) mLauncher.getDeviceProfile().iconSizePx) / preview.getWidth();
+ }
+
+ // Don't clip alpha values for the drag outline if we're using the default widget preview
+ boolean clipAlpha = !(createItemInfo instanceof PendingAddWidgetInfo &&
+ (((PendingAddWidgetInfo) createItemInfo).previewImage == 0));
+
+ // Start the drag
+ mLauncher.lockScreenOrientation();
+ mLauncher.getWorkspace().onDragStartedWithItem(createItemInfo, preview, clipAlpha);
+ mDragController.startDrag(image, preview, this, createItemInfo,
+ bounds, DragController.DRAG_ACTION_COPY, scale);
+
+ preview.recycle();
+ return true;
+ }
+
+ //
+ // Drag related handling methods that implement {@link DragSource} interface.
+ //
+
+ @Override
+ public boolean supportsFlingToDelete() {
+ return false;
+ }
+
+ @Override
+ public boolean supportsAppInfoDropTarget() {
+ return true;
+ }
+
+ /*
+ * Both this method and {@link #supportsFlingToDelete} has to return {@code false} for the
+ * {@link DeleteDropTarget} to be invisible.)
+ */
+ @Override
+ public boolean supportsDeleteDropTarget() {
+ return false;
+ }
+
+ @Override
+ public float getIntrinsicIconScaleFactor() {
+ return 0;
+ }
+
+ @Override
+ public void onFlingToDeleteCompleted() {
+ // We just dismiss the drag when we fling, so cleanup here
+ mLauncher.exitSpringLoadedDragModeDelayed(true,
+ Launcher.EXIT_SPRINGLOADED_MODE_SHORT_TIMEOUT, null);
+ mLauncher.unlockScreenOrientation(false);
+ }
+
+ @Override
+ public void onDropCompleted(View target, DragObject d, boolean isFlingToDelete,
+ boolean success) {
+ 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
+ // drop in Workspace
+ mLauncher.exitSpringLoadedDragModeDelayed(true,
+ Launcher.EXIT_SPRINGLOADED_MODE_SHORT_TIMEOUT, null);
+ }
+ mLauncher.unlockScreenOrientation(false);
+
+ // Display an error message if the drag failed due to there not being enough space on the
+ // target layout we were dropping on.
+ if (!success) {
+ boolean showOutOfSpaceMessage = false;
+ if (target instanceof Workspace) {
+ int currentScreen = mLauncher.getCurrentWorkspaceScreen();
+ Workspace workspace = (Workspace) target;
+ CellLayout layout = (CellLayout) workspace.getChildAt(currentScreen);
+ ItemInfo itemInfo = (ItemInfo) d.dragInfo;
+ if (layout != null) {
+ layout.calculateSpans(itemInfo);
+ showOutOfSpaceMessage =
+ !layout.findCellForSpan(null, itemInfo.spanX, itemInfo.spanY);
+ }
+ }
+ if (showOutOfSpaceMessage) {
+ mLauncher.showOutOfSpaceMessage(false);
+ }
+ d.deferDragViewCleanupPostAnimation = false;
+ }
+ }
+
+ //
+ // Container rendering related.
+ //
+
+ @Override
+ protected void onUpdateBackgroundAndPaddings(Rect searchBarBounds, Rect padding) {
+ // Apply the top-bottom padding to the content itself so that the launcher transition is
+ // clipped correctly
+ mContent.setPadding(0, padding.top, 0, padding.bottom);
+
+ // TODO: Use quantum_panel_dark instead of quantum_panel_shape_dark.
+ InsetDrawable background = new InsetDrawable(
+ getResources().getDrawable(R.drawable.quantum_panel_shape_dark), padding.left, 0,
+ padding.right, 0);
+ Rect bgPadding = new Rect();
+ background.getPadding(bgPadding);
+ mView.setBackground(background);
+ getRevealView().setBackground(background.getConstantState().newDrawable());
+ mView.updateBackgroundPadding(bgPadding);
+ }
+
+ /**
+ * Initialize the widget data model.
+ */
+ public void addWidgets(WidgetsModel model) {
+ mView.setWidgets(model);
+ mAdapter.setWidgetsModel(model);
+ mAdapter.notifyDataSetChanged();
+ }
+
+ private WidgetPreviewLoader getWidgetPreviewLoader() {
+ if (mWidgetPreviewLoader == null) {
+ mWidgetPreviewLoader = LauncherAppState.getInstance().getWidgetCache();
+ }
+ return mWidgetPreviewLoader;
+ }
+} \ No newline at end of file
diff --git a/src/com/android/launcher3/widget/WidgetsListAdapter.java b/src/com/android/launcher3/widget/WidgetsListAdapter.java
new file mode 100644
index 000000000..d2ea25230
--- /dev/null
+++ b/src/com/android/launcher3/widget/WidgetsListAdapter.java
@@ -0,0 +1,215 @@
+/*
+ * 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.widget;
+
+import android.annotation.TargetApi;
+import android.content.Context;
+import android.content.pm.ResolveInfo;
+import android.content.res.Resources;
+import android.os.Build;
+import android.support.v7.widget.RecyclerView;
+import android.support.v7.widget.RecyclerView.Adapter;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.ViewGroup.LayoutParams;
+import android.view.ViewGroup.MarginLayoutParams;
+import android.widget.LinearLayout;
+
+import com.android.launcher3.BubbleTextView;
+import com.android.launcher3.DeviceProfile;
+import com.android.launcher3.Launcher;
+import com.android.launcher3.LauncherAppState;
+import com.android.launcher3.LauncherAppWidgetProviderInfo;
+import com.android.launcher3.R;
+import com.android.launcher3.Utilities;
+import com.android.launcher3.WidgetPreviewLoader;
+import com.android.launcher3.model.PackageItemInfo;
+import com.android.launcher3.model.WidgetsModel;
+
+import java.util.List;
+
+/**
+ * List view adapter for the widget tray.
+ *
+ * <p>Memory vs. Performance:
+ * The less number of types of views are inserted into a {@link RecyclerView}, the more recycling
+ * happens and less memory is consumed. {@link #getItemViewType} was not overridden as there is
+ * only a single type of view.
+ */
+public class WidgetsListAdapter extends Adapter<WidgetsRowViewHolder> {
+
+ private static final String TAG = "WidgetsListAdapter";
+ private static final boolean DEBUG = false;
+
+ private Launcher mLauncher;
+ private LayoutInflater mLayoutInflater;
+
+ private WidgetsModel mWidgetsModel;
+ private WidgetPreviewLoader mWidgetPreviewLoader;
+
+ private View.OnClickListener mIconClickListener;
+ private View.OnLongClickListener mIconLongClickListener;
+
+ private static final int PRESET_INDENT_SIZE_TABLET = 56;
+ private int mIndent = 0;
+
+ public WidgetsListAdapter(Context context,
+ View.OnClickListener iconClickListener,
+ View.OnLongClickListener iconLongClickListener,
+ Launcher launcher) {
+ mLayoutInflater = LayoutInflater.from(context);
+
+ mIconClickListener = iconClickListener;
+ mIconLongClickListener = iconLongClickListener;
+ mLauncher = launcher;
+
+ setContainerHeight();
+ }
+
+ public void setWidgetsModel(WidgetsModel w) {
+ mWidgetsModel = w;
+ }
+
+ @Override
+ public int getItemCount() {
+ return mWidgetsModel.getPackageSize();
+ }
+
+ @Override
+ public void onBindViewHolder(WidgetsRowViewHolder holder, int pos) {
+ List<Object> infoList = mWidgetsModel.getSortedWidgets(pos);
+
+ ViewGroup row = ((ViewGroup) holder.getContent().findViewById(R.id.widgets_cell_list));
+ if (DEBUG) {
+ Log.d(TAG, String.format(
+ "onBindViewHolder [pos=%d, widget#=%d, row.getChildCount=%d]",
+ pos, infoList.size(), row.getChildCount()));
+ }
+
+ // Add more views.
+ // if there are too many, hide them.
+ int diff = infoList.size() - row.getChildCount();
+
+ if (diff > 0) {
+ for (int i = 0; i < diff; i++) {
+ WidgetCell widget = (WidgetCell) mLayoutInflater.inflate(
+ R.layout.widget_cell, row, false);
+
+ // set up touch.
+ widget.setOnClickListener(mIconClickListener);
+ widget.setOnLongClickListener(mIconLongClickListener);
+ LayoutParams lp = widget.getLayoutParams();
+ lp.height = widget.cellSize;
+ lp.width = widget.cellSize;
+ widget.setLayoutParams(lp);
+
+ row.addView(widget);
+ }
+ } else if (diff < 0) {
+ for (int i=infoList.size() ; i < row.getChildCount(); i++) {
+ row.getChildAt(i).setVisibility(View.GONE);
+ }
+ }
+
+ // Bind the views in the application info section.
+ PackageItemInfo infoOut = mWidgetsModel.getPackageItemInfo(pos);
+ BubbleTextView tv = ((BubbleTextView) holder.getContent().findViewById(R.id.section));
+ tv.applyFromPackageItemInfo(infoOut);
+
+ // Bind the view in the widget horizontal tray region.
+ if (getWidgetPreviewLoader() == null) {
+ return;
+ }
+ for (int i=0; i < infoList.size(); i++) {
+ WidgetCell widget = (WidgetCell) row.getChildAt(i);
+ if (infoList.get(i) instanceof LauncherAppWidgetProviderInfo) {
+ LauncherAppWidgetProviderInfo info = (LauncherAppWidgetProviderInfo) infoList.get(i);
+ PendingAddWidgetInfo pawi = new PendingAddWidgetInfo(mLauncher, info, null);
+ widget.setTag(pawi);
+ widget.applyFromAppWidgetProviderInfo(info, mWidgetPreviewLoader);
+ } else if (infoList.get(i) instanceof ResolveInfo) {
+ ResolveInfo info = (ResolveInfo) infoList.get(i);
+ PendingAddShortcutInfo pasi = new PendingAddShortcutInfo(info.activityInfo);
+ widget.setTag(pasi);
+ widget.applyFromResolveInfo(mLauncher.getPackageManager(), info, mWidgetPreviewLoader);
+ }
+ widget.ensurePreview();
+ widget.setVisibility(View.VISIBLE);
+ }
+ }
+
+ @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
+ @Override
+ public WidgetsRowViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
+ if (DEBUG) {
+ Log.v(TAG, "\nonCreateViewHolder");
+ }
+
+ ViewGroup container = (ViewGroup) mLayoutInflater.inflate(
+ R.layout.widgets_list_row_view, parent, false);
+ LinearLayout cellList = (LinearLayout) container.findViewById(R.id.widgets_cell_list);
+
+ // if the end padding is 0, then container view (horizontal scroll view) doesn't respect
+ // the end of the linear layout width + the start padding and doesn't allow scrolling.
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
+ cellList.setPaddingRelative(mIndent, 0, 1, 0);
+ } else {
+ cellList.setPadding(mIndent, 0, 1, 0);
+ }
+
+ return new WidgetsRowViewHolder(container);
+ }
+
+ @Override
+ public void onViewRecycled(WidgetsRowViewHolder holder) {
+ ViewGroup row = ((ViewGroup) holder.getContent().findViewById(R.id.widgets_cell_list));
+
+ for (int i = 0; i < row.getChildCount(); i++) {
+ WidgetCell widget = (WidgetCell) row.getChildAt(i);
+ widget.clear();
+ }
+ }
+
+ public boolean onFailedToRecycleView(WidgetsRowViewHolder holder) {
+ // If child views are animating, then the RecyclerView may choose not to recycle the view,
+ // causing extraneous onCreateViewHolder() calls. It is safe in this case to continue
+ // recycling this view, and take care in onViewRecycled() to cancel any existing
+ // animations.
+ return true;
+ }
+
+ @Override
+ public long getItemId(int pos) {
+ return pos;
+ }
+
+ private WidgetPreviewLoader getWidgetPreviewLoader() {
+ if (mWidgetPreviewLoader == null) {
+ mWidgetPreviewLoader = LauncherAppState.getInstance().getWidgetCache();
+ }
+ return mWidgetPreviewLoader;
+ }
+
+ private void setContainerHeight() {
+ Resources r = mLauncher.getResources();
+ DeviceProfile profile = mLauncher.getDeviceProfile();
+ if (profile.isLargeTablet || profile.isTablet) {
+ mIndent = Utilities.pxFromDp(PRESET_INDENT_SIZE_TABLET, r.getDisplayMetrics());
+ }
+ }
+}
diff --git a/src/com/android/launcher3/widget/WidgetsRecyclerView.java b/src/com/android/launcher3/widget/WidgetsRecyclerView.java
new file mode 100644
index 000000000..61e63cdb7
--- /dev/null
+++ b/src/com/android/launcher3/widget/WidgetsRecyclerView.java
@@ -0,0 +1,158 @@
+/*
+ * 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.widget;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.support.v7.widget.LinearLayoutManager;
+import android.util.AttributeSet;
+import android.view.View;
+import com.android.launcher3.BaseRecyclerView;
+import com.android.launcher3.R;
+import com.android.launcher3.model.PackageItemInfo;
+import com.android.launcher3.model.WidgetsModel;
+
+/**
+ * The widgets recycler view.
+ */
+public class WidgetsRecyclerView extends BaseRecyclerView {
+
+ private static final String TAG = "WidgetsRecyclerView";
+ private WidgetsModel mWidgets;
+ private ScrollPositionState mScrollPosState = new ScrollPositionState();
+
+ public WidgetsRecyclerView(Context context) {
+ this(context, null);
+ }
+
+ public WidgetsRecyclerView(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public WidgetsRecyclerView(Context context, AttributeSet attrs, int defStyleAttr) {
+ // API 21 and below only support 3 parameter ctor.
+ super(context, attrs, defStyleAttr);
+ }
+
+ public WidgetsRecyclerView(Context context, AttributeSet attrs, int defStyleAttr,
+ int defStyleRes) {
+ this(context, attrs, defStyleAttr);
+ }
+
+ @Override
+ protected void onFinishInflate() {
+ super.onFinishInflate();
+ addOnItemTouchListener(this);
+ }
+
+ public int getFastScrollerTrackColor(int defaultTrackColor) {
+ return Color.WHITE;
+ }
+
+ public int getFastScrollerThumbInactiveColor(int defaultInactiveThumbColor) {
+ return getResources().getColor(R.color.widgets_view_fastscroll_thumb_inactive_color);
+ }
+
+ /**
+ * Sets the widget model in this view, used to determine the fast scroll position.
+ */
+ public void setWidgets(WidgetsModel widgets) {
+ mWidgets = widgets;
+ }
+
+ /**
+ * We need to override the draw to ensure that we don't draw the overscroll effect beyond the
+ * background bounds.
+ */
+ @Override
+ protected void dispatchDraw(Canvas canvas) {
+ canvas.clipRect(mBackgroundPadding.left, mBackgroundPadding.top,
+ getWidth() - mBackgroundPadding.right,
+ getHeight() - mBackgroundPadding.bottom);
+ super.dispatchDraw(canvas);
+ }
+
+ /**
+ * Maps the touch (from 0..1) to the adapter position that should be visible.
+ */
+ @Override
+ public String scrollToPositionAtProgress(float touchFraction) {
+ int rowCount = mWidgets.getPackageSize();
+ if (rowCount == 0) {
+ return "";
+ }
+
+ // Stop the scroller if it is scrolling
+ stopScroll();
+
+ getCurScrollState(mScrollPosState);
+ float pos = rowCount * touchFraction;
+ int availableScrollHeight = getAvailableScrollHeight(rowCount, mScrollPosState.rowHeight, 0);
+ LinearLayoutManager layoutManager = ((LinearLayoutManager) getLayoutManager());
+ layoutManager.scrollToPositionWithOffset(0, (int) -(availableScrollHeight * touchFraction));
+
+ int posInt = (int) ((touchFraction == 1)? pos -1 : pos);
+ PackageItemInfo p = mWidgets.getPackageItemInfo(posInt);
+ return p.titleSectionName;
+ }
+
+ /**
+ * Updates the bounds for the scrollbar.
+ */
+ @Override
+ public void onUpdateScrollbar() {
+ int rowCount = mWidgets.getPackageSize();
+
+ // Skip early if, there are no items.
+ if (rowCount == 0) {
+ mScrollbar.setScrollbarThumbOffset(-1, -1);
+ return;
+ }
+
+ // Skip early if, there no child laid out in the container.
+ getCurScrollState(mScrollPosState);
+ if (mScrollPosState.rowIndex < 0) {
+ mScrollbar.setScrollbarThumbOffset(-1, -1);
+ return;
+ }
+
+ synchronizeScrollBarThumbOffsetToViewScroll(mScrollPosState, rowCount, 0);
+ }
+
+ /**
+ * Returns the current scroll state.
+ */
+ private void getCurScrollState(ScrollPositionState stateOut) {
+ stateOut.rowIndex = -1;
+ stateOut.rowTopOffset = -1;
+ stateOut.rowHeight = -1;
+
+ int rowCount = mWidgets.getPackageSize();
+
+ // Return early if there are no items
+ if (rowCount == 0) {
+ return;
+ }
+ View child = getChildAt(0);
+ int position = getChildPosition(child);
+
+ stateOut.rowIndex = position;
+ stateOut.rowTopOffset = getLayoutManager().getDecoratedTop(child);
+ stateOut.rowHeight = child.getHeight();
+ }
+} \ No newline at end of file
diff --git a/src/com/android/launcher3/LauncherAnimatorUpdateListener.java b/src/com/android/launcher3/widget/WidgetsRowViewHolder.java
index ec9fd4d16..249559ab9 100644
--- a/src/com/android/launcher3/LauncherAnimatorUpdateListener.java
+++ b/src/com/android/launcher3/widget/WidgetsRowViewHolder.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011 The Android Open Source Project
+ * 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.
@@ -13,18 +13,24 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+package com.android.launcher3.widget;
-package com.android.launcher3;
+import android.support.v7.widget.RecyclerView.ViewHolder;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+import android.widget.TextView;
-import android.animation.ValueAnimator;
-import android.animation.ValueAnimator.AnimatorUpdateListener;
+public class WidgetsRowViewHolder extends ViewHolder {
-abstract class LauncherAnimatorUpdateListener implements AnimatorUpdateListener {
- public void onAnimationUpdate(ValueAnimator animation) {
- final float b = (Float) animation.getAnimatedValue();
- final float a = 1f - b;
- onAnimationUpdate(a, b);
+ ViewGroup mContent;
+
+ public WidgetsRowViewHolder(ViewGroup v) {
+ super(v);
+ mContent = v;
}
- abstract void onAnimationUpdate(float a, float b);
-} \ No newline at end of file
+ ViewGroup getContent() {
+ return mContent;
+ }
+}
diff --git a/tests/Android.mk b/tests/Android.mk
index 762a52b8d..eba4ade48 100644
--- a/tests/Android.mk
+++ b/tests/Android.mk
@@ -1,4 +1,4 @@
-# Copyright (C) 2011 The Android Open Source Project
+# 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.
@@ -12,5 +12,26 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
-#LOCAL_PATH := $(call my-dir)
-#include $(call all-makefiles-under,$(LOCAL_PATH))
+
+LOCAL_PATH := $(call my-dir)
+
+src_dirs := src
+res_dirs := res
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_RESOURCE_DIR := $(addprefix $(LOCAL_PATH)/, $(res_dirs))
+LOCAL_AAPT_FLAGS := --auto-add-overlay
+
+LOCAL_SDK_VERSION := 21
+
+LOCAL_PACKAGE_NAME := Launcher3Tests
+
+LOCAL_INSTRUMENTATION_FOR := Launcher3
+
+include $(BUILD_PACKAGE)
diff --git a/tests/stress/AndroidManifest.xml b/tests/AndroidManifest.xml
index bcca1ff53..42ae5a38a 100644
--- a/tests/stress/AndroidManifest.xml
+++ b/tests/AndroidManifest.xml
@@ -1,5 +1,5 @@
<?xml version="2.0" encoding="utf-8"?>
-<!-- Copyright (C) 2010 The Android Open Source Project
+<!-- 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.
@@ -15,7 +15,7 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.launcher3.stress.launcherrotation">
+ package="com.android.launcher3.tests">
<application>
<uses-library android:name="android.test.runner" />
@@ -24,6 +24,6 @@
<instrumentation
android:name="android.test.InstrumentationTestRunner"
android:targetPackage="com.android.launcher3"
- android:label="Rotation stress test using Launcher2">
+ android:label="Unit tests for Launcher3">
</instrumentation>
</manifest>
diff --git a/tests/res/values/string.xml b/tests/res/values/string.xml
new file mode 100644
index 000000000..3c1ec5c61
--- /dev/null
+++ b/tests/res/values/string.xml
@@ -0,0 +1,21 @@
+<!-- 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.
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+
+ <!-- Dummy string for tests. [DO NOT TRANSLATE] -->
+ <string name="dummy" >Dummy string for tests.</string>
+
+</resources>
diff --git a/tests/src/com/android/launcher3/InvariantDeviceProfileTest.java b/tests/src/com/android/launcher3/InvariantDeviceProfileTest.java
new file mode 100644
index 000000000..1bc7c1190
--- /dev/null
+++ b/tests/src/com/android/launcher3/InvariantDeviceProfileTest.java
@@ -0,0 +1,123 @@
+/*
+ * 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;
+
+import android.graphics.PointF;
+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;
+
+/**
+ * Tests the {@link DeviceProfile} and {@link InvariantDeviceProfile}.
+ */
+@SmallTest
+public class InvariantDeviceProfileTest extends AndroidTestCase {
+
+ private static final String TAG = "DeviceProfileTest";
+ private static final boolean DEBUG = false;
+
+ private InvariantDeviceProfile mInvariantProfile;
+ private ArrayList<InvariantDeviceProfile> mPredefinedDeviceProfiles;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mInvariantProfile = new InvariantDeviceProfile(getContext());
+ mPredefinedDeviceProfiles = mInvariantProfile.getPredefinedDeviceProfiles();
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ // Nothing to tear down as this class only tests static methods.
+ }
+
+ public void testFindClosestDeviceProfile2() {
+ for (InvariantDeviceProfile idf: mPredefinedDeviceProfiles) {
+ ArrayList<InvariantDeviceProfile> closestProfiles =
+ mInvariantProfile.findClosestDeviceProfiles(
+ idf.minWidthDps, idf.minHeightDps, mPredefinedDeviceProfiles);
+ assertTrue(closestProfiles.get(0).equals(idf));
+ }
+ }
+
+ /**
+ * Used to print out how the invDistWeightedInterpolate works between device profiles to
+ * tweak the two constants that control how the interpolation curve is shaped.
+ */
+ public void testInvInterpolation() {
+
+ InvariantDeviceProfile p1 = mPredefinedDeviceProfiles.get(7); // e.g., Large Phone
+ InvariantDeviceProfile p2 = mPredefinedDeviceProfiles.get(8); // e.g., Nexus 7
+
+ ArrayList<PointF> pts = createInterpolatedPoints(
+ new PointF(p1.minWidthDps, p1.minHeightDps),
+ new PointF(p2.minWidthDps, p2.minHeightDps),
+ 20f);
+
+ for (int i = 0; i < pts.size(); i++) {
+ ArrayList<InvariantDeviceProfile> closestProfiles =
+ mInvariantProfile.findClosestDeviceProfiles(
+ pts.get(i).x, pts.get(i).y, mPredefinedDeviceProfiles);
+ InvariantDeviceProfile result =
+ mInvariantProfile.invDistWeightedInterpolate(
+ pts.get(i).x, pts.get(i).y, closestProfiles);
+ if (DEBUG) {
+ Log.d(TAG, String.format("width x height = (%f, %f)] iconSize = %f",
+ pts.get(i).x, pts.get(i).y, result.iconSize));
+ }
+ }
+ }
+
+ private ArrayList<PointF> createInterpolatedPoints(PointF a, PointF b, float numPts) {
+ ArrayList<PointF> result = new ArrayList<PointF>();
+ result.add(a);
+ for (float i = 1; i < numPts; i = i + 1.0f) {
+ result.add(new PointF((b.x * i + a.x * (numPts - i)) / numPts,
+ (b.y * i + a.y * (numPts - i)) / numPts));
+ }
+ result.add(b);
+ return result;
+ }
+
+ /**
+ * Ensures that system calls (e.g., WindowManager, DisplayMetrics) that require contexts are
+ * properly working to generate minimum width and height of the display.
+ */
+ public void test_hammerhead() {
+ if (!android.os.Build.DEVICE.equals("hammerhead")) {
+ return;
+ }
+ assertEquals(mInvariantProfile.numRows, 4);
+ assertEquals(mInvariantProfile.numColumns, 4);
+ assertEquals((int) mInvariantProfile.numHotseatIcons, 5);
+
+ DeviceProfile landscapeProfile = mInvariantProfile.landscapeProfile;
+ DeviceProfile portraitProfile = mInvariantProfile.portraitProfile;
+
+ assertEquals(portraitProfile.allAppsNumCols, 3);
+ assertEquals(landscapeProfile.allAppsNumCols, 5); // not used
+ }
+
+ // 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.
+}
diff --git a/tests/src/com/android/launcher3/util/FocusLogicTest.java b/tests/src/com/android/launcher3/util/FocusLogicTest.java
new file mode 100644
index 000000000..ea87014e9
--- /dev/null
+++ b/tests/src/com/android/launcher3/util/FocusLogicTest.java
@@ -0,0 +1,60 @@
+/*
+ * 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;
+
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.view.KeyEvent;
+
+import com.android.launcher3.util.FocusLogic;
+
+/**
+ * Tests the {@link FocusLogic} class that handles key event based focus handling.
+ */
+@SmallTest
+public final class FocusLogicTest extends AndroidTestCase {
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ // Nothing to set up as this class only tests static methods.
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ // Nothing to tear down as this class only tests static methods.
+ }
+
+ public void testShouldConsume() {
+ assertTrue(FocusLogic.shouldConsume(KeyEvent.KEYCODE_DPAD_LEFT));
+ assertTrue(FocusLogic.shouldConsume(KeyEvent.KEYCODE_DPAD_RIGHT));
+ assertTrue(FocusLogic.shouldConsume(KeyEvent.KEYCODE_DPAD_UP));
+ assertTrue(FocusLogic.shouldConsume(KeyEvent.KEYCODE_DPAD_DOWN));
+ assertTrue(FocusLogic.shouldConsume(KeyEvent.KEYCODE_MOVE_HOME));
+ assertTrue(FocusLogic.shouldConsume(KeyEvent.KEYCODE_MOVE_END));
+ assertTrue(FocusLogic.shouldConsume(KeyEvent.KEYCODE_PAGE_UP));
+ assertTrue(FocusLogic.shouldConsume(KeyEvent.KEYCODE_PAGE_DOWN));
+ assertTrue(FocusLogic.shouldConsume(KeyEvent.KEYCODE_DEL));
+ assertTrue(FocusLogic.shouldConsume(KeyEvent.KEYCODE_FORWARD_DEL));
+ }
+
+ public void testCreateSparseMatrix() {
+ // Either, 1) create a helper method to generate/instantiate all possible cell layout that
+ // 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.
+ }
+}
diff --git a/tests/stress/Android.mk b/tests/stress/Android.mk
deleted file mode 100644
index 68289bd3e..000000000
--- a/tests/stress/Android.mk
+++ /dev/null
@@ -1,31 +0,0 @@
-# Copyright (C) 2011 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-LOCAL_PATH := $(call my-dir)
-include $(CLEAR_VARS)
-
-# We only want this apk build for tests.
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_JAVA_LIBRARIES := android.test.runner
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_PACKAGE_NAME := LauncherRotationStressTest
-
-LOCAL_CERTIFICATE := shared
-
-LOCAL_INSTRUMENTATION_FOR := Launcher2
-
-include $(BUILD_PACKAGE)
diff --git a/tests/stress/src/com/android/launcher3/stress/LauncherRotationStressTest.java b/tests/stress/src/com/android/launcher3/stress/LauncherRotationStressTest.java
deleted file mode 100644
index a5b85eb19..000000000
--- a/tests/stress/src/com/android/launcher3/stress/LauncherRotationStressTest.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.launcher3.stress;
-
-
-import com.android.launcher3.Launcher;
-
-import android.content.pm.ActivityInfo;
-import android.os.SystemClock;
-import android.test.ActivityInstrumentationTestCase2;
-import android.test.RepetitiveTest;
-import android.util.Log;
-
-/**
- * Run rotation stress test using Launcher2 for 50 iterations.
- */
-public class LauncherRotationStressTest extends ActivityInstrumentationTestCase2<Launcher> {
-
- private static final int NUM_ITERATIONS = 50;
- private static final int WAIT_TIME_MS = 500;
- private static final String LOG_TAG = "LauncherRotationStressTest";
-
- public LauncherRotationStressTest() {
- super(Launcher.class);
- }
-
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- }
-
- @Override
- protected void tearDown() throws Exception {
- super.tearDown();
- }
-
- @RepetitiveTest(numIterations=NUM_ITERATIONS)
- public void testLauncherRotationStress() throws Exception {
- Launcher launcher = getActivity();
- getInstrumentation().waitForIdleSync();
- SystemClock.sleep(WAIT_TIME_MS);
- launcher.setRequestedOrientation(
- ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
- getInstrumentation().waitForIdleSync();
- SystemClock.sleep(WAIT_TIME_MS);
- launcher.setRequestedOrientation(
- ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
- }
-}
diff --git a/util/com/android/launcher3/DecoderRing.java b/util/com/android/launcher3/DecoderRing.java
index 86431d9b7..0732fe889 100644
--- a/util/com/android/launcher3/DecoderRing.java
+++ b/util/com/android/launcher3/DecoderRing.java
@@ -220,9 +220,6 @@ class DecoderRing {
if (widget.icon != null) {
writeImageData(widget.icon.data, prefix + "_icon.png");
}
- if (widget.preview != null) {
- writeImageData(widget.preview.data, prefix + "_preview.png");
- }
}
}
}