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

Commit 22702c66 authored by Giulio Fiscella's avatar Giulio Fiscella Committed by Automerger Merge Worker
Browse files

Merge changes from topic "scPermDialog" into udc-qpr-dev am: afb88164 am: bd6b9112

parents 21cbab2c bd6b9112
Loading
Loading
Loading
Loading
+5 −90
Original line number Diff line number Diff line
@@ -32,11 +32,10 @@ import android.view.ViewRootImpl
import android.view.WindowInsets
import android.view.WindowManager
import android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS
import android.widget.FrameLayout
import com.android.app.animation.Interpolators
import com.android.internal.jank.InteractionJankMonitor
import com.android.internal.jank.InteractionJankMonitor.CujType
import com.android.systemui.animation.view.LaunchableFrameLayout
import com.android.systemui.util.maybeForceFullscreen
import com.android.systemui.util.registerAnimationOnBackInvoked
import kotlin.math.roundToInt

@@ -622,96 +621,12 @@ private class AnimatedDialog(

                viewGroupWithBackground
            } else {
                // We will make the dialog window (and therefore its DecorView) fullscreen to make
                // it possible to animate outside its bounds.
                //
                // Before that, we add a new View as a child of the DecorView with the same size and
                // gravity as that DecorView, then we add all original children of the DecorView to
                // that new View. Finally we remove the background of the DecorView and add it to
                // the new View, then we make the DecorView fullscreen. This new View now acts as a
                // fake (non fullscreen) window.
                //
                // On top of that, we also add a fullscreen transparent background between the
                // DecorView and the view that we added so that we can dismiss the dialog when this
                // view is clicked. This is necessary because DecorView overrides onTouchEvent and
                // therefore we can't set the click listener directly on the (now fullscreen)
                // DecorView.
                val fullscreenTransparentBackground = FrameLayout(dialog.context)
                decorView.addView(
                    fullscreenTransparentBackground,
                    0 /* index */,
                    FrameLayout.LayoutParams(MATCH_PARENT, MATCH_PARENT)
                )

                val dialogContentWithBackground = LaunchableFrameLayout(dialog.context)
                dialogContentWithBackground.background = decorView.background

                // Make the window background transparent. Note that setting the window (or
                // DecorView) background drawable to null leads to issues with background color (not
                // being transparent) or with insets that are not refreshed. Therefore we need to
                // set it to something not null, hence we are using android.R.color.transparent
                // here.
                window.setBackgroundDrawableResource(android.R.color.transparent)

                // Close the dialog when clicking outside of it.
                fullscreenTransparentBackground.setOnClickListener { dialog.dismiss() }
                dialogContentWithBackground.isClickable = true

                // Make sure the transparent and dialog backgrounds are not focusable by
                // accessibility
                // features.
                fullscreenTransparentBackground.importantForAccessibility =
                    View.IMPORTANT_FOR_ACCESSIBILITY_NO
                dialogContentWithBackground.importantForAccessibility =
                    View.IMPORTANT_FOR_ACCESSIBILITY_NO

                fullscreenTransparentBackground.addView(
                    dialogContentWithBackground,
                    FrameLayout.LayoutParams(
                        window.attributes.width,
                        window.attributes.height,
                        window.attributes.gravity
                    )
                )

                // Move all original children of the DecorView to the new View we just added.
                for (i in 1 until decorView.childCount) {
                    val view = decorView.getChildAt(1)
                    decorView.removeViewAt(1)
                    dialogContentWithBackground.addView(view)
                }

                // Make the window fullscreen and add a layout listener to ensure it stays
                // fullscreen.
                window.setLayout(MATCH_PARENT, MATCH_PARENT)
                decorViewLayoutListener =
                    View.OnLayoutChangeListener {
                        v,
                        left,
                        top,
                        right,
                        bottom,
                        oldLeft,
                        oldTop,
                        oldRight,
                        oldBottom ->
                        if (
                            window.attributes.width != MATCH_PARENT ||
                                window.attributes.height != MATCH_PARENT
                        ) {
                            // The dialog size changed, copy its size to dialogContentWithBackground
                            // and make the dialog window full screen again.
                            val layoutParams = dialogContentWithBackground.layoutParams
                            layoutParams.width = window.attributes.width
                            layoutParams.height = window.attributes.height
                            dialogContentWithBackground.layoutParams = layoutParams
                            window.setLayout(MATCH_PARENT, MATCH_PARENT)
                        }
                    }
                decorView.addOnLayoutChangeListener(decorViewLayoutListener)

                val (dialogContentWithBackground, decorViewLayoutListener) =
                    dialog.maybeForceFullscreen()!!
                this.decorViewLayoutListener = decorViewLayoutListener
                dialogContentWithBackground
            }

        this.dialogContentWithBackground = dialogContentWithBackground
        dialogContentWithBackground.setTag(R.id.tag_dialog_background, true)

