• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
17 package com.android.wm.shell.draganddrop.anim
18 
19 import android.content.res.Resources
20 import android.graphics.Insets
21 import android.graphics.Rect
22 import com.android.wm.shell.R
23 import com.android.wm.shell.common.DisplayLayout
24 import com.android.wm.shell.draganddrop.SplitDragPolicy.Target
25 import com.android.wm.shell.shared.split.SplitScreenConstants.SPLIT_INDEX_0
26 import com.android.wm.shell.shared.split.SplitScreenConstants.SPLIT_INDEX_1
27 import com.android.wm.shell.shared.split.SplitScreenConstants.SPLIT_INDEX_2
28 import com.android.wm.shell.shared.split.SplitScreenConstants.SPLIT_INDEX_3
29 
30 /**
31  * Represents Drop Zone targets and animations for when the system is currently in a 2 app 50/50
32  * split.
33  * SnapPosition = 2_50_50
34  *
35  * NOTE: Naming convention for many variables is done as "hXtYZ"
36  * This means that variable is a transformation on the Z property for target index Y while the user
37  * is hovering over target index X
38  * Ex: h1t2scaleX=2 => User is hovering over target index 1, target index 2 should scaleX by 2
39  *
40  * TODO(b/349828130): Everything in this class is temporary, none of this is up to spec.
41  */
42 class TwoFiftyFiftyTargetAnimator : DropTargetAnimSupplier {
43     /**
44      * TODO: Could we transpose all the horizontal rects by 90 degrees and have that suffice for
45      *  top bottom split?? Hmmm... Doubt it.
46      */
getTargetsnull47     override fun getTargets(
48         displayLayout: DisplayLayout,
49         insets: Insets,
50         isLeftRightSplit: Boolean,
51         resources: Resources
52     ): Pair<List<Target>, List<List<HoverAnimProps>>> {
53         val targets : ArrayList<Target> = ArrayList()
54         val w: Int = displayLayout.width()
55         val h: Int = displayLayout.height()
56         val iw = w - insets.left - insets.right
57         val ih = h - insets.top - insets.bottom
58         val l = insets.left
59         val t = insets.top
60         val displayRegion = Rect(l, t, l + iw, t + ih)
61         val fullscreenDrawRegion = Rect(displayRegion)
62         val dividerWidth: Float = resources.getDimensionPixelSize(
63             R.dimen.split_divider_bar_width
64         ).toFloat()
65 
66         val farStartBounds = Rect()
67         farStartBounds.set(displayRegion)
68         val startBounds = Rect()
69         startBounds.set(displayRegion)
70         val endBounds = Rect()
71         endBounds.set(displayRegion)
72         val farEndBounds = Rect()
73         farEndBounds.set(displayRegion)
74         val endsPercent = 0.10f
75         val visibleStagePercent = 0.45f
76         val halfDividerWidth = dividerWidth.toInt() / 2
77         val endsWidth = Math.round(displayRegion.width() * endsPercent)
78         val stageWidth = Math.round(displayRegion.width() * visibleStagePercent)
79 
80 
81         // Place the farStart and farEnds outside of the display, and then
82         // animate them in once the hover starts
83         // | = divider; || = display boundary
84         // farStart || start | end || farEnd
85         farStartBounds.left = -endsWidth
86         farStartBounds.right = 0
87         startBounds.left = farStartBounds.right + dividerWidth.toInt()
88         startBounds.right = startBounds.left + stageWidth
89         endBounds.left = startBounds.right + dividerWidth.toInt()
90         endBounds.right = endBounds.left + stageWidth
91         farEndBounds.left = fullscreenDrawRegion.right
92         farEndBounds.right = farEndBounds.left + endsWidth
93 
94 
95         // For the hit rect, trim the divider space we've added between the
96         // rects
97         targets.add(
98             Target(
99                 Target.TYPE_SPLIT_LEFT,
100                 Rect(
101                     farStartBounds.left, farStartBounds.top,
102                     farStartBounds.right + halfDividerWidth,
103                     farStartBounds.bottom
104                 ),
105                 farStartBounds, SPLIT_INDEX_0
106             )
107         )
108         targets.add(
109             Target(
110                 Target.TYPE_SPLIT_LEFT,
111                 Rect(
112                     startBounds.left - halfDividerWidth,
113                     startBounds.top,
114                     startBounds.right + halfDividerWidth,
115                     startBounds.bottom
116                 ),
117                 startBounds, SPLIT_INDEX_1
118             )
119         )
120         targets.add(
121             Target(
122                 Target.TYPE_SPLIT_LEFT,
123                 Rect(
124                     endBounds.left - halfDividerWidth,
125                     endBounds.top, endBounds.right, endBounds.bottom
126                 ),
127                 endBounds, SPLIT_INDEX_2
128             )
129         )
130         targets.add(
131             Target(
132                 Target.TYPE_SPLIT_LEFT,
133                 Rect(
134                     farEndBounds.left - halfDividerWidth,
135                     farEndBounds.top, farEndBounds.right, farEndBounds.bottom
136                 ),
137                 farEndBounds, SPLIT_INDEX_3
138             )
139         )
140 
141 
142         // Hovering over target 0,
143         // * increase scaleX of target 0
144         // * decrease scaleX of target 1, 2
145         // * ensure target 3 offscreen
146 
147         // bring target 0 in from offscreen and expand
148         val h0t0ScaleX = stageWidth.toFloat() / endsWidth
149         val h0t0TransX: Float = stageWidth / h0t0ScaleX + dividerWidth
150         val h0t0HoverProps = HoverAnimProps(
151             targets.get(0),
152             h0t0TransX, farStartBounds.top.toFloat(), h0t0ScaleX, 1f,
153             Rect(
154                 0, 0, (stageWidth + dividerWidth).toInt(),
155                 farStartBounds.bottom
156             )
157         )
158 
159 
160         // move target 1 over to the middle/end
161         val h0t1TransX = stageWidth.toFloat()
162         val h0t1ScaleX = 1f
163         val h0t1HoverProps = HoverAnimProps(
164             targets.get(1),
165             h0t1TransX, startBounds.top.toFloat(), h0t1ScaleX, 1f,
166             Rect(
167                 stageWidth, 0, (stageWidth + h0t1TransX).toInt(),
168                 farStartBounds.bottom
169             )
170         )
171 
172 
173         // move target 2 to the very end
174         val h0t2TransX = endBounds.left + stageWidth / 2f
175         val h0t2ScaleX = endsWidth.toFloat() / stageWidth
176         val h0t2HoverProps = HoverAnimProps(
177             targets.get(2),
178             h0t2TransX, endBounds.top.toFloat(), h0t2ScaleX, 1f,
179             Rect(
180                 displayRegion.right as Int - endsWidth, 0,
181                 displayRegion.right as Int,
182                 farStartBounds.bottom
183             )
184         )
185 
186 
187         // move target 3 off-screen
188         val h0t3TransX = farEndBounds.right.toFloat()
189         val h0t3ScaleX = 1f
190         val h0t3HoverProps = HoverAnimProps(
191             targets.get(3),
192             h0t3TransX, farEndBounds.top.toFloat(), h0t3ScaleX, 1f,
193             null
194         )
195         val animPropsForHoverTarget0 =
196             listOf(h0t0HoverProps, h0t1HoverProps, h0t2HoverProps, h0t3HoverProps)
197 
198 
199         // Hovering over target 1,
200         // * Bring in target 0 from offscreen start
201         // * Shift over target 1
202         // * Slightly lower scale of target 2
203         // * Ensure target 4 offscreen
204         // bring target 0 in from offscreen
205         val h1t0TransX = 0f
206         val h1t0ScaleX = 1f
207         val h1t0HoverProps = HoverAnimProps(
208             targets.get(0),
209             h1t0TransX, farStartBounds.top.toFloat(), h1t0ScaleX, 1f,
210             Rect(
211                 0, 0, (farStartBounds.width() + dividerWidth).toInt(),
212                 farStartBounds.bottom
213             )
214         )
215 
216 
217         // move target 1 over a tiny bit by same amount and make it smaller
218         val h1t1TransX: Float = endsWidth + dividerWidth
219         val h1t1ScaleX = 1f
220         val h1t1HoverProps = HoverAnimProps(
221             targets.get(1),
222             h1t1TransX, startBounds.top.toFloat(), h1t1ScaleX, 1f,
223             Rect(
224                 h1t1TransX.toInt(), 0, (h1t1TransX + stageWidth).toInt(),
225                 farStartBounds.bottom
226             )
227         )
228 
229 
230         // move target 2 to the very end
231         val h1t2TransX = (endBounds.left + farStartBounds.width()).toFloat()
232         val h1t2ScaleX = h1t1ScaleX
233         val h1t2HoverProps = HoverAnimProps(
234             targets.get(2),
235             h1t2TransX, endBounds.top.toFloat(), h1t2ScaleX, 1f,
236             Rect(
237                 endBounds.left + farStartBounds.width(),
238                 0,
239                 (endBounds.left + farStartBounds.width() + stageWidth),
240                 farStartBounds.bottom
241             )
242         )
243 
244 
245         // move target 3 off-screen, default laid out is off-screen
246         val h1t3TransX = farEndBounds.right.toFloat()
247         val h1t3ScaleX = 1f
248         val h1t3HoverProps = HoverAnimProps(
249             targets.get(3),
250             h1t3TransX, farEndBounds.top.toFloat(), h1t3ScaleX, 1f,
251             null
252         )
253         val animPropsForHoverTarget1 =
254             listOf(h1t0HoverProps, h1t1HoverProps, h1t2HoverProps, h1t3HoverProps)
255 
256 
257         // Hovering over target 2,
258         // * Ensure Target 0 offscreen
259         // * Ensure target 1 back to start, slightly smaller scale
260         // * Slightly lower scale of target 2
261         // * Bring target 4 on screen
262         // reset target 0
263         val h2t0TransX = farStartBounds.left.toFloat()
264         val h2t0ScaleX = 1f
265         val h2t0HoverProps = HoverAnimProps(
266             targets.get(0),
267             h2t0TransX, farStartBounds.top.toFloat(), h2t0ScaleX, 1f,
268             null
269         )
270 
271 
272         // move target 1 over a tiny bit by same amount and make it smaller
273         val h2t1TransX = startBounds.left.toFloat()
274         val h2t1ScaleX = 1f
275         val h2t1HoverProps = HoverAnimProps(
276             targets.get(1),
277             h2t1TransX, startBounds.top.toFloat(), h2t1ScaleX, 1f,
278             Rect(
279                 startBounds.left, 0,
280                 (startBounds.left + stageWidth),
281                 farStartBounds.bottom
282             )
283         )
284 
285 
286         // move target 2 to the very end
287         val h2t2TransX = endBounds.left.toFloat()
288         val h2t2ScaleX = h2t1ScaleX
289         val h2t2HoverProps = HoverAnimProps(
290             targets.get(2),
291             h2t2TransX, endBounds.top.toFloat(), h2t2ScaleX, 1f,
292             Rect(
293                 (startBounds.right + dividerWidth).toInt(),
294                 0,
295                 endBounds.left + stageWidth,
296                 farStartBounds.bottom
297             )
298         )
299 
300 
301         // bring target 3 on-screen
302         val h2t3TransX = (farEndBounds.left - farEndBounds.width()).toFloat()
303         val h2t3ScaleX = 1f
304         val h2t3HoverProps = HoverAnimProps(
305             targets.get(3),
306             h2t3TransX, farEndBounds.top.toFloat(), h2t3ScaleX, 1f,
307             Rect(
308                 endBounds.right,
309                 0,
310                 displayRegion.right,
311                 farStartBounds.bottom
312             )
313         )
314         val animPropsForHoverTarget2 =
315             listOf(h2t0HoverProps, h2t1HoverProps, h2t2HoverProps, h2t3HoverProps)
316 
317 
318         // Hovering over target 3,
319         // * Ensure Target 0 offscreen
320         // * Ensure target 1 back to start, slightly smaller scale
321         // * Slightly lower scale of target 2
322         // * Bring target 4 on screen and scale up
323         // reset target 0
324         val h3t0TransX = farStartBounds.left.toFloat()
325         val h3t0ScaleX = 1f
326         val h3t0HoverProps = HoverAnimProps(
327             targets.get(0),
328             h3t0TransX, farStartBounds.top.toFloat(), h3t0ScaleX, 1f,
329             null
330         )
331 
332 
333         // move target 1 over a tiny bit by same amount and make it smaller
334         val h3t1ScaleX = endsWidth.toFloat() / stageWidth
335         val h3t1TransX = 0 - (stageWidth / (1 / h3t1ScaleX))
336         val h3t1HoverProps = HoverAnimProps(
337             targets.get(1),
338             h3t1TransX, startBounds.top.toFloat(), h3t1ScaleX, 1f,
339             Rect(
340                 0, 0,
341                 endsWidth,
342                 farStartBounds.bottom
343             )
344         )
345 
346 
347         // move target 2 towards the start
348         val h3t2TransX: Float = endsWidth + dividerWidth
349         val h3t2ScaleX = 1f
350         val h3t2HoverProps = HoverAnimProps(
351             targets.get(2),
352             h3t2TransX, endBounds.top.toFloat(), h3t2ScaleX, 1f,
353             Rect(
354                 endsWidth, 0,
355                 (endsWidth + stageWidth + dividerWidth).toInt(),
356                 farStartBounds.bottom
357             )
358         )
359 
360 
361         // bring target 3 on-screen and expand
362         val h3t3ScaleX = stageWidth.toFloat() / endsWidth
363         val h3t3TransX = endBounds.right - stageWidth / 2f
364         val h3t3HoverProps = HoverAnimProps(
365             targets.get(3),
366             h3t3TransX, farEndBounds.top.toFloat(), h3t3ScaleX, 1f,
367             Rect(
368                 displayRegion.right - stageWidth, 0,
369                 displayRegion.right,
370                 farStartBounds.bottom
371             )
372         )
373         val animPropsForHoverTarget3 =
374             listOf(h3t0HoverProps, h3t1HoverProps, h3t2HoverProps, h3t3HoverProps)
375 
376         return Pair(targets, listOf(animPropsForHoverTarget0, animPropsForHoverTarget1,
377             animPropsForHoverTarget2, animPropsForHoverTarget3))
378 
379     }
380 }