Loading src/com/android/launcher3/apppairs/AppPairIcon.java +1 −1 Original line number Diff line number Diff line Loading @@ -143,7 +143,7 @@ public class AppPairIcon extends FrameLayout implements DraggableView, Reorderab CharSequence app2 = getInfo().getSecondApp().title; String a11yTitle = getContext().getString(R.string.app_pair_name_format, app1, app2); setContentDescription( getInfo().shouldDrawAsDisabled(getContext()) getInfo().shouldReportDisabled(getContext()) ? getContext().getString(R.string.disabled_app_label, a11yTitle) : a11yTitle); } Loading src/com/android/launcher3/apppairs/AppPairIconGraphic.kt +6 −0 Original line number Diff line number Diff line Loading @@ -55,6 +55,12 @@ constructor(context: Context, attrs: AttributeSet? = null) : appIcon1.setBounds(0, 0, p.memberIconSize.toInt(), p.memberIconSize.toInt()) appIcon2.setBounds(0, 0, p.memberIconSize.toInt(), p.memberIconSize.toInt()) // If icons are unlaunchable due to screen size, manually override disabled appearance. // (otherwise, leave disabled state alone; icons will naturally inherit the app's state) val (isApp1Launchable, isApp2Launchable) = appPairInfo.isLaunchable(p.context) if (!isApp1Launchable) appIcon1.setIsDisabled(true) if (!isApp2Launchable) appIcon2.setIsDisabled(true) // Create icon drawable. val fullIconDrawable = AppPairIconDrawable(p, appIcon1, appIcon2) fullIconDrawable.setBounds(0, 0, p.iconSize, p.iconSize) Loading src/com/android/launcher3/model/data/AppPairInfo.kt +13 −9 Original line number Diff line number Diff line Loading @@ -68,11 +68,14 @@ class AppPairInfo() : CollectionInfo() { /** Returns if either of the app pair members is currently disabled. */ override fun isDisabled() = anyMatch { it.isDisabled } /** Checks if the app pair is launchable at the current screen size. */ fun isLaunchable(context: Context) = (ActivityContext.lookupContext(context) as ActivityContext).getDeviceProfile().isTablet || getAppContents().stream().noneMatch { it.hasStatusFlag(WorkspaceItemInfo.FLAG_NON_RESIZEABLE) /** Checks if member apps are launchable at the current screen size. */ fun isLaunchable(context: Context): Pair<Boolean, Boolean> { val isTablet = (ActivityContext.lookupContext(context) as ActivityContext).getDeviceProfile().isTablet return Pair( isTablet || !getFirstApp().hasStatusFlag(WorkspaceItemInfo.FLAG_NON_RESIZEABLE), isTablet || !getSecondApp().hasStatusFlag(WorkspaceItemInfo.FLAG_NON_RESIZEABLE) ) } /** Fetches high-res icons for member apps if needed. */ Loading @@ -83,13 +86,14 @@ class AppPairInfo() : CollectionInfo() { } /** * App pairs will draw as "disabled" if either of the following is true: * App pairs will report itself as "disabled" (for accessibility) if either of the following is * true: * 1) One of the member WorkspaceItemInfos is disabled (i.e. the app software itself is paused * or can't be launched for some other reason). * 2) One of the member apps can't be launched due to screen size requirements. */ fun shouldDrawAsDisabled(context: Context): Boolean { return isDisabled || !isLaunchable(context) fun shouldReportDisabled(context: Context): Boolean { return isDisabled || !isLaunchable(context).first || !isLaunchable(context).second } /** Generates a default title for the app pair and sets it. */ Loading src/com/android/launcher3/touch/ItemClickHandler.java +14 −10 Original line number Diff line number Diff line Loading @@ -149,9 +149,12 @@ public class ItemClickHandler { */ private static void onClickAppPairIcon(View v) { Launcher launcher = Launcher.getLauncher(v.getContext()); AppPairIcon appPairIcon = (AppPairIcon) v; if (!appPairIcon.getInfo().isLaunchable(launcher)) { // Display a message for app pairs that are disabled due to screen size AppPairIcon icon = (AppPairIcon) v; AppPairInfo info = icon.getInfo(); boolean isApp1Launchable = info.isLaunchable(launcher).getFirst(), isApp2Launchable = info.isLaunchable(launcher).getSecond(); if (!isApp1Launchable || !isApp2Launchable) { // App pair is unlaunchable due to screen size. boolean isFoldable = InvariantDeviceProfile.INSTANCE.get(launcher) .supportedProfiles.stream().anyMatch(dp -> dp.isTwoPanels); Toast.makeText(launcher, isFoldable Loading @@ -159,26 +162,27 @@ public class ItemClickHandler { : R.string.app_pair_unlaunchable_at_screen_size, Toast.LENGTH_SHORT).show(); return; } else if (appPairIcon.getInfo().isDisabled()) { WorkspaceItemInfo app1 = appPairIcon.getInfo().getFirstApp(); WorkspaceItemInfo app2 = appPairIcon.getInfo().getSecondApp(); } else if (info.isDisabled()) { // App pair is disabled for another reason. WorkspaceItemInfo app1 = info.getFirstApp(); WorkspaceItemInfo app2 = info.getSecondApp(); // Show the user why the app pair is disabled. if (app1.isDisabled() && app2.isDisabled()) { // Both apps are disabled, show "app pair is not available" toast. // Both apps are disabled, show generic "app pair is not available" toast. Toast.makeText(launcher, R.string.app_pair_not_available, Toast.LENGTH_SHORT) .show(); return; } else if ((app1.isDisabled() && handleDisabledItemClicked(app1, launcher)) || (app2.isDisabled() && handleDisabledItemClicked(app2, launcher))) { // Only one is disabled, and handleDisabledItemClicked() will show a toast, so we // are done. // Only one is disabled, and handleDisabledItemClicked() showed a specific toast // explaining why, so we are done. return; } } // Either the app pair is not disabled, or it is a disabled state that can be handled by // framework directly (e.g. one app is paused), so go ahead and launch. launcher.launchAppPair(appPairIcon); launcher.launchAppPair(icon); } /** Loading Loading
src/com/android/launcher3/apppairs/AppPairIcon.java +1 −1 Original line number Diff line number Diff line Loading @@ -143,7 +143,7 @@ public class AppPairIcon extends FrameLayout implements DraggableView, Reorderab CharSequence app2 = getInfo().getSecondApp().title; String a11yTitle = getContext().getString(R.string.app_pair_name_format, app1, app2); setContentDescription( getInfo().shouldDrawAsDisabled(getContext()) getInfo().shouldReportDisabled(getContext()) ? getContext().getString(R.string.disabled_app_label, a11yTitle) : a11yTitle); } Loading
src/com/android/launcher3/apppairs/AppPairIconGraphic.kt +6 −0 Original line number Diff line number Diff line Loading @@ -55,6 +55,12 @@ constructor(context: Context, attrs: AttributeSet? = null) : appIcon1.setBounds(0, 0, p.memberIconSize.toInt(), p.memberIconSize.toInt()) appIcon2.setBounds(0, 0, p.memberIconSize.toInt(), p.memberIconSize.toInt()) // If icons are unlaunchable due to screen size, manually override disabled appearance. // (otherwise, leave disabled state alone; icons will naturally inherit the app's state) val (isApp1Launchable, isApp2Launchable) = appPairInfo.isLaunchable(p.context) if (!isApp1Launchable) appIcon1.setIsDisabled(true) if (!isApp2Launchable) appIcon2.setIsDisabled(true) // Create icon drawable. val fullIconDrawable = AppPairIconDrawable(p, appIcon1, appIcon2) fullIconDrawable.setBounds(0, 0, p.iconSize, p.iconSize) Loading
src/com/android/launcher3/model/data/AppPairInfo.kt +13 −9 Original line number Diff line number Diff line Loading @@ -68,11 +68,14 @@ class AppPairInfo() : CollectionInfo() { /** Returns if either of the app pair members is currently disabled. */ override fun isDisabled() = anyMatch { it.isDisabled } /** Checks if the app pair is launchable at the current screen size. */ fun isLaunchable(context: Context) = (ActivityContext.lookupContext(context) as ActivityContext).getDeviceProfile().isTablet || getAppContents().stream().noneMatch { it.hasStatusFlag(WorkspaceItemInfo.FLAG_NON_RESIZEABLE) /** Checks if member apps are launchable at the current screen size. */ fun isLaunchable(context: Context): Pair<Boolean, Boolean> { val isTablet = (ActivityContext.lookupContext(context) as ActivityContext).getDeviceProfile().isTablet return Pair( isTablet || !getFirstApp().hasStatusFlag(WorkspaceItemInfo.FLAG_NON_RESIZEABLE), isTablet || !getSecondApp().hasStatusFlag(WorkspaceItemInfo.FLAG_NON_RESIZEABLE) ) } /** Fetches high-res icons for member apps if needed. */ Loading @@ -83,13 +86,14 @@ class AppPairInfo() : CollectionInfo() { } /** * App pairs will draw as "disabled" if either of the following is true: * App pairs will report itself as "disabled" (for accessibility) if either of the following is * true: * 1) One of the member WorkspaceItemInfos is disabled (i.e. the app software itself is paused * or can't be launched for some other reason). * 2) One of the member apps can't be launched due to screen size requirements. */ fun shouldDrawAsDisabled(context: Context): Boolean { return isDisabled || !isLaunchable(context) fun shouldReportDisabled(context: Context): Boolean { return isDisabled || !isLaunchable(context).first || !isLaunchable(context).second } /** Generates a default title for the app pair and sets it. */ Loading
src/com/android/launcher3/touch/ItemClickHandler.java +14 −10 Original line number Diff line number Diff line Loading @@ -149,9 +149,12 @@ public class ItemClickHandler { */ private static void onClickAppPairIcon(View v) { Launcher launcher = Launcher.getLauncher(v.getContext()); AppPairIcon appPairIcon = (AppPairIcon) v; if (!appPairIcon.getInfo().isLaunchable(launcher)) { // Display a message for app pairs that are disabled due to screen size AppPairIcon icon = (AppPairIcon) v; AppPairInfo info = icon.getInfo(); boolean isApp1Launchable = info.isLaunchable(launcher).getFirst(), isApp2Launchable = info.isLaunchable(launcher).getSecond(); if (!isApp1Launchable || !isApp2Launchable) { // App pair is unlaunchable due to screen size. boolean isFoldable = InvariantDeviceProfile.INSTANCE.get(launcher) .supportedProfiles.stream().anyMatch(dp -> dp.isTwoPanels); Toast.makeText(launcher, isFoldable Loading @@ -159,26 +162,27 @@ public class ItemClickHandler { : R.string.app_pair_unlaunchable_at_screen_size, Toast.LENGTH_SHORT).show(); return; } else if (appPairIcon.getInfo().isDisabled()) { WorkspaceItemInfo app1 = appPairIcon.getInfo().getFirstApp(); WorkspaceItemInfo app2 = appPairIcon.getInfo().getSecondApp(); } else if (info.isDisabled()) { // App pair is disabled for another reason. WorkspaceItemInfo app1 = info.getFirstApp(); WorkspaceItemInfo app2 = info.getSecondApp(); // Show the user why the app pair is disabled. if (app1.isDisabled() && app2.isDisabled()) { // Both apps are disabled, show "app pair is not available" toast. // Both apps are disabled, show generic "app pair is not available" toast. Toast.makeText(launcher, R.string.app_pair_not_available, Toast.LENGTH_SHORT) .show(); return; } else if ((app1.isDisabled() && handleDisabledItemClicked(app1, launcher)) || (app2.isDisabled() && handleDisabledItemClicked(app2, launcher))) { // Only one is disabled, and handleDisabledItemClicked() will show a toast, so we // are done. // Only one is disabled, and handleDisabledItemClicked() showed a specific toast // explaining why, so we are done. return; } } // Either the app pair is not disabled, or it is a disabled state that can be handled by // framework directly (e.g. one app is paused), so go ahead and launch. launcher.launchAppPair(appPairIcon); launcher.launchAppPair(icon); } /** Loading