+111 −0
Original line number Diff line number Diff line
@@ -18,6 +18,9 @@ package com.android.systemui.util

import android.app.Dialog
import android.view.View
import android.view.ViewGroup
import android.view.ViewGroup.LayoutParams.MATCH_PARENT
import android.widget.FrameLayout
import android.window.OnBackInvokedDispatcher
import com.android.systemui.animation.back.BackAnimationSpec
import com.android.systemui.animation.back.BackTransformation
@@ -25,6 +28,7 @@ import com.android.systemui.animation.back.applyTo
import com.android.systemui.animation.back.floatingSystemSurfacesForSysUi
import com.android.systemui.animation.back.onBackAnimationCallbackFrom
import com.android.systemui.animation.back.registerOnBackInvokedCallbackOnViewAttached
import com.android.systemui.animation.view.LaunchableFrameLayout

/**
 * Register on the Dialog's [OnBackInvokedDispatcher] an animation using the [BackAnimationSpec].
@@ -49,3 +53,110 @@ fun Dialog.registerAnimationOnBackInvoked(
            ),
    )
}

/**
 * Make the dialog window (and therefore its DecorView) fullscreen to make it possible to animate
 * outside its bounds. No-op if the dialog is already fullscreen.
 *
 * <p>Returns null if the dialog is already fullscreen. Otherwise, returns a pair containing a view
 * and a layout listener. The new view matches the original dialog DecorView in size, position, and
 * background. This new view will be a child of the modified, transparent, fullscreen DecorView. The
 * layout listener is listening to changes to the modified DecorView. It is the responsibility of
 * the caller to deregister the listener when the dialog is dismissed.
 */
