diff --git a/res/layout/taskbar_divider.xml b/quickstep/res/layout/taskbar_divider.xml
similarity index 66%
rename from res/layout/taskbar_divider.xml
rename to quickstep/res/layout/taskbar_divider.xml
index e25e7a30c1..73f3811ecf 100644
--- a/res/layout/taskbar_divider.xml
+++ b/quickstep/res/layout/taskbar_divider.xml
@@ -13,16 +13,16 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-
+
-
-
+ android:background="@drawable/taskbar_divider_bg" />
+
\ No newline at end of file
diff --git a/quickstep/res/layout/taskbar_divider_popup_menu.xml b/quickstep/res/layout/taskbar_divider_popup_menu.xml
new file mode 100644
index 0000000000..195443ead9
--- /dev/null
+++ b/quickstep/res/layout/taskbar_divider_popup_menu.xml
@@ -0,0 +1,98 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/quickstep/res/values/dimens.xml b/quickstep/res/values/dimens.xml
index cdb3b1ccb8..959fea7572 100644
--- a/quickstep/res/values/dimens.xml
+++ b/quickstep/res/values/dimens.xml
@@ -341,6 +341,9 @@
106dp
24dp
+
+ 300dp
+
30dp
diff --git a/quickstep/res/values/strings.xml b/quickstep/res/values/strings.xml
index 2c17ce8686..2b6f74945f 100644
--- a/quickstep/res/values/strings.xml
+++ b/quickstep/res/values/strings.xml
@@ -277,6 +277,13 @@
Taskbar hidden
Navigation bar
+
+ Always show Taskbar
+
+ Change navigation mode
+
+ Taskbar Divider
+
Move to top/left
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
index 809d715260..9db03f53a6 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
@@ -238,7 +238,8 @@ public class TaskbarActivityContext extends BaseTaskbarContext {
? new DesktopTaskbarRecentAppsController(this)
: TaskbarRecentAppsController.DEFAULT,
new TaskbarEduTooltipController(this),
- new KeyboardQuickSwitchController());
+ new KeyboardQuickSwitchController(),
+ new TaskbarDividerPopupController(this));
}
public void init(@NonNull TaskbarSharedState sharedState) {
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java
index 8efb9b0e47..1cd6f50d33 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java
@@ -60,6 +60,7 @@ public class TaskbarControllers {
public final TaskbarOverlayController taskbarOverlayController;
public final TaskbarEduTooltipController taskbarEduTooltipController;
public final KeyboardQuickSwitchController keyboardQuickSwitchController;
+ public final TaskbarDividerPopupController taskbarPinningController;
@Nullable private LoggableTaskbarController[] mControllersToLog = null;
@Nullable private BackgroundRendererController[] mBackgroundRendererControllers = null;
@@ -105,7 +106,8 @@ public class TaskbarControllers {
TaskbarSpringOnStashController taskbarSpringOnStashController,
TaskbarRecentAppsController taskbarRecentAppsController,
TaskbarEduTooltipController taskbarEduTooltipController,
- KeyboardQuickSwitchController keyboardQuickSwitchController) {
+ KeyboardQuickSwitchController keyboardQuickSwitchController,
+ TaskbarDividerPopupController taskbarPinningController) {
this.taskbarActivityContext = taskbarActivityContext;
this.taskbarDragController = taskbarDragController;
this.navButtonController = navButtonController;
@@ -130,6 +132,7 @@ public class TaskbarControllers {
this.taskbarRecentAppsController = taskbarRecentAppsController;
this.taskbarEduTooltipController = taskbarEduTooltipController;
this.keyboardQuickSwitchController = keyboardQuickSwitchController;
+ this.taskbarPinningController = taskbarPinningController;
}
/**
@@ -163,6 +166,7 @@ public class TaskbarControllers {
taskbarTranslationController.init(this);
taskbarEduTooltipController.init(this);
keyboardQuickSwitchController.init(this);
+ taskbarPinningController.init(this);
mControllersToLog = new LoggableTaskbarController[] {
taskbarDragController, navButtonController, navbarButtonsViewController,
@@ -171,7 +175,7 @@ public class TaskbarControllers {
stashedHandleViewController, taskbarStashController,
taskbarAutohideSuspendController, taskbarPopupController, taskbarInsetsController,
voiceInteractionWindowController, taskbarTranslationController,
- taskbarEduTooltipController, keyboardQuickSwitchController
+ taskbarEduTooltipController, keyboardQuickSwitchController, taskbarPinningController
};
mBackgroundRendererControllers = new BackgroundRendererController[] {
taskbarDragLayerController, taskbarScrimViewController,
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarDividerPopupController.kt b/quickstep/src/com/android/launcher3/taskbar/TaskbarDividerPopupController.kt
new file mode 100644
index 0000000000..8dbc51af7d
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarDividerPopupController.kt
@@ -0,0 +1,66 @@
+/*
+ * 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.taskbar
+
+import android.view.View
+import com.android.launcher3.LauncherPrefs
+import com.android.launcher3.LauncherPrefs.Companion.TASKBAR_PINNING
+import com.android.launcher3.taskbar.TaskbarDividerPopupView.Companion.createAndPopulate
+import java.io.PrintWriter
+
+/** Controls taskbar pinning through a popup view. */
+class TaskbarDividerPopupController(private val context: TaskbarActivityContext) :
+ TaskbarControllers.LoggableTaskbarController {
+
+ private lateinit var controllers: TaskbarControllers
+ private val launcherPrefs = LauncherPrefs.get(context)
+
+ fun init(taskbarControllers: TaskbarControllers) {
+ controllers = taskbarControllers
+ }
+
+ fun showPinningView(view: View) {
+ context.isTaskbarWindowFullscreen = true
+
+ view.post {
+ val popupView = createAndPopulate(view, context)
+ popupView.requestFocus()
+ popupView.onCloseCallback = {
+ context.onPopupVisibilityChanged(false)
+ if (launcherPrefs.get(TASKBAR_PINNING)) {
+ animateTransientToPersistentTaskBar()
+ } else {
+ animatePersistentToTransientTaskbar()
+ }
+ }
+ popupView.changePreference = {
+ launcherPrefs.put(TASKBAR_PINNING, !launcherPrefs.get(TASKBAR_PINNING))
+ }
+ context.onPopupVisibilityChanged(true)
+ popupView.show()
+ }
+ }
+
+ // TODO(b/265436799): provide animation/transition from transient taskbar to persistent one
+ private fun animateTransientToPersistentTaskBar() {}
+
+ // TODO(b/265436799): provide animation/transition from persistent taskbar to transient one
+ private fun animatePersistentToTransientTaskbar() {}
+
+ override fun dumpLogs(prefix: String, pw: PrintWriter) {
+ pw.println(prefix + "TaskbarPinningController:")
+ }
+}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarDividerPopupView.kt b/quickstep/src/com/android/launcher3/taskbar/TaskbarDividerPopupView.kt
new file mode 100644
index 0000000000..2000d984c4
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarDividerPopupView.kt
@@ -0,0 +1,171 @@
+/*
+ * 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.taskbar
+
+import android.annotation.SuppressLint
+import android.content.Context
+import android.graphics.Rect
+import android.util.AttributeSet
+import android.view.Gravity
+import android.view.MotionEvent
+import android.view.View
+import android.widget.LinearLayout
+import android.widget.Switch
+import androidx.core.view.postDelayed
+import com.android.launcher3.R
+import com.android.launcher3.popup.ArrowPopup
+import com.android.launcher3.popup.RoundedArrowDrawable
+import com.android.launcher3.util.DisplayController
+import com.android.launcher3.util.Themes
+
+/** Popup view with arrow for taskbar pinning */
+class TaskbarDividerPopupView
+@JvmOverloads
+constructor(
+ context: Context,
+ attrs: AttributeSet? = null,
+ defStyleAttr: Int = 0,
+) : ArrowPopup(context, attrs, defStyleAttr) {
+ companion object {
+ private const val TAG = "TaskbarDividerPopupView"
+ private const val DIVIDER_POPUP_CLOSING_DELAY = 500L
+
+ @JvmStatic
+ fun createAndPopulate(
+ view: View,
+ taskbarActivityContext: TaskbarActivityContext,
+ ): TaskbarDividerPopupView<*> {
+ val taskMenuViewWithArrow =
+ taskbarActivityContext.layoutInflater.inflate(
+ R.layout.taskbar_divider_popup_menu,
+ taskbarActivityContext.dragLayer,
+ false
+ ) as TaskbarDividerPopupView<*>
+
+ return taskMenuViewWithArrow.populateForView(view)
+ }
+ }
+ private lateinit var dividerView: View
+
+ private val menuWidth =
+ context.resources.getDimensionPixelSize(R.dimen.taskbar_pinning_popup_menu_width)
+ private val popupCornerRadius = Themes.getDialogCornerRadius(context)
+ private val arrowWidth = resources.getDimension(R.dimen.popup_arrow_width)
+ private val arrowHeight = resources.getDimension(R.dimen.popup_arrow_height)
+ private val arrowPointRadius = resources.getDimension(R.dimen.popup_arrow_corner_radius)
+
+ private var alwaysShowTaskbarOn = !DisplayController.isTransientTaskbar(context)
+ private var didPreferenceChange = false
+
+ /** Callback invoked when the pinning popup view is closing. */
+ var onCloseCallback: () -> Unit = {}
+
+ /**
+ * Callback invoked when the user preference changes in popup view. Preference change will be
+ * based upon current value stored in [LauncherPrefs] for `TASKBAR_PINNING`
+ */
+ var changePreference: () -> Unit = {}
+
+ init {
+ // This synchronizes the arrow and menu to open at the same time
+ mOpenChildFadeStartDelay = mOpenFadeStartDelay
+ mOpenChildFadeDuration = mOpenFadeDuration
+ mCloseFadeStartDelay = mCloseChildFadeStartDelay
+ mCloseFadeDuration = mCloseChildFadeDuration
+ }
+
+ override fun isOfType(type: Int): Boolean = type and TYPE_TASKBAR_PINNING_POPUP != 0
+
+ override fun getTargetObjectLocation(outPos: Rect) {
+ popupContainer.getDescendantRectRelativeToSelf(dividerView, outPos)
+ }
+
+ @SuppressLint("UseSwitchCompatOrMaterialCode")
+ override fun onFinishInflate() {
+ super.onFinishInflate()
+ val taskbarSwitchOption = findViewById(R.id.taskbar_switch_option)
+ val alwaysShowTaskbarSwitch = findViewById(R.id.taskbar_pinning_switch)
+ alwaysShowTaskbarSwitch.isChecked = alwaysShowTaskbarOn
+ taskbarSwitchOption.setOnClickListener {
+ alwaysShowTaskbarSwitch.isClickable = true
+ alwaysShowTaskbarSwitch.isChecked = !alwaysShowTaskbarOn
+ onClickAlwaysShowTaskbarSwitchOption()
+ }
+ }
+
+ /** Orient object as usual and then center object horizontally. */
+ override fun orientAboutObject() {
+ super.orientAboutObject()
+ x = mTempRect.centerX() - menuWidth / 2f
+ }
+
+ override fun onControllerInterceptTouchEvent(ev: MotionEvent?): Boolean {
+ if (ev?.action == MotionEvent.ACTION_DOWN) {
+ if (!popupContainer.isEventOverView(this, ev)) {
+ close(true)
+ }
+ } else if (popupContainer.isEventOverView(dividerView, ev)) {
+ return true
+ }
+ return false
+ }
+
+ private fun populateForView(view: View): TaskbarDividerPopupView<*> {
+ dividerView = view
+ return this
+ }
+
+ override fun addArrow() {
+ super.addArrow()
+ // Change arrow location to the middle of popup.
+ mArrow.x = (dividerView.x + dividerView.width / 2) - (mArrowWidth / 2)
+ }
+
+ override fun updateArrowColor() {
+ if (!Gravity.isVertical(mGravity)) {
+ mArrow.background =
+ RoundedArrowDrawable(
+ arrowWidth,
+ arrowHeight,
+ arrowPointRadius,
+ popupCornerRadius,
+ measuredWidth.toFloat(),
+ measuredHeight.toFloat(),
+ (measuredWidth - arrowWidth) / 2, // arrowOffsetX
+ 0f, // arrowOffsetY
+ false, // isPointingUp
+ true, // leftAligned
+ Themes.getAttrColor(context, R.attr.popupColorPrimary),
+ )
+ elevation = mElevation
+ mArrow.elevation = mElevation
+ }
+ }
+
+ override fun closeComplete() {
+ if (didPreferenceChange) {
+ onCloseCallback()
+ }
+ super.closeComplete()
+ }
+
+ private fun onClickAlwaysShowTaskbarSwitchOption() {
+ didPreferenceChange = true
+ changePreference()
+ // Allow switch animation to finish and then close the popup.
+ postDelayed(DIVIDER_POPUP_CLOSING_DELAY) { close(true) }
+ }
+}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java
index 3d8bf9ea63..d3c4128581 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java
@@ -20,6 +20,8 @@ import static android.content.pm.PackageManager.FEATURE_PC;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL;
+import static com.android.launcher3.LauncherPrefs.TASKBAR_PINNING;
+import static com.android.launcher3.LauncherPrefs.TASKBAR_PINNING_KEY;
import static com.android.launcher3.util.DisplayController.CHANGE_DENSITY;
import static com.android.launcher3.util.DisplayController.CHANGE_NAVIGATION_MODE;
import static com.android.launcher3.util.DisplayController.TASKBAR_NOT_DESTROYED_TAG;
@@ -32,6 +34,7 @@ import android.content.ComponentCallbacks;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.SharedPreferences;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.hardware.display.DisplayManager;
@@ -48,6 +51,7 @@ import androidx.annotation.VisibleForTesting;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.LauncherAppState;
+import com.android.launcher3.LauncherPrefs;
import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.statemanager.StatefulActivity;
import com.android.launcher3.taskbar.unfold.NonDestroyableScopedUnfoldTransitionProgressProvider;
@@ -133,6 +137,13 @@ public class TaskbarManager {
private final SimpleBroadcastReceiver mTaskbarBroadcastReceiver =
new SimpleBroadcastReceiver(this::showTaskbarFromBroadcast);
+ private final SharedPreferences.OnSharedPreferenceChangeListener
+ mTaskbarPinningPreferenceChangeListener = (sharedPreferences, key) -> {
+ if (TASKBAR_PINNING_KEY.equals(key)) {
+ recreateTaskbar();
+ }
+ };
+
@SuppressLint("WrongConstant")
public TaskbarManager(TouchInteractionService service) {
mDisplayController = DisplayController.INSTANCE.get(service);
@@ -244,6 +255,8 @@ public class TaskbarManager {
private void destroyExistingTaskbar() {
debugWhyTaskbarNotDestroyed("destroyExistingTaskbar: " + mTaskbarActivityContext);
if (mTaskbarActivityContext != null) {
+ LauncherPrefs.get(mContext).removeListener(mTaskbarPinningPreferenceChangeListener,
+ TASKBAR_PINNING);
mTaskbarActivityContext.onDestroy();
if (!FLAG_HIDE_NAVBAR_WINDOW) {
mTaskbarActivityContext = null;
@@ -380,6 +393,10 @@ public class TaskbarManager {
mTaskbarActivityContext.setUIController(
createTaskbarUIControllerForActivity(mActivity));
}
+
+ // We to wait until user unlocks the device to attach listener.
+ LauncherPrefs.get(mContext).addListener(mTaskbarPinningPreferenceChangeListener,
+ TASKBAR_PINNING);
}
public void onSystemUiFlagsChanged(int systemUiStateFlags) {
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
index 69ea9fd03a..1d90a43111 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
@@ -18,11 +18,12 @@ package com.android.launcher3.taskbar;
import static android.view.HapticFeedbackConstants.LONG_PRESS;
import static android.view.accessibility.AccessibilityManager.FLAG_CONTENT_CONTROLS;
+import static com.android.launcher3.LauncherPrefs.TASKBAR_PINNING_KEY;
import static com.android.launcher3.anim.Interpolators.EMPHASIZED;
import static com.android.launcher3.anim.Interpolators.FINAL_FRAME;
import static com.android.launcher3.anim.Interpolators.INSTANT;
import static com.android.launcher3.anim.Interpolators.LINEAR;
-import static com.android.launcher3.config.FeatureFlags.FORCE_PERSISTENT_TASKBAR;
+import static com.android.launcher3.config.FeatureFlags.ENABLE_TASKBAR_PINNING;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASKBAR_LONGPRESS_HIDE;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASKBAR_LONGPRESS_SHOW;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TRANSIENT_TASKBAR_HIDE;
@@ -324,7 +325,7 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba
// that taskbar unstashes when going to 3 button mode (supportsVisualStashing() false).
boolean isManuallyStashedInApp = supportsVisualStashing()
&& !isTransientTaskbar
- && !FORCE_PERSISTENT_TASKBAR.get()
+ && !ENABLE_TASKBAR_PINNING.get()
&& mPrefs.getBoolean(SHARED_PREFS_STASHED_KEY, DEFAULT_STASHED_PREF);
boolean isInSetup = !mActivity.isUserSetupComplete() || setupUIVisible;
updateStateForFlag(FLAG_STASHED_IN_APP_MANUAL, isManuallyStashedInApp);
@@ -353,7 +354,7 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba
* Returns whether the user can manually stash the taskbar based on the current device state.
*/
protected boolean supportsManualStashing() {
- if (FORCE_PERSISTENT_TASKBAR.get()) {
+ if (ENABLE_TASKBAR_PINNING.get() && mPrefs.getBoolean(TASKBAR_PINNING_KEY, false)) {
return false;
}
return supportsVisualStashing()
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java
index 603473945c..f099e0636f 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java
@@ -218,7 +218,8 @@ public class TaskbarView extends FrameLayout implements FolderIcon.FolderIconPar
mAllAppsButton.setOnClickListener(mControllerCallbacks.getAllAppsButtonClickListener());
}
if (mTaskbarDivider != null) {
- //TODO(b/265434705): set long press listener
+ mTaskbarDivider.setOnLongClickListener(
+ mControllerCallbacks.getTaskbarDividerLongClickListener());
}
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
index 6eb409e35d..ec3d1bcc0a 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
@@ -641,6 +641,13 @@ public class TaskbarViewController implements TaskbarControllers.LoggableTaskbar
};
}
+ public View.OnLongClickListener getTaskbarDividerLongClickListener() {
+ return v -> {
+ mControllers.taskbarPinningController.showPinningView(v);
+ return true;
+ };
+ }
+
public View.OnLongClickListener getIconOnLongClickListener() {
return mControllers.taskbarDragController::startDragOnLongClick;
}
diff --git a/quickstep/tests/src/com/android/launcher3/taskbar/TaskbarBaseTestCase.kt b/quickstep/tests/src/com/android/launcher3/taskbar/TaskbarBaseTestCase.kt
index 3bf4ad38c3..20466ad844 100644
--- a/quickstep/tests/src/com/android/launcher3/taskbar/TaskbarBaseTestCase.kt
+++ b/quickstep/tests/src/com/android/launcher3/taskbar/TaskbarBaseTestCase.kt
@@ -53,6 +53,7 @@ abstract class TaskbarBaseTestCase {
@Mock lateinit var taskbarOverlayController: TaskbarOverlayController
@Mock lateinit var taskbarEduTooltipController: TaskbarEduTooltipController
@Mock lateinit var keyboardQuickSwitchController: KeyboardQuickSwitchController
+ @Mock lateinit var taskbarPinningController: TaskbarDividerPopupController
lateinit var taskbarControllers: TaskbarControllers
@@ -91,7 +92,8 @@ abstract class TaskbarBaseTestCase {
taskbarSpringOnStashController,
taskbarRecentAppsController,
taskbarEduTooltipController,
- keyboardQuickSwitchController
+ keyboardQuickSwitchController,
+ taskbarPinningController,
)
}
}
diff --git a/res/drawable/bottom_rounded_popup_ripple.xml b/res/drawable/bottom_rounded_popup_ripple.xml
new file mode 100644
index 0000000000..739833a47c
--- /dev/null
+++ b/res/drawable/bottom_rounded_popup_ripple.xml
@@ -0,0 +1,27 @@
+
+
+
+ -
+
+
+
+
+
+
\ No newline at end of file
diff --git a/res/drawable/ic_touch.xml b/res/drawable/ic_touch.xml
new file mode 100644
index 0000000000..ea0e05c547
--- /dev/null
+++ b/res/drawable/ic_touch.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
diff --git a/res/drawable/ic_visibility.xml b/res/drawable/ic_visibility.xml
new file mode 100644
index 0000000000..864de2ec18
--- /dev/null
+++ b/res/drawable/ic_visibility.xml
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+
diff --git a/res/drawable/taskbar_divider_bg.xml b/res/drawable/taskbar_divider_bg.xml
new file mode 100644
index 0000000000..a8c2ae7032
--- /dev/null
+++ b/res/drawable/taskbar_divider_bg.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
diff --git a/res/drawable/top_rounded_popup_ripple.xml b/res/drawable/top_rounded_popup_ripple.xml
new file mode 100644
index 0000000000..7468480192
--- /dev/null
+++ b/res/drawable/top_rounded_popup_ripple.xml
@@ -0,0 +1,27 @@
+
+
+
+ -
+
+
+
+
+
+
\ No newline at end of file
diff --git a/res/values-v31/styles.xml b/res/values-v31/styles.xml
index 008a77c3a8..932ce38e59 100644
--- a/res/values-v31/styles.xml
+++ b/res/values-v31/styles.xml
@@ -24,7 +24,7 @@
- 24dp
- @android:color/transparent
- @android:color/transparent
- - @style/HomeSettings.SwitchStyle
+ - @style/SwitchStyle
- @style/HomeSettings.PreferenceTitle
- false
- true
@@ -61,13 +61,6 @@
- @bool/home_settings_icon_space_reserved
-
-
+
+
diff --git a/src/com/android/launcher3/AbstractFloatingView.java b/src/com/android/launcher3/AbstractFloatingView.java
index 29f4a6276e..31f9bfea4a 100644
--- a/src/com/android/launcher3/AbstractFloatingView.java
+++ b/src/com/android/launcher3/AbstractFloatingView.java
@@ -74,7 +74,8 @@ public abstract class AbstractFloatingView extends LinearLayout implements Touch
TYPE_TASKBAR_EDUCATION_DIALOG,
TYPE_TASKBAR_ALL_APPS,
TYPE_ADD_TO_HOME_CONFIRMATION,
- TYPE_TASKBAR_OVERLAY_PROXY
+ TYPE_TASKBAR_OVERLAY_PROXY,
+ TYPE_TASKBAR_PINNING_POPUP
})
@Retention(RetentionPolicy.SOURCE)
public @interface FloatingViewType {}
@@ -102,6 +103,7 @@ public abstract class AbstractFloatingView extends LinearLayout implements Touch
public static final int TYPE_TASKBAR_ALL_APPS = 1 << 18;
public static final int TYPE_ADD_TO_HOME_CONFIRMATION = 1 << 19;
public static final int TYPE_TASKBAR_OVERLAY_PROXY = 1 << 20;
+ public static final int TYPE_TASKBAR_PINNING_POPUP = 1 << 21;
public static final int TYPE_ALL = TYPE_FOLDER | TYPE_ACTION_POPUP
| TYPE_WIDGETS_BOTTOM_SHEET | TYPE_WIDGET_RESIZE_FRAME | TYPE_WIDGETS_FULL_SHEET
@@ -110,7 +112,7 @@ public abstract class AbstractFloatingView extends LinearLayout implements Touch
| TYPE_ICON_SURFACE | TYPE_DRAG_DROP_POPUP | TYPE_PIN_WIDGET_FROM_EXTERNAL_POPUP
| TYPE_WIDGETS_EDUCATION_DIALOG | TYPE_TASKBAR_EDUCATION_DIALOG | TYPE_TASKBAR_ALL_APPS
| TYPE_OPTIONS_POPUP_DIALOG | TYPE_ADD_TO_HOME_CONFIRMATION
- | TYPE_TASKBAR_OVERLAY_PROXY;
+ | TYPE_TASKBAR_OVERLAY_PROXY | TYPE_TASKBAR_PINNING_POPUP;
// Type of popups which should be kept open during launcher rebind
public static final int TYPE_REBIND_SAFE = TYPE_WIDGETS_FULL_SHEET
diff --git a/src/com/android/launcher3/LauncherPrefs.kt b/src/com/android/launcher3/LauncherPrefs.kt
index fb4da0c019..c98df1b099 100644
--- a/src/com/android/launcher3/LauncherPrefs.kt
+++ b/src/com/android/launcher3/LauncherPrefs.kt
@@ -273,12 +273,15 @@ class LauncherPrefs(private val encryptedContext: Context) {
@JvmStatic fun get(context: Context): LauncherPrefs = INSTANCE.get(context)
+ const val TASKBAR_PINNING_KEY = "TASKBAR_PINNING_KEY"
@JvmField val ICON_STATE = nonRestorableItem(LauncherAppState.KEY_ICON_STATE, "", true)
@JvmField val THEMED_ICONS = backedUpItem(Themes.KEY_THEMED_ICONS, false, true)
@JvmField val PROMISE_ICON_IDS = backedUpItem(InstallSessionHelper.PROMISE_ICON_IDS, "")
@JvmField val WORK_EDU_STEP = backedUpItem(WorkProfileManager.KEY_WORK_EDU_STEP, 0)
@JvmField val WORKSPACE_SIZE = backedUpItem(DeviceGridState.KEY_WORKSPACE_SIZE, "", true)
@JvmField val HOTSEAT_COUNT = backedUpItem(DeviceGridState.KEY_HOTSEAT_COUNT, -1, true)
+ @JvmField val TASKBAR_PINNING = backedUpItem(TASKBAR_PINNING_KEY, false)
+
@JvmField
val DEVICE_TYPE =
backedUpItem(DeviceGridState.KEY_DEVICE_TYPE, InvariantDeviceProfile.TYPE_PHONE, true)
diff --git a/src/com/android/launcher3/util/DisplayController.java b/src/com/android/launcher3/util/DisplayController.java
index 02ebb15cd1..776fe40f05 100644
--- a/src/com/android/launcher3/util/DisplayController.java
+++ b/src/com/android/launcher3/util/DisplayController.java
@@ -19,9 +19,10 @@ import static android.content.Intent.ACTION_CONFIGURATION_CHANGED;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
+import static com.android.launcher3.LauncherPrefs.TASKBAR_PINNING;
import static com.android.launcher3.Utilities.dpiFromPx;
+import static com.android.launcher3.config.FeatureFlags.ENABLE_TASKBAR_PINNING;
import static com.android.launcher3.config.FeatureFlags.ENABLE_TRANSIENT_TASKBAR;
-import static com.android.launcher3.config.FeatureFlags.FORCE_PERSISTENT_TASKBAR;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import static com.android.launcher3.util.FlagDebugUtils.appendFlag;
import static com.android.launcher3.util.window.WindowManagerProxy.MIN_TABLET_WIDTH;
@@ -45,6 +46,7 @@ import androidx.annotation.AnyThread;
import androidx.annotation.UiThread;
import androidx.annotation.VisibleForTesting;
+import com.android.launcher3.LauncherPrefs;
import com.android.launcher3.Utilities;
import com.android.launcher3.util.window.CachedDisplayInfo;
import com.android.launcher3.util.window.WindowManagerProxy;
@@ -101,9 +103,12 @@ public class DisplayController implements ComponentCallbacks, SafeCloseable {
private Info mInfo;
private boolean mDestroyed = false;
+ private final LauncherPrefs mPrefs;
+
private DisplayController(Context context) {
mContext = context;
mDM = context.getSystemService(DisplayManager.class);
+ mPrefs = LauncherPrefs.get(context);
Display display = mDM.getDisplay(DEFAULT_DISPLAY);
if (Utilities.ATLEAST_S) {
@@ -144,7 +149,9 @@ public class DisplayController implements ComponentCallbacks, SafeCloseable {
// TODO(b/258604917): When running in test harness, use !sTransientTaskbarStatusForTests
// once tests are updated to expect new persistent behavior such as not allowing long press
// to stash.
- if (!Utilities.isRunningInTestHarness() && FORCE_PERSISTENT_TASKBAR.get()) {
+ if (!Utilities.isRunningInTestHarness()
+ && ENABLE_TASKBAR_PINNING.get()
+ && mPrefs.get(TASKBAR_PINNING)) {
return false;
}
return getInfo().navigationMode == NavigationMode.NO_BUTTON