1 /*
2 * Copyright 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 androidx.xr.compose.subspace.layout
18
19 import androidx.annotation.RestrictTo
20 import androidx.xr.compose.subspace.node.LayoutCoordinatesAwareModifierNode
21 import androidx.xr.compose.subspace.node.SubspaceModifierNodeElement
22
23 /**
24 * Invoke [onGloballyPositioned] with the [SubspaceLayoutCoordinates] of the element when the global
25 * position of the content may have changed. Note that it will be called **after** a composition
26 * when the coordinates are finalized.
27 *
28 * This callback will be invoked at least once when the [SubspaceLayoutCoordinates] are available,
29 * and every time the element's position changes within the window. However, it is not guaranteed to
30 * be invoked every time the position _relative to the screen_ of the modified element changes. For
31 * example, the system may move the contents inside a window around without firing a callback. If
32 * you are using the [SubspaceLayoutCoordinates] to calculate position on the screen, and not just
33 * inside the window, you may not receive a callback.
34 */
35 @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX)
onGloballyPositionednull36 public fun SubspaceModifier.onGloballyPositioned(
37 onGloballyPositioned: (SubspaceLayoutCoordinates) -> Unit
38 ): SubspaceModifier = this then OnGloballyPositionedVolumeElement(onGloballyPositioned)
39
40 private class OnGloballyPositionedVolumeElement(
41 public val onGloballyPositioned: (SubspaceLayoutCoordinates) -> Unit
42 ) : SubspaceModifierNodeElement<OnGloballyPositionedNode>() {
43 override fun create(): OnGloballyPositionedNode {
44 return OnGloballyPositionedNode(onGloballyPositioned)
45 }
46
47 override fun update(node: OnGloballyPositionedNode) {
48 node.callback = onGloballyPositioned
49 }
50
51 override fun equals(other: Any?): Boolean {
52 if (this === other) return true
53 if (other !is OnGloballyPositionedVolumeElement) return false
54 return onGloballyPositioned === other.onGloballyPositioned
55 }
56
57 override fun hashCode(): Int {
58 return onGloballyPositioned.hashCode()
59 }
60 }
61
62 /** Node associated with [onGloballyPositioned]. */
63 private class OnGloballyPositionedNode(public var callback: (SubspaceLayoutCoordinates) -> Unit) :
64 SubspaceModifier.Node(), LayoutCoordinatesAwareModifierNode {
onLayoutCoordinatesnull65 override fun onLayoutCoordinates(coordinates: SubspaceLayoutCoordinates) {
66 callback(coordinates)
67 }
68 }
69