Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b00e0e0d authored by Jordan Demeulenaere's avatar Jordan Demeulenaere Committed by Automerger Merge Worker
Browse files

Merge "Animate the power menu when triggered from QS" into sc-v2-dev am: f1650d86

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/16214754

Change-Id: I1cb82550010b154e0696ee31a4cd990a0ff9d451
parents 536c260e f1650d86
Loading
Loading
Loading
Loading
+112 −61
Original line number Original line Diff line number Diff line
@@ -27,7 +27,6 @@ import android.os.Looper
import android.util.Log
import android.util.Log
import android.util.MathUtils
import android.util.MathUtils
import android.view.GhostView
import android.view.GhostView
import android.view.Gravity
import android.view.View
import android.view.View
import android.view.ViewGroup
import android.view.ViewGroup
import android.view.ViewTreeObserver.OnPreDrawListener
import android.view.ViewTreeObserver.OnPreDrawListener
@@ -87,10 +86,11 @@ class DialogLaunchAnimator(
        // If the parent of the view we are launching from is the background of some other animated
        // If the parent of the view we are launching from is the background of some other animated
        // dialog, then this means the caller intent is to launch a dialog from another dialog. In
        // dialog, then this means the caller intent is to launch a dialog from another dialog. In
        // this case, we also animate the parent (which is the dialog background).
        // this case, we also animate the parent (which is the dialog background).
        val animatedParent = openedDialogs
        val animatedParent = openedDialogs.firstOrNull {
            .firstOrNull { it.dialogContentParent == view.parent }
            it.dialogContentWithBackground == view || it.dialogContentWithBackground == view.parent
        val parentHostDialog = animatedParent?.hostDialog
        }
        val animateFrom = animatedParent?.dialogContentParent ?: view
        val dialogContentWithBackground = animatedParent?.dialogContentWithBackground
        val animateFrom = dialogContentWithBackground ?: view


        // Make sure we don't run the launch animation from the same view twice at the same time.
        // Make sure we don't run the launch animation from the same view twice at the same time.
        if (animateFrom.getTag(TAG_LAUNCH_ANIMATION_RUNNING) != null) {
        if (animateFrom.getTag(TAG_LAUNCH_ANIMATION_RUNNING) != null) {
@@ -109,7 +109,7 @@ class DialogLaunchAnimator(
                onDialogDismissed = { openedDialogs.remove(it) },
                onDialogDismissed = { openedDialogs.remove(it) },
                originalDialog = dialog,
                originalDialog = dialog,
                animateBackgroundBoundsChange,
                animateBackgroundBoundsChange,
                openedDialogs.firstOrNull { it.hostDialog == parentHostDialog }
                animatedParent
        )
        )
        val hostDialog = animatedDialog.hostDialog
        val hostDialog = animatedDialog.hostDialog
        openedDialogs.add(animatedDialog)
        openedDialogs.add(animatedDialog)
@@ -288,13 +288,12 @@ private class AnimatedDialog(
    private val hostDialogRoot = FrameLayout(context)
    private val hostDialogRoot = FrameLayout(context)


    /**
    /**
     * The parent of the original dialog content view, that serves as a fake window that will have
     * The dialog content with its background. When animating a fullscreen dialog, this is just the
     * the same size as the original dialog window and to which we will set the original dialog
     * first ViewGroup of the dialog that has a background. When animating a normal (not fullscreen)
     * window background.
     * dialog, this is an additional view that serves as a fake window that will have the same size
     * as the original dialog window and to which we will set the original dialog window background.
     */
     */
    val dialogContentParent = FrameLayout(context).apply {
    var dialogContentWithBackground: ViewGroup? = null
        id = DIALOG_CONTENT_PARENT_ID
    }


    /**
    /**
     * The background color of [originalDialogView], taking into consideration the [originalDialog]
     * The background color of [originalDialogView], taking into consideration the [originalDialog]
@@ -451,59 +450,87 @@ private class AnimatedDialog(
        hostDialogRoot.setOnClickListener { hostDialog.dismiss() }
        hostDialogRoot.setOnClickListener { hostDialog.dismiss() }
        dialogView.isClickable = true
        dialogView.isClickable = true


        // Set the background of the window dialog to the dialog itself.
        // Remove the original dialog view from its parent.
        // TODO(b/193634619): Support dialog windows without background.
        (dialogView.parent as? ViewGroup)?.removeView(dialogView)
        // TODO(b/193634619): Support dialog whose background comes from the content view instead of

        // the window.
        val originalDialogWindow = originalDialog.window!!
        val typedArray =
        val isOriginalWindowFullScreen =
            originalDialog.context.obtainStyledAttributes(com.android.internal.R.styleable.Window)
            originalDialogWindow.attributes.width == ViewGroup.LayoutParams.MATCH_PARENT &&
        val backgroundRes =
            originalDialogWindow.attributes.height == ViewGroup.LayoutParams.MATCH_PARENT
            typedArray.getResourceId(com.android.internal.R.styleable.Window_windowBackground, 0)
        if (isOriginalWindowFullScreen) {
        typedArray.recycle()
            // If the original dialog window is fullscreen, then we look for the first ViewGroup
        if (backgroundRes == 0) {
            // that has a background and animate towards that ViewGroup given that this is probably
            throw IllegalStateException("Dialogs with no backgrounds on window are not supported")
            // what represents the actual dialog view.
        }
            dialogContentWithBackground = findFirstViewGroupWithBackground(dialogView)

                ?: throw IllegalStateException("Unable to find ViewGroup with background")
        // Add a parent view to the original dialog view to which we will set the original dialog

        // window background. This View serves as a fake window with background, so that we are sure
        // that we don't override the dialog view paddings with the window background that usually
        // has insets.
        dialogContentParent.setBackgroundResource(backgroundRes)
            hostDialogRoot.addView(
            hostDialogRoot.addView(
            dialogContentParent,
                dialogView,


            // We give it the size of its original dialog window.
                FrameLayout.LayoutParams(
                FrameLayout.LayoutParams(
                originalDialog.window.attributes.width,
                    ViewGroup.LayoutParams.MATCH_PARENT,
                originalDialog.window.attributes.height,
                    ViewGroup.LayoutParams.MATCH_PARENT
                Gravity.CENTER
                )
                )
            )
            )
        } else {
            // Add a parent view to the original dialog view to which we will set the original
            // dialog window background. This View serves as a fake window with background, so that
            // we are sure that we don't override the original dialog content view paddings with the
            // window background that usually has insets.
            dialogContentWithBackground = FrameLayout(context).apply {
                id = DIALOG_CONTENT_PARENT_ID


        // Make the dialog view parent invisible for now, to make sure it's not drawn yet.
                // TODO(b/193634619): Support dialog windows without background.
        dialogContentParent.visibility = View.INVISIBLE
                background = originalDialogWindow.decorView?.background

                    ?: throw IllegalStateException(
        val background = dialogContentParent.background!!
                        "Dialogs with no backgrounds on window are not supported")
        originalDialogBackgroundColor =
            GhostedViewLaunchAnimatorController.findGradientDrawable(background)
                ?.color
                ?.defaultColor ?: Color.BLACK


        // Add the dialog view to its parent (that has the original window background).
                addView(
        (dialogView.parent as? ViewGroup)?.removeView(dialogView)
        dialogContentParent.addView(
                    dialogView,
                    dialogView,


            // It should match its parent size, which is sized the same as the original dialog
                    // It should match its parent size, which is sized the same as the original
            // window.
                    // dialog window.
                    FrameLayout.LayoutParams(
                    FrameLayout.LayoutParams(
                        ViewGroup.LayoutParams.MATCH_PARENT,
                        ViewGroup.LayoutParams.MATCH_PARENT,
                        ViewGroup.LayoutParams.MATCH_PARENT
                        ViewGroup.LayoutParams.MATCH_PARENT
                    )
                    )
                )
                )
            }

            // Add the parent (that has the background) to the host window.
            hostDialogRoot.addView(
                dialogContentWithBackground,

                // We give it the size and gravity of its original dialog window.
                FrameLayout.LayoutParams(
                    originalDialogWindow.attributes.width,
                    originalDialogWindow.attributes.height,
                    originalDialogWindow.attributes.gravity
                )
            )
        }

        val dialogContentWithBackground = this.dialogContentWithBackground!!

        // Make the dialog and its background invisible for now, to make sure it's not drawn yet.
        dialogContentWithBackground.visibility = View.INVISIBLE

        val background = dialogContentWithBackground.background!!
        originalDialogBackgroundColor =
            GhostedViewLaunchAnimatorController.findGradientDrawable(background)
                ?.color
                ?.defaultColor ?: Color.BLACK

        if (isOriginalWindowFullScreen) {
            // If the original window is full screen, the ViewGroup with background might already be
            // correctly laid out. Make sure we relayout and that the layout listener below is still
            // called.
            dialogContentWithBackground.layout(0, 0, 0, 0)
            dialogContentWithBackground.requestLayout()
        }


        // Start the animation when the dialog is laid out in the center of the host dialog.
        // Start the animation when the dialog is laid out in the center of the host dialog.
        dialogContentParent.addOnLayoutChangeListener(object : View.OnLayoutChangeListener {
        dialogContentWithBackground.addOnLayoutChangeListener(object : View.OnLayoutChangeListener {
            override fun onLayoutChange(
            override fun onLayoutChange(
                view: View,
                view: View,
                left: Int,
                left: Int,
@@ -515,7 +542,7 @@ private class AnimatedDialog(
                oldRight: Int,
                oldRight: Int,
                oldBottom: Int
                oldBottom: Int
            ) {
            ) {
                dialogContentParent.removeOnLayoutChangeListener(this)
                dialogContentWithBackground.removeOnLayoutChangeListener(this)


                isOriginalDialogViewLaidOut = true
                isOriginalDialogViewLaidOut = true
                maybeStartLaunchAnimation()
                maybeStartLaunchAnimation()
@@ -523,6 +550,25 @@ private class AnimatedDialog(
        })
        })
    }
    }


    private fun findFirstViewGroupWithBackground(view: View): ViewGroup? {
        if (view !is ViewGroup) {
            return null
        }

        if (view.background != null) {
            return view
        }

        for (i in 0 until view.childCount) {
            val match = findFirstViewGroupWithBackground(view.getChildAt(i))
            if (match != null) {
                return match
            }
        }

        return null
    }

    fun onOriginalDialogSizeChanged() {
    fun onOriginalDialogSizeChanged() {
        // The dialog is the single child of the root.
        // The dialog is the single child of the root.
        if (hostDialogRoot.childCount != 1) {
        if (hostDialogRoot.childCount != 1) {
@@ -571,7 +617,8 @@ private class AnimatedDialog(
                // at the end of the launch animation, because the lauch animation already correctly
                // at the end of the launch animation, because the lauch animation already correctly
                // handles bounds changes.
                // handles bounds changes.
                if (backgroundLayoutListener != null) {
                if (backgroundLayoutListener != null) {
                    dialogContentParent.addOnLayoutChangeListener(backgroundLayoutListener)
                    dialogContentWithBackground!!
                        .addOnLayoutChangeListener(backgroundLayoutListener)
                }
                }
            }
            }
        )
        )
@@ -638,10 +685,12 @@ private class AnimatedDialog(
                (touchSurface as? LaunchableView)?.setShouldBlockVisibilityChanges(false)
                (touchSurface as? LaunchableView)?.setShouldBlockVisibilityChanges(false)


                touchSurface.visibility = View.VISIBLE
                touchSurface.visibility = View.VISIBLE
                dialogContentParent.visibility = View.INVISIBLE
                val dialogContentWithBackground = this.dialogContentWithBackground!!
                dialogContentWithBackground.visibility = View.INVISIBLE


                if (backgroundLayoutListener != null) {
                if (backgroundLayoutListener != null) {
                    dialogContentParent.removeOnLayoutChangeListener(backgroundLayoutListener)
                    dialogContentWithBackground
                        .removeOnLayoutChangeListener(backgroundLayoutListener)
                }
                }


                // The animated ghost was just removed. We create a temporary ghost that will be
                // The animated ghost was just removed. We create a temporary ghost that will be
@@ -674,8 +723,8 @@ private class AnimatedDialog(
    ) {
    ) {
        // Create 2 ghost controllers to animate both the dialog and the touch surface in the host
        // Create 2 ghost controllers to animate both the dialog and the touch surface in the host
        // dialog.
        // dialog.
        val startView = if (isLaunching) touchSurface else dialogContentParent
        val startView = if (isLaunching) touchSurface else dialogContentWithBackground!!
        val endView = if (isLaunching) dialogContentParent else touchSurface
        val endView = if (isLaunching) dialogContentWithBackground!! else touchSurface
        val startViewController = GhostedViewLaunchAnimatorController(startView)
        val startViewController = GhostedViewLaunchAnimatorController(startView)
        val endViewController = GhostedViewLaunchAnimatorController(endView)
        val endViewController = GhostedViewLaunchAnimatorController(endView)
        startViewController.launchContainer = hostDialogRoot
        startViewController.launchContainer = hostDialogRoot
@@ -736,7 +785,9 @@ private class AnimatedDialog(
    }
    }


    private fun shouldAnimateDialogIntoView(): Boolean {
    private fun shouldAnimateDialogIntoView(): Boolean {
        if (exitAnimationDisabled) {
        // Don't animate if the dialog was previously hidden using hide() (either on the host dialog
        // or on the original dialog) or if we disabled the exit animation.
        if (exitAnimationDisabled || !hostDialog.isShowing) {
            return false
            return false
        }
        }


+4 −4
Original line number Original line Diff line number Diff line
@@ -373,11 +373,11 @@
        <item name="android:windowIsFloating">true</item>
        <item name="android:windowIsFloating">true</item>
    </style>
    </style>


    <style name="Theme.SystemUI.Dialog.GlobalActionsLite" parent="@android:style/Theme.DeviceDefault.Light.NoActionBar.Fullscreen">
    <style name="Theme.SystemUI.Dialog.GlobalActionsLite" parent="Theme.SystemUI.Dialog">
        <item name="android:windowIsFloating">true</item>
        <!-- Settings windowFullscreen: true is necessary to be able to intercept touch events -->
        <!-- that would otherwise be intercepted by the Shade. -->
        <item name="android:windowFullscreen">true</item>
        <item name="android:windowBackground">@android:color/transparent</item>
        <item name="android:windowBackground">@android:color/transparent</item>
        <item name="android:backgroundDimEnabled">true</item>
        <item name="android:windowCloseOnTouchOutside">true</item>
    </style>
    </style>


    <style name="QSBorderlessButton">
    <style name="QSBorderlessButton">
+89 −156

File changed.

Preview size limit exceeded, changes collapsed.

+1 −1
Original line number Original line Diff line number Diff line
@@ -82,7 +82,7 @@ public class GlobalActionsImpl implements GlobalActions, CommandQueue.Callbacks
        if (mDisabled) return;
        if (mDisabled) return;
        mGlobalActionsDialog = mGlobalActionsDialogLazy.get();
        mGlobalActionsDialog = mGlobalActionsDialogLazy.get();
        mGlobalActionsDialog.showOrHideDialog(mKeyguardStateController.isShowing(),
        mGlobalActionsDialog.showOrHideDialog(mKeyguardStateController.isShowing(),
                mDeviceProvisionedController.isDeviceProvisioned());
                mDeviceProvisionedController.isDeviceProvisioned(), null /* view */);
    }
    }


    @Override
    @Override
+1 −1
Original line number Original line Diff line number Diff line
@@ -116,7 +116,7 @@ class FooterActionsController @Inject constructor(
            }
            }
        } else if (v === powerMenuLite) {
        } else if (v === powerMenuLite) {
            uiEventLogger.log(GlobalActionsDialogLite.GlobalActionsEvent.GA_OPEN_QS)
            uiEventLogger.log(GlobalActionsDialogLite.GlobalActionsEvent.GA_OPEN_QS)
            globalActionsDialog.showOrHideDialog(false, true)
            globalActionsDialog.showOrHideDialog(false, true, v)
        }
        }
    }
    }


Loading