1 /*
2 * Copyright (C) 2024 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 package com.android.wm.shell.desktopmode.common
17
18 import android.graphics.Rect
19 import com.android.internal.jank.Cuj
20 import com.android.wm.shell.desktopmode.DesktopModeEventLogger.Companion.InputMethod
21 import com.android.wm.shell.desktopmode.DesktopModeEventLogger.Companion.ResizeTrigger
22 import com.android.wm.shell.desktopmode.DesktopModeUiEventLogger.DesktopUiEventEnum
23 import com.android.wm.shell.desktopmode.common.ToggleTaskSizeInteraction.AmbiguousSource
24 import com.android.wm.shell.desktopmode.common.ToggleTaskSizeInteraction.Source
25
26 /** Represents a user interaction to toggle a desktop task's size from to maximize or vice versa. */
27 data class ToggleTaskSizeInteraction
28 @JvmOverloads
29 constructor(
30 val direction: Direction,
31 val source: Source,
32 val inputMethod: InputMethod,
33 val animationStartBounds: Rect? = null,
34 ) {
35 constructor(
36 isMaximized: Boolean,
37 source: Source,
38 inputMethod: InputMethod,
39 ) : this(
40 direction = if (isMaximized) Direction.RESTORE else Direction.MAXIMIZE,
41 source = source,
42 inputMethod = inputMethod,
43 )
44
45 val jankTag: String? =
46 when (source) {
47 Source.HEADER_BUTTON_TO_MAXIMIZE -> "caption_bar_button"
48 Source.HEADER_BUTTON_TO_RESTORE -> "caption_bar_button"
49 Source.KEYBOARD_SHORTCUT -> null
50 Source.HEADER_DRAG_TO_TOP -> null
51 Source.MAXIMIZE_MENU_TO_MAXIMIZE -> "maximize_menu"
52 Source.MAXIMIZE_MENU_TO_RESTORE -> "maximize_menu"
53 Source.DOUBLE_TAP_TO_MAXIMIZE -> "double_tap"
54 Source.DOUBLE_TAP_TO_RESTORE -> "double_tap"
55 }
56 val uiEvent: DesktopUiEventEnum? =
57 when (source) {
58 Source.HEADER_BUTTON_TO_MAXIMIZE ->
59 DesktopUiEventEnum.DESKTOP_WINDOW_MAXIMIZE_BUTTON_TAP
60 Source.HEADER_BUTTON_TO_RESTORE -> DesktopUiEventEnum.DESKTOP_WINDOW_RESTORE_BUTTON_TAP
61 Source.KEYBOARD_SHORTCUT -> null
62 Source.HEADER_DRAG_TO_TOP -> null
63 Source.MAXIMIZE_MENU_TO_MAXIMIZE -> {
64 DesktopUiEventEnum.DESKTOP_WINDOW_MAXIMIZE_BUTTON_MENU_TAP_TO_MAXIMIZE
65 }
66 Source.MAXIMIZE_MENU_TO_RESTORE -> {
67 DesktopUiEventEnum.DESKTOP_WINDOW_MAXIMIZE_BUTTON_MENU_TAP_TO_RESTORE
68 }
69 Source.DOUBLE_TAP_TO_MAXIMIZE -> {
70 DesktopUiEventEnum.DESKTOP_WINDOW_HEADER_DOUBLE_TAP_TO_MAXIMIZE
71 }
72 Source.DOUBLE_TAP_TO_RESTORE -> {
73 DesktopUiEventEnum.DESKTOP_WINDOW_HEADER_DOUBLE_TAP_TO_RESTORE
74 }
75 }
76 val resizeTrigger =
77 when (source) {
78 Source.HEADER_BUTTON_TO_MAXIMIZE -> ResizeTrigger.MAXIMIZE_BUTTON
79 Source.HEADER_BUTTON_TO_RESTORE -> ResizeTrigger.MAXIMIZE_BUTTON
80 Source.KEYBOARD_SHORTCUT -> ResizeTrigger.UNKNOWN_RESIZE_TRIGGER
81 Source.HEADER_DRAG_TO_TOP -> ResizeTrigger.DRAG_TO_TOP_RESIZE_TRIGGER
82 Source.MAXIMIZE_MENU_TO_MAXIMIZE -> ResizeTrigger.MAXIMIZE_MENU
83 Source.MAXIMIZE_MENU_TO_RESTORE -> ResizeTrigger.MAXIMIZE_MENU
84 Source.DOUBLE_TAP_TO_MAXIMIZE -> ResizeTrigger.DOUBLE_TAP_APP_HEADER
85 Source.DOUBLE_TAP_TO_RESTORE -> ResizeTrigger.DOUBLE_TAP_APP_HEADER
86 }
87 val cujTracing: Int? =
88 when (source) {
89 Source.HEADER_BUTTON_TO_MAXIMIZE -> Cuj.CUJ_DESKTOP_MODE_MAXIMIZE_WINDOW
90 Source.HEADER_BUTTON_TO_RESTORE -> Cuj.CUJ_DESKTOP_MODE_UNMAXIMIZE_WINDOW
91 Source.KEYBOARD_SHORTCUT -> null
92 Source.HEADER_DRAG_TO_TOP -> null
93 Source.MAXIMIZE_MENU_TO_MAXIMIZE -> null
94 Source.MAXIMIZE_MENU_TO_RESTORE -> null
95 Source.DOUBLE_TAP_TO_MAXIMIZE -> null
96 Source.DOUBLE_TAP_TO_RESTORE -> null
97 }
98
99 /** The direction to which the task is being resized. */
100 enum class Direction {
101 MAXIMIZE,
102 RESTORE,
103 }
104
105 /** The user interaction source. */
106 enum class Source {
107 HEADER_BUTTON_TO_MAXIMIZE,
108 HEADER_BUTTON_TO_RESTORE,
109 KEYBOARD_SHORTCUT,
110 HEADER_DRAG_TO_TOP,
111 MAXIMIZE_MENU_TO_MAXIMIZE,
112 MAXIMIZE_MENU_TO_RESTORE,
113 DOUBLE_TAP_TO_MAXIMIZE,
114 DOUBLE_TAP_TO_RESTORE,
115 }
116
117 /**
118 * Temporary sources for interactions that should be broken into more specific sources, for
119 * example, the header button click should use [Source.HEADER_BUTTON_TO_MAXIMIZE] and
120 * [Source.HEADER_BUTTON_TO_RESTORE].
121 *
122 * TODO: b/341320112 - break these out into different [Source]s.
123 */
124 enum class AmbiguousSource {
125 HEADER_BUTTON,
126 MAXIMIZE_MENU,
127 DOUBLE_TAP,
128 }
129 }
130
131 /** Returns the non-ambiguous [Source] based on the maximized state of the task. */
AmbiguousSourcenull132 fun AmbiguousSource.toSource(isMaximized: Boolean): Source {
133 return when (this) {
134 AmbiguousSource.HEADER_BUTTON ->
135 if (isMaximized) {
136 Source.HEADER_BUTTON_TO_RESTORE
137 } else {
138 Source.HEADER_BUTTON_TO_MAXIMIZE
139 }
140 AmbiguousSource.MAXIMIZE_MENU ->
141 if (isMaximized) {
142 Source.MAXIMIZE_MENU_TO_RESTORE
143 } else {
144 Source.MAXIMIZE_MENU_TO_MAXIMIZE
145 }
146 AmbiguousSource.DOUBLE_TAP ->
147 if (isMaximized) {
148 Source.DOUBLE_TAP_TO_RESTORE
149 } else {
150 Source.DOUBLE_TAP_TO_MAXIMIZE
151 }
152 }
153 }
154