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

Commit 7b15a02b authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Implement expand menu error icon" into main

parents 9ccc4e8e d72cc8d2
Loading
Loading
Loading
Loading
+31 −0
Original line number Diff line number Diff line
<?xml version="1.0" encoding="utf-8"?>
<!--
  ~ Copyright (C) 2025 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="960"
    android:viewportHeight="960">

    <path
        android:fillColor="#FFB4AB"
        android:pathData="M480,0 A480,480 0 1,1 480,960 A480,480 0 1,1 480,0Z" />

    <path
        android:fillColor="#000000"
        android:fillType="evenOdd"
        android:pathData="M480,680Q497,680 508.5,668.5Q520,657 520,640Q520,623 508.5,611.5Q497,600 480,600Q463,600 451.5,611.5Q440,623 440,640Q440,657 451.5,668.5Q463,680 480,680ZM440,520L520,520L520,280L440,280L440,520Z" />
</vector>
+35 −14
Original line number Diff line number Diff line
@@ -43,23 +43,44 @@
            android:focusable="false"
            android:scaleType="centerCrop"/>

        <FrameLayout
            android:id="@+id/app_name_layout"
            android:layout_marginStart="8dp"
            android:layout_gravity="center_vertical"
            android:layout_weight="1"
            android:layout_width="0dp"
            android:layout_height="wrap_content">

            <TextView
                android:id="@+id/application_name"
            android:layout_width="0dp"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
            android:maxWidth="130dp"
                android:maxWidth="@dimen/desktop_mode_header_app_name_max_width"
                android:textSize="14sp"
                android:textFontWeight="500"
                android:lineHeight="20sp"
            android:layout_gravity="center_vertical"
            android:layout_weight="1"
            android:layout_marginStart="8dp"
                android:layout_gravity="start|center_vertical"
                android:singleLine="true"
            android:ellipsize="end"
                android:ellipsize="none"
                android:clickable="false"
                android:focusable="false"
                tools:text="Gmail"/>

            <ImageView
                android:id="@+id/expand_menu_error"
                android:src="@drawable/expand_menu_error"
                android:layout_width="@dimen/desktop_mode_header_expand_menu_error_image_width"
                android:layout_height="@dimen/desktop_mode_header_expand_menu_error_image_width"
                android:layout_gravity="end|center_vertical"
                android:layout_marginStart="@dimen/desktop_mode_header_expand_menu_error_image_margin"
                android:clickable="false"
                android:focusable="false"
                android:screenReaderFocusable="false"
                android:importantForAccessibility="no"
                android:contentDescription="@null"
                android:scaleType="centerCrop"/>
        </FrameLayout>

        <ImageButton
            android:id="@+id/expand_menu_button"
            android:layout_width="16dp"
+9 −0
Original line number Diff line number Diff line
@@ -661,6 +661,15 @@
    <!-- The horizontal inset to apply to the close button's ripple drawable -->
    <dimen name="desktop_mode_header_close_ripple_inset_horizontal">6dp</dimen>

    <!-- The max width of the app name shown on the app header -->
    <dimen name="desktop_mode_header_app_name_max_width">130dp</dimen>
    <!-- The width of the fadeout effect applied to a long app name shown on the app header -->
    <dimen name="desktop_mode_header_app_name_fadeout_width">48dp</dimen>
    <!-- The width of the expand menu error image on the app header -->
    <dimen name="desktop_mode_header_expand_menu_error_image_width">16dp</dimen>
    <!-- The margin added between app name and expand menu error image on the app header -->
    <dimen name="desktop_mode_header_expand_menu_error_image_margin">8dp</dimen>

    <!-- The padding added to all sides of windowing education tooltip -->
    <dimen name="desktop_windowing_education_tooltip_padding">8dp</dimen>

+91 −0
Original line number Diff line number Diff line
@@ -22,10 +22,13 @@ import android.content.res.ColorStateList
import android.content.res.Configuration
import android.graphics.Bitmap
import android.graphics.Color
import android.graphics.LinearGradient
import android.graphics.Rect
import android.graphics.Shader
import android.os.Bundle
import android.view.View
import android.view.View.OnLongClickListener
import android.view.ViewTreeObserver
import android.view.ViewTreeObserver.OnGlobalLayoutListener
import android.view.accessibility.AccessibilityEvent
import android.view.accessibility.AccessibilityNodeInfo
@@ -48,6 +51,7 @@ import com.android.internal.R.color.materialColorSecondaryContainer
import com.android.internal.R.color.materialColorSurfaceContainerHigh
import com.android.internal.R.color.materialColorSurfaceContainerLow
import com.android.internal.R.color.materialColorSurfaceDim
import com.android.window.flags.Flags
import com.android.wm.shell.R
import com.android.wm.shell.desktopmode.DesktopModeUiEventLogger
import com.android.wm.shell.desktopmode.DesktopModeUiEventLogger.DesktopUiEventEnum.A11Y_ACTION_MAXIMIZE_RESTORE
@@ -66,6 +70,7 @@ import com.android.wm.shell.windowdecor.common.Theme
import com.android.wm.shell.windowdecor.common.createBackgroundDrawable
import com.android.wm.shell.windowdecor.extension.isLightCaptionBarAppearance
import com.android.wm.shell.windowdecor.extension.isTransparentCaptionBarAppearance
import kotlin.math.roundToInt

