Merge "Exposing functionality to pin Taskbar from TaskbarDividerPopupView." into udc-dev

This commit is contained in:
Jagrut Desai
2023-04-21 16:15:07 +00:00
committed by Android (Google) Code Review
24 changed files with 549 additions and 30 deletions
@@ -13,16 +13,16 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/taskbar_divider_container"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="@dimen/taskbar_icon_min_touch_size"
android:layout_height="@dimen/taskbar_icon_min_touch_size"
android:contentDescription="@string/taskbar_divider_a11y_title"
android:backgroundTint="@android:color/transparent">
<View
android:id="@+id/taskbar_divider_bar"
android:layout_height="32dp"
android:layout_width="2dp"
android:layout_gravity="center"
android:background="@drawable/bg_rounded_corner_bottom_sheet_handle" />
<!-- TODO(b/265347148): Create separate drawable -->
</FrameLayout>
android:background="@drawable/taskbar_divider_bg" />
</FrameLayout>
@@ -0,0 +1,98 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2023 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<com.android.launcher3.taskbar.TaskbarDividerPopupView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="@dimen/taskbar_pinning_popup_menu_width"
android:layout_height="wrap_content"
android:focusable="true"
android:background="@drawable/popup_background_material_u"
android:orientation="vertical">
<LinearLayout
android:id="@+id/taskbar_switch_option"
android:layout_width="match_parent"
android:layout_height="52dp"
android:layout_gravity="center_vertical"
android:elevation="2dp"
android:focusable="true"
android:clickable="true"
android:gravity="center_vertical"
android:orientation="horizontal"
android:background="@drawable/top_rounded_popup_ripple"
android:paddingEnd="10dp"
android:paddingStart="10dp"
android:theme="@style/PopupItem">
<View
android:layout_margin="6dp"
android:layout_width="20dp"
android:layout_height="20dp"
android:background="@drawable/ic_visibility"
android:backgroundTint="?android:attr/textColorPrimary" />
<Switch
style="@style/BaseIcon"
android:id="@+id/taskbar_pinning_switch"
android:background="@null"
android:clickable="false"
android:gravity="start|center_vertical"
android:textAlignment="viewStart"
android:paddingStart="12dp"
android:singleLine="true"
android:ellipsize="end"
android:textSize="14sp"
android:textColor="?android:attr/textColorPrimary"
android:text="@string/always_show_taskbar" />
</LinearLayout>
<LinearLayout
android:id="@+id/navigation_mode_switch_option"
android:layout_width="match_parent"
android:layout_height="52dp"
android:layout_gravity="center_vertical"
android:elevation="2dp"
android:clickable="true"
android:focusable="true"
android:background="@drawable/bottom_rounded_popup_ripple"
android:gravity="center_vertical"
android:orientation="horizontal"
android:paddingEnd="10dp"
android:paddingStart="10dp"
android:theme="@style/PopupItem">
<View
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_margin="4dp"
android:background="@drawable/ic_touch"
android:backgroundTint="?android:attr/textColorPrimary" />
<com.android.launcher3.BubbleTextView
style="@style/BaseIcon"
android:id="@+id/change_navigation_mode_text"
android:gravity="start|center_vertical"
android:textAlignment="viewStart"
android:paddingStart="12dp"
android:singleLine="true"
android:ellipsize="end"
android:textSize="14sp"
android:textColor="?android:attr/textColorPrimary"
android:text="@string/change_navigation_mode" />
</LinearLayout>
</com.android.launcher3.taskbar.TaskbarDividerPopupView>
+3
View File
@@ -341,6 +341,9 @@
<dimen name="taskbar_edu_features_lottie_height">106dp</dimen>
<dimen name="taskbar_edu_features_horizontal_spacing">24dp</dimen>
<!--- Taskbar Pinning -->
<dimen name="taskbar_pinning_popup_menu_width">300dp</dimen>
<!-- Recents overview -->
<dimen name="recents_filter_icon_size">30dp</dimen>
+7
View File
@@ -277,6 +277,13 @@
<string name="taskbar_a11y_hidden_title">Taskbar hidden</string>
<!-- Accessibility title for the Taskbar window on phones. [CHAR_LIMIT=NONE] -->
<string name="taskbar_phone_a11y_title">Navigation bar</string>
<!-- Text in popup dialog for user to switch between always showing Taskbar or not. [CHAR LIMIT=30] -->
<string name="always_show_taskbar">Always show Taskbar</string>
<!-- Text in popup dialog for user to switch between system navigation modes. [CHAR LIMIT=30] -->
<string name="change_navigation_mode">Change navigation mode</string>
<!-- Accessibility title for the Taskbar vertical divider icon. [CHAR_LIMIT=NONE] -->
<string name="taskbar_divider_a11y_title">Taskbar Divider</string>
<!-- Label for moving drop target to the top or left side of the screen, depending on orientation (from the Taskbar only). -->
<string name="move_drop_target_top_or_left">Move to top&#47;left</string>
@@ -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) {
@@ -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,
@@ -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:")
}
}
@@ -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<T : TaskbarActivityContext>
@JvmOverloads
constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0,
) : ArrowPopup<T>(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<LinearLayout>(R.id.taskbar_switch_option)
val alwaysShowTaskbarSwitch = findViewById<Switch>(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) }
}
}
@@ -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);
@@ -249,6 +260,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;
@@ -385,6 +398,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) {
@@ -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()
@@ -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());
}
}
@@ -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;
}
@@ -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,
)
}
}
@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2023 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="?android:attr/colorControlHighlight">
<item android:id="@android:id/mask">
<shape android:shape="rectangle">
<solid android:color="#FFFFFFFF"/>
<corners android:bottomLeftRadius="@dimen/dialogCornerRadius"
android:bottomRightRadius="@dimen/dialogCornerRadius"
android:topLeftRadius="0dp"
android:topRightRadius="0dp"/>
</shape>
</item>
</ripple>
+25
View File
@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2023 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="M18.19,12.44l-3.24,-1.62c1.29,-1 2.12,-2.56 2.12,-4.32c0,-3.03 -2.47,-5.5 -5.5,-5.5s-5.5,2.47 -5.5,5.5c0,2.13 1.22,3.98 3,4.89v3.26c-2.11,-0.45 -2.01,-0.44 -2.26,-0.44c-0.53,0 -1.03,0.21 -1.41,0.59L4,16.22l5.09,5.09C9.52,21.75 10.12,22 10.74,22h6.3c0.98,0 1.81,-0.7 1.97,-1.67l0.8,-4.71C20.03,14.32 19.38,13.04 18.19,12.44zM17.84,15.29L17.04,20h-6.3c-0.09,0 -0.17,-0.04 -0.24,-0.1l-3.68,-3.68l4.25,0.89V6.5c0,-0.28 0.22,-0.5 0.5,-0.5c0.28,0 0.5,0.22 0.5,0.5v6h1.76l3.46,1.73C17.69,14.43 17.91,14.86 17.84,15.29zM8.07,6.5c0,-1.93 1.57,-3.5 3.5,-3.5s3.5,1.57 3.5,3.5c0,0.95 -0.38,1.81 -1,2.44V6.5c0,-1.38 -1.12,-2.5 -2.5,-2.5c-1.38,0 -2.5,1.12 -2.5,2.5v2.44C8.45,8.31 8.07,7.45 8.07,6.5z"/>
</vector>
+29
View File
@@ -0,0 +1,29 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2023 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="20dp"
android:height="20dp"
android:viewportWidth="20"
android:viewportHeight="20">
<group>
<path
android:pathData="M10,5.833C7.933,5.833 6.25,7.517 6.25,9.583C6.25,11.65 7.933,13.333 10,13.333C12.067,13.333 13.75,11.65 13.75,9.583C13.75,7.517 12.067,5.833 10,5.833ZM10,11.833C8.758,11.833 7.75,10.825 7.75,9.583C7.75,8.342 8.758,7.333 10,7.333C11.242,7.333 12.25,8.342 12.25,9.583C12.25,10.825 11.242,11.833 10,11.833Z"
android:fillColor="#191C1D"/>
<path
android:pathData="M10.001,3.333C5.834,3.333 2.276,5.925 0.834,9.583C2.276,13.242 5.834,15.833 10.001,15.833C14.167,15.833 17.726,13.242 19.167,9.583C17.726,5.925 14.167,3.333 10.001,3.333ZM10.001,14.167C6.842,14.167 4.026,12.392 2.651,9.583C4.026,6.775 6.842,5 10.001,5C13.159,5 15.976,6.775 17.351,9.583C15.976,12.392 13.159,14.167 10.001,14.167Z"
android:fillColor="#191C1D"/>
</group>
</vector>
+21
View File
@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2023 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<shape xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
android:shape="rectangle" >
<solid android:color="?androidprv:attr/colorSurfaceVariant"/>
<corners android:radius="1dp" />
</shape>
+27
View File
@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2023 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="?android:attr/colorControlHighlight">
<item android:id="@android:id/mask">
<shape android:shape="rectangle">
<solid android:color="#FFFFFFFF"/>
<corners android:bottomLeftRadius="0dp"
android:bottomRightRadius="0dp"
android:topLeftRadius="@dimen/dialogCornerRadius"
android:topRightRadius="@dimen/dialogCornerRadius"/>
</shape>
</item>
</ripple>
+1 -8
View File
@@ -24,7 +24,7 @@
<item name="android:listPreferredItemPaddingStart">24dp</item>
<item name="android:navigationBarColor">@android:color/transparent</item>
<item name="android:statusBarColor">@android:color/transparent</item>
<item name="android:switchStyle">@style/HomeSettings.SwitchStyle</item>
<item name="android:switchStyle">@style/SwitchStyle</item>
<item name="android:textAppearanceListItem">@style/HomeSettings.PreferenceTitle</item>
<item name="android:windowActionBar">false</item>
<item name="android:windowNoTitle">true</item>
@@ -61,13 +61,6 @@
<item name="iconSpaceReserved">@bool/home_settings_icon_space_reserved</item>
</style>
<style name="HomeSettings.SwitchStyle"
parent="@android:style/Widget.Material.CompoundButton.Switch">
<item name="android:switchMinWidth">52dp</item>
<item name="android:thumb">@drawable/home_settings_switch_thumb</item>
<item name="android:track">@drawable/home_settings_switch_track</item>
</style>
<style name="HomeSettings.PreferenceTitle"
parent="@android:style/TextAppearance.Material.Subhead">
<item name="android:fontFamily">google-sans</item>
+1 -1
View File
@@ -23,7 +23,7 @@
<item name="android:listPreferredItemPaddingStart">24dp</item>
<item name="android:navigationBarColor">@android:color/transparent</item>
<item name="android:statusBarColor">@android:color/transparent</item>
<item name="android:switchStyle">@style/HomeSettings.SwitchStyle</item>
<item name="android:switchStyle">@style/SwitchStyle</item>
<item name="android:textAppearanceListItem">@style/HomeSettings.PreferenceTitle</item>
<item name="android:windowActionBar">false</item>
<item name="android:windowNoTitle">true</item>
+8 -1
View File
@@ -65,12 +65,19 @@
<item name="overviewScrimColor">@color/overview_scrim</item>
<item name="preloadIconAccentColor">@color/preload_icon_accent_color_light</item>
<item name="preloadIconBackgroundColor">@color/preload_icon_background_color_light</item>
<item name="android:windowTranslucentStatus">false</item>
<item name="android:windowTranslucentNavigation">false</item>
<item name="android:windowDrawsSystemBarBackgrounds">true</item>
<item name="android:statusBarColor">#00000000</item>
<item name="android:navigationBarColor">#00000000</item>
<item name="android:switchStyle">@style/SwitchStyle</item>
</style>
<style name="SwitchStyle"
parent="@android:style/Widget.Material.CompoundButton.Switch">
<item name="android:switchMinWidth">52dp</item>
<item name="android:thumb">@drawable/home_settings_switch_thumb</item>
<item name="android:track">@drawable/home_settings_switch_track</item>
</style>
<style name="LauncherTheme.DarkMainColor" parent="@style/LauncherTheme" />
@@ -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
@@ -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)
@@ -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