abf18e9c03
Fix kotlin nullable errors that were exposed by setting the retention of android.annotation.NonNull and android.annotation.Nullable to class retention. This relands I26edfec35dca14abe90b08e3c74de0446eda95d2 with a fix in SplitSelectDataHolder.kt to call createPackageContext when user is null instead of asserting that it is not null. Bug: 294110802 Test: builds Test: WMShellFlickerServiceTests Change-Id: I4525d0fa83a1db9cc5cff90f340fc3f863537c01
204 lines
7.6 KiB
Kotlin
204 lines
7.6 KiB
Kotlin
/*
|
|
* 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.content.Intent
|
|
import android.graphics.Rect
|
|
import android.graphics.drawable.GradientDrawable
|
|
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
|
|
private const val SETTINGS_PACKAGE_NAME = "com.android.settings"
|
|
private const val CHANGE_NAVIGATION_MODE_ACTION =
|
|
"com.android.settings.NAVIGATION_MODE_SETTINGS"
|
|
|
|
@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: (preferenceChanged: Boolean) -> 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 = requireViewById<LinearLayout>(R.id.taskbar_switch_option)
|
|
val alwaysShowTaskbarSwitch = requireViewById<Switch>(R.id.taskbar_pinning_switch)
|
|
val navigationModeChangeOption =
|
|
requireViewById<LinearLayout>(R.id.navigation_mode_switch_option)
|
|
alwaysShowTaskbarSwitch.isChecked = alwaysShowTaskbarOn
|
|
taskbarSwitchOption.setOnClickListener {
|
|
alwaysShowTaskbarSwitch.isClickable = true
|
|
alwaysShowTaskbarSwitch.isChecked = !alwaysShowTaskbarOn
|
|
onClickAlwaysShowTaskbarSwitchOption()
|
|
}
|
|
navigationModeChangeOption.setOnClickListener {
|
|
context.startActivity(
|
|
Intent(CHANGE_NAVIGATION_MODE_ACTION)
|
|
.setPackage(SETTINGS_PACKAGE_NAME)
|
|
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
|
)
|
|
}
|
|
}
|
|
|
|
/** 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
|
|
tryUpdateBackground()
|
|
return this
|
|
}
|
|
|
|
/** Updates the text background to match the shape of this background (when applicable). */
|
|
private fun tryUpdateBackground() {
|
|
if (background !is GradientDrawable) {
|
|
return
|
|
}
|
|
val background = background as GradientDrawable
|
|
val color = context.getColor(R.color.popup_shade_first)
|
|
val backgroundMask = GradientDrawable()
|
|
backgroundMask.setColor(color)
|
|
backgroundMask.shape = GradientDrawable.RECTANGLE
|
|
if (background.cornerRadii != null) {
|
|
backgroundMask.cornerRadii = background.cornerRadii
|
|
} else {
|
|
backgroundMask.cornerRadius = background.cornerRadius
|
|
}
|
|
|
|
setBackground(backgroundMask)
|
|
}
|
|
|
|
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
|
|
context.getColor(R.color.popup_shade_first),
|
|
)
|
|
elevation = mElevation
|
|
mArrow.elevation = mElevation
|
|
}
|
|
}
|
|
|
|
override fun closeComplete() {
|
|
onCloseCallback(didPreferenceChange)
|
|
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) }
|
|
}
|
|
}
|