/**
 * A desktop mode window decoration used when the window is floating (i.e. freeform). It hosts
@@ -104,6 +109,30 @@ class AppHeaderViewHolder(
    private val headerButtonsRippleRadius = context.resources
        .getDimensionPixelSize(R.dimen.desktop_mode_header_buttons_ripple_radius)

    /**
     * The max width of the app name shown on the app header.
     **/
    private val appNameMaxWidth = context.resources
        .getDimensionPixelSize(R.dimen.desktop_mode_header_app_name_max_width)

    /**
     * The width of the fadeout effect applied to a long app name shown on the app header.
     **/
    private val appNameFadeoutWidth = context.resources
        .getDimensionPixelSize(R.dimen.desktop_mode_header_app_name_fadeout_width)

    /**
     * The width of the expand menu error image on the app header.
     **/
    private val expandMenuErrorImageWidth = context.resources
        .getDimensionPixelSize(R.dimen.desktop_mode_header_expand_menu_error_image_width)

    /**
     * The margin added between app name and expand menu error image on the app header.
     **/
    private val expandMenuErrorImageMargin = context.resources
        .getDimensionPixelSize(R.dimen.desktop_mode_header_expand_menu_error_image_margin)

    /**
     * The app chip, minimize, maximize and close button's height extends to the top & bottom edges
     * of the header, and their width may be larger than their height. This is by design to increase
@@ -147,6 +176,9 @@ class AppHeaderViewHolder(
    private val minimizeWindowButton: ImageButton = rootView.requireViewById(R.id.minimize_window)
    private val appNameTextView: TextView = rootView.requireViewById(R.id.application_name)
    private val appIconImageView: ImageView = rootView.requireViewById(R.id.application_icon)
    private val expandMenuErrorImageView: ImageView =
        rootView.requireViewById(R.id.expand_menu_error)

    val appNameTextWidth: Int
        get() = appNameTextView.width

@@ -349,6 +381,60 @@ class AppHeaderViewHolder(
        a11yTextRestore = context.getString(R.string.restore_button_text, name)

        updateMaximizeButtonContentDescription()
        updateAppNameLayoutAndEffect()
    }

    private fun updateAppNameLayoutAndEffect() {
        if (!Flags.enableRestartMenuForConnectedDisplays()) return
        appNameTextView.viewTreeObserver.addOnPreDrawListener(
            object : ViewTreeObserver.OnPreDrawListener {
                override fun onPreDraw(): Boolean {
                    appNameTextView.viewTreeObserver.removeOnPreDrawListener(this)
                    val errorIconWidth =
                        expandMenuErrorImageWidth + expandMenuErrorImageMargin
                    val textWidth =
                        appNameTextView.paint.measureText(appNameTextView.text.toString())
                            .roundToInt()
                    val isRestartMenuShown =
                        currentTaskInfo.appCompatTaskInfo.isRestartMenuEnabledForDisplayMove

                    // Adjust the right padding of the app text so the error icon will be placed
                    // properly. In case the text is short enough, the padding will be
                    // |errorIconWidth| so the error icon will look like being placed to the right
                    // of the text. Otherwise, the error icon will overlap with the text.
                    val errorIconPadding = if (isRestartMenuShown && textWidth <= appNameMaxWidth) {
                        minOf(appNameMaxWidth - textWidth, errorIconWidth)
                    } else {
                        0
                    }
                    appNameTextView.setPaddingRelative(0, 0, errorIconPadding, 0)

                    // In case the app text (and the error icon) is too long to fit in the app
                    // header, fade out the text by applying the custom shader.
                    val availableWidth = if (isRestartMenuShown) {
                        appNameMaxWidth - errorIconWidth
                    } else {
                        appNameMaxWidth
                    }
                    if (textWidth > availableWidth) {
                        val textColor = appNameTextView.currentTextColor
                        val transparentColor = Color.argb(
                            0, Color.red(textColor),
                            Color.green(textColor), Color.blue(textColor)
                        )
                        appNameTextView.paint.shader = LinearGradient(
                            (availableWidth - appNameFadeoutWidth).toFloat(),
                            0f,
                            availableWidth.toFloat(),
                            0f,
                            textColor,
                            transparentColor,
                            Shader.TileMode.CLAMP
                        )
                    }
                    return true
                }
        })
    }

    private fun updateMaximizeButtonContentDescription() {
@@ -412,6 +498,7 @@ class AppHeaderViewHolder(
        minimizeWindowButton.imageAlpha = alpha
        closeWindowButton.imageAlpha = alpha
        expandMenuButton.imageAlpha = alpha
        expandMenuErrorImageView.imageAlpha = alpha
        context.withStyledAttributes(
            set = null,
            attrs = intArrayOf(
@@ -467,6 +554,9 @@ class AppHeaderViewHolder(
                drawableInsets = appChipDrawableInsets,
            )
            expandMenuButton.imageTintList = colorStateList
            expandMenuErrorImageView.visibility =
                if (currentTaskInfo.appCompatTaskInfo.isRestartMenuEnabledForDisplayMove)
                    View.VISIBLE else View.GONE
            appNameTextView.apply {
                isVisible = header.type == Header.Type.DEFAULT
                setTextColor(colorStateList)
@@ -524,6 +614,7 @@ class AppHeaderViewHolder(
                }
            }
            updateMaximizeButtonContentDescription()
            updateAppNameLayoutAndEffect()
        }
        // Close button.
        closeWindowButton.apply {