mirror of
https://github.com/LawnchairLauncher/lawnchair.git
synced 2026-02-19 18:58:19 +00:00
Merge "Predictive back: widget to all apps" into tm-qpr-dev
This commit is contained in:
@@ -194,7 +194,8 @@ public class TaskbarDragLayer extends BaseDragLayer<TaskbarActivityContext> {
|
||||
public boolean dispatchKeyEvent(KeyEvent event) {
|
||||
if (event.getAction() == ACTION_UP && event.getKeyCode() == KEYCODE_BACK) {
|
||||
AbstractFloatingView topView = AbstractFloatingView.getTopOpenView(mActivity);
|
||||
if (topView != null && topView.onBackPressed()) {
|
||||
if (topView != null && topView.canHandleBack()) {
|
||||
topView.onBackInvoked();
|
||||
// Handled by the floating view.
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -71,7 +71,8 @@ public class TaskbarOverlayDragLayer extends
|
||||
public boolean dispatchKeyEvent(KeyEvent event) {
|
||||
if (event.getAction() == ACTION_UP && event.getKeyCode() == KEYCODE_BACK) {
|
||||
AbstractFloatingView topView = AbstractFloatingView.getTopOpenView(mActivity);
|
||||
if (topView != null && topView.onBackPressed()) {
|
||||
if (topView != null && topView.canHandleBack()) {
|
||||
topView.onBackInvoked();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -84,6 +84,7 @@ import com.android.launcher3.DeviceProfile;
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.LauncherSettings.Favorites;
|
||||
import com.android.launcher3.LauncherState;
|
||||
import com.android.launcher3.OnBackPressedHandler;
|
||||
import com.android.launcher3.QuickstepAccessibilityDelegate;
|
||||
import com.android.launcher3.QuickstepTransitionManager;
|
||||
import com.android.launcher3.R;
|
||||
@@ -638,20 +639,49 @@ public class QuickstepLauncher extends Launcher {
|
||||
getOnBackInvokedDispatcher().registerOnBackInvokedCallback(
|
||||
OnBackInvokedDispatcher.PRIORITY_DEFAULT,
|
||||
new OnBackAnimationCallback() {
|
||||
|
||||
@Nullable OnBackPressedHandler mActiveOnBackPressedHandler;
|
||||
|
||||
@Override
|
||||
public void onBackStarted(@NonNull BackEvent backEvent) {
|
||||
if (mActiveOnBackPressedHandler != null) {
|
||||
mActiveOnBackPressedHandler.onBackCancelled();
|
||||
}
|
||||
mActiveOnBackPressedHandler = getOnBackPressedHandler();
|
||||
mActiveOnBackPressedHandler.onBackStarted();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackInvoked() {
|
||||
onBackPressed();
|
||||
// Recreate mActiveOnBackPressedHandler if necessary to avoid NPE because:
|
||||
// 1. b/260636433: In 3-button-navigation mode, onBackStarted() is not
|
||||
// called on ACTION_DOWN before onBackInvoked() is called in ACTION_UP.
|
||||
// 2. Launcher#onBackPressed() will call onBackInvoked() without calling
|
||||
// onBackInvoked() beforehand.
|
||||
if (mActiveOnBackPressedHandler == null) {
|
||||
mActiveOnBackPressedHandler = getOnBackPressedHandler();
|
||||
}
|
||||
mActiveOnBackPressedHandler.onBackInvoked();
|
||||
mActiveOnBackPressedHandler = null;
|
||||
TestLogging.recordEvent(TestProtocol.SEQUENCE_MAIN, "onBackInvoked");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackProgressed(@NonNull BackEvent backEvent) {
|
||||
QuickstepLauncher.this.onBackProgressed(backEvent.getProgress());
|
||||
if (!FeatureFlags.IS_STUDIO_BUILD && mActiveOnBackPressedHandler == null) {
|
||||
return;
|
||||
}
|
||||
mActiveOnBackPressedHandler
|
||||
.onBackProgressed(backEvent.getProgress());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackCancelled() {
|
||||
QuickstepLauncher.this.onBackCancelled();
|
||||
if (!FeatureFlags.IS_STUDIO_BUILD && mActiveOnBackPressedHandler == null) {
|
||||
return;
|
||||
}
|
||||
mActiveOnBackPressedHandler.onBackCancelled();
|
||||
mActiveOnBackPressedHandler = null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -111,11 +111,6 @@ public class AllAppsEduView extends AbstractFloatingView {
|
||||
return (type & TYPE_ALL_APPS_EDU) != 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onBackPressed() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canInterceptEventsInSystemGestureRegion() {
|
||||
return true;
|
||||
|
||||
@@ -46,7 +46,8 @@ import java.lang.annotation.RetentionPolicy;
|
||||
/**
|
||||
* Base class for a View which shows a floating UI on top of the launcher UI.
|
||||
*/
|
||||
public abstract class AbstractFloatingView extends LinearLayout implements TouchController {
|
||||
public abstract class AbstractFloatingView extends LinearLayout implements TouchController,
|
||||
OnBackPressedHandler {
|
||||
|
||||
@IntDef(flag = true, value = {
|
||||
TYPE_FOLDER,
|
||||
@@ -165,12 +166,16 @@ public abstract class AbstractFloatingView extends LinearLayout implements Touch
|
||||
|
||||
protected abstract boolean isOfType(@FloatingViewType int type);
|
||||
|
||||
/** @return Whether the back is consumed. If false, Launcher will handle the back as well. */
|
||||
public boolean onBackPressed() {
|
||||
close(true);
|
||||
/** Return true if this view can consume back press. */
|
||||
public boolean canHandleBack() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackInvoked() {
|
||||
close(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onControllerTouchEvent(MotionEvent ev) {
|
||||
return false;
|
||||
|
||||
@@ -125,9 +125,13 @@ public abstract class BaseDraggingActivity extends BaseActivity
|
||||
mCurrentActionMode = null;
|
||||
}
|
||||
|
||||
protected boolean isInAutoCancelActionMode() {
|
||||
return mCurrentActionMode != null && AUTO_CANCEL_ACTION_MODE == mCurrentActionMode.getTag();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean finishAutoCancelActionMode() {
|
||||
if (mCurrentActionMode != null && AUTO_CANCEL_ACTION_MODE == mCurrentActionMode.getTag()) {
|
||||
if (isInAutoCancelActionMode()) {
|
||||
mCurrentActionMode.finish();
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -560,6 +560,61 @@ public class Launcher extends StatefulActivity<LauncherState>
|
||||
setTitle(R.string.home_screen);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide {@link OnBackPressedHandler} in below order:
|
||||
* <ol>
|
||||
* <li> auto cancel action mode handler
|
||||
* <li> drag handler
|
||||
* <li> view handler
|
||||
* <li> state handler
|
||||
* </ol>
|
||||
*
|
||||
* A back gesture (a single click on back button, or a swipe back gesture that contains a series
|
||||
* of swipe events) should be handled by the same handler from above list. For a new back
|
||||
* gesture, a new handler should be regenerated.
|
||||
*
|
||||
* Note that state handler will always be handling the back press event if the previous 3 don't.
|
||||
*/
|
||||
@NonNull
|
||||
protected OnBackPressedHandler getOnBackPressedHandler() {
|
||||
// #1 auto cancel action mode handler
|
||||
if (isInAutoCancelActionMode()) {
|
||||
return this::finishAutoCancelActionMode;
|
||||
}
|
||||
|
||||
// #2 drag handler
|
||||
if (mDragController.isDragging()) {
|
||||
return mDragController::cancelDrag;
|
||||
}
|
||||
|
||||
// #3 view handler
|
||||
AbstractFloatingView topView =
|
||||
AbstractFloatingView.getTopOpenView(Launcher.this);
|
||||
if (topView != null && topView.canHandleBack()) {
|
||||
return topView;
|
||||
}
|
||||
|
||||
// #4 state handler
|
||||
return new OnBackPressedHandler() {
|
||||
@Override
|
||||
public void onBackInvoked() {
|
||||
onStateBack();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackProgressed(
|
||||
@FloatRange(from = 0.0, to = 1.0) float backProgress) {
|
||||
mStateManager.getState().onBackProgressed(
|
||||
Launcher.this, backProgress);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackCancelled() {
|
||||
mStateManager.getState().onBackCancelled(Launcher.this);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
protected LauncherOverlayManager getDefaultOverlay() {
|
||||
return new LauncherOverlayManager() { };
|
||||
}
|
||||
@@ -2047,36 +2102,13 @@ public class Launcher extends StatefulActivity<LauncherState>
|
||||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
if (finishAutoCancelActionMode()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (mDragController.isDragging()) {
|
||||
mDragController.cancelDrag();
|
||||
return;
|
||||
}
|
||||
|
||||
// Note: There should be at most one log per method call. This is enforced implicitly
|
||||
// by using if-else statements.
|
||||
AbstractFloatingView topView = AbstractFloatingView.getTopOpenView(this);
|
||||
if (topView == null || !topView.onBackPressed()) {
|
||||
// Not handled by the floating view.
|
||||
onStateBack();
|
||||
}
|
||||
getOnBackPressedHandler().onBackInvoked();
|
||||
}
|
||||
|
||||
protected void onStateBack() {
|
||||
mStateManager.getState().onBackPressed(this);
|
||||
}
|
||||
|
||||
protected void onBackProgressed(@FloatRange(from = 0.0, to = 1.0) float backProgress) {
|
||||
mStateManager.getState().onBackProgressed(this, backProgress);
|
||||
}
|
||||
|
||||
protected void onBackCancelled() {
|
||||
mStateManager.getState().onBackCancelled(this);
|
||||
}
|
||||
|
||||
protected void onScreenOnChanged(boolean isOn) {
|
||||
// Reset AllApps to its initial state only if we are not in the middle of
|
||||
// processing a multi-step drop
|
||||
|
||||
45
src/com/android/launcher3/OnBackPressedHandler.java
Normal file
45
src/com/android/launcher3/OnBackPressedHandler.java
Normal file
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* 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.launcher3;
|
||||
|
||||
import androidx.annotation.FloatRange;
|
||||
|
||||
/**
|
||||
* Interface that mimics {@link android.window.OnBackInvokedCallback} without dependencies on U's
|
||||
* API such as {@link android.window.BackEvent}.
|
||||
*
|
||||
* <p> Impl can assume below order during a back gesture:
|
||||
* <ol>
|
||||
* <li> [optional] one {@link #onBackStarted()} will be called to start the gesture
|
||||
* <li> zero or multiple {@link #onBackProgressed(float)} will be called during swipe gesture
|
||||
* <li> either one of {@link #onBackInvoked()} or {@link #onBackCancelled()} will be called to end
|
||||
* the gesture
|
||||
*/
|
||||
public interface OnBackPressedHandler {
|
||||
|
||||
/** Called when back has started. */
|
||||
default void onBackStarted() {}
|
||||
|
||||
/** Called when back is committed. */
|
||||
void onBackInvoked();
|
||||
|
||||
/** Called with back gesture's progress. */
|
||||
default void onBackProgressed(@FloatRange(from = 0.0, to = 1.0) float backProgress) {}
|
||||
|
||||
/** Called when user drops the back gesture. */
|
||||
default void onBackCancelled() {}
|
||||
}
|
||||
@@ -81,10 +81,10 @@ public class DiscoveryBounce extends AbstractFloatingView {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onBackPressed() {
|
||||
super.onBackPressed();
|
||||
// Go back to the previous state (from a user's perspective this floating view isn't
|
||||
// something to go back from).
|
||||
public boolean canHandleBack() {
|
||||
// Since DiscoveryBounce doesn't handle back, onBackInvoked() won't be called and we should
|
||||
// close it without animation.
|
||||
close(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -1579,17 +1579,14 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo
|
||||
return getOpenView(activityContext, TYPE_FOLDER);
|
||||
}
|
||||
|
||||
/**
|
||||
* Navigation bar back key or hardware input back key has been issued.
|
||||
*/
|
||||
/** Navigation bar back key or hardware input back key has been issued. */
|
||||
@Override
|
||||
public boolean onBackPressed() {
|
||||
public void onBackInvoked() {
|
||||
if (isEditingName()) {
|
||||
mFolderName.dispatchBackKey();
|
||||
} else {
|
||||
super.onBackPressed();
|
||||
super.onBackInvoked();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -175,8 +175,9 @@ public class SecondaryDisplayLauncher extends BaseDraggingActivity
|
||||
// Note: There should be at most one log per method call. This is enforced implicitly
|
||||
// by using if-else statements.
|
||||
AbstractFloatingView topView = AbstractFloatingView.getTopOpenView(this);
|
||||
if (topView != null && topView.onBackPressed()) {
|
||||
if (topView != null && topView.canHandleBack()) {
|
||||
// Handled by the floating view.
|
||||
topView.onBackInvoked();
|
||||
} else {
|
||||
showAppDrawer(false);
|
||||
}
|
||||
|
||||
@@ -17,7 +17,9 @@ package com.android.launcher3.widget.picker;
|
||||
|
||||
import static android.view.View.MeasureSpec.makeMeasureSpec;
|
||||
|
||||
import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY;
|
||||
import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_Y;
|
||||
import static com.android.launcher3.allapps.AllAppsTransitionController.SWIPE_ALL_APPS_TO_HOME_MIN_SCALE;
|
||||
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_WIDGETSTRAY_SEARCHED;
|
||||
import static com.android.launcher3.testing.shared.TestProtocol.NORMAL_STATE_ORDINAL;
|
||||
|
||||
@@ -45,6 +47,7 @@ import android.view.animation.Interpolator;
|
||||
import android.widget.Button;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.FloatRange;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
import androidx.recyclerview.widget.DefaultItemAnimator;
|
||||
@@ -54,6 +57,7 @@ import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.LauncherAppState;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.anim.Interpolators;
|
||||
import com.android.launcher3.anim.PendingAnimation;
|
||||
import com.android.launcher3.compat.AccessibilityManagerCompat;
|
||||
import com.android.launcher3.model.UserManagerState;
|
||||
@@ -264,6 +268,15 @@ public class WidgetsFullSheet extends BaseWidgetSheet
|
||||
attachScrollbarToRecyclerView(currentRecyclerView);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackProgressed(@FloatRange(from = 0.0, to = 1.0) float progress) {
|
||||
float deceleratedProgress =
|
||||
Interpolators.PREDICTIVE_BACK_DECELERATED_EASE.getInterpolation(progress);
|
||||
float scaleProgress = SWIPE_ALL_APPS_TO_HOME_MIN_SCALE
|
||||
+ (1 - SWIPE_ALL_APPS_TO_HOME_MIN_SCALE) * (1 - deceleratedProgress);
|
||||
SCALE_PROPERTY.set(this, scaleProgress);
|
||||
}
|
||||
|
||||
private void attachScrollbarToRecyclerView(WidgetsRecyclerView recyclerView) {
|
||||
recyclerView.bindFastScrollbar();
|
||||
if (mCurrentWidgetsRecyclerView != recyclerView) {
|
||||
@@ -736,12 +749,12 @@ public class WidgetsFullSheet extends BaseWidgetSheet
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onBackPressed() {
|
||||
public void onBackInvoked() {
|
||||
if (mIsInSearchMode) {
|
||||
mSearchBar.reset();
|
||||
return true;
|
||||
} else {
|
||||
super.onBackInvoked();
|
||||
}
|
||||
return super.onBackPressed();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
Reference in New Issue
Block a user