mirror of
https://github.com/LawnchairLauncher/lawnchair.git
synced 2026-03-03 01:16:49 +00:00
Merge "Revert "Revert "Add a way to stash/unstash transient taskbar.""" into tm-qpr-dev am: 8ed5ac05fd
Original change: https://googleplex-android-review.googlesource.com/c/platform/packages/apps/Launcher3/+/20356225 Change-Id: I105e7ac5928083ef4d3793c76a0da357338c8b3b Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
@@ -292,6 +292,7 @@
|
||||
<dimen name="taskbar_app_window_threshold">150dp</dimen>
|
||||
<dimen name="taskbar_home_overview_threshold">225dp</dimen>
|
||||
<dimen name="taskbar_catch_up_threshold">300dp</dimen>
|
||||
<dimen name="taskbar_nav_threshold">40dp</dimen>
|
||||
|
||||
<!-- Taskbar 3 button spacing -->
|
||||
<dimen name="taskbar_button_space_inbetween">24dp</dimen>
|
||||
|
||||
@@ -24,6 +24,8 @@ import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL;
|
||||
import static com.android.launcher3.AbstractFloatingView.TYPE_ALL;
|
||||
import static com.android.launcher3.AbstractFloatingView.TYPE_REBIND_SAFE;
|
||||
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_FOLDER_OPEN;
|
||||
import static com.android.launcher3.taskbar.TaskbarAutohideSuspendController.FLAG_AUTOHIDE_SUSPEND_DRAGGING;
|
||||
import static com.android.launcher3.taskbar.TaskbarAutohideSuspendController.FLAG_AUTOHIDE_SUSPEND_FULLSCREEN;
|
||||
import static com.android.launcher3.taskbar.TaskbarManager.FLAG_HIDE_NAVBAR_WINDOW;
|
||||
import static com.android.launcher3.testing.shared.ResourceUtils.getBoolByName;
|
||||
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED;
|
||||
@@ -75,6 +77,7 @@ import com.android.launcher3.model.data.FolderInfo;
|
||||
import com.android.launcher3.model.data.ItemInfo;
|
||||
import com.android.launcher3.model.data.WorkspaceItemInfo;
|
||||
import com.android.launcher3.popup.PopupDataProvider;
|
||||
import com.android.launcher3.taskbar.TaskbarAutohideSuspendController.AutohideSuspendFlag;
|
||||
import com.android.launcher3.taskbar.allapps.TaskbarAllAppsController;
|
||||
import com.android.launcher3.taskbar.overlay.TaskbarOverlayController;
|
||||
import com.android.launcher3.testing.TestLogging;
|
||||
@@ -297,13 +300,19 @@ public class TaskbarActivityContext extends BaseTaskbarContext {
|
||||
// Taskbar is on the logical bottom of the screen
|
||||
boolean isVerticalBarLayout = TaskbarManager.isPhoneMode(deviceProfile) &&
|
||||
deviceProfile.isLandscape;
|
||||
|
||||
int windowFlags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
|
||||
| WindowManager.LayoutParams.FLAG_SLIPPERY
|
||||
| WindowManager.LayoutParams.FLAG_SPLIT_TOUCH;
|
||||
if (DisplayController.isTransientTaskbar(this)) {
|
||||
windowFlags |= WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
|
||||
| WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH;
|
||||
}
|
||||
WindowManager.LayoutParams windowLayoutParams = new WindowManager.LayoutParams(
|
||||
isVerticalBarLayout ? mLastRequestedNonFullscreenHeight : MATCH_PARENT,
|
||||
isVerticalBarLayout ? MATCH_PARENT : mLastRequestedNonFullscreenHeight,
|
||||
type,
|
||||
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
|
||||
| WindowManager.LayoutParams.FLAG_SLIPPERY
|
||||
| WindowManager.LayoutParams.FLAG_SPLIT_TOUCH,
|
||||
windowFlags,
|
||||
PixelFormat.TRANSLUCENT);
|
||||
windowLayoutParams.setTitle(WINDOW_TITLE);
|
||||
windowLayoutParams.packageName = getPackageName();
|
||||
@@ -467,7 +476,7 @@ public class TaskbarActivityContext extends BaseTaskbarContext {
|
||||
|
||||
@Override
|
||||
public void onDragEnd() {
|
||||
maybeSetTaskbarWindowNotFullscreen();
|
||||
onDragEndOrViewRemoved();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -571,25 +580,34 @@ public class TaskbarActivityContext extends BaseTaskbarContext {
|
||||
.updateValue(darkIntensity);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called to update a {@link AutohideSuspendFlag} with a new value.
|
||||
*/
|
||||
public void setAutohideSuspendFlag(@AutohideSuspendFlag int flag, boolean newValue) {
|
||||
mControllers.taskbarAutohideSuspendController.updateFlag(flag, newValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the TaskbarContainer to MATCH_PARENT vs original Taskbar size.
|
||||
*/
|
||||
public void setTaskbarWindowFullscreen(boolean fullscreen) {
|
||||
mControllers.taskbarAutohideSuspendController.updateFlag(
|
||||
TaskbarAutohideSuspendController.FLAG_AUTOHIDE_SUSPEND_FULLSCREEN, fullscreen);
|
||||
setAutohideSuspendFlag(FLAG_AUTOHIDE_SUSPEND_FULLSCREEN, fullscreen);
|
||||
mIsFullscreen = fullscreen;
|
||||
setTaskbarWindowHeight(fullscreen ? MATCH_PARENT : mLastRequestedNonFullscreenHeight);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverts Taskbar window to its original size, if all floating views are closed and there is
|
||||
* no system drag operation in progress.
|
||||
* Called when drag ends or when a view is removed from the DragLayer.
|
||||
*/
|
||||
void maybeSetTaskbarWindowNotFullscreen() {
|
||||
if (AbstractFloatingView.getAnyView(this, TYPE_ALL) == null
|
||||
&& !mControllers.taskbarDragController.isSystemDragInProgress()) {
|
||||
void onDragEndOrViewRemoved() {
|
||||
boolean isDragInProgress = mControllers.taskbarDragController.isSystemDragInProgress();
|
||||
|
||||
if (!isDragInProgress && !AbstractFloatingView.hasOpenView(this, TYPE_ALL)) {
|
||||
// Reverts Taskbar window to its original size
|
||||
setTaskbarWindowFullscreen(false);
|
||||
}
|
||||
|
||||
setAutohideSuspendFlag(FLAG_AUTOHIDE_SUSPEND_DRAGGING, isDragInProgress);
|
||||
}
|
||||
|
||||
public boolean isTaskbarWindowFullscreen() {
|
||||
@@ -703,6 +721,7 @@ public class TaskbarActivityContext extends BaseTaskbarContext {
|
||||
Task task = (Task) tag;
|
||||
ActivityManagerWrapper.getInstance().startActivityFromRecents(task.key,
|
||||
ActivityOptions.makeBasic());
|
||||
mControllers.taskbarStashController.updateAndAnimateTransientTaskbar(true);
|
||||
} else if (tag instanceof FolderInfo) {
|
||||
FolderIcon folderIcon = (FolderIcon) view;
|
||||
Folder folder = folderIcon.getFolder();
|
||||
@@ -762,6 +781,7 @@ public class TaskbarActivityContext extends BaseTaskbarContext {
|
||||
}
|
||||
|
||||
mControllers.uiController.onTaskbarIconLaunched(info);
|
||||
mControllers.taskbarStashController.updateAndAnimateTransientTaskbar(true);
|
||||
} catch (NullPointerException | ActivityNotFoundException | SecurityException e) {
|
||||
Toast.makeText(this, R.string.activity_not_found, Toast.LENGTH_SHORT)
|
||||
.show();
|
||||
@@ -771,6 +791,7 @@ public class TaskbarActivityContext extends BaseTaskbarContext {
|
||||
} else if (tag instanceof AppInfo) {
|
||||
startItemInfoActivity((AppInfo) tag);
|
||||
mControllers.uiController.onTaskbarIconLaunched((AppInfo) tag);
|
||||
mControllers.taskbarStashController.updateAndAnimateTransientTaskbar(true);
|
||||
} else {
|
||||
Log.e(TAG, "Unknown type clicked: " + tag);
|
||||
}
|
||||
@@ -805,6 +826,20 @@ public class TaskbarActivityContext extends BaseTaskbarContext {
|
||||
return mControllers.taskbarStashController.onLongPressToUnstashTaskbar();
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when we want to unstash taskbar when user performs swipes up gesture.
|
||||
*/
|
||||
public void onSwipeToUnstashTaskbar() {
|
||||
mControllers.taskbarStashController.updateAndAnimateTransientTaskbar(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a transient Autohide flag suspend status changes.
|
||||
*/
|
||||
public void onTransientAutohideSuspendFlagChanged(boolean isSuspended) {
|
||||
mControllers.taskbarStashController.updateTaskbarTimeout(isSuspended);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
|
||||
@@ -33,21 +33,28 @@ import java.util.StringJoiner;
|
||||
public class TaskbarAutohideSuspendController implements
|
||||
TaskbarControllers.LoggableTaskbarController {
|
||||
|
||||
// Taskbar window is fullscreen.
|
||||
public static final int FLAG_AUTOHIDE_SUSPEND_FULLSCREEN = 1 << 0;
|
||||
// User is dragging item.
|
||||
public static final int FLAG_AUTOHIDE_SUSPEND_DRAGGING = 1 << 1;
|
||||
// User has touched down but has not lifted finger.
|
||||
public static final int FLAG_AUTOHIDE_SUSPEND_TOUCHING = 1 << 2;
|
||||
|
||||
@IntDef(flag = true, value = {
|
||||
FLAG_AUTOHIDE_SUSPEND_FULLSCREEN,
|
||||
FLAG_AUTOHIDE_SUSPEND_DRAGGING,
|
||||
FLAG_AUTOHIDE_SUSPEND_TOUCHING,
|
||||
})
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
public @interface AutohideSuspendFlag {}
|
||||
|
||||
private final TaskbarActivityContext mActivity;
|
||||
private final SystemUiProxy mSystemUiProxy;
|
||||
|
||||
private @AutohideSuspendFlag int mAutohideSuspendFlags = 0;
|
||||
|
||||
public TaskbarAutohideSuspendController(TaskbarActivityContext activity) {
|
||||
mActivity = activity;
|
||||
mSystemUiProxy = SystemUiProxy.INSTANCE.get(activity);
|
||||
}
|
||||
|
||||
@@ -59,12 +66,27 @@ public class TaskbarAutohideSuspendController implements
|
||||
* Adds or removes the given flag, then notifies system UI proxy whether to suspend auto-hide.
|
||||
*/
|
||||
public void updateFlag(@AutohideSuspendFlag int flag, boolean enabled) {
|
||||
int flagsBefore = mAutohideSuspendFlags;
|
||||
if (enabled) {
|
||||
mAutohideSuspendFlags |= flag;
|
||||
} else {
|
||||
mAutohideSuspendFlags &= ~flag;
|
||||
}
|
||||
mSystemUiProxy.notifyTaskbarAutohideSuspend(mAutohideSuspendFlags != 0);
|
||||
if (flagsBefore == mAutohideSuspendFlags) {
|
||||
// Nothing has changed, no need to notify.
|
||||
return;
|
||||
}
|
||||
|
||||
boolean isSuspended = isSuspended();
|
||||
mSystemUiProxy.notifyTaskbarAutohideSuspend(isSuspended);
|
||||
mActivity.onTransientAutohideSuspendFlagChanged(isSuspended);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true iff taskbar autohide is currently suspended.
|
||||
*/
|
||||
public boolean isSuspended() {
|
||||
return mAutohideSuspendFlags != 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -79,6 +101,7 @@ public class TaskbarAutohideSuspendController implements
|
||||
appendFlag(str, flags, FLAG_AUTOHIDE_SUSPEND_FULLSCREEN,
|
||||
"FLAG_AUTOHIDE_SUSPEND_FULLSCREEN");
|
||||
appendFlag(str, flags, FLAG_AUTOHIDE_SUSPEND_DRAGGING, "FLAG_AUTOHIDE_SUSPEND_DRAGGING");
|
||||
appendFlag(str, flags, FLAG_AUTOHIDE_SUSPEND_TOUCHING, "FLAG_AUTOHIDE_SUSPEND_TOUCHING");
|
||||
return str.toString();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -115,6 +115,14 @@ public class TaskbarDragLayer extends BaseDragLayer<TaskbarActivityContext> {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouchEvent(MotionEvent ev) {
|
||||
if (mControllerCallbacks != null && ev.getAction() == MotionEvent.ACTION_OUTSIDE) {
|
||||
mControllerCallbacks.onActionOutsideEvent();
|
||||
}
|
||||
return super.onTouchEvent(ev);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewRemoved(View child) {
|
||||
super.onViewRemoved(child);
|
||||
|
||||
@@ -23,6 +23,7 @@ import android.view.ViewTreeObserver;
|
||||
import com.android.launcher3.DeviceProfile;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.util.DimensionUtils;
|
||||
import com.android.launcher3.util.DisplayController;
|
||||
import com.android.launcher3.util.TouchController;
|
||||
import com.android.quickstep.AnimatedFloat;
|
||||
|
||||
@@ -165,11 +166,25 @@ public class TaskbarDragLayerController implements TaskbarControllers.LoggableTa
|
||||
mControllers.taskbarInsetsController.updateInsetsTouchability(insetsInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called whenever TaskbarDragLayer receives an ACTION_OUTSIDE event.
|
||||
*/
|
||||
public void onActionOutsideEvent() {
|
||||
if (!DisplayController.isTransientTaskbar(mActivity)) {
|
||||
return;
|
||||
}
|
||||
if (mControllers.taskbarStashController.isStashed()) {
|
||||
return;
|
||||
}
|
||||
|
||||
mControllers.taskbarStashController.updateAndAnimateTransientTaskbar(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a child is removed from TaskbarDragLayer.
|
||||
*/
|
||||
public void onDragLayerViewRemoved() {
|
||||
mActivity.maybeSetTaskbarWindowNotFullscreen();
|
||||
mActivity.onDragEndOrViewRemoved();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -39,11 +39,13 @@ import android.view.ViewConfiguration;
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.android.internal.jank.InteractionJankMonitor;
|
||||
import com.android.launcher3.Alarm;
|
||||
import com.android.launcher3.DeviceProfile;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.anim.AnimatorListeners;
|
||||
import com.android.launcher3.testing.shared.TestProtocol;
|
||||
import com.android.launcher3.util.DisplayController;
|
||||
import com.android.launcher3.util.MultiPropertyFactory.MultiProperty;
|
||||
import com.android.quickstep.AnimatedFloat;
|
||||
import com.android.quickstep.SystemUiProxy;
|
||||
@@ -70,6 +72,7 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba
|
||||
public static final int FLAG_STASHED_IN_TASKBAR_ALL_APPS = 1 << 7; // All apps is visible.
|
||||
public static final int FLAG_IN_SETUP = 1 << 8; // In the Setup Wizard
|
||||
public static final int FLAG_STASHED_SMALL_SCREEN = 1 << 9; // phone screen gesture nav, stashed
|
||||
public static final int FLAG_STASHED_IN_APP_AUTO = 1 << 10; // Autohide (transient taskbar).
|
||||
|
||||
// If any of these flags are enabled, isInApp should return true.
|
||||
private static final int FLAGS_IN_APP = FLAG_IN_APP | FLAG_IN_SETUP;
|
||||
@@ -78,7 +81,7 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba
|
||||
private static final int FLAGS_STASHED_IN_APP = FLAG_STASHED_IN_APP_MANUAL
|
||||
| FLAG_STASHED_IN_APP_PINNED | FLAG_STASHED_IN_APP_EMPTY | FLAG_STASHED_IN_APP_SETUP
|
||||
| FLAG_STASHED_IN_APP_IME | FLAG_STASHED_IN_TASKBAR_ALL_APPS
|
||||
| FLAG_STASHED_SMALL_SCREEN;
|
||||
| FLAG_STASHED_SMALL_SCREEN | FLAG_STASHED_IN_APP_AUTO;
|
||||
|
||||
private static final int FLAGS_STASHED_IN_APP_IGNORING_IME =
|
||||
FLAGS_STASHED_IN_APP & ~FLAG_STASHED_IN_APP_IME;
|
||||
@@ -132,6 +135,9 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba
|
||||
*/
|
||||
private static final boolean DEFAULT_STASHED_PREF = false;
|
||||
|
||||
// Auto stashes when user has not interacted with the Taskbar after X ms.
|
||||
private static final long NO_TOUCH_TIMEOUT_TO_STASH_MS = 5000;
|
||||
|
||||
private final TaskbarActivityContext mActivity;
|
||||
private final SharedPreferences mPrefs;
|
||||
private final int mStashedHeight;
|
||||
@@ -162,6 +168,8 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba
|
||||
|
||||
private boolean mEnableManualStashingDuringTests = false;
|
||||
|
||||
private final Alarm mTimeoutAlarm = new Alarm();
|
||||
|
||||
// Evaluate whether the handle should be stashed
|
||||
private final StatePropertyHolder mStatePropertyHolder = new StatePropertyHolder(
|
||||
flags -> {
|
||||
@@ -210,13 +218,16 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba
|
||||
StashedHandleViewController.ALPHA_INDEX_STASHED);
|
||||
mTaskbarStashedHandleHintScale = stashedHandleController.getStashedHandleHintScale();
|
||||
|
||||
boolean isTransientTaskbar = DisplayController.isTransientTaskbar(mActivity);
|
||||
// We use supportsVisualStashing() here instead of supportsManualStashing() because we want
|
||||
// it to work properly for tests that recreate taskbar. This check is here just to ensure
|
||||
// that taskbar unstashes when going to 3 button mode (supportsVisualStashing() false).
|
||||
boolean isManuallyStashedInApp = supportsVisualStashing()
|
||||
&& mPrefs.getBoolean(SHARED_PREFS_STASHED_KEY, DEFAULT_STASHED_PREF);
|
||||
&& mPrefs.getBoolean(SHARED_PREFS_STASHED_KEY, DEFAULT_STASHED_PREF)
|
||||
&& !isTransientTaskbar;
|
||||
boolean isInSetup = !mActivity.isUserSetupComplete() || setupUIVisible;
|
||||
updateStateForFlag(FLAG_STASHED_IN_APP_MANUAL, isManuallyStashedInApp);
|
||||
updateStateForFlag(FLAG_STASHED_IN_APP_AUTO, isTransientTaskbar);
|
||||
updateStateForFlag(FLAG_STASHED_IN_APP_SETUP, isInSetup);
|
||||
updateStateForFlag(FLAG_IN_SETUP, isInSetup);
|
||||
updateStateForFlag(FLAG_STASHED_SMALL_SCREEN, isPhoneMode()
|
||||
@@ -243,7 +254,8 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba
|
||||
protected boolean supportsManualStashing() {
|
||||
return supportsVisualStashing()
|
||||
&& isInApp()
|
||||
&& (!Utilities.IS_RUNNING_IN_TEST_HARNESS || mEnableManualStashingDuringTests);
|
||||
&& (!Utilities.IS_RUNNING_IN_TEST_HARNESS || mEnableManualStashingDuringTests)
|
||||
&& !DisplayController.isTransientTaskbar(mActivity);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -376,6 +388,20 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba
|
||||
return mStashedHeight;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stash or unstashes the transient taskbar.
|
||||
*/
|
||||
public void updateAndAnimateTransientTaskbar(boolean stash) {
|
||||
if (!DisplayController.isTransientTaskbar(mActivity)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (hasAnyFlag(FLAG_STASHED_IN_APP_AUTO) != stash) {
|
||||
updateStateForFlag(FLAG_STASHED_IN_APP_AUTO, stash);
|
||||
applyState();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Should be called when long pressing the nav region when taskbar is present.
|
||||
* @return Whether taskbar was stashed and now is unstashed.
|
||||
@@ -549,11 +575,17 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba
|
||||
public void onAnimationStart(Animator animation) {
|
||||
mIsStashed = isStashed;
|
||||
onIsStashedChanged(mIsStashed);
|
||||
|
||||
cancelTimeoutIfExists();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
mAnimator = null;
|
||||
|
||||
if (!mIsStashed) {
|
||||
tryStartTaskbarTimeout();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -779,6 +811,54 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba
|
||||
mControllers.rotationButtonController.onTaskbarStateChange(visible, stashed);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancels a timeout if any exists.
|
||||
*/
|
||||
public void cancelTimeoutIfExists() {
|
||||
if (mTimeoutAlarm.alarmPending()) {
|
||||
mTimeoutAlarm.cancelAlarm();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the status of the taskbar timeout.
|
||||
* @param isAutohideSuspended If true, cancels any existing timeout
|
||||
* If false, attempts to re/start the timeout
|
||||
*/
|
||||
public void updateTaskbarTimeout(boolean isAutohideSuspended) {
|
||||
if (!DisplayController.isTransientTaskbar(mActivity)) {
|
||||
return;
|
||||
}
|
||||
if (isAutohideSuspended) {
|
||||
cancelTimeoutIfExists();
|
||||
} else {
|
||||
tryStartTaskbarTimeout();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to start timer to auto hide the taskbar based on time.
|
||||
*/
|
||||
public void tryStartTaskbarTimeout() {
|
||||
if (!DisplayController.isTransientTaskbar(mActivity)) {
|
||||
return;
|
||||
}
|
||||
if (mIsStashed) {
|
||||
return;
|
||||
}
|
||||
cancelTimeoutIfExists();
|
||||
|
||||
mTimeoutAlarm.setOnAlarmListener(this::onTaskbarTimeout);
|
||||
mTimeoutAlarm.setAlarm(NO_TOUCH_TIMEOUT_TO_STASH_MS);
|
||||
}
|
||||
|
||||
private void onTaskbarTimeout(Alarm alarm) {
|
||||
if (mControllers.taskbarAutohideSuspendController.isSuspended()) {
|
||||
return;
|
||||
}
|
||||
updateAndAnimateTransientTaskbar(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dumpLogs(String prefix, PrintWriter pw) {
|
||||
pw.println(prefix + "TaskbarStashController:");
|
||||
@@ -794,17 +874,18 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba
|
||||
}
|
||||
|
||||
private static String getStateString(int flags) {
|
||||
StringJoiner str = new StringJoiner("|");
|
||||
appendFlag(str, flags, FLAGS_IN_APP, "FLAG_IN_APP");
|
||||
appendFlag(str, flags, FLAG_STASHED_IN_APP_MANUAL, "FLAG_STASHED_IN_APP_MANUAL");
|
||||
appendFlag(str, flags, FLAG_STASHED_IN_APP_PINNED, "FLAG_STASHED_IN_APP_PINNED");
|
||||
appendFlag(str, flags, FLAG_STASHED_IN_APP_EMPTY, "FLAG_STASHED_IN_APP_EMPTY");
|
||||
appendFlag(str, flags, FLAG_STASHED_IN_APP_SETUP, "FLAG_STASHED_IN_APP_SETUP");
|
||||
appendFlag(str, flags, FLAG_STASHED_IN_APP_IME, "FLAG_STASHED_IN_APP_IME");
|
||||
appendFlag(str, flags, FLAG_IN_STASHED_LAUNCHER_STATE, "FLAG_IN_STASHED_LAUNCHER_STATE");
|
||||
appendFlag(str, flags, FLAG_STASHED_IN_TASKBAR_ALL_APPS, "FLAG_STASHED_IN_APP_ALL_APPS");
|
||||
appendFlag(str, flags, FLAG_IN_SETUP, "FLAG_IN_SETUP");
|
||||
return str.toString();
|
||||
StringJoiner sj = new StringJoiner("|");
|
||||
appendFlag(sj, flags, FLAGS_IN_APP, "FLAG_IN_APP");
|
||||
appendFlag(sj, flags, FLAG_STASHED_IN_APP_MANUAL, "FLAG_STASHED_IN_APP_MANUAL");
|
||||
appendFlag(sj, flags, FLAG_STASHED_IN_APP_PINNED, "FLAG_STASHED_IN_APP_PINNED");
|
||||
appendFlag(sj, flags, FLAG_STASHED_IN_APP_EMPTY, "FLAG_STASHED_IN_APP_EMPTY");
|
||||
appendFlag(sj, flags, FLAG_STASHED_IN_APP_SETUP, "FLAG_STASHED_IN_APP_SETUP");
|
||||
appendFlag(sj, flags, FLAG_STASHED_IN_APP_IME, "FLAG_STASHED_IN_APP_IME");
|
||||
appendFlag(sj, flags, FLAG_IN_STASHED_LAUNCHER_STATE, "FLAG_IN_STASHED_LAUNCHER_STATE");
|
||||
appendFlag(sj, flags, FLAG_STASHED_IN_TASKBAR_ALL_APPS, "FLAG_STASHED_IN_TASKBAR_ALL_APPS");
|
||||
appendFlag(sj, flags, FLAG_IN_SETUP, "FLAG_IN_SETUP");
|
||||
appendFlag(sj, flags, FLAG_STASHED_IN_APP_AUTO, "FLAG_STASHED_IN_APP_AUTO");
|
||||
return sj.toString();
|
||||
}
|
||||
|
||||
private class StatePropertyHolder {
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package com.android.launcher3.taskbar;
|
||||
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.annotation.CallSuper;
|
||||
@@ -104,6 +105,15 @@ public class TaskbarUIController {
|
||||
return mControllers.taskbarStashController.isStashed();
|
||||
}
|
||||
|
||||
/*
|
||||
* @param ev MotionEvent in screen coordinates.
|
||||
* @return Whether any Taskbar item could handle the given MotionEvent if given the chance.
|
||||
*/
|
||||
public boolean isEventOverAnyTaskbarItem(MotionEvent ev) {
|
||||
return mControllers.taskbarViewController.isEventOverAnyItem(ev)
|
||||
|| mControllers.navbarButtonsViewController.isEventOverAnyItem(ev);
|
||||
}
|
||||
|
||||
@CallSuper
|
||||
protected void dumpLogs(String prefix, PrintWriter pw) {
|
||||
pw.println(String.format(
|
||||
|
||||
@@ -344,13 +344,23 @@ public class TaskbarView extends FrameLayout implements FolderIcon.FolderIconPar
|
||||
return super.dispatchTouchEvent(ev);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onInterceptTouchEvent(MotionEvent ev) {
|
||||
mControllerCallbacks.onInterceptTouchEvent(ev);
|
||||
return super.onInterceptTouchEvent(ev);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouchEvent(MotionEvent event) {
|
||||
if (!mTouchEnabled) {
|
||||
return true;
|
||||
}
|
||||
if (mIconLayoutBounds.left <= event.getX() && event.getX() <= mIconLayoutBounds.right) {
|
||||
// Don't allow long pressing between icons, or above/below them.
|
||||
if (mIconLayoutBounds.left <= event.getX()
|
||||
&& event.getX() <= mIconLayoutBounds.right
|
||||
&& !DisplayController.isTransientTaskbar(mActivityContext)) {
|
||||
// Don't allow long pressing between icons, or above/below them
|
||||
// unless its transient taskbar.
|
||||
mControllerCallbacks.clearTouchInProgress();
|
||||
return true;
|
||||
}
|
||||
if (mControllerCallbacks.onTouchEvent(event)) {
|
||||
@@ -367,6 +377,7 @@ public class TaskbarView extends FrameLayout implements FolderIcon.FolderIconPar
|
||||
|
||||
public void setTouchesEnabled(boolean touchEnabled) {
|
||||
this.mTouchEnabled = touchEnabled;
|
||||
mControllerCallbacks.clearTouchInProgress();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -22,6 +22,8 @@ import static com.android.launcher3.Utilities.squaredHypot;
|
||||
import static com.android.launcher3.anim.Interpolators.LINEAR;
|
||||
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASKBAR_ALLAPPS_BUTTON_TAP;
|
||||
import static com.android.launcher3.taskbar.TaskbarManager.isPhoneMode;
|
||||
import static com.android.launcher3.touch.SingleAxisSwipeDetector.DIRECTION_NEGATIVE;
|
||||
import static com.android.launcher3.touch.SingleAxisSwipeDetector.VERTICAL;
|
||||
import static com.android.quickstep.AnimatedFloat.VALUE;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
@@ -31,6 +33,7 @@ import android.util.Log;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.core.graphics.ColorUtils;
|
||||
import androidx.core.view.OneShotPreDrawListener;
|
||||
|
||||
@@ -47,6 +50,7 @@ import com.android.launcher3.config.FeatureFlags;
|
||||
import com.android.launcher3.folder.FolderIcon;
|
||||
import com.android.launcher3.icons.ThemedIconDrawable;
|
||||
import com.android.launcher3.model.data.ItemInfo;
|
||||
import com.android.launcher3.touch.SingleAxisSwipeDetector;
|
||||
import com.android.launcher3.util.DisplayController;
|
||||
import com.android.launcher3.util.HorizontalInsettableView;
|
||||
import com.android.launcher3.util.ItemInfoMatcher;
|
||||
@@ -95,6 +99,9 @@ public class TaskbarViewController implements TaskbarControllers.LoggableTaskbar
|
||||
|
||||
private final TaskbarModelCallbacks mModelCallbacks;
|
||||
|
||||
// Captures swipe down action to close transient taskbar.
|
||||
protected @Nullable SingleAxisSwipeDetector mSwipeDownDetector;
|
||||
|
||||
// Initialized in init.
|
||||
private TaskbarControllers mControllers;
|
||||
|
||||
@@ -117,6 +124,31 @@ public class TaskbarViewController implements TaskbarControllers.LoggableTaskbar
|
||||
mTaskbarBottomMargin = DisplayController.isTransientTaskbar(activity)
|
||||
? activity.getResources().getDimensionPixelSize(R.dimen.transient_taskbar_margin)
|
||||
: 0;
|
||||
|
||||
if (DisplayController.isTransientTaskbar(mActivity)) {
|
||||
mSwipeDownDetector = new SingleAxisSwipeDetector(activity,
|
||||
new SingleAxisSwipeDetector.Listener() {
|
||||
private float mLastDisplacement;
|
||||
|
||||
@Override
|
||||
public boolean onDrag(float displacement) {
|
||||
mLastDisplacement = displacement;
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDragEnd(float velocity) {
|
||||
if (mLastDisplacement > 0) {
|
||||
mControllers.taskbarStashController
|
||||
.updateAndAnimateTransientTaskbar(true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDragStart(boolean start, float startDisplacement) {}
|
||||
}, VERTICAL);
|
||||
mSwipeDownDetector.setDetectableScrollConditions(DIRECTION_NEGATIVE, false);
|
||||
}
|
||||
}
|
||||
|
||||
public void init(TaskbarControllers controllers) {
|
||||
@@ -438,6 +470,8 @@ public class TaskbarViewController implements TaskbarControllers.LoggableTaskbar
|
||||
private float mDownX, mDownY;
|
||||
private boolean mCanceledStashHint;
|
||||
|
||||
private boolean mTouchInProgress;
|
||||
|
||||
public View.OnClickListener getIconOnClickListener() {
|
||||
return mActivity.getItemOnClickListener();
|
||||
}
|
||||
@@ -458,38 +492,76 @@ public class TaskbarViewController implements TaskbarControllers.LoggableTaskbar
|
||||
.updateAndAnimateIsManuallyStashedInApp(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Simply listens to all intercept touch events passed to TaskbarView.
|
||||
*/
|
||||
public void onInterceptTouchEvent(MotionEvent ev) {
|
||||
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
|
||||
mTouchInProgress = true;
|
||||
}
|
||||
|
||||
if (mTouchInProgress && mSwipeDownDetector != null) {
|
||||
mSwipeDownDetector.onTouchEvent(ev);
|
||||
}
|
||||
|
||||
if (ev.getAction() == MotionEvent.ACTION_UP
|
||||
|| ev.getAction() == MotionEvent.ACTION_CANCEL) {
|
||||
clearTouchInProgress();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the first chance to handle TaskbarView#onTouchEvent, and return whether we want to
|
||||
* consume the touch so TaskbarView treats it as an ACTION_CANCEL.
|
||||
*/
|
||||
public boolean onTouchEvent(MotionEvent motionEvent) {
|
||||
boolean shouldConsumeTouch = false;
|
||||
boolean clearTouchInProgress = false;
|
||||
|
||||
final float x = motionEvent.getRawX();
|
||||
final float y = motionEvent.getRawY();
|
||||
switch (motionEvent.getAction()) {
|
||||
case MotionEvent.ACTION_DOWN:
|
||||
mTouchInProgress = true;
|
||||
mDownX = x;
|
||||
mDownY = y;
|
||||
mControllers.taskbarStashController.startStashHint(/* animateForward = */ true);
|
||||
mCanceledStashHint = false;
|
||||
break;
|
||||
case MotionEvent.ACTION_MOVE:
|
||||
if (!mCanceledStashHint
|
||||
if (mTouchInProgress
|
||||
&& !mCanceledStashHint
|
||||
&& squaredHypot(mDownX - x, mDownY - y) > mSquaredTouchSlop) {
|
||||
mControllers.taskbarStashController.startStashHint(
|
||||
/* animateForward= */ false);
|
||||
mCanceledStashHint = true;
|
||||
return true;
|
||||
shouldConsumeTouch = true;
|
||||
}
|
||||
break;
|
||||
case MotionEvent.ACTION_UP:
|
||||
case MotionEvent.ACTION_CANCEL:
|
||||
if (!mCanceledStashHint) {
|
||||
if (mTouchInProgress && !mCanceledStashHint) {
|
||||
mControllers.taskbarStashController.startStashHint(
|
||||
/* animateForward= */ false);
|
||||
}
|
||||
clearTouchInProgress = true;
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
|
||||
if (mTouchInProgress && mSwipeDownDetector != null) {
|
||||
mSwipeDownDetector.onTouchEvent(motionEvent);
|
||||
}
|
||||
if (clearTouchInProgress) {
|
||||
clearTouchInProgress();
|
||||
}
|
||||
return shouldConsumeTouch;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures that we do not pass any more touch events to the SwipeDetector.
|
||||
*/
|
||||
public void clearTouchInProgress() {
|
||||
mTouchInProgress = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -15,9 +15,14 @@
|
||||
*/
|
||||
package com.android.quickstep.inputconsumers;
|
||||
|
||||
import static android.view.MotionEvent.INVALID_POINTER_ID;
|
||||
|
||||
import static com.android.launcher3.Utilities.squaredHypot;
|
||||
import static com.android.launcher3.taskbar.TaskbarAutohideSuspendController.FLAG_AUTOHIDE_SUSPEND_TOUCHING;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.PointF;
|
||||
import android.view.GestureDetector;
|
||||
import android.view.GestureDetector.SimpleOnGestureListener;
|
||||
import android.view.MotionEvent;
|
||||
@@ -25,6 +30,7 @@ import android.view.MotionEvent;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.taskbar.TaskbarActivityContext;
|
||||
import com.android.launcher3.util.DisplayController;
|
||||
import com.android.quickstep.InputConsumer;
|
||||
import com.android.systemui.shared.system.InputMonitorCompat;
|
||||
|
||||
@@ -37,20 +43,32 @@ public class TaskbarStashInputConsumer extends DelegateInputConsumer {
|
||||
private final GestureDetector mLongPressDetector;
|
||||
private final float mSquaredTouchSlop;
|
||||
|
||||
|
||||
private float mDownX, mDownY;
|
||||
private float mLongPressDownX, mLongPressDownY;
|
||||
private boolean mCanceledUnstashHint;
|
||||
private final float mUnstashArea;
|
||||
private final float mScreenWidth;
|
||||
|
||||
private final int mTaskbarThreshold;
|
||||
private boolean mHasPassedTaskbarThreshold;
|
||||
|
||||
private final PointF mDownPos = new PointF();
|
||||
private final PointF mLastPos = new PointF();
|
||||
private int mActivePointerId = INVALID_POINTER_ID;
|
||||
|
||||
private final boolean mIsTransientTaskbar;
|
||||
|
||||
public TaskbarStashInputConsumer(Context context, InputConsumer delegate,
|
||||
InputMonitorCompat inputMonitor, TaskbarActivityContext taskbarActivityContext) {
|
||||
super(delegate, inputMonitor);
|
||||
mTaskbarActivityContext = taskbarActivityContext;
|
||||
mSquaredTouchSlop = Utilities.squaredTouchSlop(context);
|
||||
mScreenWidth = taskbarActivityContext.getDeviceProfile().widthPx;
|
||||
mUnstashArea = context.getResources()
|
||||
.getDimensionPixelSize(R.dimen.taskbar_unstash_input_area);
|
||||
|
||||
Resources res = context.getResources();
|
||||
mUnstashArea = res.getDimensionPixelSize(R.dimen.taskbar_unstash_input_area);
|
||||
mTaskbarThreshold = res.getDimensionPixelSize(R.dimen.taskbar_nav_threshold);
|
||||
|
||||
mIsTransientTaskbar = DisplayController.isTransientTaskbar(context);
|
||||
|
||||
mLongPressDetector = new GestureDetector(context, new SimpleOnGestureListener() {
|
||||
@Override
|
||||
@@ -76,28 +94,71 @@ public class TaskbarStashInputConsumer extends DelegateInputConsumer {
|
||||
final float y = ev.getRawY();
|
||||
switch (ev.getAction()) {
|
||||
case MotionEvent.ACTION_DOWN:
|
||||
mActivePointerId = ev.getPointerId(0);
|
||||
mDownPos.set(ev.getX(), ev.getY());
|
||||
mLastPos.set(mDownPos);
|
||||
|
||||
mHasPassedTaskbarThreshold = false;
|
||||
mTaskbarActivityContext.setAutohideSuspendFlag(
|
||||
FLAG_AUTOHIDE_SUSPEND_TOUCHING, true);
|
||||
if (isInArea(x)) {
|
||||
mDownX = x;
|
||||
mDownY = y;
|
||||
mTaskbarActivityContext.startTaskbarUnstashHint(
|
||||
/* animateForward = */ true);
|
||||
mCanceledUnstashHint = false;
|
||||
if (!mIsTransientTaskbar) {
|
||||
mLongPressDownX = x;
|
||||
mLongPressDownY = y;
|
||||
mTaskbarActivityContext.startTaskbarUnstashHint(
|
||||
/* animateForward = */ true);
|
||||
mCanceledUnstashHint = false;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case MotionEvent.ACTION_POINTER_UP:
|
||||
int ptrIdx = ev.getActionIndex();
|
||||
int ptrId = ev.getPointerId(ptrIdx);
|
||||
if (ptrId == mActivePointerId) {
|
||||
final int newPointerIdx = ptrIdx == 0 ? 1 : 0;
|
||||
mDownPos.set(
|
||||
ev.getX(newPointerIdx) - (mLastPos.x - mDownPos.x),
|
||||
ev.getY(newPointerIdx) - (mLastPos.y - mDownPos.y));
|
||||
mLastPos.set(ev.getX(newPointerIdx), ev.getY(newPointerIdx));
|
||||
mActivePointerId = ev.getPointerId(newPointerIdx);
|
||||
}
|
||||
break;
|
||||
case MotionEvent.ACTION_MOVE:
|
||||
if (!mCanceledUnstashHint
|
||||
&& squaredHypot(mDownX - x, mDownY - y) > mSquaredTouchSlop) {
|
||||
if (!mIsTransientTaskbar
|
||||
&& !mCanceledUnstashHint
|
||||
&& squaredHypot(mLongPressDownX - x, mLongPressDownY - y)
|
||||
> mSquaredTouchSlop) {
|
||||
mTaskbarActivityContext.startTaskbarUnstashHint(
|
||||
/* animateForward = */ false);
|
||||
mCanceledUnstashHint = true;
|
||||
}
|
||||
|
||||
int pointerIndex = ev.findPointerIndex(mActivePointerId);
|
||||
if (pointerIndex == INVALID_POINTER_ID) {
|
||||
break;
|
||||
}
|
||||
mLastPos.set(ev.getX(pointerIndex), ev.getY(pointerIndex));
|
||||
float displacementY = mLastPos.y - mDownPos.y;
|
||||
float verticalDist = Math.abs(displacementY);
|
||||
boolean passedTaskbarThreshold = verticalDist >= mTaskbarThreshold;
|
||||
|
||||
if (!mHasPassedTaskbarThreshold
|
||||
&& passedTaskbarThreshold
|
||||
&& mIsTransientTaskbar) {
|
||||
mHasPassedTaskbarThreshold = true;
|
||||
|
||||
mTaskbarActivityContext.onSwipeToUnstashTaskbar();
|
||||
}
|
||||
break;
|
||||
case MotionEvent.ACTION_UP:
|
||||
case MotionEvent.ACTION_CANCEL:
|
||||
if (!mCanceledUnstashHint) {
|
||||
if (!mIsTransientTaskbar && !mCanceledUnstashHint) {
|
||||
mTaskbarActivityContext.startTaskbarUnstashHint(
|
||||
/* animateForward = */ false);
|
||||
}
|
||||
mTaskbarActivityContext.setAutohideSuspendFlag(
|
||||
FLAG_AUTOHIDE_SUSPEND_TOUCHING, false);
|
||||
mHasPassedTaskbarThreshold = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -111,7 +172,9 @@ public class TaskbarStashInputConsumer extends DelegateInputConsumer {
|
||||
}
|
||||
|
||||
private void onLongPressDetected(MotionEvent motionEvent) {
|
||||
if (mTaskbarActivityContext != null && isInArea(motionEvent.getRawX())) {
|
||||
if (mTaskbarActivityContext != null
|
||||
&& isInArea(motionEvent.getRawX())
|
||||
&& !mIsTransientTaskbar) {
|
||||
boolean taskBarPressed = mTaskbarActivityContext.onLongPressToUnstashTaskbar();
|
||||
if (taskBarPressed) {
|
||||
setActive(motionEvent);
|
||||
|
||||
Reference in New Issue
Block a user