fun Dialog.maybeForceFullscreen(): Pair<LaunchableFrameLayout, View.OnLayoutChangeListener>? {
    // Create the dialog so that its onCreate() method is called, which usually sets the dialog
    // content.
    create()

    val window = window!!
    val decorView = window.decorView as ViewGroup

    val isWindowFullscreen =
        window.attributes.width == MATCH_PARENT && window.attributes.height == MATCH_PARENT
    if (isWindowFullscreen) {
        return null
    }

    // We will make the dialog window (and therefore its DecorView) fullscreen to make it possible
    // to animate outside its bounds.
    //
    // Before that, we add a new View as a child of the DecorView with the same size and gravity as
    // that DecorView, then we add all original children of the DecorView to that new View. Finally
    // we remove the background of the DecorView and add it to the new View, then we make the
    // DecorView fullscreen. This new View now acts as a fake (non fullscreen) window.
    //
    // On top of that, we also add a fullscreen transparent background between the DecorView and the
    // view that we added so that we can dismiss the dialog when this view is clicked. This is
    // necessary because DecorView overrides onTouchEvent and therefore we can't set the click
    // listener directly on the (now fullscreen) DecorView.
    val fullscreenTransparentBackground = FrameLayout(context)
    decorView.addView(
        fullscreenTransparentBackground,
        0 /* index */,
        FrameLayout.LayoutParams(MATCH_PARENT, MATCH_PARENT)
    )

    val dialogContentWithBackground = LaunchableFrameLayout(context)
    dialogContentWithBackground.background = decorView.background

    // Make the window background transparent. Note that setting the window (or DecorView)
    // background drawable to null leads to issues with background color (not being transparent) or
    // with insets that are not refreshed. Therefore we need to set it to something not null, hence
    // we are using android.R.color.transparent here.
    window.setBackgroundDrawableResource(android.R.color.transparent)

    // Close the dialog when clicking outside of it.
    fullscreenTransparentBackground.setOnClickListener { dismiss() }
    dialogContentWithBackground.isClickable = true

    // Make sure the transparent and dialog backgrounds are not focusable by accessibility
    // features.
    fullscreenTransparentBackground.importantForAccessibility = View.IMPORTANT_FOR_ACCESSIBILITY_NO
    dialogContentWithBackground.importantForAccessibility = View.IMPORTANT_FOR_ACCESSIBILITY_NO

    fullscreenTransparentBackground.addView(
        dialogContentWithBackground,
        FrameLayout.LayoutParams(
            window.attributes.width,
            window.attributes.height,
            window.attributes.gravity
        )
    )

    // Move all original children of the DecorView to the new View we just added.
    for (i in 1 until decorView.childCount) {
        val view = decorView.getChildAt(1)
        decorView.removeViewAt(1)
        dialogContentWithBackground.addView(view)
    }

    // Make the window fullscreen and add a layout listener to ensure it stays fullscreen.
    window.setLayout(MATCH_PARENT, MATCH_PARENT)
    val decorViewLayoutListener =
        View.OnLayoutChangeListener {
            v,
            left,
            top,
            right,
            bottom,
            oldLeft,
            oldTop,
            oldRight,
            oldBottom ->
            if (
                window.attributes.width != MATCH_PARENT || window.attributes.height != MATCH_PARENT
            ) {
                // The dialog size changed, copy its size to dialogContentWithBackground and make
                // the dialog window full screen again.
                val layoutParams = dialogContentWithBackground.layoutParams
                layoutParams.width = window.attributes.width
                layoutParams.height = window.attributes.height
                dialogContentWithBackground.layoutParams = layoutParams
                window.setLayout(MATCH_PARENT, MATCH_PARENT)
            }
        }
    decorView.addOnLayoutChangeListener(decorViewLayoutListener)

    return dialogContentWithBackground to decorViewLayoutListener
}
+31 −0
Original line number Diff line number Diff line
<!--
  ~ 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.
  -->

<!-- TODO(b/273761935): This drawable night variant is identical to the standard drawable. Delete once the drawable cache correctly invalidates for attributes that reference colors that change when the UI mode changes. -->
<vector
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
    android:width="24dp"
    android:height="24dp"
    android:viewportWidth="24"
    android:viewportHeight="24">
  <path
      android:pathData="M0,12C0,5.373 5.373,0 12,0C18.627,0 24,5.373 24,12C24,18.627 18.627,24 12,24C5.373,24 0,18.627 0,12Z"
      android:fillColor="?androidprv:attr/materialColorSurfaceContainerHigh"/>
  <path
      android:pathData="M7.607,9.059L6.667,9.999L12,15.332L17.333,9.999L16.393,9.059L12,13.445"
      android:fillColor="?androidprv:attr/materialColorOnSurface"/>
</vector>
+31 −0
Original line number Diff line number Diff line
<!--
  ~ 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.
  -->

<!-- TODO(b/273761935): This drawable night variant is identical to the standard drawable. Delete once the drawable cache correctly invalidates for attributes that reference colors that change when the UI mode changes. -->
<vector
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
    android:width="24dp"
    android:height="24dp"
    android:viewportWidth="24"
    android:viewportHeight="24">
  <path
      android:pathData="M0,12C0,5.3726 5.3726,0 12,0C18.6274,0 24,5.3726 24,12C24,18.6274 18.6274,24 12,24C5.3726,24 0,18.6274 0,12Z"
      android:fillColor="?androidprv:attr/materialColorSurfaceContainerHigh"/>
  <path
      android:pathData="M16.3934,14.9393L17.3334,13.9993L12.0001,8.666L6.6667,13.9993L7.6068,14.9393L12.0001,10.5527"
      android:fillColor="?androidprv:attr/materialColorOnSurface"/>
</vector>
+29 −0
Original line number Diff line number Diff line
<!--
  ~ Copyright (C) 2022 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:colorControlHighlight">
    <item android:id="@android:id/background">
        <shape
            android:shape="oval"
            android:id="@id/background"
            android:gravity="center">
            <size
                android:height="24dp"
                android:width="24dp"/>
            <solid android:color="@android:color/white"/>
        </shape>
    </item>
</ripple>
 No newline at end of file
Loading