Merge "Scale recents during quick switch for large screens." into sc-v2-dev
diff --git a/lint-baseline-launcher3.xml b/lint-baseline-launcher3.xml
index e77c889..94345a6 100644
--- a/lint-baseline-launcher3.xml
+++ b/lint-baseline-launcher3.xml
@@ -584,4 +584,15 @@
column="17"/>
</issue>
+ <issue
+ id="NewApi"
+ message="Call requires API level 27 (current min is 26): `android.app.WallpaperManager#getWallpaperColors`"
+ errorLine1=" : WallpaperManager.getInstance(context).getWallpaperColors(FLAG_SYSTEM);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~">
+ <location
+ file="packages/apps/Launcher3/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java"
+ line="288"
+ column="61"/>
+ </issue>
+
</issues>
diff --git a/quickstep/res/layout/taskbar.xml b/quickstep/res/layout/taskbar.xml
index dfa17d6..c0e0862 100644
--- a/quickstep/res/layout/taskbar.xml
+++ b/quickstep/res/layout/taskbar.xml
@@ -36,18 +36,27 @@
android:layout_height="wrap_content"
android:layout_gravity="bottom" >
+ <FrameLayout
+ android:id="@+id/start_contextual_buttons"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:paddingLeft="@dimen/taskbar_nav_buttons_spacing"
+ android:paddingRight="@dimen/taskbar_nav_buttons_spacing"
+ android:gravity="center_vertical"
+ android:layout_gravity="start"/>
+
<LinearLayout
- android:id="@+id/start_nav_buttons"
+ android:id="@+id/end_nav_buttons"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:orientation="horizontal"
android:paddingLeft="@dimen/taskbar_nav_buttons_spacing"
android:paddingRight="@dimen/taskbar_nav_buttons_spacing"
android:gravity="center_vertical"
- android:layout_gravity="start"/>
+ android:layout_gravity="end"/>
<FrameLayout
- android:id="@+id/end_nav_buttons"
+ android:id="@+id/end_contextual_buttons"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:paddingLeft="@dimen/taskbar_nav_buttons_spacing"
diff --git a/quickstep/res/values-hi/strings.xml b/quickstep/res/values-hi/strings.xml
index 86f9017..23ffad3 100644
--- a/quickstep/res/values-hi/strings.xml
+++ b/quickstep/res/values-hi/strings.xml
@@ -46,7 +46,7 @@
<string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"सुझाए गए ऐप्लिकेशन की सुविधा बंद है"</string>
<string name="hotseat_prediction_content_description" msgid="4582028296938078419">"सुझाया गया ऐप्लिकेशन: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="1711645592102201538">"पक्का करें कि आप स्क्रीन की दाईं या बाईं ओर के बिल्कुल किनारे से स्वाइप कर रहे हों."</string>
- <string name="back_gesture_feedback_cancelled" msgid="3274382913290074496">"पक्का करें कि आप स्क्रीन के दाएं या बाएं किनारे से, स्क्रीन के बीच तक स्वाइप करें और फिर अपनी उंगली उठा लें."</string>
+ <string name="back_gesture_feedback_cancelled" msgid="3274382913290074496">"स्क्रीन के दाएं या बाएं किनारे से स्क्रीन के बीच तक स्वाइप करें और अपनी उंगली उठा लें."</string>
<string name="back_gesture_feedback_complete_with_overview_follow_up" msgid="9176400654037014471">"आपने स्क्रीन के दाएं किनारे से स्वाइप करके, पिछली स्क्रीन पर वापस जाने का तरीका सीख लिया है. अब, एक ऐप से दूसरे ऐप पर जाने का तरीका सीखें."</string>
<string name="back_gesture_feedback_complete_without_follow_up" msgid="6405649621667113830">"आपने पेज पर पीछे ले जाने वाले हाथ के जेस्चर (हाव-भाव) के बारे में जान लिया है."</string>
<string name="back_gesture_feedback_swipe_in_nav_bar" msgid="1148198467090405643">"देखे लें कि आप स्क्रीन पर बिल्कुल नीचे तक स्वाइप न कर रहे हों."</string>
diff --git a/quickstep/res/values-ja/strings.xml b/quickstep/res/values-ja/strings.xml
index 3ee1b99..9c2adef 100644
--- a/quickstep/res/values-ja/strings.xml
+++ b/quickstep/res/values-ja/strings.xml
@@ -48,16 +48,16 @@
<string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="1711645592102201538">"右端または左端からスワイプしてください。"</string>
<string name="back_gesture_feedback_cancelled" msgid="3274382913290074496">"画面の右端または左端から中央に向かってスワイプし、指を離してください。"</string>
<string name="back_gesture_feedback_complete_with_overview_follow_up" msgid="9176400654037014471">"右側からスワイプして前の画面に戻る方法を学習しました。次は、アプリを切り替える方法を覚えましょう。"</string>
- <string name="back_gesture_feedback_complete_without_follow_up" msgid="6405649621667113830">"「戻る」操作を完了しました。"</string>
+ <string name="back_gesture_feedback_complete_without_follow_up" msgid="6405649621667113830">"「戻る」操作を学習しました。"</string>
<string name="back_gesture_feedback_swipe_in_nav_bar" msgid="1148198467090405643">"スワイプする際は画面の下部に近づきすぎないようにしましょう。"</string>
<string name="back_gesture_tutorial_confirm_subtitle" msgid="5181305411668713250">"「戻る」操作の感度を変更するには [設定] に移動します"</string>
- <string name="back_gesture_intro_title" msgid="19551256430224428">"スワイプで戻りましょう"</string>
+ <string name="back_gesture_intro_title" msgid="19551256430224428">"スワイプで戻る"</string>
<string name="back_gesture_intro_subtitle" msgid="7912576483031802797">"直前の画面に戻るには、画面の左端または右端から中央に向かってスワイプします。"</string>
<string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="1446774096007065298">"画面の下端から上にスワイプしてください。"</string>
<string name="home_gesture_feedback_overview_detected" msgid="1557523944897393013">"指を離す前にいったん止めないでください。"</string>
<string name="home_gesture_feedback_wrong_swipe_direction" msgid="6993979358080825438">"まっすぐ上にスワイプしてください。"</string>
- <string name="home_gesture_feedback_complete_with_follow_up" msgid="1427872029729605034">"「ホームに戻る」操作を完了しました。次は、前の画面に戻る方法を覚えましょう。"</string>
- <string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"「ホームに戻る」操作を完了しました。"</string>
+ <string name="home_gesture_feedback_complete_with_follow_up" msgid="1427872029729605034">"「ホームに戻る」操作を学習しました。次は、前の画面に戻る方法を覚えましょう。"</string>
+ <string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"「ホームに戻る」操作を学習しました。"</string>
<string name="home_gesture_intro_title" msgid="836590312858441830">"スワイプでホームに戻る"</string>
<string name="home_gesture_intro_subtitle" msgid="2632238748497975326">"画面を下から上にスワイプします。この操作でいつでもホーム画面に戻れます。"</string>
<string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="3032757898111577225">"画面の下端から上にスワイプしてください。"</string>
@@ -65,7 +65,7 @@
<string name="overview_gesture_feedback_wrong_swipe_direction" msgid="6725820500906747925">"まっすぐ上にスワイプしてから、いったん指を止めてください。"</string>
<string name="overview_gesture_feedback_complete_with_follow_up" msgid="3544611727467765026">"主な操作方法を覚えました。操作を OFF にするには、設定に移動してください。"</string>
<string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"「アプリを切り替える」操作を完了しました。"</string>
- <string name="overview_gesture_intro_title" msgid="2902054412868489378">"スワイプでアプリを切り替え"</string>
+ <string name="overview_gesture_intro_title" msgid="2902054412868489378">"スワイプでアプリを切り替える"</string>
<string name="overview_gesture_intro_subtitle" msgid="4968091015637850859">"アプリを切り替えるには、画面を下から上にスワイプして長押しし、指を離します。"</string>
<string name="gesture_tutorial_confirm_title" msgid="6201516182040074092">"設定完了"</string>
<string name="gesture_tutorial_action_button_label" msgid="6249846312991332122">"完了"</string>
@@ -81,7 +81,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"スクリーンショット"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"この操作はアプリまたは組織で許可されていません"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"操作チュートリアルをスキップしますか?"</string>
- <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"これは後から <xliff:g id="NAME">%1$s</xliff:g> アプリで確認できます"</string>
+ <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"チュートリアルは後から <xliff:g id="NAME">%1$s</xliff:g> アプリで確認できます"</string>
<string name="gesture_tutorial_action_button_label_cancel" msgid="3809842569351264108">"キャンセル"</string>
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"スキップ"</string>
</resources>
diff --git a/quickstep/res/values-mn/strings.xml b/quickstep/res/values-mn/strings.xml
index dfa98e7..79fbca6 100644
--- a/quickstep/res/values-mn/strings.xml
+++ b/quickstep/res/values-mn/strings.xml
@@ -47,7 +47,7 @@
<string name="hotseat_prediction_content_description" msgid="4582028296938078419">"Таамаглаж буй апп: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="1711645592102201538">"Та баруун зах эсвэл зүүн захын булангаас шударна уу."</string>
<string name="back_gesture_feedback_cancelled" msgid="3274382913290074496">"Та баруун эсвэл зүүн булангаас дэлгэцийн дунд хэсэг хүртэл шударч, суллана уу."</string>
- <string name="back_gesture_feedback_complete_with_overview_follow_up" msgid="9176400654037014471">"Та буцахын тулд баруунаас хэрхэн шудрахыг мэдэж авлаа Дараа нь аппыг хэрхэн сэлгэхийг мэдэж аваарай."</string>
+ <string name="back_gesture_feedback_complete_with_overview_follow_up" msgid="9176400654037014471">"Та буцахын тулд баруунаас хэрхэн шудрахыг мэдэж авлаа. Дараа нь аппууд хооронд хэрхэн сэлгэхийг мэдэж аваарай."</string>
<string name="back_gesture_feedback_complete_without_follow_up" msgid="6405649621667113830">"Та буцах зангааг гүйцэтгэлээ."</string>
<string name="back_gesture_feedback_swipe_in_nav_bar" msgid="1148198467090405643">"Та дэлгэцийн доод хэсэгтэй хэт ойр бүү шудраарай."</string>
<string name="back_gesture_tutorial_confirm_subtitle" msgid="5181305411668713250">"Буцах зангааны мэдрэгшлийг өөрчлөх бол Тохиргоо руу очно уу"</string>
diff --git a/quickstep/res/values-ne/strings.xml b/quickstep/res/values-ne/strings.xml
index 4428cec..d873795 100644
--- a/quickstep/res/values-ne/strings.xml
+++ b/quickstep/res/values-ne/strings.xml
@@ -23,7 +23,7 @@
<string name="recent_task_option_freeform" msgid="48863056265284071">"फ्रिफर्म"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"हालसालैको कुनै पनि वस्तु छैन"</string>
<string name="accessibility_app_usage_settings" msgid="6312864233673544149">"एपको उपयोगका सेटिङहरू"</string>
- <string name="recents_clear_all" msgid="5328176793634888831">"सबै खाली गर्नुहोस्"</string>
+ <string name="recents_clear_all" msgid="5328176793634888831">"सबै मेटाउनुहोस्"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"हालसालैका एपहरू"</string>
<string name="task_contents_description_with_remaining_time" msgid="4479688746574672685">"<xliff:g id="TASK_DESCRIPTION">%1$s</xliff:g>, <xliff:g id="REMAINING_TIME">%2$s</xliff:g>"</string>
<string name="shorter_duration_less_than_one_minute" msgid="4722015666335015336">"< १ मिनेट"</string>
diff --git a/quickstep/res/values-th/strings.xml b/quickstep/res/values-th/strings.xml
index 96e9060..52b2878 100644
--- a/quickstep/res/values-th/strings.xml
+++ b/quickstep/res/values-th/strings.xml
@@ -81,7 +81,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"ภาพหน้าจอ"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"แอปหรือองค์กรของคุณไม่อนุญาตการดำเนินการนี้"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"ข้ามบทแนะนำการนำทางไหม"</string>
- <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"คุณดูบทแนะนำนี้ได้ภายหลังในแอป <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"คุณดูบทแนะนำนี้ได้ภายหลังในแอป \"<xliff:g id="NAME">%1$s</xliff:g>\""</string>
<string name="gesture_tutorial_action_button_label_cancel" msgid="3809842569351264108">"ยกเลิก"</string>
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"ข้าม"</string>
</resources>
diff --git a/quickstep/res/values-vi/strings.xml b/quickstep/res/values-vi/strings.xml
index 6c192b2..7bd0c70 100644
--- a/quickstep/res/values-vi/strings.xml
+++ b/quickstep/res/values-vi/strings.xml
@@ -47,11 +47,11 @@
<string name="hotseat_prediction_content_description" msgid="4582028296938078419">"Ứng dụng dự đoán: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="1711645592102201538">"Hãy vuốt từ mép ngoài cùng bên phải hoặc ngoài cùng bên trái."</string>
<string name="back_gesture_feedback_cancelled" msgid="3274382913290074496">"Hãy vuốt từ mép phải hoặc mép trái tới giữa màn hình rồi thả tay ra."</string>
- <string name="back_gesture_feedback_complete_with_overview_follow_up" msgid="9176400654037014471">"Bạn đã tìm hiểu cách vuốt từ mép phải để quay lại. Tiếp theo, hãy tìm hiểu cách chuyển đổi ứng dụng."</string>
+ <string name="back_gesture_feedback_complete_with_overview_follow_up" msgid="9176400654037014471">"Bạn đã học được cách vuốt từ mép phải để quay lại. Tiếp theo, hãy tìm hiểu cách chuyển đổi ứng dụng."</string>
<string name="back_gesture_feedback_complete_without_follow_up" msgid="6405649621667113830">"Bạn đã thực hiện xong cử chỉ quay lại."</string>
<string name="back_gesture_feedback_swipe_in_nav_bar" msgid="1148198467090405643">"Hãy nhớ không được vuốt quá gần phần cuối màn hình."</string>
<string name="back_gesture_tutorial_confirm_subtitle" msgid="5181305411668713250">"Để thay đổi độ nhạy của cử chỉ quay lại, hãy vào mục Cài đặt"</string>
- <string name="back_gesture_intro_title" msgid="19551256430224428">"Hãy vuốt để quay lại"</string>
+ <string name="back_gesture_intro_title" msgid="19551256430224428">"Vuốt để quay lại"</string>
<string name="back_gesture_intro_subtitle" msgid="7912576483031802797">"Để quay lại màn hình gần đây nhất, hãy vuốt từ mép trái hoặc mép phải tới chính giữa màn hình."</string>
<string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="1446774096007065298">"Hãy vuốt lên từ mép dưới cùng của màn hình."</string>
<string name="home_gesture_feedback_overview_detected" msgid="1557523944897393013">"Hãy nhớ không được tạm dừng trước khi nhấc ngón tay."</string>
@@ -75,7 +75,7 @@
<string name="gesture_tutorial_step" msgid="1279786122817620968">"Hướng dẫn <xliff:g id="CURRENT">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
<string name="allset_title" msgid="5021126669778966707">"Đã hoàn tất!"</string>
<string name="allset_hint" msgid="2384632994739392447">"Vuốt lên để chuyển đến Màn hình chính"</string>
- <string name="allset_description" msgid="6350320429953234580">"Hiện giờ, bạn đã có thể sử dụng điện thoại"</string>
+ <string name="allset_description" msgid="6350320429953234580">"Vậy là bạn đã sẵn sàng sử dụng điện thoại của mình"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Chế độ cài đặt di chuyển trên hệ thống"</annotation></string>
<string name="action_share" msgid="2648470652637092375">"Chia sẻ"</string>
<string name="action_screenshot" msgid="8171125848358142917">"Chụp ảnh màn hình"</string>
diff --git a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
index ebf8fb7..2da8a45 100644
--- a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
+++ b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
@@ -40,7 +40,6 @@
import static com.android.launcher3.dragndrop.DragLayer.ALPHA_INDEX_TRANSITIONS;
import static com.android.launcher3.statehandlers.DepthController.DEPTH;
import static com.android.launcher3.util.DisplayController.getSingleFrameMs;
-import static com.android.quickstep.TaskUtils.taskIsATargetWithMode;
import static com.android.quickstep.TaskViewUtils.findTaskViewToLaunch;
import static com.android.systemui.shared.system.QuickStepContract.getWindowCornerRadius;
import static com.android.systemui.shared.system.QuickStepContract.supportsRoundedCornersOnWindows;
@@ -1047,7 +1046,7 @@
mLauncherOpenTransition = RemoteAnimationAdapterCompat.buildRemoteTransition(
new LauncherAnimationRunner(mHandler, mWallpaperOpenTransitionRunner,
false /* startAtFrontOfQueue */));
- mLauncherOpenTransition.addHomeOpenCheck();
+ mLauncherOpenTransition.addHomeOpenCheck(mLauncher.getComponentName());
SystemUiProxy.INSTANCE.getNoCreate().registerRemoteTransition(mLauncherOpenTransition);
}
}
diff --git a/quickstep/src/com/android/launcher3/appprediction/PredictionRowView.java b/quickstep/src/com/android/launcher3/appprediction/PredictionRowView.java
index de04082..6afbf9a 100644
--- a/quickstep/src/com/android/launcher3/appprediction/PredictionRowView.java
+++ b/quickstep/src/com/android/launcher3/appprediction/PredictionRowView.java
@@ -96,6 +96,13 @@
private void updateVisibility() {
setVisibility(mPredictionsEnabled ? VISIBLE : GONE);
+ if (mLauncher.getAppsView() != null) {
+ if (mPredictionsEnabled) {
+ mLauncher.getAppsView().getAppsStore().registerIconContainer(this);
+ } else {
+ mLauncher.getAppsView().getAppsStore().unregisterIconContainer(this);
+ }
+ }
}
@Override
diff --git a/quickstep/src/com/android/launcher3/statehandlers/DepthController.java b/quickstep/src/com/android/launcher3/statehandlers/DepthController.java
index 82582ee..370fb8e 100644
--- a/quickstep/src/com/android/launcher3/statehandlers/DepthController.java
+++ b/quickstep/src/com/android/launcher3/statehandlers/DepthController.java
@@ -100,9 +100,12 @@
}
};
- private final Consumer<Boolean> mCrossWindowBlurListener = (enabled) -> {
- mCrossWindowBlursEnabled = enabled;
- dispatchTransactionSurface();
+ private final Consumer<Boolean> mCrossWindowBlurListener = new Consumer<Boolean>() {
+ @Override
+ public void accept(Boolean enabled) {
+ mCrossWindowBlursEnabled = enabled;
+ dispatchTransactionSurface(mDepth);
+ }
};
private final Launcher mLauncher;
@@ -189,14 +192,14 @@
if (mSurface != surface) {
mSurface = surface;
if (surface != null) {
- dispatchTransactionSurface();
+ dispatchTransactionSurface(mDepth);
}
}
}
@Override
public void setState(LauncherState toState) {
- if (mIgnoreStateChangesDuringMultiWindowAnimation) {
+ if (mSurface == null || mIgnoreStateChangesDuringMultiWindowAnimation) {
return;
}
@@ -204,7 +207,7 @@
if (Float.compare(mDepth, toDepth) != 0) {
setDepth(toDepth);
} else if (toState == LauncherState.OVERVIEW) {
- dispatchTransactionSurface();
+ dispatchTransactionSurface(mDepth);
}
}
@@ -243,31 +246,36 @@
if (Float.compare(mDepth, depthF) == 0) {
return;
}
- mDepth = depthF;
- dispatchTransactionSurface();
+ if (dispatchTransactionSurface(depthF)) {
+ mDepth = depthF;
+ }
}
- private void dispatchTransactionSurface() {
+ private boolean dispatchTransactionSurface(float depth) {
boolean supportsBlur = BlurUtils.supportsBlursOnWindows();
+ if (supportsBlur && (mSurface == null || !mSurface.isValid())) {
+ return false;
+ }
ensureDependencies();
IBinder windowToken = mLauncher.getRootView().getWindowToken();
if (windowToken != null) {
- mWallpaperManager.setWallpaperZoomOut(windowToken, mDepth);
+ mWallpaperManager.setWallpaperZoomOut(windowToken, depth);
}
- if (supportsBlur && (mSurface != null && mSurface.isValid())) {
+ if (supportsBlur) {
// We cannot mark the window as opaque in overview because there will be an app window
// below the launcher layer, and we need to draw it -- without blurs.
boolean isOverview = mLauncher.isInState(LauncherState.OVERVIEW);
boolean opaque = mLauncher.getScrimView().isFullyOpaque() && !isOverview;
int blur = opaque || isOverview || !mCrossWindowBlursEnabled
- || mBlurDisabledForAppLaunch ? 0 : (int) (mDepth * mMaxBlurRadius);
+ || mBlurDisabledForAppLaunch ? 0 : (int) (depth * mMaxBlurRadius);
new SurfaceControl.Transaction()
.setBackgroundBlurRadius(mSurface, blur)
.setOpaque(mSurface, opaque)
.apply();
}
+ return true;
}
@Override
diff --git a/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java b/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java
index 8b11154..b5c834d 100644
--- a/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java
@@ -233,11 +233,6 @@
}
}
- @Override
- public boolean onLongPressToUnstashTaskbar() {
- return mControllers.taskbarStashController.onLongPressToUnstashTaskbar();
- }
-
/**
* @param ev MotionEvent in screen coordinates.
* @return Whether any Taskbar item could handle the given MotionEvent if given the chance.
diff --git a/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java b/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java
index 1edeba0..357dc7b 100644
--- a/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java
@@ -79,8 +79,10 @@
private final TaskbarActivityContext mContext;
private final FrameLayout mNavButtonsView;
- private final ViewGroup mStartContainer;
- private final ViewGroup mEndContainer;
+ private final ViewGroup mNavButtonContainer;
+ // Used for IME+A11Y buttons
+ private final ViewGroup mEndContextualContainer;
+ private final ViewGroup mStartContextualContainer;
// Initialized in init.
private TaskbarControllers mControllers;
@@ -91,8 +93,9 @@
public NavbarButtonsViewController(TaskbarActivityContext context, FrameLayout navButtonsView) {
mContext = context;
mNavButtonsView = navButtonsView;
- mStartContainer = mNavButtonsView.findViewById(R.id.start_nav_buttons);
- mEndContainer = mNavButtonsView.findViewById(R.id.end_nav_buttons);
+ mNavButtonContainer = mNavButtonsView.findViewById(R.id.end_nav_buttons);
+ mEndContextualContainer = mNavButtonsView.findViewById(R.id.end_contextual_buttons);
+ mStartContextualContainer = mNavButtonsView.findViewById(R.id.start_contextual_buttons);
}
/**
@@ -114,21 +117,22 @@
// IME switcher
View imeSwitcherButton = addButton(R.drawable.ic_ime_switcher, BUTTON_IME_SWITCH,
- mEndContainer, mControllers.navButtonController, R.id.ime_switcher);
+ mEndContextualContainer, mControllers.navButtonController, R.id.ime_switcher);
mPropertyHolders.add(new StatePropertyHolder(imeSwitcherButton,
flags -> ((flags & MASK_IME_SWITCHER_VISIBLE) == MASK_IME_SWITCHER_VISIBLE)
&& ((flags & FLAG_ROTATION_BUTTON_VISIBLE) == 0)
&& ((flags & FLAG_A11Y_VISIBLE) == 0)));
- mBackButton = addButton(R.drawable.ic_sysbar_back, BUTTON_BACK,
- mStartContainer, mControllers.navButtonController, R.id.back);
+ View imeDownButton = addButton(R.drawable.ic_sysbar_back, BUTTON_BACK,
+ mStartContextualContainer, mControllers.navButtonController, R.id.back);
+ imeDownButton.setRotation(Utilities.isRtl(mContext.getResources()) ? 90 : -90);
// Rotate when Ime visible
- mPropertyHolders.add(new StatePropertyHolder(mBackButton,
- flags -> (flags & FLAG_IME_VISIBLE) == 0, View.ROTATION, 0,
- Utilities.isRtl(mContext.getResources()) ? 90 : -90));
+ mPropertyHolders.add(new StatePropertyHolder(imeDownButton,
+ flags -> (flags & FLAG_IME_VISIBLE) != 0));
if (mContext.isThreeButtonNav()) {
- initButtons(mStartContainer, mEndContainer, mControllers.navButtonController);
+ initButtons(mNavButtonContainer, mEndContextualContainer,
+ mControllers.navButtonController);
// Animate taskbar background when IME shows
mPropertyHolders.add(new StatePropertyHolder(
@@ -142,21 +146,18 @@
// Rotation button
RotationButton rotationButton = new RotationButtonImpl(
- addButton(mEndContainer, R.id.rotate_suggestion));
+ addButton(mEndContextualContainer, R.id.rotate_suggestion));
rotationButton.hide();
mControllers.rotationButtonController.setRotationButton(rotationButton);
} else {
mControllers.rotationButtonController.setRotationButton(new RotationButton() {});
- // Show when IME is visible
- mPropertyHolders.add(new StatePropertyHolder(mBackButton,
- flags -> (flags & FLAG_IME_VISIBLE) != 0));
}
applyState();
mPropertyHolders.forEach(StatePropertyHolder::endAnimation);
}
- private void initButtons(ViewGroup startContainer, ViewGroup endContainer,
+ private void initButtons(ViewGroup navContainer, ViewGroup endContainer,
TaskbarNavButtonController navButtonController) {
// Hide when keyguard is showing, show when bouncer is showing
@@ -164,14 +165,19 @@
flags -> (flags & FLAG_KEYGUARD_VISIBLE) == 0 ||
(flags & FLAG_ONLY_BACK_FOR_BOUNCER_VISIBLE) != 0));
+ mBackButton = addButton(R.drawable.ic_sysbar_back, BUTTON_BACK,
+ mNavButtonContainer, mControllers.navButtonController, R.id.back);
+ mPropertyHolders.add(new StatePropertyHolder(mBackButton,
+ flags -> (flags & FLAG_IME_VISIBLE) == 0));
+
// home and recents buttons
- View homeButton = addButton(R.drawable.ic_sysbar_home, BUTTON_HOME, startContainer,
+ View homeButton = addButton(R.drawable.ic_sysbar_home, BUTTON_HOME, navContainer,
navButtonController, R.id.home);
mPropertyHolders.add(new StatePropertyHolder(homeButton,
flags -> (flags & FLAG_IME_VISIBLE) == 0 &&
(flags & FLAG_KEYGUARD_VISIBLE) == 0));
View recentsButton = addButton(R.drawable.ic_sysbar_recent, BUTTON_RECENTS,
- startContainer, navButtonController, R.id.recent_apps);
+ navContainer, navButtonController, R.id.recent_apps);
mPropertyHolders.add(new StatePropertyHolder(recentsButton,
flags -> (flags & FLAG_IME_VISIBLE) == 0 &&
(flags & FLAG_KEYGUARD_VISIBLE) == 0));
diff --git a/quickstep/src/com/android/launcher3/taskbar/StashedHandleViewController.java b/quickstep/src/com/android/launcher3/taskbar/StashedHandleViewController.java
index 8c14ff6..df37261 100644
--- a/quickstep/src/com/android/launcher3/taskbar/StashedHandleViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/StashedHandleViewController.java
@@ -40,6 +40,8 @@
private final int mStashedHandleHeight;
private final AnimatedFloat mTaskbarStashedHandleAlpha = new AnimatedFloat(
this::updateStashedHandleAlpha);
+ private final AnimatedFloat mTaskbarStashedHandleHintScale = new AnimatedFloat(
+ this::updateStashedHandleHintScale);
// Initialized in init.
private TaskbarControllers mControllers;
@@ -64,6 +66,7 @@
mStashedHandleView.getLayoutParams().height = mActivity.getDeviceProfile().taskbarSize;
updateStashedHandleAlpha();
+ mTaskbarStashedHandleHintScale.updateValue(1f);
final int stashedTaskbarHeight = mControllers.taskbarStashController.getStashedHeight();
mStashedHandleView.setOutlineProvider(new ViewOutlineProvider() {
@@ -80,12 +83,24 @@
outline.setRoundRect(mStashedHandleBounds, mStashedHandleRadius);
}
});
+
+ mStashedHandleView.addOnLayoutChangeListener((view, i, i1, i2, i3, i4, i5, i6, i7) -> {
+ final int stashedCenterX = view.getWidth() / 2;
+ final int stashedCenterY = view.getHeight() - stashedTaskbarHeight / 2;
+
+ view.setPivotX(stashedCenterX);
+ view.setPivotY(stashedCenterY);
+ });
}
public AnimatedFloat getStashedHandleAlpha() {
return mTaskbarStashedHandleAlpha;
}
+ public AnimatedFloat getStashedHandleHintScale() {
+ return mTaskbarStashedHandleHintScale;
+ }
+
/**
* Creates and returns a {@link RevealOutlineAnimation} Animator that updates the stashed handle
* shape and size. When stashed, the shape is a thin rounded pill. When unstashed, the shape
@@ -105,4 +120,9 @@
protected void updateStashedHandleAlpha() {
mStashedHandleView.setAlpha(mTaskbarStashedHandleAlpha.value);
}
+
+ protected void updateStashedHandleHintScale() {
+ mStashedHandleView.setScaleX(mTaskbarStashedHandleHintScale.value);
+ mStashedHandleView.setScaleY(mTaskbarStashedHandleHintScale.value);
+ }
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
index e11f4c1..dbe528f 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
@@ -332,4 +332,20 @@
AbstractFloatingView.closeAllOpenViews(this);
}
+
+ /**
+ * Called when we detect a long press in the nav region before passing the gesture slop.
+ * @return Whether taskbar handled the long press, and thus should cancel the gesture.
+ */
+ public boolean onLongPressToUnstashTaskbar() {
+ return mControllers.taskbarStashController.onLongPressToUnstashTaskbar();
+ }
+
+ /**
+ * Called when we detect a motion down or up/cancel in the nav region while stashed.
+ * @param animateForward Whether to animate towards the unstashed hint state or back to stashed.
+ */
+ public void startTaskbarUnstashHint(boolean animateForward) {
+ mControllers.taskbarStashController.startUnstashHint(animateForward);
+ }
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java
index a226db9..45eabed 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java
@@ -27,6 +27,7 @@
import android.view.Display;
import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
import com.android.launcher3.BaseQuickstepLauncher;
import com.android.launcher3.DeviceProfile;
@@ -188,4 +189,8 @@
mDisplayController.removeChangeListener(this);
mSysUINavigationMode.removeModeChangeListener(this);
}
+
+ public @Nullable TaskbarActivityContext getCurrentActivityContext() {
+ return mTaskbarActivityContext;
+ }
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
index 6e20398..0efec53 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
@@ -23,6 +23,7 @@
import android.annotation.Nullable;
import android.content.SharedPreferences;
import android.content.res.Resources;
+import android.view.ViewConfiguration;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
@@ -47,6 +48,22 @@
private static final float STASHED_TASKBAR_SCALE = 0.5f;
/**
+ * How long the hint animation plays, starting on motion down.
+ */
+ private static final long TASKBAR_HINT_STASH_DURATION =
+ ViewConfiguration.DEFAULT_LONG_PRESS_TIMEOUT;
+
+ /**
+ * The scale that TaskbarView animates to when hinting towards the stashed state.
+ */
+ private static final float STASHED_TASKBAR_HINT_SCALE = 0.9f;
+
+ /**
+ * The scale that the stashed handle animates to when hinting towards the unstashed state.
+ */
+ private static final float UNSTASHED_TASKBAR_HANDLE_HINT_SCALE = 1.1f;
+
+ /**
* The SharedPreferences key for whether user has manually stashed the taskbar.
*/
private static final String SHARED_PREFS_STASHED_KEY = "taskbar_is_stashed";
@@ -71,6 +88,7 @@
private AnimatedFloat mIconTranslationYForStash;
// Stashed handle properties.
private AnimatedFloat mTaskbarStashedHandleAlpha;
+ private AnimatedFloat mTaskbarStashedHandleHintScale;
/** Whether the user has manually invoked taskbar stashing, which we persist. */
private boolean mIsStashedInApp;
@@ -102,6 +120,7 @@
StashedHandleViewController stashedHandleController =
controllers.stashedHandleViewController;
mTaskbarStashedHandleAlpha = stashedHandleController.getStashedHandleAlpha();
+ mTaskbarStashedHandleHintScale = stashedHandleController.getStashedHandleHintScale();
mIsStashedInApp = supportsStashing()
&& mPrefs.getBoolean(SHARED_PREFS_STASHED_KEY, DEFAULT_STASHED_PREF);
@@ -114,7 +133,13 @@
* Returns whether the user can manually stash the taskbar based on the current device state.
*/
private boolean supportsStashing() {
- return !mActivity.isThreeButtonNav();
+ return !mActivity.isThreeButtonNav()
+ && (!Utilities.IS_RUNNING_IN_TEST_HARNESS || supportsStashingForTests());
+ }
+
+ private boolean supportsStashingForTests() {
+ // TODO: enable this for tests that specifically check stash/unstash behavior.
+ return false;
}
/**
@@ -240,6 +265,9 @@
if (stashedHandleRevealAnim != null) {
fullLengthAnimatorSet.play(stashedHandleRevealAnim);
}
+ // Return the stashed handle to its default scale in case it was changed as part of the
+ // feedforward hint. Note that the reveal animation above also visually scales it.
+ fullLengthAnimatorSet.play(mTaskbarStashedHandleHintScale.animateToValue(1f));
fullLengthAnimatorSet.setDuration(duration);
firstHalfAnimatorSet.setDuration((long) (duration * firstHalfDurationScale));
@@ -265,4 +293,36 @@
});
return mAnimator;
}
+
+ /**
+ * Creates and starts a partial stash animation, hinting at the new state that will trigger when
+ * long press is detected.
+ * @param animateForward Whether we are going towards the new stashed state or returning to the
+ * unstashed state.
+ */
+ public void startStashHint(boolean animateForward) {
+ if (isStashed() || !supportsStashing()) {
+ // Already stashed, no need to hint in that direction.
+ return;
+ }
+ mIconScaleForStash.animateToValue(
+ animateForward ? STASHED_TASKBAR_HINT_SCALE : 1)
+ .setDuration(TASKBAR_HINT_STASH_DURATION).start();
+ }
+
+ /**
+ * Creates and starts a partial unstash animation, hinting at the new state that will trigger
+ * when long press is detected.
+ * @param animateForward Whether we are going towards the new unstashed state or returning to
+ * the stashed state.
+ */
+ public void startUnstashHint(boolean animateForward) {
+ if (!isStashed()) {
+ // Already unstashed, no need to hint in that direction.
+ return;
+ }
+ mTaskbarStashedHandleHintScale.animateToValue(
+ animateForward ? UNSTASHED_TASKBAR_HANDLE_HINT_SCALE : 1)
+ .setDuration(TASKBAR_HINT_STASH_DURATION).start();
+ }
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java
index 6d0e3c6..260cedc 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java
@@ -33,8 +33,4 @@
}
protected void updateContentInsets(Rect outContentInsets) { }
-
- protected boolean onLongPressToUnstashTaskbar() {
- return false;
- }
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java
index 820d40a..a4a92f7 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java
@@ -194,24 +194,30 @@
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
int count = getChildCount();
int spaceNeeded = count * (mItemMarginLeftRight * 2 + mIconTouchSize);
- int iconStart = (right - left - spaceNeeded) / 2;
- int startOffset = ApiWrapper.getHotseatStartOffset(getContext());
- if (startOffset > iconStart) {
- int diff = startOffset - iconStart;
- iconStart = isLayoutRtl() ? (iconStart - diff) : iconStart + diff;
+ int navSpaceNeeded = ApiWrapper.getHotseatEndOffset(getContext());
+ boolean layoutRtl = isLayoutRtl();
+ int iconEnd = right - (right - left - spaceNeeded) / 2;
+ boolean needMoreSpaceForNav = layoutRtl ?
+ navSpaceNeeded > (iconEnd - spaceNeeded) :
+ iconEnd > (right - navSpaceNeeded);
+ if (needMoreSpaceForNav) {
+ int offset = layoutRtl ?
+ navSpaceNeeded - (iconEnd - spaceNeeded) :
+ (right - navSpaceNeeded) - iconEnd;
+ iconEnd += offset;
}
// Layout the children
- mIconLayoutBounds.left = iconStart;
+ mIconLayoutBounds.right = iconEnd;
mIconLayoutBounds.top = (bottom - top - mIconTouchSize) / 2;
mIconLayoutBounds.bottom = mIconLayoutBounds.top + mIconTouchSize;
- for (int i = 0; i < count; i++) {
- View child = getChildAt(i);
- iconStart += mItemMarginLeftRight;
- int iconEnd = iconStart + mIconTouchSize;
+ for (int i = count; i > 0; i--) {
+ View child = getChildAt(i - 1);
+ iconEnd -= mItemMarginLeftRight;
+ int iconStart = iconEnd - mIconTouchSize;
child.layout(iconStart, mIconLayoutBounds.top, iconEnd, mIconLayoutBounds.bottom);
- iconStart = iconEnd + mItemMarginLeftRight;
+ iconEnd = iconStart - mItemMarginLeftRight;
}
- mIconLayoutBounds.right = iconStart;
+ mIconLayoutBounds.left = iconEnd;
}
@Override
@@ -222,6 +228,15 @@
return super.dispatchTouchEvent(ev);
}
+ @Override
+ public boolean onTouchEvent(MotionEvent event) {
+ if (!mTouchEnabled) {
+ return true;
+ }
+ mControllerCallbacks.onTouchEvent(event);
+ return super.onTouchEvent(event);
+ }
+
public void setTouchesEnabled(boolean touchEnabled) {
this.mTouchEnabled = touchEnabled;
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
index 94c0ebe..6b95f08 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
@@ -17,14 +17,17 @@
import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY;
import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_X;
+import static com.android.launcher3.Utilities.squaredHypot;
import static com.android.launcher3.anim.Interpolators.LINEAR;
import static com.android.quickstep.AnimatedFloat.VALUE;
import android.graphics.Rect;
+import android.view.MotionEvent;
import android.view.View;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.LauncherAppState;
+import com.android.launcher3.Utilities;
import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.anim.PendingAnimation;
import com.android.launcher3.model.data.ItemInfo;
@@ -188,6 +191,11 @@
* Callbacks for {@link TaskbarView} to interact with its controller.
*/
public class TaskbarViewCallbacks {
+ private final float mSquaredTouchSlop = Utilities.squaredTouchSlop(mActivity);
+
+ private float mDownX, mDownY;
+ private boolean mCanceledStashHint;
+
public View.OnClickListener getIconOnClickListener() {
return mActivity::onTaskbarIconClicked;
}
@@ -199,5 +207,33 @@
public View.OnLongClickListener getBackgroundOnLongClickListener() {
return view -> mControllers.taskbarStashController.updateAndAnimateIsStashedInApp(true);
}
+
+ public void onTouchEvent(MotionEvent motionEvent) {
+ final float x = motionEvent.getRawX();
+ final float y = motionEvent.getRawY();
+ switch (motionEvent.getAction()) {
+ case MotionEvent.ACTION_DOWN:
+ mDownX = x;
+ mDownY = y;
+ mControllers.taskbarStashController.startStashHint(/* animateForward = */ true);
+ mCanceledStashHint = false;
+ break;
+ case MotionEvent.ACTION_MOVE:
+ if (!mCanceledStashHint
+ && squaredHypot(mDownX - x, mDownY - y) > mSquaredTouchSlop) {
+ mControllers.taskbarStashController.startStashHint(
+ /* animateForward= */ false);
+ mCanceledStashHint = true;
+ }
+ break;
+ case MotionEvent.ACTION_UP:
+ case MotionEvent.ACTION_CANCEL:
+ if (!mCanceledStashHint) {
+ mControllers.taskbarStashController.startStashHint(
+ /* animateForward= */ false);
+ }
+ break;
+ }
+ }
}
}
diff --git a/quickstep/src/com/android/launcher3/uioverrides/ApiWrapper.java b/quickstep/src/com/android/launcher3/uioverrides/ApiWrapper.java
index a595f54..85943b6 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/ApiWrapper.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/ApiWrapper.java
@@ -44,9 +44,9 @@
}
/**
- * Returns the minimum space that should be left empty at the start of hotseat
+ * Returns the minimum space that should be left empty at the end of hotseat
*/
- public static int getHotseatStartOffset(Context context) {
+ public static int getHotseatEndOffset(Context context) {
if (SysUINavigationMode.INSTANCE.get(context).getMode() == Mode.THREE_BUTTONS) {
Resources res = context.getResources();
return 2 * res.getDimensionPixelSize(R.dimen.taskbar_nav_buttons_spacing)
diff --git a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
index 830b7fa..357d407 100644
--- a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
+++ b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
@@ -546,7 +546,7 @@
@Override
public void onMotionPauseDetected() {
mHasMotionEverBeenPaused = true;
- maybeUpdateRecentsAttachedState();
+ maybeUpdateRecentsAttachedState(true/* animate */, true/* moveFocusedTask */);
performHapticFeedback();
}
@@ -557,18 +557,24 @@
};
}
- public void maybeUpdateRecentsAttachedState() {
+ private void maybeUpdateRecentsAttachedState() {
maybeUpdateRecentsAttachedState(true /* animate */);
}
+ private void maybeUpdateRecentsAttachedState(boolean animate) {
+ maybeUpdateRecentsAttachedState(animate, false /* moveFocusedTask */);
+ }
+
/**
* Determines whether to show or hide RecentsView. The window is always
* synchronized with its corresponding TaskView in RecentsView, so if
* RecentsView is shown, it will appear to be attached to the window.
*
* Note this method has no effect unless the navigation mode is NO_BUTTON.
+ * @param animate whether to animate when attaching RecentsView
+ * @param moveFocusedTask whether to move focused task to front when attaching
*/
- private void maybeUpdateRecentsAttachedState(boolean animate) {
+ private void maybeUpdateRecentsAttachedState(boolean animate, boolean moveFocusedTask) {
if (!mDeviceState.isFullyGesturalNavMode() || mRecentsView == null) {
return;
}
@@ -587,6 +593,12 @@
} else {
recentsAttachedToAppWindow = mHasMotionEverBeenPaused || mIsLikelyToStartNewTask;
}
+ if (moveFocusedTask && !mAnimationFactory.hasRecentsEverAttachedToAppWindow()
+ && recentsAttachedToAppWindow) {
+ // Only move focused task if RecentsView has never been attached before, to avoid
+ // TaskView jumping to new position as we move the tasks.
+ mRecentsView.moveFocusedTaskToFront();
+ }
mAnimationFactory.setRecentsAttachedToAppWindow(recentsAttachedToAppWindow, animate);
// Reapply window transform throughout the attach animation, as the animation affects how
diff --git a/quickstep/src/com/android/quickstep/BaseActivityInterface.java b/quickstep/src/com/android/quickstep/BaseActivityInterface.java
index 1412b1a..11fb1d0 100644
--- a/quickstep/src/com/android/quickstep/BaseActivityInterface.java
+++ b/quickstep/src/com/android/quickstep/BaseActivityInterface.java
@@ -267,20 +267,32 @@
Gravity.apply(Gravity.CENTER, outWidth, outHeight, potentialTaskRect, outRect);
}
- private PointF getTaskDimension(Context context, DeviceProfile dp) {
+ private static PointF getTaskDimension(Context context, DeviceProfile dp) {
PointF dimension = new PointF();
+ getTaskDimension(context, dp, dimension);
+ return dimension;
+ }
+
+ /**
+ * Gets the dimension of the task in the current system state.
+ */
+ public static void getTaskDimension(Context context, DeviceProfile dp, PointF out) {
if (dp.isMultiWindowMode) {
WindowBounds bounds = SplitScreenBounds.INSTANCE.getSecondaryWindowBounds(context);
- dimension.x = bounds.availableSize.x;
- dimension.y = bounds.availableSize.y;
+ if (TaskView.CLIP_STATUS_AND_NAV_BARS) {
+ out.x = bounds.availableSize.x;
+ out.y = bounds.availableSize.y;
+ } else {
+ out.x = bounds.availableSize.x + bounds.insets.left + bounds.insets.right;
+ out.y = bounds.availableSize.y + bounds.insets.top + bounds.insets.bottom;
+ }
} else if (TaskView.CLIP_STATUS_AND_NAV_BARS) {
- dimension.x = dp.availableWidthPx;
- dimension.y = dp.availableHeightPx;
+ out.x = dp.availableWidthPx;
+ out.y = dp.availableHeightPx;
} else {
- dimension.x = dp.widthPx;
- dimension.y = dp.heightPx;
+ out.x = dp.widthPx;
+ out.y = dp.heightPx;
}
- return dimension;
}
/**
@@ -364,14 +376,6 @@
}
/**
- * Called when we detect a long press in the nav region before passing the gesture slop.
- * @return Whether taskbar handled the long press, and thus should cancel the gesture.
- */
- public boolean onLongPressToUnstashTaskbar() {
- return false;
- }
-
- /**
* Returns the color of the scrim behind overview when at rest in this state.
* Return {@link Color#TRANSPARENT} for no scrim.
*/
@@ -396,6 +400,10 @@
default boolean isRecentsAttachedToAppWindow() {
return false;
}
+
+ default boolean hasRecentsEverAttachedToAppWindow() {
+ return false;
+ }
}
class DefaultAnimationFactory implements AnimationFactory {
@@ -405,6 +413,7 @@
private final Consumer<AnimatorControllerWithResistance> mCallback;
private boolean mIsAttachedToWindow;
+ private boolean mHasEverAttachedToWindow;
DefaultAnimationFactory(Consumer<AnimatorControllerWithResistance> callback) {
mCallback = callback;
@@ -458,6 +467,9 @@
}
mIsAttachedToWindow = attached;
RecentsView recentsView = mActivity.getOverviewPanel();
+ if (attached) {
+ mHasEverAttachedToWindow = true;
+ }
Animator fadeAnim = mActivity.getStateManager()
.createStateElementAnimation(INDEX_RECENTS_FADE_ANIM, attached ? 1 : 0);
@@ -487,6 +499,11 @@
return mIsAttachedToWindow;
}
+ @Override
+ public boolean hasRecentsEverAttachedToAppWindow() {
+ return mHasEverAttachedToWindow;
+ }
+
protected void createBackgroundToOverviewAnim(ACTIVITY_TYPE activity, PendingAnimation pa) {
// Scale down recents from being full screen to being in overview.
RecentsView recentsView = activity.getOverviewPanel();
diff --git a/quickstep/src/com/android/quickstep/LauncherActivityInterface.java b/quickstep/src/com/android/quickstep/LauncherActivityInterface.java
index 94a47e6..5deb75e 100644
--- a/quickstep/src/com/android/quickstep/LauncherActivityInterface.java
+++ b/quickstep/src/com/android/quickstep/LauncherActivityInterface.java
@@ -318,15 +318,6 @@
}
@Override
- public boolean onLongPressToUnstashTaskbar() {
- LauncherTaskbarUIController taskbarController = getTaskbarController();
- if (taskbarController == null) {
- return super.onLongPressToUnstashTaskbar();
- }
- return taskbarController.onLongPressToUnstashTaskbar();
- }
-
- @Override
protected int getOverviewScrimColorForState(BaseQuickstepLauncher launcher,
LauncherState state) {
return state.getWorkspaceScrimColor(launcher);
diff --git a/quickstep/src/com/android/quickstep/SystemUiProxy.java b/quickstep/src/com/android/quickstep/SystemUiProxy.java
index dac6981..11ca4b1 100644
--- a/quickstep/src/com/android/quickstep/SystemUiProxy.java
+++ b/quickstep/src/com/android/quickstep/SystemUiProxy.java
@@ -358,7 +358,7 @@
try {
mSystemUiProxy.setSplitScreenMinimized(minimized);
} catch (RemoteException e) {
- Log.w(TAG, "Failed call stopScreenPinning", e);
+ Log.w(TAG, "Failed call setSplitScreenMinimized", e);
}
}
}
diff --git a/quickstep/src/com/android/quickstep/TouchInteractionService.java b/quickstep/src/com/android/quickstep/TouchInteractionService.java
index af1a01a..b038c7b 100644
--- a/quickstep/src/com/android/quickstep/TouchInteractionService.java
+++ b/quickstep/src/com/android/quickstep/TouchInteractionService.java
@@ -307,7 +307,6 @@
return sConnected;
}
-
public static boolean isInitialized() {
return sIsInitialized;
}
@@ -680,7 +679,7 @@
StatefulActivity activity = activityInterface.getCreatedActivity();
if (activity != null && activity.getDeviceProfile().isTaskbarPresent) {
base = new TaskbarStashInputConsumer(this, base, mInputMonitorCompat,
- activityInterface);
+ mTaskbarManager.getCurrentActivityContext());
}
if (FeatureFlags.ENABLE_QUICK_CAPTURE_GESTURE.get()) {
diff --git a/quickstep/src/com/android/quickstep/inputconsumers/TaskbarStashInputConsumer.java b/quickstep/src/com/android/quickstep/inputconsumers/TaskbarStashInputConsumer.java
index 83f689f..dbe260a 100644
--- a/quickstep/src/com/android/quickstep/inputconsumers/TaskbarStashInputConsumer.java
+++ b/quickstep/src/com/android/quickstep/inputconsumers/TaskbarStashInputConsumer.java
@@ -15,12 +15,15 @@
*/
package com.android.quickstep.inputconsumers;
+import static com.android.launcher3.Utilities.squaredHypot;
+
import android.content.Context;
import android.view.GestureDetector;
import android.view.GestureDetector.SimpleOnGestureListener;
import android.view.MotionEvent;
-import com.android.quickstep.BaseActivityInterface;
+import com.android.launcher3.Utilities;
+import com.android.launcher3.taskbar.TaskbarActivityContext;
import com.android.quickstep.InputConsumer;
import com.android.systemui.shared.system.InputMonitorCompat;
@@ -29,13 +32,18 @@
*/
public class TaskbarStashInputConsumer extends DelegateInputConsumer {
- private final BaseActivityInterface mActivityInterface;
+ private final TaskbarActivityContext mTaskbarActivityContext;
private final GestureDetector mLongPressDetector;
+ private final float mSquaredTouchSlop;
+
+ private float mDownX, mDownY;
+ private boolean mCanceledUnstashHint;
public TaskbarStashInputConsumer(Context context, InputConsumer delegate,
- InputMonitorCompat inputMonitor, BaseActivityInterface activityInterface) {
+ InputMonitorCompat inputMonitor, TaskbarActivityContext taskbarActivityContext) {
super(delegate, inputMonitor);
- mActivityInterface = activityInterface;
+ mTaskbarActivityContext = taskbarActivityContext;
+ mSquaredTouchSlop = Utilities.squaredTouchSlop(context);
mLongPressDetector = new GestureDetector(context, new SimpleOnGestureListener() {
@Override
@@ -55,11 +63,41 @@
mLongPressDetector.onTouchEvent(ev);
if (mState != STATE_ACTIVE) {
mDelegate.onMotionEvent(ev);
+
+ if (mTaskbarActivityContext != null) {
+ final float x = ev.getRawX();
+ final float y = ev.getRawY();
+ switch (ev.getAction()) {
+ case MotionEvent.ACTION_DOWN:
+ mDownX = x;
+ mDownY = y;
+ mTaskbarActivityContext.startTaskbarUnstashHint(
+ /* animateForward = */ true);
+ mCanceledUnstashHint = false;
+ break;
+ case MotionEvent.ACTION_MOVE:
+ if (!mCanceledUnstashHint
+ && squaredHypot(mDownX - x, mDownY - y) > mSquaredTouchSlop) {
+ mTaskbarActivityContext.startTaskbarUnstashHint(
+ /* animateForward = */ false);
+ mCanceledUnstashHint = true;
+ }
+ break;
+ case MotionEvent.ACTION_UP:
+ case MotionEvent.ACTION_CANCEL:
+ if (!mCanceledUnstashHint) {
+ mTaskbarActivityContext.startTaskbarUnstashHint(
+ /* animateForward = */ false);
+ }
+ break;
+ }
+ }
}
}
private void onLongPressDetected(MotionEvent motionEvent) {
- if (mActivityInterface.onLongPressToUnstashTaskbar()) {
+ if (mTaskbarActivityContext != null
+ && mTaskbarActivityContext.onLongPressToUnstashTaskbar()) {
setActive(motionEvent);
}
}
diff --git a/quickstep/src/com/android/quickstep/util/RecentsOrientedState.java b/quickstep/src/com/android/quickstep/util/RecentsOrientedState.java
index c515bdf..7cfd151 100644
--- a/quickstep/src/com/android/quickstep/util/RecentsOrientedState.java
+++ b/quickstep/src/com/android/quickstep/util/RecentsOrientedState.java
@@ -25,6 +25,7 @@
import static com.android.launcher3.states.RotationHelper.ALLOW_ROTATION_PREFERENCE_KEY;
import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
import static com.android.launcher3.util.SettingsCache.ROTATION_SETTING_URI;
+import static com.android.quickstep.BaseActivityInterface.getTaskDimension;
import static java.lang.annotation.RetentionPolicy.SOURCE;
@@ -49,7 +50,6 @@
import com.android.launcher3.touch.PagedOrientationHandler;
import com.android.launcher3.util.DisplayController;
import com.android.launcher3.util.SettingsCache;
-import com.android.launcher3.util.WindowBounds;
import com.android.quickstep.BaseActivityInterface;
import com.android.quickstep.SystemUiProxy;
import com.android.quickstep.views.TaskView;
@@ -401,12 +401,7 @@
fullHeight -= insets.top + insets.bottom;
}
- if (dp.isMultiWindowMode) {
- WindowBounds bounds = SplitScreenBounds.INSTANCE.getSecondaryWindowBounds(mContext);
- outPivot.set(bounds.availableSize.x, bounds.availableSize.y);
- } else {
- outPivot.set(fullWidth, fullHeight);
- }
+ getTaskDimension(mContext, dp, outPivot);
float scale = Math.min(outPivot.x / taskView.width(), outPivot.y / taskView.height());
// We also scale the preview as part of fullScreenParams, so account for that as well.
if (fullWidth > 0) {
diff --git a/quickstep/src/com/android/quickstep/views/AllAppsEduView.java b/quickstep/src/com/android/quickstep/views/AllAppsEduView.java
index f67940a..04a7baa 100644
--- a/quickstep/src/com/android/quickstep/views/AllAppsEduView.java
+++ b/quickstep/src/com/android/quickstep/views/AllAppsEduView.java
@@ -17,13 +17,10 @@
import static com.android.launcher3.LauncherState.ALL_APPS;
import static com.android.launcher3.LauncherState.NORMAL;
-import static com.android.launcher3.anim.Interpolators.ACCEL;
import static com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN;
import static com.android.launcher3.anim.Interpolators.LINEAR;
import static com.android.launcher3.anim.Interpolators.OVERSHOOT_1_7;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ALL_APPS_EDU_SHOWN;
-import static com.android.launcher3.states.StateAnimationConfig.ANIM_ALL_APPS_FADE;
-import static com.android.launcher3.states.StateAnimationConfig.ANIM_SCRIM_FADE;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
@@ -35,7 +32,7 @@
import android.graphics.drawable.GradientDrawable;
import android.util.AttributeSet;
import android.view.MotionEvent;
-import android.view.ViewGroup;
+import android.view.View;
import androidx.core.graphics.ColorUtils;
@@ -44,25 +41,21 @@
import com.android.launcher3.Launcher;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
-import com.android.launcher3.allapps.AllAppsTransitionController;
import com.android.launcher3.anim.AnimatorPlaybackController;
-import com.android.launcher3.anim.Interpolators;
-import com.android.launcher3.anim.PendingAnimation;
import com.android.launcher3.dragndrop.DragLayer;
-import com.android.launcher3.states.StateAnimationConfig;
+import com.android.launcher3.uioverrides.touchcontrollers.PortraitStatesTouchController;
import com.android.launcher3.util.Themes;
import com.android.quickstep.util.MultiValueUpdateListener;
/**
* View used to educate the user on how to access All Apps when in No Nav Button navigation mode.
- * Consumes all touches until after the animation is completed and the view is removed.
+ * If the user drags on the view, the animation is overridden so the user can swipe to All Apps or
+ * Home.
*/
public class AllAppsEduView extends AbstractFloatingView {
- private static final float HINT_PROG_SCRIM_THRESHOLD = 0.06f;
- private static final float HINT_PROG_CONTENT_THRESHOLD = 0.08f;
-
private Launcher mLauncher;
+ private AllAppsEduTouchController mTouchController;
private AnimatorSet mAnimation;
@@ -124,7 +117,34 @@
}
@Override
+ public boolean onControllerTouchEvent(MotionEvent ev) {
+ mTouchController.onControllerTouchEvent(ev);
+ if (mAnimation != null) {
+ updateAnimationOnTouchEvent(ev);
+ }
+ return super.onControllerTouchEvent(ev);
+ }
+
+ private void updateAnimationOnTouchEvent(MotionEvent ev) {
+ switch (ev.getActionMasked()) {
+ case MotionEvent.ACTION_DOWN:
+ mAnimation.pause();
+ return;
+ case MotionEvent.ACTION_UP:
+ case MotionEvent.ACTION_CANCEL:
+ mAnimation.resume();
+ return;
+ }
+
+ if (mTouchController.isDraggingOrSettling()) {
+ mAnimation = null;
+ handleClose(false);
+ }
+ }
+
+ @Override
public boolean onControllerInterceptTouchEvent(MotionEvent ev) {
+ mTouchController.onControllerInterceptTouchEvent(ev);
return true;
}
@@ -145,23 +165,9 @@
int secondPart = 1200;
int introDuration = firstPart + secondPart;
- StateAnimationConfig config = new StateAnimationConfig();
- config.setInterpolator(ANIM_ALL_APPS_FADE, Interpolators.clampToProgress(ACCEL,
- HINT_PROG_SCRIM_THRESHOLD, HINT_PROG_CONTENT_THRESHOLD));
- config.setInterpolator(ANIM_SCRIM_FADE,
- Interpolators.clampToProgress(ACCEL, 0, HINT_PROG_CONTENT_THRESHOLD));
- config.duration = secondPart;
- config.userControlled = false;
AnimatorPlaybackController stateAnimationController =
- mLauncher.getStateManager().createAnimationToNewWorkspace(ALL_APPS, config);
- float maxAllAppsProgress = mLauncher.getDeviceProfile().isLandscape ? 0.35f : 0.15f;
-
- AllAppsTransitionController allAppsController = mLauncher.getAllAppsController();
- PendingAnimation allAppsAlpha = new PendingAnimation(config.duration);
- allAppsController.setAlphas(ALL_APPS, config, allAppsAlpha);
- mLauncher.getWorkspace().getStateTransitionAnimation().setScrim(allAppsAlpha, ALL_APPS,
- config);
- mAnimation.play(allAppsAlpha.buildAnim());
+ mTouchController.initAllAppsAnimation();
+ float maxAllAppsProgress = 0.75f;
ValueAnimator intro = ValueAnimator.ofFloat(0, 1f);
intro.setInterpolator(LINEAR);
@@ -198,6 +204,7 @@
mGradient.setAlpha(0);
}
});
+ mLauncher.getAppsView().setVisibility(View.VISIBLE);
mAnimation.play(intro);
ValueAnimator closeAllApps = ValueAnimator.ofFloat(maxAllAppsProgress, 0f);
@@ -223,6 +230,7 @@
private void init(Launcher launcher) {
mLauncher = launcher;
+ mTouchController = new AllAppsEduTouchController(mLauncher);
int accentColor = Themes.getColorAccent(launcher);
mGradient = new GradientDrawable(GradientDrawable.Orientation.TOP_BOTTOM,
@@ -250,9 +258,8 @@
*/
public static void show(Launcher launcher) {
final DragLayer dragLayer = launcher.getDragLayer();
- ViewGroup parent = (ViewGroup) dragLayer.getParent();
- AllAppsEduView view = launcher.getViewCache().getView(R.layout.all_apps_edu_view,
- launcher, parent);
+ AllAppsEduView view = (AllAppsEduView) launcher.getLayoutInflater().inflate(
+ R.layout.all_apps_edu_view, dragLayer, false);
view.init(launcher);
launcher.getDragLayer().addView(view);
launcher.getStatsLogManager().logger().log(LAUNCHER_ALL_APPS_EDU_SHOWN);
@@ -260,4 +267,27 @@
view.requestLayout();
view.playAnimation();
}
+
+ private static class AllAppsEduTouchController extends PortraitStatesTouchController {
+
+ private AllAppsEduTouchController(Launcher l) {
+ super(l);
+ }
+
+ @Override
+ protected boolean canInterceptTouch(MotionEvent ev) {
+ return true;
+ }
+
+ private AnimatorPlaybackController initAllAppsAnimation() {
+ mFromState = NORMAL;
+ mToState = ALL_APPS;
+ mProgressMultiplier = initCurrentAnimation();
+ return mCurrentAnimation;
+ }
+
+ private boolean isDraggingOrSettling() {
+ return mDetector.isDraggingOrSettling();
+ }
+ }
}
diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java
index 6844f9f..edda439 100644
--- a/quickstep/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/RecentsView.java
@@ -563,6 +563,10 @@
* removed from recentsView
*/
private int mSplitHiddenTaskViewIndex;
+ /**
+ * The task to be removed and immediately re-added. Should not be added to task pool.
+ */
+ private TaskView mMovingTaskView;
// Keeps track of the index where the first TaskView should be
private int mTaskViewStartIndex = 0;
@@ -826,9 +830,12 @@
public void onViewRemoved(View child) {
super.onViewRemoved(child);
- // Clear the task data for the removed child if it was visible unless it's the initial
- // taskview for entering split screen, we only pretend to dismiss the task
- if (child instanceof TaskView && child != mSplitHiddenTaskView) {
+ // Clear the task data for the removed child if it was visible unless:
+ // - It's the initial taskview for entering split screen, we only pretend to dismiss the
+ // task
+ // - It's the focused task to be moved to the front, we immediately re-add the task
+ if (child instanceof TaskView && child != mSplitHiddenTaskView
+ && child != mMovingTaskView) {
TaskView taskView = (TaskView) child;
mHasVisibleTaskData.delete(taskView.getTaskId());
mTaskViewPool.recycle(taskView);
@@ -1121,6 +1128,42 @@
}
}
+ /**
+ * Moves the focused task to the front of the carousel in tablets, to minimize animation
+ * required to focus the task in grid.
+ */
+ public void moveFocusedTaskToFront() {
+ if (!(mActivity.getDeviceProfile().isTablet && FeatureFlags.ENABLE_OVERVIEW_GRID.get())) {
+ return;
+ }
+
+ TaskView focusedTaskView = getFocusedTaskView();
+ if (focusedTaskView == null) {
+ return;
+ }
+
+ if (indexOfChild(focusedTaskView) != mCurrentPage) {
+ return;
+ }
+
+ if (mCurrentPage == mTaskViewStartIndex) {
+ return;
+ }
+
+ int primaryScroll = mOrientationHandler.getPrimaryScroll(this);
+ int currentPageScroll = getScrollForPage(mCurrentPage);
+ mCurrentPageScrollDiff = primaryScroll - currentPageScroll;
+
+ mMovingTaskView = focusedTaskView;
+ removeView(focusedTaskView);
+ mMovingTaskView = null;
+ focusedTaskView.onRecycle();
+ addView(focusedTaskView, mTaskViewStartIndex);
+ setCurrentPage(mTaskViewStartIndex);
+
+ updateGridProperties();
+ }
+
protected void applyLoadPlan(ArrayList<Task> tasks) {
if (mPendingAnimation != null) {
mPendingAnimation.addEndListener(success -> applyLoadPlan(tasks));
@@ -1542,7 +1585,8 @@
* and unloads the associated task data for tasks that are no longer visible.
*/
public void loadVisibleTaskData(@TaskView.TaskDataChanges int dataChanges) {
- if (!mOverviewStateEnabled || mTaskListChangeId == -1) {
+ boolean hasLeftOverview = !mOverviewStateEnabled && mScroller.isFinished();
+ if (hasLeftOverview || mTaskListChangeId == -1) {
// Skip loading visible task data if we've already left the overview state, or if the
// task list hasn't been loaded yet (the task views will not reflect the task list)
return;
@@ -1791,7 +1835,7 @@
.displayOverviewTasksAsGrid(mActivity.getDeviceProfile())) {
TaskView runningTaskView = getRunningTaskView();
float runningTaskPrimaryGridTranslation = 0;
- if (indexOfChild(runningTaskView) != getNextPage()) {
+ if (runningTaskView != null && indexOfChild(runningTaskView) != getNextPage()) {
// Apply the gird translation to running task unless it's being snapped to.
runningTaskPrimaryGridTranslation = mOrientationHandler.getPrimaryValue(
runningTaskView.getGridTranslationX(),
@@ -2599,6 +2643,7 @@
}
protected void onDismissAnimationEnds() {
+ AccessibilityManagerCompat.sendDismissAnimationEndsEventToTest(getContext());
}
public PendingAnimation createAllTasksDismissAnimation(long duration) {
@@ -3088,6 +3133,9 @@
splitController.getLayoutParamsForActivePosition(getResources(),
mActivity.getDeviceProfile()));
mSplitPlaceholderView.setIcon(taskView.getIconView());
+ if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
+ finishRecentsAnimation(true, null);
+ }
}
public PendingAnimation createSplitSelectInitAnimation() {
diff --git a/quickstep/src/com/android/quickstep/views/TaskView.java b/quickstep/src/com/android/quickstep/views/TaskView.java
index 2e154f6..159052a 100644
--- a/quickstep/src/com/android/quickstep/views/TaskView.java
+++ b/quickstep/src/com/android/quickstep/views/TaskView.java
@@ -531,6 +531,9 @@
if (getTask() == null) {
return;
}
+ if (confirmSecondSplitSelectApp()) {
+ return;
+ }
if (ENABLE_QUICKSTEP_LIVE_TILE.get() && isRunningTask()) {
if (!mIsClickableAsLiveTile) {
return;
@@ -549,7 +552,7 @@
if (targets == null) {
// If the recents animation is cancelled somehow between the parent if block and
// here, try to launch the task as a non live tile task.
- launcherNonLiveTileTask();
+ launchTaskAnimated();
return;
}
@@ -567,19 +570,22 @@
});
anim.start();
} else {
- launcherNonLiveTileTask();
+ launchTaskAnimated();
}
mActivity.getStatsLogManager().logger().withItemInfo(getItemInfo())
.log(LAUNCHER_TASK_LAUNCH_TAP);
}
- private void launcherNonLiveTileTask() {
- if (mActivity.isInState(OVERVIEW_SPLIT_SELECT)) {
- // User tapped to select second split screen app
+ /**
+ * @return {@code true} if user is already in split select mode and this tap was to choose the
+ * second app. {@code false} otherwise
+ */
+ private boolean confirmSecondSplitSelectApp() {
+ boolean isSelectingSecondSplitApp = mActivity.isInState(OVERVIEW_SPLIT_SELECT);
+ if (isSelectingSecondSplitApp) {
getRecentsView().confirmSplitSelect(this);
- } else {
- launchTaskAnimated();
}
+ return isSelectingSecondSplitApp;
}
/**
diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java
index 624862d..edd44e3 100644
--- a/src/com/android/launcher3/DeviceProfile.java
+++ b/src/com/android/launcher3/DeviceProfile.java
@@ -777,7 +777,7 @@
int taskbarOffset = getTaskbarOffsetY();
int hotseatTopDiff = hotseatHeight - taskbarSize - taskbarOffset;
- int startOffset = ApiWrapper.getHotseatStartOffset(context);
+ int endOffset = ApiWrapper.getHotseatEndOffset(context);
int requiredWidth = iconSizePx * numShownHotseatIcons;
Resources res = context.getResources();
@@ -785,16 +785,16 @@
float taskbarIconSpacing = 2 * res.getDimension(R.dimen.taskbar_icon_spacing);
int maxSize = (int) (requiredWidth
* (taskbarIconSize + taskbarIconSpacing) / taskbarIconSize);
- int hotseatSize = Math.min(maxSize, availableWidthPx - startOffset);
+ int hotseatSize = Math.min(maxSize, availableWidthPx - endOffset);
int sideSpacing = (availableWidthPx - hotseatSize) / 2;
mHotseatPadding.set(sideSpacing, hotseatTopDiff, sideSpacing, taskbarOffset);
- if (startOffset > sideSpacing) {
+ if (endOffset > sideSpacing) {
int diff = Utilities.isRtl(context.getResources())
- ? sideSpacing - startOffset
- : startOffset - sideSpacing;
- mHotseatPadding.left += diff;
- mHotseatPadding.right -= diff;
+ ? sideSpacing - endOffset
+ : endOffset - sideSpacing;
+ mHotseatPadding.left -= diff;
+ mHotseatPadding.right += diff;
}
} else {
// We want the edges of the hotseat to line up with the edges of the workspace, but the
diff --git a/src/com/android/launcher3/allapps/AllAppsStore.java b/src/com/android/launcher3/allapps/AllAppsStore.java
index 2443b83..7bc3eec 100644
--- a/src/com/android/launcher3/allapps/AllAppsStore.java
+++ b/src/com/android/launcher3/allapps/AllAppsStore.java
@@ -132,7 +132,7 @@
}
public void registerIconContainer(ViewGroup container) {
- if (container != null) {
+ if (container != null && !mIconContainers.contains(container)) {
mIconContainers.add(container);
}
}
diff --git a/src/com/android/launcher3/allapps/DiscoveryBounce.java b/src/com/android/launcher3/allapps/DiscoveryBounce.java
index d8ef18e..be261f7 100644
--- a/src/com/android/launcher3/allapps/DiscoveryBounce.java
+++ b/src/com/android/launcher3/allapps/DiscoveryBounce.java
@@ -20,16 +20,17 @@
import android.animation.Animator;
import android.animation.AnimatorInflater;
-import android.animation.AnimatorListenerAdapter;
import android.os.Handler;
import android.os.UserManager;
import android.view.MotionEvent;
+import android.view.View;
import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherState;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
+import com.android.launcher3.anim.AnimatorListeners;
import com.android.launcher3.statemanager.StateManager.StateListener;
import com.android.launcher3.util.OnboardingPrefs;
@@ -53,21 +54,15 @@
public void onStateTransitionComplete(LauncherState finalState) {}
};
- public DiscoveryBounce(Launcher launcher, float delta) {
+ public DiscoveryBounce(Launcher launcher) {
super(launcher, null);
mLauncher = launcher;
- AllAppsTransitionController controller = mLauncher.getAllAppsController();
mDiscoBounceAnimation =
AnimatorInflater.loadAnimator(launcher, R.animator.discovery_bounce);
- mDiscoBounceAnimation.setTarget(new VerticalProgressWrapper(controller, delta));
- mDiscoBounceAnimation.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- handleClose(false);
- }
- });
- mDiscoBounceAnimation.addListener(controller.getProgressAnimatorListener());
+ mDiscoBounceAnimation.setTarget(new VerticalProgressWrapper(
+ launcher.getHotseat(), mLauncher.getDragLayer().getHeight()));
+ mDiscoBounceAnimation.addListener(AnimatorListeners.forEndCallback(this::handleClose));
launcher.getStateManager().addStateListener(mStateListener);
}
@@ -104,9 +99,9 @@
if (mIsOpen) {
mIsOpen = false;
mLauncher.getDragLayer().removeView(this);
- // Reset the all-apps progress to what ever it was previously.
- mLauncher.getAllAppsController().setProgress(mLauncher.getStateManager()
- .getState().getVerticalProgress(mLauncher));
+ // Reset the translation to what ever it was previously.
+ mLauncher.getHotseat().setTranslationY(mLauncher.getStateManager().getState()
+ .getHotseatScaleAndTranslation(mLauncher).translationY);
mLauncher.getStateManager().removeStateListener(mStateListener);
}
}
@@ -141,29 +136,28 @@
return;
}
onboardingPrefs.incrementEventCount(OnboardingPrefs.HOME_BOUNCE_COUNT);
-
- new DiscoveryBounce(launcher, 0).show();
+ new DiscoveryBounce(launcher).show();
}
/**
- * A wrapper around {@link AllAppsTransitionController} allowing a fixed shift in the value.
+ * A wrapper around hotseat animator allowing a fixed shift in the value.
*/
public static class VerticalProgressWrapper {
- private final float mDelta;
- private final AllAppsTransitionController mController;
+ private final View mView;
+ private final float mLimit;
- private VerticalProgressWrapper(AllAppsTransitionController controller, float delta) {
- mController = controller;
- mDelta = delta;
+ private VerticalProgressWrapper(View view, float limit) {
+ mView = view;
+ mLimit = limit;
}
public float getProgress() {
- return mController.getProgress() + mDelta;
+ return 1 + mView.getTranslationY() / mLimit;
}
public void setProgress(float progress) {
- mController.setProgress(progress - mDelta);
+ mView.setTranslationY(mLimit * (progress - 1));
}
}
}
diff --git a/src/com/android/launcher3/compat/AccessibilityManagerCompat.java b/src/com/android/launcher3/compat/AccessibilityManagerCompat.java
index 92bc19a..97052b2 100644
--- a/src/com/android/launcher3/compat/AccessibilityManagerCompat.java
+++ b/src/com/android/launcher3/compat/AccessibilityManagerCompat.java
@@ -87,7 +87,14 @@
if (accessibilityManager == null) return;
sendEventToTest(accessibilityManager, context, TestProtocol.PAUSE_DETECTED_MESSAGE, null);
- Log.d(TestProtocol.HOME_TO_OVERVIEW_FLAKY, "sendPauseDetectedEventToTest");
+ }
+
+ public static void sendDismissAnimationEndsEventToTest(Context context) {
+ final AccessibilityManager accessibilityManager = getAccessibilityManagerForTest(context);
+ if (accessibilityManager == null) return;
+
+ sendEventToTest(accessibilityManager, context, TestProtocol.DISMISS_ANIMATION_ENDS_MESSAGE,
+ null);
}
private static void sendEventToTest(
diff --git a/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java b/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java
index 1da8028..94778a2 100644
--- a/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java
+++ b/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java
@@ -15,6 +15,7 @@
*/
package com.android.launcher3.graphics;
+import static android.app.WallpaperManager.FLAG_SYSTEM;
import static android.view.View.MeasureSpec.EXACTLY;
import static android.view.View.MeasureSpec.makeMeasureSpec;
import static android.view.View.VISIBLE;
@@ -27,6 +28,7 @@
import android.annotation.TargetApi;
import android.app.Fragment;
import android.app.WallpaperColors;
+import android.app.WallpaperManager;
import android.appwidget.AppWidgetHost;
import android.appwidget.AppWidgetHostView;
import android.appwidget.AppWidgetProviderInfo;
@@ -214,7 +216,7 @@
public LauncherPreviewRenderer(Context context,
InvariantDeviceProfile idp,
- WallpaperColors wallpaperColors) {
+ WallpaperColors wallpaperColorsOverride) {
super(context);
mUiHandler = new Handler(Looper.getMainLooper());
@@ -280,16 +282,18 @@
mDp.workspacePadding.bottom);
mWorkspaceScreens.put(FIRST_SCREEN_ID, firstScreen);
- if (FeatureFlags.WIDGETS_IN_LAUNCHER_PREVIEW.get()) {
- mAppWidgetHost = new LauncherPreviewAppWidgetHost(context);
- mWallpaperColorResources = wallpaperColors != null
- ? LocalColorExtractor.newInstance(context)
- .generateColorsOverride(wallpaperColors)
- : null;
+ if (Utilities.ATLEAST_S) {
+ WallpaperColors wallpaperColors = wallpaperColorsOverride != null
+ ? wallpaperColorsOverride
+ : WallpaperManager.getInstance(context).getWallpaperColors(FLAG_SYSTEM);
+ mWallpaperColorResources = LocalColorExtractor.newInstance(context)
+ .generateColorsOverride(wallpaperColors);
} else {
- mAppWidgetHost = null;
mWallpaperColorResources = null;
}
+ mAppWidgetHost = FeatureFlags.WIDGETS_IN_LAUNCHER_PREVIEW.get()
+ ? new LauncherPreviewAppWidgetHost(context)
+ : null;
}
/** Populate preview and render it. */
@@ -405,6 +409,10 @@
view.updateAppWidget(null);
}
+ if (mWallpaperColorResources != null) {
+ view.setColorResources(mWallpaperColorResources);
+ }
+
view.setTag(info);
addInScreenFromBind(view, info);
}
@@ -537,12 +545,9 @@
}
}
- private class LauncherPreviewAppWidgetHostView extends BaseLauncherAppWidgetHostView {
+ private static class LauncherPreviewAppWidgetHostView extends BaseLauncherAppWidgetHostView {
private LauncherPreviewAppWidgetHostView(Context context) {
super(context);
- if (Utilities.ATLEAST_S && mWallpaperColorResources != null) {
- setColorResources(mWallpaperColorResources);
- }
}
@Override
diff --git a/src/com/android/launcher3/testing/TestProtocol.java b/src/com/android/launcher3/testing/TestProtocol.java
index a9d3998..65bec25 100644
--- a/src/com/android/launcher3/testing/TestProtocol.java
+++ b/src/com/android/launcher3/testing/TestProtocol.java
@@ -24,6 +24,7 @@
public static final String SWITCHED_TO_STATE_MESSAGE = "TAPL_SWITCHED_TO_STATE";
public static final String SCROLL_FINISHED_MESSAGE = "TAPL_SCROLL_FINISHED";
public static final String PAUSE_DETECTED_MESSAGE = "TAPL_PAUSE_DETECTED";
+ public static final String DISMISS_ANIMATION_ENDS_MESSAGE = "TAPL_DISMISS_ANIMATION_ENDS";
public static final int NORMAL_STATE_ORDINAL = 0;
public static final int SPRING_LOADED_STATE_ORDINAL = 1;
public static final int OVERVIEW_STATE_ORDINAL = 2;
@@ -111,5 +112,4 @@
public static final String PERMANENT_DIAG_TAG = "TaplTarget";
public static final String WORK_PROFILE_REMOVED = "b/159671700";
public static final String FALLBACK_ACTIVITY_NO_SET = "b/181019015";
- public static final String HOME_TO_OVERVIEW_FLAKY = "b/193440212";
}
diff --git a/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java b/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java
index 90f37f3..5f8a4d4 100644
--- a/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java
+++ b/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java
@@ -65,12 +65,12 @@
protected LauncherState mToState;
protected AnimatorPlaybackController mCurrentAnimation;
protected boolean mGoingBetweenStates = true;
+ // Ratio of transition process [0, 1] to drag displacement (px)
+ protected float mProgressMultiplier;
private boolean mNoIntercept;
private boolean mIsLogContainerSet;
private float mStartProgress;
- // Ratio of transition process [0, 1] to drag displacement (px)
- private float mProgressMultiplier;
private float mDisplacementShift;
private boolean mCanBlockFling;
private boolean mAllAppsOvershootStarted;
diff --git a/src/com/android/launcher3/views/FloatingIconView.java b/src/com/android/launcher3/views/FloatingIconView.java
index 3027db6..872adec 100644
--- a/src/com/android/launcher3/views/FloatingIconView.java
+++ b/src/com/android/launcher3/views/FloatingIconView.java
@@ -580,11 +580,6 @@
if (originalView instanceof IconLabelDotView) {
setIconAndDotVisible(originalView, true);
}
- if (originalView instanceof BubbleTextView) {
- BubbleTextView btv = (BubbleTextView) originalView;
- btv.setIconVisible(true);
- btv.setForceHideDot(true);
- }
view.finish(dragLayer);
}
} else {
diff --git a/src/com/android/launcher3/views/RecyclerViewFastScroller.java b/src/com/android/launcher3/views/RecyclerViewFastScroller.java
index a88b8b7..1c2534d 100644
--- a/src/com/android/launcher3/views/RecyclerViewFastScroller.java
+++ b/src/com/android/launcher3/views/RecyclerViewFastScroller.java
@@ -278,12 +278,7 @@
mIgnoreDragGesture |= absDeltaY > mConfig.getScaledPagingTouchSlop();
if (!mIsDragging && !mIgnoreDragGesture && mRv.supportsFastScrolling()) {
- // condition #1: triggering thumb is distance, angle based
- if ((isNearThumb(mDownX, mLastY)
- && absDeltaY > mConfig.getScaledPagingTouchSlop()
- && absDeltaY > absDeltaX)
- // condition#2: Fastscroll function is now time based
- || (isNearScrollBar(mDownX) && ev.getEventTime() - mDownTimeStampMillis
+ if ((isNearThumb(mDownX, mLastY) && ev.getEventTime() - mDownTimeStampMillis
> FASTSCROLL_THRESHOLD_MILLIS)) {
calcTouchOffsetAndPrepToFastScroll(mDownY, mLastY);
}
@@ -433,9 +428,6 @@
}
private void updatePopupY(int lastTouchY) {
- if (!mPopupVisible) {
- return;
- }
int height = mPopupView.getHeight();
// Aligns the rounded corner of the pop up with the top of the thumb.
float top = mRv.getScrollBarTop() + lastTouchY + (getScrollThumbRadius() / 2f)
diff --git a/src/com/android/launcher3/widget/PendingAppWidgetHostView.java b/src/com/android/launcher3/widget/PendingAppWidgetHostView.java
index 47f30be..d3a0190 100644
--- a/src/com/android/launcher3/widget/PendingAppWidgetHostView.java
+++ b/src/com/android/launcher3/widget/PendingAppWidgetHostView.java
@@ -85,7 +85,6 @@
setBackgroundResource(R.drawable.pending_widget_bg);
setWillNotDraw(false);
- setElevation(getResources().getDimension(R.dimen.pending_widget_elevation));
updateAppWidget(null);
setOnClickListener(ItemClickHandler.INSTANCE);
diff --git a/src_ui_overrides/com/android/launcher3/uioverrides/ApiWrapper.java b/src_ui_overrides/com/android/launcher3/uioverrides/ApiWrapper.java
index c606861..cc90e6c 100644
--- a/src_ui_overrides/com/android/launcher3/uioverrides/ApiWrapper.java
+++ b/src_ui_overrides/com/android/launcher3/uioverrides/ApiWrapper.java
@@ -39,9 +39,9 @@
}
/**
- * Returns the minimum space that should be left empty at the start of hotseat
+ * Returns the minimum space that should be left empty at the end of hotseat
*/
- public static int getHotseatStartOffset(Context context) {
+ public static int getHotseatEndOffset(Context context) {
return 0;
}
}
diff --git a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
index 5e57df6..bf4eba0 100644
--- a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
+++ b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
@@ -128,9 +128,6 @@
}
public static void checkDetectedLeaks(LauncherInstrumentation launcher) {
- // TODO(b/191449914): Temporarily disable leak detection on tablets until bug is resolved.
- if (launcher.isTablet()) return;
-
if (sActivityLeakReported) return;
if (sStrictmodeDetectedActivityLeak != null) {
diff --git a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
index ef809d5..1f64131 100644
--- a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
+++ b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
@@ -207,6 +207,11 @@
public LauncherInstrumentation(Instrumentation instrumentation) {
mInstrumentation = instrumentation;
mDevice = UiDevice.getInstance(instrumentation);
+ try {
+ mDevice.executeShellCommand("am wait-for-broadcast-idle");
+ } catch (IOException e) {
+ log("Failed to wait for broadcast idle");
+ }
// Launcher should run in test harness so that custom accessibility protocol between
// Launcher and TAPL is enabled. In-process tests enable this protocol with a direct call
@@ -509,9 +514,8 @@
void fail(String message) {
checkForAnomaly();
Assert.fail(formatSystemHealthMessage(formatErrorWithEvents(
- "http://go/tapl test failure:\nContext: " + getContextDescription()
- + " => resulting visible state is " + getVisibleStateMessage()
- + ";\nDetails: " + message, true)));
+ "http://go/tapl test failure: " + message + ";\nContext: " + getContextDescription()
+ + "; now visible state is " + getVisibleStateMessage(), true)));
}
private String getContextDescription() {
@@ -741,17 +745,13 @@
dumpViewHierarchy();
action = "swiping up to home";
- final boolean launcherIsVisible = isLauncherVisible();
swipeToState(
displaySize.x / 2, displaySize.y - 1,
displaySize.x / 2, 0,
ZERO_BUTTON_STEPS_FROM_BACKGROUND_TO_HOME, NORMAL_STATE_ORDINAL,
- launcherWasVisible
+ launcherWasVisible || isTablet()
? GestureScope.INSIDE_TO_OUTSIDE
: GestureScope.OUTSIDE_WITH_PILFER);
- // b/193653850: launcherWasVisible is a flaky indicator.
- log("launcherWasVisible: " + launcherWasVisible + ", launcherIsVisible: "
- + launcherIsVisible);
}
} else {
log("Hierarchy before clicking home:");
diff --git a/tests/tapl/com/android/launcher3/tapl/OverviewTask.java b/tests/tapl/com/android/launcher3/tapl/OverviewTask.java
index 657b74d..71c0abb 100644
--- a/tests/tapl/com/android/launcher3/tapl/OverviewTask.java
+++ b/tests/tapl/com/android/launcher3/tapl/OverviewTask.java
@@ -59,9 +59,14 @@
final Rect taskBounds = mLauncher.getVisibleBounds(mTask);
final int centerX = taskBounds.centerX();
final int centerY = taskBounds.centerY();
- mLauncher.linearGesture(centerX, centerY, centerX, 0, 10, false,
- LauncherInstrumentation.GestureScope.INSIDE);
- mLauncher.waitForIdle();
+ mLauncher.executeAndWaitForLauncherEvent(
+ () -> mLauncher.linearGesture(centerX, centerY, centerX, 0, 10, false,
+ LauncherInstrumentation.GestureScope.INSIDE),
+ event -> TestProtocol.DISMISS_ANIMATION_ENDS_MESSAGE.equals(
+ event.getClassName()),
+ () -> "Didn't receive a dismiss animation ends message: " + centerX + ", "
+ + centerY,
+ "swiping to dismiss");
}
}