Merge "Show a persistent toast when selecting desktop apps on home screen" into udc-qpr-dev
This commit is contained in:
@@ -0,0 +1,23 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?><!--
|
||||||
|
Copyright (C) 2023 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"
|
||||||
|
xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
|
||||||
|
android:shape="rectangle">
|
||||||
|
|
||||||
|
<corners android:radius="@dimen/rounded_button_radius" />
|
||||||
|
<solid android:color="?androidprv:attr/materialColorPrimaryContainer" />
|
||||||
|
</shape>
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?><!--
|
||||||
|
Copyright (C) 2023 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.quickstep.views.DesktopAppSelectView
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="@dimen/desktop_mode_floating_app_select_height"
|
||||||
|
android:layout_gravity="top|center_horizontal"
|
||||||
|
android:background="@drawable/bg_floating_desktop_select"
|
||||||
|
android:elevation="@dimen/desktop_mode_floating_app_select_elevation"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/desktop_app_select_text"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginEnd="@dimen/desktop_mode_floating_app_select_text_margin"
|
||||||
|
android:layout_marginStart="@dimen/desktop_mode_floating_app_select_margin"
|
||||||
|
android:drawablePadding="@dimen/desktop_mode_floating_app_select_text_margin"
|
||||||
|
android:drawableStart="@drawable/ic_desktop"
|
||||||
|
android:drawableTint="?androidprv:attr/materialColorOnPrimaryContainer"
|
||||||
|
android:fontFamily="google-sans-medium"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:text="@string/desktop_select_app_toast"
|
||||||
|
android:textColor="?androidprv:attr/materialColorOnPrimaryContainer"
|
||||||
|
android:textSize="@dimen/desktop_mode_floating_app_select_text_size" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/close_button"
|
||||||
|
style="@android:style/Widget.DeviceDefault.Button.Borderless"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginEnd="@dimen/desktop_mode_floating_app_select_margin"
|
||||||
|
android:minWidth="0dp"
|
||||||
|
android:fontFamily="google-sans-medium"
|
||||||
|
android:text="@string/desktop_button_close_app_toast"
|
||||||
|
android:textAllCaps="false"
|
||||||
|
android:textColor="?androidprv:attr/materialColorPrimary"
|
||||||
|
android:textSize="@dimen/desktop_mode_floating_app_select_text_size" />
|
||||||
|
|
||||||
|
</com.android.quickstep.views.DesktopAppSelectView>
|
||||||
@@ -383,4 +383,12 @@
|
|||||||
<dimen name="keyboard_quick_switch_task_view_radius">16dp</dimen>
|
<dimen name="keyboard_quick_switch_task_view_radius">16dp</dimen>
|
||||||
<dimen name="keyboard_quick_switch_no_recent_items_icon_size">24dp</dimen>
|
<dimen name="keyboard_quick_switch_no_recent_items_icon_size">24dp</dimen>
|
||||||
<dimen name="keyboard_quick_switch_no_recent_items_icon_margin">8dp</dimen>
|
<dimen name="keyboard_quick_switch_no_recent_items_icon_margin">8dp</dimen>
|
||||||
|
|
||||||
|
<!-- Desktop mode -->
|
||||||
|
<dimen name="desktop_mode_floating_app_select_height">56dp</dimen>
|
||||||
|
<dimen name="desktop_mode_floating_app_select_elevation">4dp</dimen>
|
||||||
|
<dimen name="desktop_mode_floating_app_select_margin">16dp</dimen>
|
||||||
|
<dimen name="desktop_mode_floating_app_select_text_size">14sp</dimen>
|
||||||
|
<dimen name="desktop_mode_floating_app_select_text_margin">8dp</dimen>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -298,4 +298,10 @@
|
|||||||
|
|
||||||
<!-- Accessibility label for quick switch tiles showing split tasks [CHAR LIMIT=NONE] -->
|
<!-- Accessibility label for quick switch tiles showing split tasks [CHAR LIMIT=NONE] -->
|
||||||
<string name="quick_switch_split_task"><xliff:g id="app_name_1" example="Chrome">%1$s</xliff:g> and <xliff:g id="app_name_2" example="Gmail">%2$s</xliff:g></string>
|
<string name="quick_switch_split_task"><xliff:g id="app_name_1" example="Chrome">%1$s</xliff:g> and <xliff:g id="app_name_2" example="Gmail">%2$s</xliff:g></string>
|
||||||
|
|
||||||
|
<!-- ******* Desktop ******* -->
|
||||||
|
<!-- Text shown in popup to choose a desktop app. [CHAR LIMIT=60] -->
|
||||||
|
<string name="desktop_select_app_toast">Adding app to Desktop</string>
|
||||||
|
<!-- Text shown on a button that closes the popup for choosing a desktop app. [CHAR_LIMIT=40] -->
|
||||||
|
<string name="desktop_button_close_app_toast">Cancel</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -17,11 +17,9 @@ package com.android.launcher3.statehandlers;
|
|||||||
|
|
||||||
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
|
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
|
||||||
|
|
||||||
import android.os.RemoteException;
|
|
||||||
import android.os.SystemProperties;
|
import android.os.SystemProperties;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.Toast;
|
|
||||||
|
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
@@ -30,6 +28,7 @@ import com.android.launcher3.LauncherState;
|
|||||||
import com.android.launcher3.statemanager.StatefulActivity;
|
import com.android.launcher3.statemanager.StatefulActivity;
|
||||||
import com.android.launcher3.uioverrides.QuickstepLauncher;
|
import com.android.launcher3.uioverrides.QuickstepLauncher;
|
||||||
import com.android.quickstep.SystemUiProxy;
|
import com.android.quickstep.SystemUiProxy;
|
||||||
|
import com.android.quickstep.views.DesktopAppSelectView;
|
||||||
import com.android.wm.shell.desktopmode.IDesktopTaskListener;
|
import com.android.wm.shell.desktopmode.IDesktopTaskListener;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -49,6 +48,7 @@ public class DesktopVisibilityController {
|
|||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private IDesktopTaskListener mDesktopTaskListener;
|
private IDesktopTaskListener mDesktopTaskListener;
|
||||||
|
private DesktopAppSelectView mSelectAppToast;
|
||||||
|
|
||||||
public DesktopVisibilityController(Launcher launcher) {
|
public DesktopVisibilityController(Launcher launcher) {
|
||||||
mLauncher = launcher;
|
mLauncher = launcher;
|
||||||
@@ -60,17 +60,22 @@ public class DesktopVisibilityController {
|
|||||||
public void registerSystemUiListener() {
|
public void registerSystemUiListener() {
|
||||||
mDesktopTaskListener = new IDesktopTaskListener.Stub() {
|
mDesktopTaskListener = new IDesktopTaskListener.Stub() {
|
||||||
@Override
|
@Override
|
||||||
public void onVisibilityChanged(int displayId, boolean visible) throws RemoteException {
|
public void onVisibilityChanged(int displayId, boolean visible) {
|
||||||
// TODO(b/261234402): move visibility from sysui state to listener
|
// TODO(b/261234402): move visibility from sysui state to listener
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onStashedChanged(int displayId, boolean stashed) throws RemoteException {
|
public void onStashedChanged(int displayId, boolean stashed) {
|
||||||
// TODO(b/261234402): show a persistent toast
|
|
||||||
MAIN_EXECUTOR.execute(() -> {
|
MAIN_EXECUTOR.execute(() -> {
|
||||||
if (stashed && displayId == mLauncher.getDisplayId()) {
|
if (displayId == mLauncher.getDisplayId()) {
|
||||||
Toast.makeText(mLauncher, "Adding app to Desktop",
|
if (DEBUG) {
|
||||||
Toast.LENGTH_SHORT).show();
|
Log.d(TAG, "desktop stashed changed value=" + stashed);
|
||||||
|
}
|
||||||
|
if (stashed) {
|
||||||
|
showSelectAppToast();
|
||||||
|
} else {
|
||||||
|
hideSelectAppToast();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -110,6 +115,7 @@ public class DesktopVisibilityController {
|
|||||||
if (!isDesktopModeSupported()) {
|
if (!isDesktopModeSupported()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (freeformTasksVisible != mFreeformTasksVisible) {
|
if (freeformTasksVisible != mFreeformTasksVisible) {
|
||||||
mFreeformTasksVisible = freeformTasksVisible;
|
mFreeformTasksVisible = freeformTasksVisible;
|
||||||
if (mFreeformTasksVisible) {
|
if (mFreeformTasksVisible) {
|
||||||
@@ -219,4 +225,28 @@ public class DesktopVisibilityController {
|
|||||||
activity.setResumed();
|
activity.setResumed();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void showSelectAppToast() {
|
||||||
|
if (mSelectAppToast != null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (DEBUG) {
|
||||||
|
Log.d(TAG, "show toast to select desktop apps");
|
||||||
|
}
|
||||||
|
Runnable onCloseCallback = () -> {
|
||||||
|
SystemUiProxy.INSTANCE.get(mLauncher).hideStashedDesktopApps(mLauncher.getDisplayId());
|
||||||
|
};
|
||||||
|
mSelectAppToast = DesktopAppSelectView.show(mLauncher, onCloseCallback);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void hideSelectAppToast() {
|
||||||
|
if (mSelectAppToast == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (DEBUG) {
|
||||||
|
Log.d(TAG, "hide toast to select desktop apps");
|
||||||
|
}
|
||||||
|
mSelectAppToast.hide();
|
||||||
|
mSelectAppToast = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1161,6 +1161,17 @@ public class SystemUiProxy implements ISystemUiProxy {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Call shell to hide desktop apps that may be stashed */
|
||||||
|
public void hideStashedDesktopApps(int displayId) {
|
||||||
|
if (mDesktopMode != null) {
|
||||||
|
try {
|
||||||
|
mDesktopMode.hideStashedDesktopApps(displayId);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
Log.w(TAG, "Failed call hideStashedDesktopApps", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** Call shell to get number of visible freeform tasks */
|
/** Call shell to get number of visible freeform tasks */
|
||||||
public int getVisibleDesktopTaskCount(int displayId) {
|
public int getVisibleDesktopTaskCount(int displayId) {
|
||||||
if (mDesktopMode != null) {
|
if (mDesktopMode != null) {
|
||||||
|
|||||||
@@ -0,0 +1,108 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2023 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.quickstep.views;
|
||||||
|
|
||||||
|
import static com.android.launcher3.anim.Interpolators.LINEAR;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.util.AttributeSet;
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
|
import com.android.launcher3.Launcher;
|
||||||
|
import com.android.launcher3.R;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Floating view show on launcher home screen that notifies the user that an app will be launched to
|
||||||
|
* the desktop.
|
||||||
|
*/
|
||||||
|
public class DesktopAppSelectView extends LinearLayout {
|
||||||
|
|
||||||
|
private static final int HIDE_DURATION = 83;
|
||||||
|
|
||||||
|
private final Launcher mLauncher;
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private Runnable mOnCloseCallback = null;
|
||||||
|
private boolean mIsHideAnimationRunning;
|
||||||
|
|
||||||
|
public DesktopAppSelectView(Context context) {
|
||||||
|
this(context, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public DesktopAppSelectView(Context context, AttributeSet attrs) {
|
||||||
|
this(context, attrs, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public DesktopAppSelectView(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||||
|
this(context, attrs, defStyleAttr, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public DesktopAppSelectView(Context context, AttributeSet attrs, int defStyleAttr,
|
||||||
|
int defStyleRes) {
|
||||||
|
super(context, attrs, defStyleAttr, defStyleRes);
|
||||||
|
mLauncher = Launcher.getLauncher(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show the popup on launcher home screen
|
||||||
|
*
|
||||||
|
* @param onCloseCallback optional callback that is called when user clicks the close button
|
||||||
|
* @return the created view
|
||||||
|
*/
|
||||||
|
public static DesktopAppSelectView show(Launcher launcher, @Nullable Runnable onCloseCallback) {
|
||||||
|
DesktopAppSelectView view = (DesktopAppSelectView) launcher.getLayoutInflater().inflate(
|
||||||
|
R.layout.floating_desktop_app_select, launcher.getDragLayer(), false);
|
||||||
|
view.setOnCloseClickCallback(onCloseCallback);
|
||||||
|
launcher.getDragLayer().addView(view);
|
||||||
|
return view;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onFinishInflate() {
|
||||||
|
super.onFinishInflate();
|
||||||
|
findViewById(R.id.close_button).setOnClickListener(v -> {
|
||||||
|
if (!mIsHideAnimationRunning) {
|
||||||
|
hide();
|
||||||
|
if (mOnCloseCallback != null) {
|
||||||
|
mOnCloseCallback.run();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hide the floating view
|
||||||
|
*/
|
||||||
|
public void hide() {
|
||||||
|
if (!mIsHideAnimationRunning) {
|
||||||
|
mIsHideAnimationRunning = true;
|
||||||
|
animate().alpha(0).setDuration(HIDE_DURATION).setInterpolator(LINEAR).withEndAction(
|
||||||
|
() -> {
|
||||||
|
mLauncher.getDragLayer().removeView(this);
|
||||||
|
mIsHideAnimationRunning = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a callback that is called when close button is clicked
|
||||||
|
*/
|
||||||
|
public void setOnCloseClickCallback(@Nullable Runnable callback) {
|
||||||
|
mOnCloseCallback = callback;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user