Merge "Messager implementation for KSP" into androidx-master-dev
diff --git a/compose/integration-tests/demos/src/androidTest/java/androidx/compose/integration/demos/test/DemoTest.kt b/compose/integration-tests/demos/src/androidTest/java/androidx/compose/integration/demos/test/DemoTest.kt
index 4321a86..a830e81 100644
--- a/compose/integration-tests/demos/src/androidTest/java/androidx/compose/integration/demos/test/DemoTest.kt
+++ b/compose/integration-tests/demos/src/androidTest/java/androidx/compose/integration/demos/test/DemoTest.kt
@@ -249,8 +249,8 @@
get() = if (size == 1) first().title else drop(1).joinToString(" > ")
/**
- * Trims the tree of [Demo]s represented by this [DemoCategory] by cutting all leave demos and
- * removing all empty categories as a result.
+ * Trims the tree of [Demo]s represented by this [DemoCategory] by cutting all leave demos for
+ * which the [predicate] returns `false` and recursively removing all empty categories as a result.
*/
private fun DemoCategory.filter(
path: List<DemoCategory> = emptyList(),
diff --git a/compose/material/material/api/current.txt b/compose/material/material/api/current.txt
index b8e9fd8..d608c2a 100644
--- a/compose/material/material/api/current.txt
+++ b/compose/material/material/api/current.txt
@@ -338,13 +338,17 @@
}
public final class FloatingActionButtonConstants {
- method @androidx.compose.runtime.Composable public float animateDefaultElevation-PzTOHyI(androidx.compose.foundation.InteractionState interactionState, optional float defaultElevation, optional float pressedElevation);
+ method @androidx.compose.runtime.Composable public androidx.compose.material.FloatingActionButtonElevation defaultElevation-ioHfwGI(optional float defaultElevation, optional float pressedElevation);
field public static final androidx.compose.material.FloatingActionButtonConstants INSTANCE;
}
+ @androidx.compose.material.ExperimentalMaterialApi @androidx.compose.runtime.Stable public interface FloatingActionButtonElevation {
+ method public float elevation-D9Ej5fM(androidx.compose.foundation.InteractionState interactionState);
+ }
+
public final class FloatingActionButtonKt {
- method @androidx.compose.runtime.Composable public static void ExtendedFloatingActionButton-SrDf79w(kotlin.jvm.functions.Function0<kotlin.Unit> text, kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function0<kotlin.Unit>? icon, optional androidx.compose.foundation.InteractionState interactionState, optional androidx.compose.ui.graphics.Shape shape, optional long backgroundColor, optional long contentColor, optional float elevation);
- method @androidx.compose.runtime.Composable public static void FloatingActionButton-pvsAfIA(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.foundation.InteractionState interactionState, optional androidx.compose.ui.graphics.Shape shape, optional long backgroundColor, optional long contentColor, optional float elevation, kotlin.jvm.functions.Function0<kotlin.Unit> icon);
+ method @androidx.compose.runtime.Composable public static void ExtendedFloatingActionButton-i36UMrA(kotlin.jvm.functions.Function0<kotlin.Unit> text, kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function0<kotlin.Unit>? icon, optional androidx.compose.foundation.InteractionState interactionState, optional androidx.compose.ui.graphics.Shape shape, optional long backgroundColor, optional long contentColor, optional androidx.compose.material.FloatingActionButtonElevation elevation);
+ method @androidx.compose.runtime.Composable public static void FloatingActionButton-lf3tHAI(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.foundation.InteractionState interactionState, optional androidx.compose.ui.graphics.Shape shape, optional long backgroundColor, optional long contentColor, optional androidx.compose.material.FloatingActionButtonElevation elevation, kotlin.jvm.functions.Function0<kotlin.Unit> icon);
}
@androidx.compose.material.ExperimentalMaterialApi @androidx.compose.runtime.Immutable public final class FractionalThreshold implements androidx.compose.material.ThresholdConfig {
@@ -614,8 +618,18 @@
method public <T> androidx.compose.runtime.savedinstancestate.Saver<androidx.compose.material.SwipeableState<T>,T> Saver(androidx.compose.animation.core.AnimationClockObservable clock, androidx.compose.animation.core.AnimationSpec<java.lang.Float> animationSpec, kotlin.jvm.functions.Function1<? super T,java.lang.Boolean> confirmStateChange);
}
+ @androidx.compose.material.ExperimentalMaterialApi @androidx.compose.runtime.Stable public interface SwitchColors {
+ method public long thumbColor-0d7_KjU(boolean enabled, boolean checked);
+ method public long trackColor-0d7_KjU(boolean enabled, boolean checked);
+ }
+
+ public final class SwitchConstants {
+ method @androidx.compose.runtime.Composable public androidx.compose.material.SwitchColors defaultColors-R8aI8sA(optional long checkedThumbColor, optional long checkedTrackColor, optional float checkedTrackAlpha, optional long uncheckedThumbColor, optional long uncheckedTrackColor, optional float uncheckedTrackAlpha, optional long disabledCheckedThumbColor, optional long disabledCheckedTrackColor, optional long disabledUncheckedThumbColor, optional long disabledUncheckedTrackColor);
+ field public static final androidx.compose.material.SwitchConstants INSTANCE;
+ }
+
public final class SwitchKt {
- method @androidx.compose.runtime.Composable public static void Switch-vndggBo(boolean checked, kotlin.jvm.functions.Function1<? super java.lang.Boolean,kotlin.Unit> onCheckedChange, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional androidx.compose.foundation.InteractionState interactionState, optional long color);
+ method @androidx.compose.runtime.Composable public static void Switch(boolean checked, kotlin.jvm.functions.Function1<? super java.lang.Boolean,kotlin.Unit> onCheckedChange, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional androidx.compose.foundation.InteractionState interactionState, optional androidx.compose.material.SwitchColors colors);
}
public final class TabConstants {
diff --git a/compose/material/material/api/public_plus_experimental_current.txt b/compose/material/material/api/public_plus_experimental_current.txt
index b8e9fd8..d608c2a 100644
--- a/compose/material/material/api/public_plus_experimental_current.txt
+++ b/compose/material/material/api/public_plus_experimental_current.txt
@@ -338,13 +338,17 @@
}
public final class FloatingActionButtonConstants {
- method @androidx.compose.runtime.Composable public float animateDefaultElevation-PzTOHyI(androidx.compose.foundation.InteractionState interactionState, optional float defaultElevation, optional float pressedElevation);
+ method @androidx.compose.runtime.Composable public androidx.compose.material.FloatingActionButtonElevation defaultElevation-ioHfwGI(optional float defaultElevation, optional float pressedElevation);
field public static final androidx.compose.material.FloatingActionButtonConstants INSTANCE;
}
+ @androidx.compose.material.ExperimentalMaterialApi @androidx.compose.runtime.Stable public interface FloatingActionButtonElevation {
+ method public float elevation-D9Ej5fM(androidx.compose.foundation.InteractionState interactionState);
+ }
+
public final class FloatingActionButtonKt {
- method @androidx.compose.runtime.Composable public static void ExtendedFloatingActionButton-SrDf79w(kotlin.jvm.functions.Function0<kotlin.Unit> text, kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function0<kotlin.Unit>? icon, optional androidx.compose.foundation.InteractionState interactionState, optional androidx.compose.ui.graphics.Shape shape, optional long backgroundColor, optional long contentColor, optional float elevation);
- method @androidx.compose.runtime.Composable public static void FloatingActionButton-pvsAfIA(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.foundation.InteractionState interactionState, optional androidx.compose.ui.graphics.Shape shape, optional long backgroundColor, optional long contentColor, optional float elevation, kotlin.jvm.functions.Function0<kotlin.Unit> icon);
+ method @androidx.compose.runtime.Composable public static void ExtendedFloatingActionButton-i36UMrA(kotlin.jvm.functions.Function0<kotlin.Unit> text, kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function0<kotlin.Unit>? icon, optional androidx.compose.foundation.InteractionState interactionState, optional androidx.compose.ui.graphics.Shape shape, optional long backgroundColor, optional long contentColor, optional androidx.compose.material.FloatingActionButtonElevation elevation);
+ method @androidx.compose.runtime.Composable public static void FloatingActionButton-lf3tHAI(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.foundation.InteractionState interactionState, optional androidx.compose.ui.graphics.Shape shape, optional long backgroundColor, optional long contentColor, optional androidx.compose.material.FloatingActionButtonElevation elevation, kotlin.jvm.functions.Function0<kotlin.Unit> icon);
}
@androidx.compose.material.ExperimentalMaterialApi @androidx.compose.runtime.Immutable public final class FractionalThreshold implements androidx.compose.material.ThresholdConfig {
@@ -614,8 +618,18 @@
method public <T> androidx.compose.runtime.savedinstancestate.Saver<androidx.compose.material.SwipeableState<T>,T> Saver(androidx.compose.animation.core.AnimationClockObservable clock, androidx.compose.animation.core.AnimationSpec<java.lang.Float> animationSpec, kotlin.jvm.functions.Function1<? super T,java.lang.Boolean> confirmStateChange);
}
+ @androidx.compose.material.ExperimentalMaterialApi @androidx.compose.runtime.Stable public interface SwitchColors {
+ method public long thumbColor-0d7_KjU(boolean enabled, boolean checked);
+ method public long trackColor-0d7_KjU(boolean enabled, boolean checked);
+ }
+
+ public final class SwitchConstants {
+ method @androidx.compose.runtime.Composable public androidx.compose.material.SwitchColors defaultColors-R8aI8sA(optional long checkedThumbColor, optional long checkedTrackColor, optional float checkedTrackAlpha, optional long uncheckedThumbColor, optional long uncheckedTrackColor, optional float uncheckedTrackAlpha, optional long disabledCheckedThumbColor, optional long disabledCheckedTrackColor, optional long disabledUncheckedThumbColor, optional long disabledUncheckedTrackColor);
+ field public static final androidx.compose.material.SwitchConstants INSTANCE;
+ }
+
public final class SwitchKt {
- method @androidx.compose.runtime.Composable public static void Switch-vndggBo(boolean checked, kotlin.jvm.functions.Function1<? super java.lang.Boolean,kotlin.Unit> onCheckedChange, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional androidx.compose.foundation.InteractionState interactionState, optional long color);
+ method @androidx.compose.runtime.Composable public static void Switch(boolean checked, kotlin.jvm.functions.Function1<? super java.lang.Boolean,kotlin.Unit> onCheckedChange, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional androidx.compose.foundation.InteractionState interactionState, optional androidx.compose.material.SwitchColors colors);
}
public final class TabConstants {
diff --git a/compose/material/material/api/restricted_current.txt b/compose/material/material/api/restricted_current.txt
index b8e9fd8..d608c2a 100644
--- a/compose/material/material/api/restricted_current.txt
+++ b/compose/material/material/api/restricted_current.txt
@@ -338,13 +338,17 @@
}
public final class FloatingActionButtonConstants {
- method @androidx.compose.runtime.Composable public float animateDefaultElevation-PzTOHyI(androidx.compose.foundation.InteractionState interactionState, optional float defaultElevation, optional float pressedElevation);
+ method @androidx.compose.runtime.Composable public androidx.compose.material.FloatingActionButtonElevation defaultElevation-ioHfwGI(optional float defaultElevation, optional float pressedElevation);
field public static final androidx.compose.material.FloatingActionButtonConstants INSTANCE;
}
+ @androidx.compose.material.ExperimentalMaterialApi @androidx.compose.runtime.Stable public interface FloatingActionButtonElevation {
+ method public float elevation-D9Ej5fM(androidx.compose.foundation.InteractionState interactionState);
+ }
+
public final class FloatingActionButtonKt {
- method @androidx.compose.runtime.Composable public static void ExtendedFloatingActionButton-SrDf79w(kotlin.jvm.functions.Function0<kotlin.Unit> text, kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function0<kotlin.Unit>? icon, optional androidx.compose.foundation.InteractionState interactionState, optional androidx.compose.ui.graphics.Shape shape, optional long backgroundColor, optional long contentColor, optional float elevation);
- method @androidx.compose.runtime.Composable public static void FloatingActionButton-pvsAfIA(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.foundation.InteractionState interactionState, optional androidx.compose.ui.graphics.Shape shape, optional long backgroundColor, optional long contentColor, optional float elevation, kotlin.jvm.functions.Function0<kotlin.Unit> icon);
+ method @androidx.compose.runtime.Composable public static void ExtendedFloatingActionButton-i36UMrA(kotlin.jvm.functions.Function0<kotlin.Unit> text, kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function0<kotlin.Unit>? icon, optional androidx.compose.foundation.InteractionState interactionState, optional androidx.compose.ui.graphics.Shape shape, optional long backgroundColor, optional long contentColor, optional androidx.compose.material.FloatingActionButtonElevation elevation);
+ method @androidx.compose.runtime.Composable public static void FloatingActionButton-lf3tHAI(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.foundation.InteractionState interactionState, optional androidx.compose.ui.graphics.Shape shape, optional long backgroundColor, optional long contentColor, optional androidx.compose.material.FloatingActionButtonElevation elevation, kotlin.jvm.functions.Function0<kotlin.Unit> icon);
}
@androidx.compose.material.ExperimentalMaterialApi @androidx.compose.runtime.Immutable public final class FractionalThreshold implements androidx.compose.material.ThresholdConfig {
@@ -614,8 +618,18 @@
method public <T> androidx.compose.runtime.savedinstancestate.Saver<androidx.compose.material.SwipeableState<T>,T> Saver(androidx.compose.animation.core.AnimationClockObservable clock, androidx.compose.animation.core.AnimationSpec<java.lang.Float> animationSpec, kotlin.jvm.functions.Function1<? super T,java.lang.Boolean> confirmStateChange);
}
+ @androidx.compose.material.ExperimentalMaterialApi @androidx.compose.runtime.Stable public interface SwitchColors {
+ method public long thumbColor-0d7_KjU(boolean enabled, boolean checked);
+ method public long trackColor-0d7_KjU(boolean enabled, boolean checked);
+ }
+
+ public final class SwitchConstants {
+ method @androidx.compose.runtime.Composable public androidx.compose.material.SwitchColors defaultColors-R8aI8sA(optional long checkedThumbColor, optional long checkedTrackColor, optional float checkedTrackAlpha, optional long uncheckedThumbColor, optional long uncheckedTrackColor, optional float uncheckedTrackAlpha, optional long disabledCheckedThumbColor, optional long disabledCheckedTrackColor, optional long disabledUncheckedThumbColor, optional long disabledUncheckedTrackColor);
+ field public static final androidx.compose.material.SwitchConstants INSTANCE;
+ }
+
public final class SwitchKt {
- method @androidx.compose.runtime.Composable public static void Switch-vndggBo(boolean checked, kotlin.jvm.functions.Function1<? super java.lang.Boolean,kotlin.Unit> onCheckedChange, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional androidx.compose.foundation.InteractionState interactionState, optional long color);
+ method @androidx.compose.runtime.Composable public static void Switch(boolean checked, kotlin.jvm.functions.Function1<? super java.lang.Boolean,kotlin.Unit> onCheckedChange, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional androidx.compose.foundation.InteractionState interactionState, optional androidx.compose.material.SwitchColors colors);
}
public final class TabConstants {
diff --git a/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/FloatingActionButtonTest.kt b/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/FloatingActionButtonTest.kt
index d21c220..53c306b36 100644
--- a/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/FloatingActionButtonTest.kt
+++ b/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/FloatingActionButtonTest.kt
@@ -182,7 +182,9 @@
FloatingActionButton(
modifier = Modifier.testTag("myButton"),
onClick = {},
- elevation = 0.dp
+ elevation = FloatingActionButtonConstants.defaultElevation(
+ defaultElevation = 0.dp
+ )
) {
Box(Modifier.preferredSize(10.dp, 10.dp))
}
@@ -216,7 +218,9 @@
ExtendedFloatingActionButton(
modifier = Modifier.testTag("myButton"),
onClick = {},
- elevation = 0.dp,
+ elevation = FloatingActionButtonConstants.defaultElevation(
+ defaultElevation = 0.dp
+ ),
text = { Box(Modifier.preferredSize(10.dp, 50.dp)) }
)
}
diff --git a/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/SwitchScreenshotTest.kt b/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/SwitchScreenshotTest.kt
index f58903e..27d114c 100644
--- a/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/SwitchScreenshotTest.kt
+++ b/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/SwitchScreenshotTest.kt
@@ -93,7 +93,11 @@
fun switchTest_checked_customColor() {
rule.setMaterialContent {
Box(wrapperModifier) {
- Switch(checked = true, onCheckedChange = { }, color = Color.Red)
+ Switch(
+ checked = true,
+ onCheckedChange = { },
+ colors = SwitchConstants.defaultColors(checkedThumbColor = Color.Red)
+ )
}
}
assertToggeableAgainstGolden("switch_checked_customColor")
diff --git a/compose/material/material/src/commonMain/kotlin/androidx/compose/material/Elevation.kt b/compose/material/material/src/commonMain/kotlin/androidx/compose/material/Elevation.kt
index c8df7bb..ce86b3e 100644
--- a/compose/material/material/src/commonMain/kotlin/androidx/compose/material/Elevation.kt
+++ b/compose/material/material/src/commonMain/kotlin/androidx/compose/material/Elevation.kt
@@ -60,8 +60,8 @@
*
* Typically you should use [animateElevation] instead, which uses these [AnimationSpec]s
* internally. [animateElevation] in turn is used by the defaults for [Button] and
- * [FloatingActionButton] - inside [ButtonConstants.animateDefaultElevation] and
- * [FloatingActionButtonConstants.animateDefaultElevation] respectively.
+ * [FloatingActionButton] - inside [ButtonConstants.defaultElevation] and
+ * [FloatingActionButtonConstants.defaultElevation] respectively.
*
* @see animateElevation
*/
diff --git a/compose/material/material/src/commonMain/kotlin/androidx/compose/material/FloatingActionButton.kt b/compose/material/material/src/commonMain/kotlin/androidx/compose/material/FloatingActionButton.kt
index 9833bc6..fca7d76 100644
--- a/compose/material/material/src/commonMain/kotlin/androidx/compose/material/FloatingActionButton.kt
+++ b/compose/material/material/src/commonMain/kotlin/androidx/compose/material/FloatingActionButton.kt
@@ -16,8 +16,11 @@
package androidx.compose.material
+import androidx.compose.animation.AnimatedValueModel
import androidx.compose.animation.VectorConverter
-import androidx.compose.animation.animatedValue
+import androidx.compose.animation.asDisposableClock
+import androidx.compose.animation.core.AnimationClockObservable
+import androidx.compose.animation.core.AnimationVector1D
import androidx.compose.foundation.Interaction
import androidx.compose.foundation.InteractionState
import androidx.compose.foundation.ProvideTextStyle
@@ -33,12 +36,13 @@
import androidx.compose.foundation.layout.preferredWidth
import androidx.compose.foundation.shape.CornerSize
import androidx.compose.runtime.Composable
-import androidx.compose.runtime.onCommit
+import androidx.compose.runtime.Stable
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.Shape
+import androidx.compose.ui.platform.AnimationClockAmbient
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
@@ -62,11 +66,11 @@
* @param shape The [Shape] of this FAB
* @param backgroundColor The background color. Use [Color.Transparent] to have no color
* @param contentColor The preferred content color for content inside this FAB
- * @param elevation The z-coordinate at which to place this FAB. This controls the size
- * of the shadow below the FAB. See [FloatingActionButtonConstants.animateDefaultElevation] for
- * the default elevation that animates between [Interaction]s.
+ * @param elevation [FloatingActionButtonElevation] used to resolve the elevation for this FAB
+ * in different states. This controls the size of the shadow below the FAB.
* @param icon the content of this FAB
*/
+@OptIn(ExperimentalMaterialApi::class)
@Composable
fun FloatingActionButton(
onClick: () -> Unit,
@@ -75,7 +79,7 @@
shape: Shape = MaterialTheme.shapes.small.copy(CornerSize(percent = 50)),
backgroundColor: Color = MaterialTheme.colors.secondary,
contentColor: Color = contentColorFor(backgroundColor),
- elevation: Dp = FloatingActionButtonConstants.animateDefaultElevation(interactionState),
+ elevation: FloatingActionButtonElevation = FloatingActionButtonConstants.defaultElevation(),
icon: @Composable () -> Unit
) {
// TODO(aelias): Avoid manually managing the ripple once http://b/157687898
@@ -90,7 +94,7 @@
shape = shape,
color = backgroundColor,
contentColor = contentColor,
- elevation = elevation
+ elevation = elevation.elevation(interactionState)
) {
ProvideTextStyle(MaterialTheme.typography.button) {
Box(
@@ -131,10 +135,10 @@
* @param shape The [Shape] of this FAB
* @param backgroundColor The background color. Use [Color.Transparent] to have no color
* @param contentColor The preferred content color. Will be used by text and iconography
- * @param elevation The z-coordinate at which to place this FAB. This controls the size
- * of the shadow below the button. See [FloatingActionButtonConstants.animateDefaultElevation] for
- * the default elevation that animates between [Interaction]s.
+ * @param elevation [FloatingActionButtonElevation] used to resolve the elevation for this FAB
+ * in different states. This controls the size of the shadow below the FAB.
*/
+@OptIn(ExperimentalMaterialApi::class)
@Composable
fun ExtendedFloatingActionButton(
text: @Composable () -> Unit,
@@ -145,7 +149,7 @@
shape: Shape = MaterialTheme.shapes.small.copy(CornerSize(percent = 50)),
backgroundColor: Color = MaterialTheme.colors.secondary,
contentColor: Color = contentColorFor(backgroundColor),
- elevation: Dp = FloatingActionButtonConstants.animateDefaultElevation(interactionState)
+ elevation: FloatingActionButtonElevation = FloatingActionButtonConstants.defaultElevation()
) {
FloatingActionButton(
modifier = modifier.preferredSizeIn(
@@ -180,31 +184,70 @@
}
/**
+ * Represents the elevation for a floating action button in different states.
+ *
+ * See [FloatingActionButtonConstants.defaultElevation] for the default elevation used in a
+ * [FloatingActionButton] and [ExtendedFloatingActionButton].
+ */
+@ExperimentalMaterialApi
+@Stable
+interface FloatingActionButtonElevation {
+ /**
+ * Represents the elevation used in a floating action button, depending on [interactionState].
+ *
+ * @param interactionState the [InteractionState] for this floating action button
+ */
+ fun elevation(interactionState: InteractionState): Dp
+}
+
+/**
* Contains the default values used by [FloatingActionButton]
*/
object FloatingActionButtonConstants {
// TODO: b/152525426 add support for focused and hovered states
/**
- * Represents the default elevation for a button in different [Interaction]s, and how the
- * elevation animates between them.
+ * Creates a [FloatingActionButtonElevation] that will animate between the provided values
+ * according to the Material specification.
*
- * @param interactionState the [InteractionState] for this [FloatingActionButton], representing
- * the current visual state, such as whether it is [Interaction.Pressed] or not.
- * @param defaultElevation the elevation to use when the [FloatingActionButton] is has no
+ * @param defaultElevation the elevation to use when the [FloatingActionButton] has no
* [Interaction]s
* @param pressedElevation the elevation to use when the [FloatingActionButton] is
* [Interaction.Pressed].
*/
+ @OptIn(ExperimentalMaterialApi::class)
@Composable
- fun animateDefaultElevation(
- interactionState: InteractionState,
+ fun defaultElevation(
defaultElevation: Dp = 6.dp,
pressedElevation: Dp = 12.dp
// focused: Dp = 8.dp,
// hovered: Dp = 8.dp,
- ): Dp {
- class InteractionHolder(var interaction: Interaction?)
+ ): FloatingActionButtonElevation {
+ val clock = AnimationClockAmbient.current.asDisposableClock()
+ return remember(defaultElevation, pressedElevation, clock) {
+ DefaultFloatingActionButtonElevation(
+ defaultElevation = defaultElevation,
+ pressedElevation = pressedElevation,
+ clock = clock
+ )
+ }
+ }
+}
+/**
+ * Default [FloatingActionButtonElevation] implementation.
+ */
+@OptIn(ExperimentalMaterialApi::class)
+@Stable
+private class DefaultFloatingActionButtonElevation(
+ private val defaultElevation: Dp,
+ private val pressedElevation: Dp,
+ private val clock: AnimationClockObservable
+) : FloatingActionButtonElevation {
+ private val lazyAnimatedElevation = LazyAnimatedValue<Dp, AnimationVector1D> { target ->
+ AnimatedValueModel(initialValue = target, typeConverter = Dp.VectorConverter, clock = clock)
+ }
+
+ override fun elevation(interactionState: InteractionState): Dp {
val interaction = interactionState.value.lastOrNull {
it is Interaction.Pressed
}
@@ -214,20 +257,18 @@
else -> defaultElevation
}
- val previousInteractionHolder = remember { InteractionHolder(interaction) }
+ val animatedElevation = lazyAnimatedElevation.animatedValueForTarget(target)
- val animatedElevation = animatedValue(target, Dp.VectorConverter)
-
- onCommit(target) {
+ if (animatedElevation.targetValue != target) {
+ val lastInteraction = when (animatedElevation.targetValue) {
+ pressedElevation -> Interaction.Pressed
+ else -> null
+ }
animatedElevation.animateElevation(
- from = previousInteractionHolder.interaction,
+ from = lastInteraction,
to = interaction,
target = target
)
-
- // Update the last interaction, so we know what AnimationSpec to use if we animate
- // away from a state
- previousInteractionHolder.interaction = interaction
}
return animatedElevation.value
diff --git a/compose/material/material/src/commonMain/kotlin/androidx/compose/material/Switch.kt b/compose/material/material/src/commonMain/kotlin/androidx/compose/material/Switch.kt
index c36fb53..822b37a 100644
--- a/compose/material/material/src/commonMain/kotlin/androidx/compose/material/Switch.kt
+++ b/compose/material/material/src/commonMain/kotlin/androidx/compose/material/Switch.kt
@@ -32,7 +32,10 @@
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material.ripple.RippleIndication
import androidx.compose.runtime.Composable
+import androidx.compose.runtime.Immutable
+import androidx.compose.runtime.Stable
import androidx.compose.runtime.State
+import androidx.compose.runtime.emptyContent
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
@@ -61,7 +64,8 @@
* present on this Switch. You can create and pass in your own remembered
* [InteractionState] if you want to read the [InteractionState] and customize the appearance /
* behavior of this Switch in different [Interaction]s.
- * @param color main color of the track and thumb when the Switch is checked
+ * @param colors [SwitchColors] that will be used to determine the color of the thumb and track
+ * in different states. See [SwitchConstants.defaultColors].
*/
@Composable
@OptIn(ExperimentalMaterialApi::class)
@@ -71,7 +75,7 @@
modifier: Modifier = Modifier,
enabled: Boolean = true,
interactionState: InteractionState = remember { InteractionState() },
- color: Color = MaterialTheme.colors.secondaryVariant
+ colors: SwitchColors = SwitchConstants.defaultColors()
) {
val minBound = 0f
val maxBound = with(DensityAmbient.current) { ThumbPathLength.toPx() }
@@ -103,34 +107,61 @@
SwitchImpl(
checked = checked,
enabled = enabled,
- checkedColor = color,
+ colors = colors,
thumbValue = swipeableState.offset,
interactionState = interactionState
)
}
}
+/**
+ * Represents the colors used by a [Switch] in different states
+ *
+ * See [SwitchConstants.defaultColors] for the default implementation that follows Material
+ * specifications.
+ */
+@ExperimentalMaterialApi
+@Stable
+interface SwitchColors {
+
+ /**
+ * Represents the color used for the switch's thumb, depending on [enabled] and [checked].
+ *
+ * @param enabled whether the [Switch] is enabled or not
+ * @param checked whether the [Switch] is checked or not
+ */
+ fun thumbColor(enabled: Boolean, checked: Boolean): Color
+
+ /**
+ * Represents the color used for the switch's track, depending on [enabled] and [checked].
+ *
+ * @param enabled whether the [Switch] is enabled or not
+ * @param checked whether the [Switch] is checked or not
+ */
+ fun trackColor(enabled: Boolean, checked: Boolean): Color
+}
+
+@OptIn(ExperimentalMaterialApi::class)
@Composable
private fun BoxScope.SwitchImpl(
checked: Boolean,
enabled: Boolean,
- checkedColor: Color,
+ colors: SwitchColors,
thumbValue: State<Float>,
interactionState: InteractionState
) {
val hasInteraction =
Interaction.Pressed in interactionState || Interaction.Dragged in interactionState
- val elevation =
- if (hasInteraction) {
- SwitchDefaults.ThumbPressedElevation
- } else {
- SwitchDefaults.ThumbDefaultElevation
- }
- val trackColor = SwitchDefaults.resolveTrackColor(checked, enabled, checkedColor)
- val thumbColor = SwitchDefaults.resolveThumbColor(checked, enabled, checkedColor)
+ val elevation = if (hasInteraction) {
+ ThumbPressedElevation
+ } else {
+ ThumbDefaultElevation
+ }
Canvas(Modifier.align(Alignment.Center).fillMaxSize()) {
+ val trackColor = colors.trackColor(enabled, checked)
drawTrack(trackColor, TrackWidth.toPx(), TrackStrokeWidth.toPx())
}
+ val thumbColor = colors.thumbColor(enabled, checked)
Surface(
shape = CircleShape,
color = thumbColor,
@@ -142,8 +173,9 @@
interactionState = interactionState,
indication = RippleIndication(radius = ThumbRippleRadius, bounded = false)
)
- .size(ThumbDiameter)
- ) {}
+ .size(ThumbDiameter),
+ content = emptyContent()
+ )
}
private fun DrawScope.drawTrack(trackColor: Color, trackWidth: Float, strokeWidth: Float) {
@@ -170,61 +202,121 @@
private val AnimationSpec = TweenSpec<Float>(durationMillis = 100)
-internal object SwitchDefaults {
+private val ThumbDefaultElevation = 1.dp
+private val ThumbPressedElevation = 6.dp
- const val CheckedTrackOpacity = 0.54f
- const val UncheckedTrackOpacity = 0.38f
-
- val ThumbDefaultElevation = 1.dp
- val ThumbPressedElevation = 6.dp
-
+/**
+ * Contains the default values used by [Switch]
+ */
+object SwitchConstants {
+ /**
+ * Creates a [SwitchColors] that represents the different colors used in a [Switch] in
+ * different states.
+ *
+ * @param checkedThumbColor the color used for the thumb when enabled and checked
+ * @param checkedTrackColor the color used for the track when enabled and checked
+ * @param checkedTrackAlpha the alpha applied to [checkedTrackColor] and
+ * [disabledCheckedTrackColor]
+ * @param uncheckedThumbColor the color used for the thumb when enabled and unchecked
+ * @param uncheckedTrackColor the color used for the track when enabled and unchecked
+ * @param uncheckedTrackAlpha the alpha applied to [uncheckedTrackColor] and
+ * [disabledUncheckedTrackColor]
+ * @param disabledCheckedThumbColor the color used for the thumb when disabled and checked
+ * @param disabledCheckedTrackColor the color used for the track when disabled and checked
+ * @param disabledUncheckedThumbColor the color used for the thumb when disabled and unchecked
+ * @param disabledUncheckedTrackColor the color used for the track when disabled and unchecked
+ */
+ @OptIn(ExperimentalMaterialApi::class)
@Composable
- private val uncheckedTrackColor
- get() = MaterialTheme.colors.onSurface
-
- @Composable
- private fun makeDisabledCheckedTrackColor(checkedColor: Color) = AmbientEmphasisLevels.current
- .disabled
- .applyEmphasis(checkedColor)
- .compositeOver(MaterialTheme.colors.surface)
-
- @Composable
- private val disabledUncheckedTrackColor
- get() = AmbientEmphasisLevels.current.disabled.applyEmphasis(MaterialTheme.colors.onSurface)
+ fun defaultColors(
+ checkedThumbColor: Color = MaterialTheme.colors.secondaryVariant,
+ checkedTrackColor: Color = checkedThumbColor,
+ checkedTrackAlpha: Float = 0.54f,
+ uncheckedThumbColor: Color = MaterialTheme.colors.surface,
+ uncheckedTrackColor: Color = MaterialTheme.colors.onSurface,
+ uncheckedTrackAlpha: Float = 0.38f,
+ disabledCheckedThumbColor: Color = AmbientEmphasisLevels.current.disabled
+ .applyEmphasis(checkedThumbColor)
+ .compositeOver(MaterialTheme.colors.surface),
+ disabledCheckedTrackColor: Color = AmbientEmphasisLevels.current.disabled
+ .applyEmphasis(checkedTrackColor)
+ .compositeOver(MaterialTheme.colors.surface),
+ disabledUncheckedThumbColor: Color = AmbientEmphasisLevels.current.disabled
+ .applyEmphasis(uncheckedThumbColor)
+ .compositeOver(MaterialTheme.colors.surface),
+ disabledUncheckedTrackColor: Color = AmbientEmphasisLevels.current.disabled
+ .applyEmphasis(uncheckedTrackColor)
.compositeOver(MaterialTheme.colors.surface)
+ ): SwitchColors = DefaultSwitchColors(
+ checkedThumbColor = checkedThumbColor,
+ checkedTrackColor = checkedTrackColor.copy(alpha = checkedTrackAlpha),
+ uncheckedThumbColor = uncheckedThumbColor,
+ uncheckedTrackColor = uncheckedTrackColor.copy(alpha = uncheckedTrackAlpha),
+ disabledCheckedThumbColor = disabledCheckedThumbColor,
+ disabledCheckedTrackColor = disabledCheckedTrackColor.copy(alpha = checkedTrackAlpha),
+ disabledUncheckedThumbColor = disabledUncheckedThumbColor,
+ disabledUncheckedTrackColor = disabledUncheckedTrackColor.copy(alpha = uncheckedTrackAlpha)
+ )
+}
- @Composable
- private val uncheckedThumbColor
- get() = MaterialTheme.colors.surface
-
- @Composable
- private fun makeDisabledCheckedThumbColor(checkedColor: Color) = AmbientEmphasisLevels.current
- .disabled
- .applyEmphasis(checkedColor)
- .compositeOver(MaterialTheme.colors.surface)
-
- @Composable
- private val disabledUncheckedThumbColor
- get() = AmbientEmphasisLevels.current.disabled.applyEmphasis(MaterialTheme.colors.surface)
- .compositeOver(MaterialTheme.colors.surface)
-
- @Composable
- internal fun resolveTrackColor(checked: Boolean, enabled: Boolean, checkedColor: Color): Color {
- return if (checked) {
- val color = if (enabled) checkedColor else makeDisabledCheckedTrackColor(checkedColor)
- color.copy(alpha = CheckedTrackOpacity)
+/**
+ * Default [SwitchColors] implementation.
+ */
+@OptIn(ExperimentalMaterialApi::class)
+@Immutable
+private class DefaultSwitchColors(
+ private val checkedThumbColor: Color,
+ private val checkedTrackColor: Color,
+ private val uncheckedThumbColor: Color,
+ private val uncheckedTrackColor: Color,
+ private val disabledCheckedThumbColor: Color,
+ private val disabledCheckedTrackColor: Color,
+ private val disabledUncheckedThumbColor: Color,
+ private val disabledUncheckedTrackColor: Color
+) : SwitchColors {
+ override fun thumbColor(enabled: Boolean, checked: Boolean): Color {
+ return if (enabled) {
+ if (checked) checkedThumbColor else uncheckedThumbColor
} else {
- val color = if (enabled) uncheckedTrackColor else disabledUncheckedTrackColor
- color.copy(alpha = UncheckedTrackOpacity)
+ if (checked) disabledCheckedThumbColor else disabledUncheckedThumbColor
}
}
- @Composable
- internal fun resolveThumbColor(checked: Boolean, enabled: Boolean, checkedColor: Color): Color {
- return if (checked) {
- if (enabled) checkedColor else makeDisabledCheckedThumbColor(checkedColor)
+ override fun trackColor(enabled: Boolean, checked: Boolean): Color {
+ return if (enabled) {
+ if (checked) checkedTrackColor else uncheckedTrackColor
} else {
- if (enabled) uncheckedThumbColor else disabledUncheckedThumbColor
+ if (checked) disabledCheckedTrackColor else disabledUncheckedTrackColor
}
}
-}
\ No newline at end of file
+
+ override fun equals(other: Any?): Boolean {
+ if (this === other) return true
+ if (other == null || this::class != other::class) return false
+
+ other as DefaultSwitchColors
+
+ if (checkedThumbColor != other.checkedThumbColor) return false
+ if (checkedTrackColor != other.checkedTrackColor) return false
+ if (uncheckedThumbColor != other.uncheckedThumbColor) return false
+ if (uncheckedTrackColor != other.uncheckedTrackColor) return false
+ if (disabledCheckedThumbColor != other.disabledCheckedThumbColor) return false
+ if (disabledCheckedTrackColor != other.disabledCheckedTrackColor) return false
+ if (disabledUncheckedThumbColor != other.disabledUncheckedThumbColor) return false
+ if (disabledUncheckedTrackColor != other.disabledUncheckedTrackColor) return false
+
+ return true
+ }
+
+ override fun hashCode(): Int {
+ var result = checkedThumbColor.hashCode()
+ result = 31 * result + checkedTrackColor.hashCode()
+ result = 31 * result + uncheckedThumbColor.hashCode()
+ result = 31 * result + uncheckedTrackColor.hashCode()
+ result = 31 * result + disabledCheckedThumbColor.hashCode()
+ result = 31 * result + disabledCheckedTrackColor.hashCode()
+ result = 31 * result + disabledUncheckedThumbColor.hashCode()
+ result = 31 * result + disabledUncheckedTrackColor.hashCode()
+ return result
+ }
+}
diff --git a/compose/ui/ui/api/current.txt b/compose/ui/ui/api/current.txt
index 7a830ff..99045b7 100644
--- a/compose/ui/ui/api/current.txt
+++ b/compose/ui/ui/api/current.txt
@@ -1521,9 +1521,6 @@
package androidx.compose.ui.input.pointer {
public final class ConsumedData {
- method public long component1-F1C5BW0();
- method public boolean component2();
- method public androidx.compose.ui.input.pointer.ConsumedData copy-Dkz3Of0(long positionChange, boolean downChange);
method public boolean getDownChange();
method public long getPositionChange-F1C5BW0();
method public void setDownChange(boolean p);
@@ -2331,9 +2328,6 @@
method public static androidx.compose.runtime.ProvidableAmbient<androidx.compose.ui.selection.SelectionRegistrar> getSelectionRegistrarAmbient();
}
- public final class SimpleContainerKt {
- }
-
public final class SimpleLayoutKt {
}
diff --git a/compose/ui/ui/api/public_plus_experimental_current.txt b/compose/ui/ui/api/public_plus_experimental_current.txt
index 7a830ff..99045b7 100644
--- a/compose/ui/ui/api/public_plus_experimental_current.txt
+++ b/compose/ui/ui/api/public_plus_experimental_current.txt
@@ -1521,9 +1521,6 @@
package androidx.compose.ui.input.pointer {
public final class ConsumedData {
- method public long component1-F1C5BW0();
- method public boolean component2();
- method public androidx.compose.ui.input.pointer.ConsumedData copy-Dkz3Of0(long positionChange, boolean downChange);
method public boolean getDownChange();
method public long getPositionChange-F1C5BW0();
method public void setDownChange(boolean p);
@@ -2331,9 +2328,6 @@
method public static androidx.compose.runtime.ProvidableAmbient<androidx.compose.ui.selection.SelectionRegistrar> getSelectionRegistrarAmbient();
}
- public final class SimpleContainerKt {
- }
-
public final class SimpleLayoutKt {
}
diff --git a/compose/ui/ui/api/restricted_current.txt b/compose/ui/ui/api/restricted_current.txt
index d75d3e6..23d9152 100644
--- a/compose/ui/ui/api/restricted_current.txt
+++ b/compose/ui/ui/api/restricted_current.txt
@@ -1568,9 +1568,6 @@
package androidx.compose.ui.input.pointer {
public final class ConsumedData {
- method public long component1-F1C5BW0();
- method public boolean component2();
- method public androidx.compose.ui.input.pointer.ConsumedData copy-Dkz3Of0(long positionChange, boolean downChange);
method public boolean getDownChange();
method public long getPositionChange-F1C5BW0();
method public void setDownChange(boolean p);
@@ -2408,9 +2405,6 @@
method public static androidx.compose.runtime.ProvidableAmbient<androidx.compose.ui.selection.SelectionRegistrar> getSelectionRegistrarAmbient();
}
- public final class SimpleContainerKt {
- }
-
public final class SimpleLayoutKt {
}
diff --git a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/input/pointer/AndroidPointerInputTest.kt b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/input/pointer/AndroidPointerInputTest.kt
index c0ad627..365db7b 100644
--- a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/input/pointer/AndroidPointerInputTest.kt
+++ b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/input/pointer/AndroidPointerInputTest.kt
@@ -41,7 +41,6 @@
import androidx.compose.ui.platform.AndroidComposeView
import androidx.compose.ui.platform.setContent
import androidx.compose.ui.unit.IntSize
-import androidx.compose.ui.unit.milliseconds
import androidx.compose.ui.util.fastForEach
import androidx.compose.ui.viewinterop.AndroidView
import androidx.test.filters.SmallTest
@@ -239,7 +238,7 @@
// when run from Android Studio. This seems to be caused by b/158099918. Once that is
// fixed, @Ignore can be removed.
@Ignore
- fun dispatchTouchEvent_throughLayersOfAndroidAndCompose_hitsChildPointerInputFilter() {
+ fun dispatchTouchEvent_throughLayersOfAndroidAndCompose_hitsChildWithCorrectCoords() {
// Arrange
@@ -297,7 +296,8 @@
// Assert
assertThat(log).hasSize(1)
- assertThat(log[0]).isEqualTo(listOf(down(0, 0.milliseconds, 0f, 0f)))
+ assertThat(log[0]).hasSize(1)
+ assertThat(log[0][0].current.position).isEqualTo(Offset(0f, 0f))
}
}
@@ -417,7 +417,8 @@
// Assert
assertThat(log).hasSize(1)
- assertThat(log[0]).isEqualTo(listOf(down(0, 0.milliseconds, 0f, 0f)))
+ assertThat(log[0]).hasSize(1)
+ assertThat(log[0][0].current.position).isEqualTo(Offset(0f, 0f))
}
}
diff --git a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/input/pointer/HitPathTrackerTest.kt b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/input/pointer/HitPathTrackerTest.kt
index 0fb2a00..388eef5 100644
--- a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/input/pointer/HitPathTrackerTest.kt
+++ b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/input/pointer/HitPathTrackerTest.kt
@@ -237,7 +237,9 @@
assertThat(log).hasSize(3)
// Verify call values
PointerEventPass.values().forEachIndexed { index, value ->
- assertThat(log[index].pointerEvent).isEqualTo(pointerEventOf(down(13)))
+ PointerEventSubject
+ .assertThat(log[index].pointerEvent)
+ .isStructurallyEqualTo(pointerEventOf(down(13)))
assertThat(log[index].pass).isEqualTo(value)
}
}
@@ -259,7 +261,9 @@
assertThat(onPointerEventLog[1].pointerInputFilter).isEqualTo(pif2)
assertThat(onPointerEventLog[2].pointerInputFilter).isEqualTo(pif3)
onPointerEventLog.forEach {
- assertThat(it.pointerEvent).isEqualTo(pointerEventOf(down(13)))
+ PointerEventSubject
+ .assertThat(it.pointerEvent)
+ .isStructurallyEqualTo(pointerEventOf(down(13)))
}
}
@@ -284,7 +288,9 @@
assertThat(onPointerEventLog[4].pointerInputFilter).isEqualTo(pif2)
assertThat(onPointerEventLog[5].pointerInputFilter).isEqualTo(pif1)
onPointerEventLog.forEach {
- assertThat(it.pointerEvent).isEqualTo(pointerEventOf(down(13)))
+ PointerEventSubject
+ .assertThat(it.pointerEvent)
+ .isStructurallyEqualTo(pointerEventOf(down(13)))
}
}
@@ -317,7 +323,9 @@
assertThat(log2).hasSize(4)
log1.forEach {
- assertThat(it.pointerEvent).isEqualTo(pointerEventOf(event1))
+ PointerEventSubject
+ .assertThat(it.pointerEvent)
+ .isStructurallyEqualTo(pointerEventOf(event1))
}
assertThat(log1[0].pointerInputFilter).isEqualTo(pif1)
@@ -368,36 +376,52 @@
// Verifies that the events traverse between parent and child1 in the correct order.
assertThat(log1[0].pointerInputFilter).isEqualTo(parent)
- assertThat(log1[0].pointerEvent).isEqualTo(pointerEventOf(event1, event2))
+ PointerEventSubject
+ .assertThat(log1[0].pointerEvent)
+ .isStructurallyEqualTo(pointerEventOf(event1, event2))
assertThat(log1[0].pass).isEqualTo(PointerEventPass.Initial)
assertThat(log1[1].pointerInputFilter).isEqualTo(child1)
- assertThat(log1[1].pointerEvent).isEqualTo(pointerEventOf(event1))
+ PointerEventSubject
+ .assertThat(log1[1].pointerEvent)
+ .isStructurallyEqualTo(pointerEventOf(event1))
assertThat(log1[1].pass).isEqualTo(PointerEventPass.Initial)
assertThat(log1[2].pointerInputFilter).isEqualTo(child1)
- assertThat(log1[2].pointerEvent).isEqualTo(pointerEventOf(event1))
+ PointerEventSubject
+ .assertThat(log1[2].pointerEvent)
+ .isStructurallyEqualTo(pointerEventOf(event1))
assertThat(log1[2].pass).isEqualTo(PointerEventPass.Main)
assertThat(log1[3].pointerInputFilter).isEqualTo(parent)
- assertThat(log1[3].pointerEvent).isEqualTo(pointerEventOf(event1, event2))
+ PointerEventSubject
+ .assertThat(log1[3].pointerEvent)
+ .isStructurallyEqualTo(pointerEventOf(event1, event2))
assertThat(log1[3].pass).isEqualTo(PointerEventPass.Main)
// Verifies that the events traverse between parent and child2 in the correct order.
assertThat(log1[0].pointerInputFilter).isEqualTo(parent)
- assertThat(log1[0].pointerEvent).isEqualTo(pointerEventOf(event1, event2))
+ PointerEventSubject
+ .assertThat(log1[0].pointerEvent)
+ .isStructurallyEqualTo(pointerEventOf(event1, event2))
assertThat(log1[0].pass).isEqualTo(PointerEventPass.Initial)
assertThat(log1[1].pointerInputFilter).isEqualTo(child1)
- assertThat(log1[1].pointerEvent).isEqualTo(pointerEventOf(event1))
+ PointerEventSubject
+ .assertThat(log1[1].pointerEvent)
+ .isStructurallyEqualTo(pointerEventOf(event1))
assertThat(log1[1].pass).isEqualTo(PointerEventPass.Initial)
assertThat(log1[2].pointerInputFilter).isEqualTo(child1)
- assertThat(log1[2].pointerEvent).isEqualTo(pointerEventOf(event1))
+ PointerEventSubject
+ .assertThat(log1[2].pointerEvent)
+ .isStructurallyEqualTo(pointerEventOf(event1))
assertThat(log1[2].pass).isEqualTo(PointerEventPass.Main)
assertThat(log1[3].pointerInputFilter).isEqualTo(parent)
- assertThat(log1[3].pointerEvent).isEqualTo(pointerEventOf(event1, event2))
+ PointerEventSubject
+ .assertThat(log1[3].pointerEvent)
+ .isStructurallyEqualTo(pointerEventOf(event1, event2))
assertThat(log1[3].pass).isEqualTo(PointerEventPass.Main)
}
@@ -424,7 +448,9 @@
// Verify PointerEvent
log1.forEach {
- assertThat(it.pointerEvent).isEqualTo(pointerEventOf(event1, event2))
+ PointerEventSubject
+ .assertThat(it.pointerEvent)
+ .isStructurallyEqualTo(pointerEventOf(event1, event2))
}
// Verify dispatch order
@@ -442,7 +468,9 @@
fun dispatchChanges_noNodes_nothingChanges() {
val (result, _) = hitPathTracker.dispatchChanges(internalPointerEventOf(down(5)))
- assertThat(result.changes.values.first()).isEqualTo(down(5))
+ PointerInputChangeSubject
+ .assertThat(result.changes.values.first())
+ .isStructurallyEqualTo(down(5))
}
@Test
@@ -460,8 +488,9 @@
val (result, _) = hitPathTracker.dispatchChanges(internalPointerEventOf(down(13)))
- assertThat(result.changes.values.first())
- .isEqualTo(down(13).apply { consumeDownChange() })
+ PointerInputChangeSubject
+ .assertThat(result.changes.values.first())
+ .isStructurallyEqualTo(down(13).apply { consumeDownChange() })
}
@Test
@@ -525,51 +554,66 @@
.filter { it.pass == PointerEventPass.Initial || it.pass == PointerEventPass.Main }
assertThat(log1[0].pointerInputFilter).isEqualTo(pif1)
- assertThat(log1[0].pointerEvent).isEqualTo(pointerEventOf(expectedChange))
+ PointerEventSubject
+ .assertThat(log1[0].pointerEvent)
+ .isStructurallyEqualTo(pointerEventOf(expectedChange))
assertThat(log1[0].pass).isEqualTo(PointerEventPass.Initial)
assertThat(log1[1].pointerInputFilter).isEqualTo(pif2)
- assertThat(log1[1].pointerEvent).isEqualTo(
- pointerEventOf(
- expectedChange.apply { consumePositionChange(0f, 1f) }
+ PointerEventSubject
+ .assertThat(log1[1].pointerEvent)
+ .isStructurallyEqualTo(
+ pointerEventOf(
+ expectedChange.apply { consumePositionChange(0f, 1f) }
+ )
)
- )
assertThat(log1[1].pass).isEqualTo(PointerEventPass.Initial)
assertThat(log1[2].pointerInputFilter).isEqualTo(pif3)
- assertThat(log1[2].pointerEvent).isEqualTo(
- pointerEventOf(
- expectedChange.apply { consumePositionChange(0f, 2f) }
+ PointerEventSubject
+ .assertThat(log1[2].pointerEvent)
+ .isStructurallyEqualTo(
+ pointerEventOf(
+ expectedChange.apply { consumePositionChange(0f, 2f) }
+ )
)
- )
assertThat(log1[2].pass).isEqualTo(PointerEventPass.Initial)
assertThat(log1[3].pointerInputFilter).isEqualTo(pif3)
- assertThat(log1[3].pointerEvent).isEqualTo(
- pointerEventOf(
- expectedChange.apply { consumePositionChange(0f, 3f) }
+ PointerEventSubject
+ .assertThat(log1[3].pointerEvent)
+ .isStructurallyEqualTo(
+ pointerEventOf(
+ expectedChange.apply { consumePositionChange(0f, 3f) }
+ )
)
- )
assertThat(log1[3].pass).isEqualTo(PointerEventPass.Main)
assertThat(log1[4].pointerInputFilter).isEqualTo(pif2)
- assertThat(log1[4].pointerEvent).isEqualTo(
- pointerEventOf(
- expectedChange.apply { consumePositionChange(0f, 4f) }
+ PointerEventSubject
+ .assertThat(log1[4].pointerEvent)
+ .isStructurallyEqualTo(
+ pointerEventOf(
+ expectedChange.apply { consumePositionChange(0f, 4f) }
+ )
)
- )
assertThat(log1[4].pass).isEqualTo(PointerEventPass.Main)
assertThat(log1[5].pointerInputFilter).isEqualTo(pif1)
- assertThat(log1[5].pointerEvent).isEqualTo(
- pointerEventOf(
- expectedChange.apply { consumePositionChange(0f, 5f) }
+ PointerEventSubject
+ .assertThat(log1[5].pointerEvent)
+ .isStructurallyEqualTo(
+ pointerEventOf(
+ expectedChange.apply { consumePositionChange(0f, 5f) }
+ )
)
- )
assertThat(log1[5].pass).isEqualTo(PointerEventPass.Main)
- assertThat(result.changes.values.first())
- .isEqualTo(expectedChange.apply { consumePositionChange(0f, 6f) })
+ PointerInputChangeSubject
+ .assertThat(result.changes.values.first())
+ .isStructurallyEqualTo(
+ expectedChange.apply { consumePositionChange(0f, 6f) }
+ )
}
@Test
@@ -659,68 +703,88 @@
.filter { it.pointerInputFilter == pif3 || it.pointerInputFilter == pif4 }
assertThat(log1[0].pointerInputFilter).isEqualTo(pif1)
- assertThat(log1[0].pointerEvent).isEqualTo(pointerEventOf(expectedEvent1))
+ PointerEventSubject
+ .assertThat(log1[0].pointerEvent)
+ .isStructurallyEqualTo(pointerEventOf(expectedEvent1))
assertThat(log1[0].pass).isEqualTo(PointerEventPass.Initial)
assertThat(log1[1].pointerInputFilter).isEqualTo(pif2)
- assertThat(log1[1].pointerEvent).isEqualTo(
- pointerEventOf(
- expectedEvent1.apply { consumePositionChange(0f, 1f) }
+ PointerEventSubject
+ .assertThat(log1[1].pointerEvent)
+ .isStructurallyEqualTo(
+ pointerEventOf(
+ expectedEvent1.apply { consumePositionChange(0f, 1f) }
+ )
)
- )
assertThat(log1[1].pass).isEqualTo(PointerEventPass.Initial)
assertThat(log1[2].pointerInputFilter).isEqualTo(pif2)
- assertThat(log1[2].pointerEvent).isEqualTo(
- pointerEventOf(
- expectedEvent1.apply { consumePositionChange(0f, 2f) }
+ PointerEventSubject
+ .assertThat(log1[2].pointerEvent)
+ .isStructurallyEqualTo(
+ pointerEventOf(
+ expectedEvent1.apply { consumePositionChange(0f, 2f) }
+ )
)
- )
assertThat(log1[2].pass).isEqualTo(PointerEventPass.Main)
assertThat(log1[3].pointerInputFilter).isEqualTo(pif1)
- assertThat(log1[3].pointerEvent).isEqualTo(
- pointerEventOf(
- expectedEvent1.apply { consumePositionChange(0f, 3f) }
+ PointerEventSubject
+ .assertThat(log1[3].pointerEvent)
+ .isStructurallyEqualTo(
+ pointerEventOf(
+ expectedEvent1.apply { consumePositionChange(0f, 3f) }
+ )
)
- )
assertThat(log1[3].pass).isEqualTo(PointerEventPass.Main)
assertThat(log2[0].pointerInputFilter).isEqualTo(pif3)
- assertThat(log2[0].pointerEvent).isEqualTo(pointerEventOf(expectedEvent2))
+ PointerEventSubject
+ .assertThat(log2[0].pointerEvent)
+ .isStructurallyEqualTo(pointerEventOf(expectedEvent2))
assertThat(log2[0].pass).isEqualTo(PointerEventPass.Initial)
assertThat(log2[1].pointerInputFilter).isEqualTo(pif4)
- assertThat(log2[1].pointerEvent).isEqualTo(
- pointerEventOf(
- expectedEvent2.apply { consumePositionChange(0f, -1f) }
+ PointerEventSubject
+ .assertThat(log2[1].pointerEvent)
+ .isStructurallyEqualTo(
+ pointerEventOf(
+ expectedEvent2.apply { consumePositionChange(0f, -1f) }
+ )
)
- )
assertThat(log2[1].pass).isEqualTo(PointerEventPass.Initial)
assertThat(log2[2].pointerInputFilter).isEqualTo(pif4)
- assertThat(log2[2].pointerEvent).isEqualTo(
- pointerEventOf(
- expectedEvent2.apply { consumePositionChange(0f, -2f) }
+ PointerEventSubject
+ .assertThat(log2[2].pointerEvent)
+ .isStructurallyEqualTo(
+ pointerEventOf(
+ expectedEvent2.apply { consumePositionChange(0f, -2f) }
+ )
)
- )
assertThat(log2[2].pass).isEqualTo(PointerEventPass.Main)
assertThat(log2[3].pointerInputFilter).isEqualTo(pif3)
- assertThat(log2[3].pointerEvent).isEqualTo(
- pointerEventOf(
- expectedEvent2.apply { consumePositionChange(0f, -3f) }
+ PointerEventSubject
+ .assertThat(log2[3].pointerEvent)
+ .isStructurallyEqualTo(
+ pointerEventOf(
+ expectedEvent2.apply { consumePositionChange(0f, -3f) }
+ )
)
- )
assertThat(log2[3].pass).isEqualTo(PointerEventPass.Main)
assertThat(result.changes).hasSize(2)
- assertThat(result.changes[actualEvent1.id]).isEqualTo(
- expectedEvent1.apply { consumePositionChange(0f, 4f) }
- )
- assertThat(result.changes[actualEvent2.id]).isEqualTo(
- expectedEvent2.apply { consumePositionChange(0f, -4f) }
- )
+ PointerInputChangeSubject
+ .assertThat(result.changes[actualEvent1.id])
+ .isStructurallyEqualTo(
+ expectedEvent1.apply { consumePositionChange(0f, 4f) }
+ )
+ PointerInputChangeSubject
+ .assertThat(result.changes[actualEvent2.id])
+ .isStructurallyEqualTo(
+ expectedEvent2.apply { consumePositionChange(0f, -4f) }
+ )
}
@Test
@@ -801,57 +865,73 @@
.filter { it.pass == PointerEventPass.Initial || it.pass == PointerEventPass.Main }
assertThat(log1[0].pointerInputFilter).isEqualTo(parent)
- assertThat(log1[0].pointerEvent).isEqualTo(pointerEventOf(expectedEvent1, expectedEvent2))
+ PointerEventSubject
+ .assertThat(log1[0].pointerEvent)
+ .isStructurallyEqualTo(pointerEventOf(expectedEvent1, expectedEvent2))
assertThat(log1[0].pass).isEqualTo(PointerEventPass.Initial)
assertThat(log1[1].pointerInputFilter).isEqualTo(child1)
- assertThat(log1[1].pointerEvent).isEqualTo(
- pointerEventOf(
- expectedEvent1.apply { consumePositionChange(0f, 1f) }
+ PointerEventSubject
+ .assertThat(log1[1].pointerEvent)
+ .isStructurallyEqualTo(
+ pointerEventOf(
+ expectedEvent1.apply { consumePositionChange(0f, 1f) }
+ )
)
- )
assertThat(log1[1].pass).isEqualTo(PointerEventPass.Initial)
assertThat(log1[2].pointerInputFilter).isEqualTo(child1)
- assertThat(log1[2].pointerEvent).isEqualTo(
- pointerEventOf(
- expectedEvent1.apply { consumePositionChange(0f, 2f) }
+ PointerEventSubject
+ .assertThat(log1[2].pointerEvent)
+ .isStructurallyEqualTo(
+ pointerEventOf(
+ expectedEvent1.apply { consumePositionChange(0f, 2f) }
+ )
)
- )
assertThat(log1[2].pass).isEqualTo(PointerEventPass.Main)
assertThat(log1[3].pointerInputFilter).isEqualTo(child2)
- assertThat(log1[3].pointerEvent).isEqualTo(
- pointerEventOf(
- expectedEvent2.apply { consumePositionChange(0f, 1f) }
+ PointerEventSubject
+ .assertThat(log1[3].pointerEvent)
+ .isStructurallyEqualTo(
+ pointerEventOf(
+ expectedEvent2.apply { consumePositionChange(0f, 1f) }
+ )
)
- )
assertThat(log1[3].pass).isEqualTo(PointerEventPass.Initial)
assertThat(log1[4].pointerInputFilter).isEqualTo(child2)
- assertThat(log1[4].pointerEvent).isEqualTo(
- pointerEventOf(
- expectedEvent2.apply { consumePositionChange(0f, 4f) }
+ PointerEventSubject
+ .assertThat(log1[4].pointerEvent)
+ .isStructurallyEqualTo(
+ pointerEventOf(
+ expectedEvent2.apply { consumePositionChange(0f, 4f) }
+ )
)
- )
assertThat(log1[4].pass).isEqualTo(PointerEventPass.Main)
assertThat(log1[5].pointerInputFilter).isEqualTo(parent)
- assertThat(log1[5].pointerEvent).isEqualTo(
- pointerEventOf(
- expectedEvent1.apply { consumePositionChange(0f, 20f) },
- expectedEvent2.apply { consumePositionChange(0f, 40f) }
+ PointerEventSubject
+ .assertThat(log1[5].pointerEvent)
+ .isStructurallyEqualTo(
+ pointerEventOf(
+ expectedEvent1.apply { consumePositionChange(0f, 20f) },
+ expectedEvent2.apply { consumePositionChange(0f, 40f) }
+ )
)
- )
assertThat(log1[5].pass).isEqualTo(PointerEventPass.Main)
assertThat(result.changes).hasSize(2)
- assertThat(result.changes[actualEvent1.id]).isEqualTo(
- expectedEvent1.apply { consumePositionChange(0f, 10f) }
- )
- assertThat(result.changes[actualEvent2.id]).isEqualTo(
- expectedEvent2.apply { consumePositionChange(0f, 10f) }
- )
+ PointerInputChangeSubject
+ .assertThat(result.changes[actualEvent1.id])
+ .isStructurallyEqualTo(
+ expectedEvent1.apply { consumePositionChange(0f, 10f) }
+ )
+ PointerInputChangeSubject
+ .assertThat(result.changes[actualEvent2.id])
+ .isStructurallyEqualTo(
+ expectedEvent2.apply { consumePositionChange(0f, 10f) }
+ )
}
@Test
@@ -911,43 +991,55 @@
.filter { it.pass == PointerEventPass.Initial || it.pass == PointerEventPass.Main }
assertThat(log1[0].pointerInputFilter).isEqualTo(child1)
- assertThat(log1[0].pointerEvent).isEqualTo(pointerEventOf(expectedEvent1, expectedEvent2))
+ PointerEventSubject
+ .assertThat(log1[0].pointerEvent)
+ .isStructurallyEqualTo(pointerEventOf(expectedEvent1, expectedEvent2))
assertThat(log1[0].pass).isEqualTo(PointerEventPass.Initial)
assertThat(log1[1].pointerInputFilter).isEqualTo(child2)
- assertThat(log1[1].pointerEvent).isEqualTo(
- pointerEventOf(
- expectedEvent1.apply { consumePositionChange(0f, 1f) },
- expectedEvent2.apply { consumePositionChange(0f, 1f) }
+ PointerEventSubject
+ .assertThat(log1[1].pointerEvent)
+ .isStructurallyEqualTo(
+ pointerEventOf(
+ expectedEvent1.apply { consumePositionChange(0f, 1f) },
+ expectedEvent2.apply { consumePositionChange(0f, 1f) }
+ )
)
- )
assertThat(log1[1].pass).isEqualTo(PointerEventPass.Initial)
assertThat(log1[2].pointerInputFilter).isEqualTo(child2)
- assertThat(log1[2].pointerEvent).isEqualTo(
- pointerEventOf(
- expectedEvent1.apply { consumePositionChange(0f, 2f) },
- expectedEvent2.apply { consumePositionChange(0f, 2f) }
+ PointerEventSubject
+ .assertThat(log1[2].pointerEvent)
+ .isStructurallyEqualTo(
+ pointerEventOf(
+ expectedEvent1.apply { consumePositionChange(0f, 2f) },
+ expectedEvent2.apply { consumePositionChange(0f, 2f) }
+ )
)
- )
assertThat(log1[2].pass).isEqualTo(PointerEventPass.Main)
assertThat(log1[3].pointerInputFilter).isEqualTo(child1)
- assertThat(log1[3].pointerEvent).isEqualTo(
- pointerEventOf(
- expectedEvent1.apply { consumePositionChange(0f, 3f) },
- expectedEvent2.apply { consumePositionChange(0f, 3f) }
+ PointerEventSubject
+ .assertThat(log1[3].pointerEvent)
+ .isStructurallyEqualTo(
+ pointerEventOf(
+ expectedEvent1.apply { consumePositionChange(0f, 3f) },
+ expectedEvent2.apply { consumePositionChange(0f, 3f) }
+ )
)
- )
assertThat(log1[3].pass).isEqualTo(PointerEventPass.Main)
assertThat(result.changes).hasSize(2)
- assertThat(result.changes[actualEvent1.id]).isEqualTo(
- expectedEvent1.apply { consumePositionChange(0f, 4f) }
- )
- assertThat(result.changes[actualEvent2.id]).isEqualTo(
- expectedEvent2.apply { consumePositionChange(0f, 4f) }
- )
+ PointerInputChangeSubject
+ .assertThat(result.changes[actualEvent1.id])
+ .isStructurallyEqualTo(
+ expectedEvent1.apply { consumePositionChange(0f, 4f) }
+ )
+ PointerInputChangeSubject
+ .assertThat(result.changes[actualEvent2.id])
+ .isStructurallyEqualTo(
+ expectedEvent2.apply { consumePositionChange(0f, 4f) }
+ )
}
@Test
@@ -3578,7 +3670,9 @@
assertThat(log1).hasSize(6)
log1.forEach {
- assertThat(it.pointerEvent).isEqualTo(expected)
+ PointerEventSubject
+ .assertThat(it.pointerEvent)
+ .isStructurallyEqualTo(expected)
}
}
diff --git a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/input/pointer/PointerInputEventProcessorTest.kt b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/input/pointer/PointerInputEventProcessorTest.kt
index e2e5c19..a287a55 100644
--- a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/input/pointer/PointerInputEventProcessorTest.kt
+++ b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/input/pointer/PointerInputEventProcessorTest.kt
@@ -51,13 +51,7 @@
import androidx.compose.ui.unit.minus
import androidx.test.filters.SmallTest
import com.google.common.truth.Truth.assertThat
-import com.nhaarman.mockitokotlin2.any
-import com.nhaarman.mockitokotlin2.eq
-import com.nhaarman.mockitokotlin2.inOrder
-import com.nhaarman.mockitokotlin2.never
import com.nhaarman.mockitokotlin2.spy
-import com.nhaarman.mockitokotlin2.times
-import com.nhaarman.mockitokotlin2.verify
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@@ -106,8 +100,7 @@
fun process_downMoveUp_convertedCorrectlyAndTraversesAllPassesInCorrectOrder() {
// Arrange
-
- val pointerInputFilter = spy(MockPointerInputFilter())
+ val pointerInputFilter = PointerInputFilterMock()
val layoutNode = LayoutNode(
0,
0,
@@ -126,53 +119,14 @@
val events = arrayOf(
PointerInputEvent(8712, Uptime.Boot + 3.milliseconds, offset, true),
PointerInputEvent(8712, Uptime.Boot + 11.milliseconds, offset2, true),
- PointerInputEvent(8712, Uptime.Boot + 13.milliseconds, offset2, false)
+ PointerInputEvent(8712, Uptime.Boot + 13.milliseconds, null, false)
)
- val expectedChanges = arrayOf(
- PointerInputChange(
- id = PointerId(8712),
- current = PointerInputData(
- Uptime.Boot + 3.milliseconds,
- offset,
- true
- ),
- previous = PointerInputData(
- null,
- null,
- false
- ),
- consumed = ConsumedData()
- ),
- PointerInputChange(
- id = PointerId(8712),
- current = PointerInputData(
- Uptime.Boot + 11.milliseconds,
- offset2,
- true
- ),
- previous = PointerInputData(
- Uptime.Boot + 3.milliseconds,
- offset,
- true
- ),
- consumed = ConsumedData()
- ),
- PointerInputChange(
- id = PointerId(8712),
- current = PointerInputData(
- Uptime.Boot + 13.milliseconds,
- offset2,
- false
- ),
- previous = PointerInputData(
- Uptime.Boot + 11.milliseconds,
- offset2,
- true
- ),
- consumed = ConsumedData()
- )
- )
+ val down = down(8712, 3.milliseconds, offset.x, offset.y)
+ val move = down.moveTo(11.milliseconds, offset2.x, offset2.y)
+ val up = move.up(13.milliseconds)
+
+ val expectedChanges = arrayOf(down, move, up)
// Act
@@ -180,22 +134,22 @@
// Assert
+ val log = pointerInputFilter.log.getOnPointerEventLog()
+
// Verify call count
- verify(
- pointerInputFilter,
- times(PointerEventPass.values().size * expectedChanges.size)
- ).onPointerEventMock(any(), any(), any())
+ assertThat(log)
+ .hasSize(PointerEventPass.values().size * expectedChanges.size)
// Verify call values
- inOrder(pointerInputFilter) {
- for (expected in expectedChanges) {
- for (pass in PointerEventPass.values()) {
- verify(pointerInputFilter).onPointerEventMock(
- eq(pointerEventOf(expected)),
- eq(pass),
- any()
- )
- }
+ var count = 0
+ expectedChanges.forEach { change ->
+ PointerEventPass.values().forEach { pass ->
+ val item = log[count]
+ PointerEventSubject
+ .assertThat(item.pointerEvent)
+ .isStructurallyEqualTo(pointerEventOf(change))
+ assertThat(item.pass).isEqualTo(pass)
+ count++
}
}
}
@@ -206,7 +160,7 @@
// Arrange
val childOffset = Offset(100f, 200f)
- val pointerInputFilter = spy(MockPointerInputFilter())
+ val pointerInputFilter = PointerInputFilterMock()
val layoutNode = LayoutNode(
100, 200, 301, 401,
PointerInputModifierImpl2(
@@ -252,19 +206,22 @@
// Assert
+ val log =
+ pointerInputFilter
+ .log
+ .getOnPointerEventLog()
+ .filter { it.pass == PointerEventPass.Initial }
+
// Verify call count
- verify(pointerInputFilter, times(expectedChanges.size)).onPointerEventMock(
- any(),
- eq(PointerEventPass.Initial),
- any()
- )
+ assertThat(log)
+ .hasSize(expectedChanges.size)
+
// Verify call values
- for (expected in expectedChanges) {
- verify(pointerInputFilter).onPointerEventMock(
- eq(pointerEventOf(expected)),
- eq(PointerEventPass.Initial),
- any()
- )
+ expectedChanges.forEachIndexed { index, change ->
+ val item = log[index]
+ PointerEventSubject
+ .assertThat(item.pointerEvent)
+ .isStructurallyEqualTo(pointerEventOf(change))
}
}
@@ -273,7 +230,7 @@
// Arrange
- val pointerInputFilter = spy(MockPointerInputFilter())
+ val pointerInputFilter = PointerInputFilterMock()
val layoutNode = LayoutNode(
100, 200, 301, 401,
PointerInputModifierImpl2(
@@ -306,7 +263,7 @@
// Assert
- verify(pointerInputFilter, never()).onPointerEventMock(any(), any(), any())
+ assertThat(pointerInputFilter.log.getOnPointerEventLog()).hasSize(0)
}
@Test
@@ -327,9 +284,10 @@
private fun process_partialTreeHits(numberOfChildrenHit: Int) {
// Arrange
- val childPointerInputFilter = spy(MockPointerInputFilter())
- val middlePointerInputFilter = spy(MockPointerInputFilter())
- val parentPointerInputFilter = spy(MockPointerInputFilter())
+ val log = mutableListOf<LogEntry>()
+ val childPointerInputFilter = PointerInputFilterMock(log)
+ val middlePointerInputFilter = PointerInputFilterMock(log)
+ val parentPointerInputFilter = PointerInputFilterMock(log)
val childLayoutNode =
LayoutNode(
@@ -373,57 +331,29 @@
// Assert
+ val filteredLog = log.getOnPointerEventLog().filter { it.pass == PointerEventPass.Initial }
+
when (numberOfChildrenHit) {
3 -> {
- verify(parentPointerInputFilter).onPointerEventMock(
- any(),
- eq(PointerEventPass.Initial),
- any()
- )
- verify(middlePointerInputFilter).onPointerEventMock(
- any(),
- eq(PointerEventPass.Initial),
- any()
- )
- verify(childPointerInputFilter).onPointerEventMock(
- any(),
- eq(PointerEventPass.Initial),
- any()
- )
+ assertThat(filteredLog).hasSize(3)
+ assertThat(filteredLog[0].pointerInputFilter)
+ .isSameInstanceAs(parentPointerInputFilter)
+ assertThat(filteredLog[1].pointerInputFilter)
+ .isSameInstanceAs(middlePointerInputFilter)
+ assertThat(filteredLog[2].pointerInputFilter)
+ .isSameInstanceAs(childPointerInputFilter)
}
2 -> {
- verify(parentPointerInputFilter).onPointerEventMock(
- any(),
- eq(PointerEventPass.Initial),
- any()
- )
- verify(middlePointerInputFilter).onPointerEventMock(
- any(),
- eq(PointerEventPass.Initial),
- any()
- )
- verify(childPointerInputFilter, never()).onPointerEventMock(
- any(),
- any(),
- any()
- )
+ assertThat(filteredLog).hasSize(2)
+ assertThat(filteredLog[0].pointerInputFilter)
+ .isSameInstanceAs(parentPointerInputFilter)
+ assertThat(filteredLog[1].pointerInputFilter)
+ .isSameInstanceAs(middlePointerInputFilter)
}
1 -> {
- verify(parentPointerInputFilter).onPointerEventMock(
- any(),
- eq(PointerEventPass.Initial),
- any()
- )
- verify(middlePointerInputFilter, never()).onPointerEventMock(
- any(),
- any(),
- any()
- )
- verify(childPointerInputFilter, never()).onPointerEventMock(
- any(),
- any(),
- any()
- )
+ assertThat(filteredLog).hasSize(1)
+ assertThat(filteredLog[0].pointerInputFilter)
+ .isSameInstanceAs(parentPointerInputFilter)
}
else -> throw IllegalStateException()
}
@@ -512,8 +442,12 @@
val log = pointerInputFilter.log.getOnPointerEventLog()
assertThat(log).hasSize(3)
- assertThat(log[0].pointerEvent.changes.first()).isEqualTo(expectedInput)
- assertThat(log[1].pointerEvent.changes.first()).isEqualTo(expectedOutput)
+ PointerInputChangeSubject
+ .assertThat(log[0].pointerEvent.changes.first())
+ .isStructurallyEqualTo(expectedInput)
+ PointerInputChangeSubject
+ .assertThat(log[1].pointerEvent.changes.first())
+ .isStructurallyEqualTo(expectedOutput)
}
@Test
@@ -571,9 +505,10 @@
// Arrange
- val childPointerInputFilter = spy(MockPointerInputFilter())
- val middlePointerInputFilter = spy(MockPointerInputFilter())
- val parentPointerInputFilter = spy(MockPointerInputFilter())
+ val log = mutableListOf<LogEntry>()
+ val childPointerInputFilter = PointerInputFilterMock(log)
+ val middlePointerInputFilter = PointerInputFilterMock(log)
+ val parentPointerInputFilter = PointerInputFilterMock(log)
val childOffset = Offset(cX1.toFloat(), cY1.toFloat())
val childLayoutNode = LayoutNode(
@@ -610,12 +545,6 @@
val down = PointerInputEvent(0, Uptime.Boot + 7.milliseconds, offset, true)
- val pointerInputHandlers = arrayOf(
- parentPointerInputFilter,
- middlePointerInputFilter,
- childPointerInputFilter
- )
-
val expectedPointerInputChanges = arrayOf(
PointerInputChange(
id = PointerId(0),
@@ -673,24 +602,75 @@
// Assert
+ val filteredLog = log.getOnPointerEventLog()
+
// Verify call count
- pointerInputHandlers.forEach {
- verify(it, times(PointerEventPass.values().size)).onPointerEventMock(
- any(),
- any(),
- any()
- )
- }
+ assertThat(filteredLog).hasSize(PointerEventPass.values().size * 3)
+
// Verify call values
- for (pass in PointerEventPass.values()) {
- for (i in pointerInputHandlers.indices) {
- verify(pointerInputHandlers[i]).onPointerEventMock(
- pointerEventOf(expectedPointerInputChanges[i]),
- pass,
- expectedSizes[i]
- )
- }
- }
+ filteredLog.verifyOnPointerEventCall(
+ 0,
+ parentPointerInputFilter,
+ pointerEventOf(expectedPointerInputChanges[0]),
+ PointerEventPass.Initial,
+ expectedSizes[0]
+ )
+ filteredLog.verifyOnPointerEventCall(
+ 1,
+ middlePointerInputFilter,
+ pointerEventOf(expectedPointerInputChanges[1]),
+ PointerEventPass.Initial,
+ expectedSizes[1]
+ )
+ filteredLog.verifyOnPointerEventCall(
+ 2,
+ childPointerInputFilter,
+ pointerEventOf(expectedPointerInputChanges[2]),
+ PointerEventPass.Initial,
+ expectedSizes[2]
+ )
+ filteredLog.verifyOnPointerEventCall(
+ 3,
+ childPointerInputFilter,
+ pointerEventOf(expectedPointerInputChanges[2]),
+ PointerEventPass.Main,
+ expectedSizes[2]
+ )
+ filteredLog.verifyOnPointerEventCall(
+ 4,
+ middlePointerInputFilter,
+ pointerEventOf(expectedPointerInputChanges[1]),
+ PointerEventPass.Main,
+ expectedSizes[1]
+ )
+ filteredLog.verifyOnPointerEventCall(
+ 5,
+ parentPointerInputFilter,
+ pointerEventOf(expectedPointerInputChanges[0]),
+ PointerEventPass.Main,
+ expectedSizes[0]
+ )
+ filteredLog.verifyOnPointerEventCall(
+ 6,
+ parentPointerInputFilter,
+ pointerEventOf(expectedPointerInputChanges[0]),
+ PointerEventPass.Final,
+ expectedSizes[0]
+ )
+ filteredLog.verifyOnPointerEventCall(
+ 7,
+ middlePointerInputFilter,
+ pointerEventOf(expectedPointerInputChanges[1]),
+ PointerEventPass.Final,
+ expectedSizes[1]
+ )
+ filteredLog.verifyOnPointerEventCall(
+ 8,
+ childPointerInputFilter,
+ pointerEventOf(expectedPointerInputChanges[2]),
+ PointerEventPass.Final,
+ expectedSizes[2]
+ )
}
/**
@@ -716,8 +696,9 @@
// Arrange
- val childPointerInputFilter1 = spy(MockPointerInputFilter())
- val childPointerInputFilter2 = spy(MockPointerInputFilter())
+ val log = mutableListOf<LogEntry>()
+ val childPointerInputFilter1 = PointerInputFilterMock(log)
+ val childPointerInputFilter2 = PointerInputFilterMock(log)
val childLayoutNode1 =
LayoutNode(
@@ -787,26 +768,61 @@
// Assert
// Verify call count
- verify(childPointerInputFilter1, times(PointerEventPass.values().size))
- .onPointerEventMock(any(), any(), any())
- verify(childPointerInputFilter2, times(PointerEventPass.values().size))
- .onPointerEventMock(any(), any(), any())
+
+ val child1Log =
+ log.getOnPointerEventLog().filter { it.pointerInputFilter === childPointerInputFilter1 }
+ val child2Log =
+ log.getOnPointerEventLog().filter { it.pointerInputFilter === childPointerInputFilter2 }
+ assertThat(child1Log).hasSize(PointerEventPass.values().size)
+ assertThat(child2Log).hasSize(PointerEventPass.values().size)
// Verify call values
- for (pointerEventPass in PointerEventPass.values()) {
- verify(childPointerInputFilter1)
- .onPointerEventMock(
- pointerEventOf(expectedChange1),
- pointerEventPass,
- IntSize(50, 50)
- )
- verify(childPointerInputFilter2)
- .onPointerEventMock(
- pointerEventOf(expectedChange2),
- pointerEventPass,
- IntSize(50, 50)
- )
- }
+
+ val expectedBounds = IntSize(50, 50)
+
+ child1Log.verifyOnPointerEventCall(
+ 0,
+ null,
+ pointerEventOf(expectedChange1),
+ PointerEventPass.Initial,
+ expectedBounds
+ )
+ child1Log.verifyOnPointerEventCall(
+ 1,
+ null,
+ pointerEventOf(expectedChange1),
+ PointerEventPass.Main,
+ expectedBounds
+ )
+ child1Log.verifyOnPointerEventCall(
+ 2,
+ null,
+ pointerEventOf(expectedChange1),
+ PointerEventPass.Final,
+ expectedBounds
+ )
+
+ child2Log.verifyOnPointerEventCall(
+ 0,
+ null,
+ pointerEventOf(expectedChange2),
+ PointerEventPass.Initial,
+ expectedBounds
+ )
+ child2Log.verifyOnPointerEventCall(
+ 1,
+ null,
+ pointerEventOf(expectedChange2),
+ PointerEventPass.Main,
+ expectedBounds
+ )
+ child2Log.verifyOnPointerEventCall(
+ 2,
+ null,
+ pointerEventOf(expectedChange2),
+ PointerEventPass.Final,
+ expectedBounds
+ )
}
/**
@@ -834,9 +850,10 @@
@Test
fun process_3DownOnOverlappingPointerNodes_hitAndDispatchInfoAreCorrect() {
- val childPointerInputFilter1 = spy(MockPointerInputFilter())
- val childPointerInputFilter2 = spy(MockPointerInputFilter())
- val childPointerInputFilter3 = spy(MockPointerInputFilter())
+ val log = mutableListOf<LogEntry>()
+ val childPointerInputFilter1 = PointerInputFilterMock(log)
+ val childPointerInputFilter2 = PointerInputFilterMock(log)
+ val childPointerInputFilter3 = PointerInputFilterMock(log)
val childLayoutNode1 = LayoutNode(
0, 0, 100, 100,
@@ -928,35 +945,85 @@
// Assert
- // Verify call count
- verify(childPointerInputFilter1, times(PointerEventPass.values().size))
- .onPointerEventMock(any(), any(), any())
- verify(childPointerInputFilter2, times(PointerEventPass.values().size))
- .onPointerEventMock(any(), any(), any())
- verify(childPointerInputFilter3, times(PointerEventPass.values().size))
- .onPointerEventMock(any(), any(), any())
+ val child1Log =
+ log.getOnPointerEventLog().filter { it.pointerInputFilter === childPointerInputFilter1 }
+ val child2Log =
+ log.getOnPointerEventLog().filter { it.pointerInputFilter === childPointerInputFilter2 }
+ val child3Log =
+ log.getOnPointerEventLog().filter { it.pointerInputFilter === childPointerInputFilter3 }
+ assertThat(child1Log).hasSize(PointerEventPass.values().size)
+ assertThat(child2Log).hasSize(PointerEventPass.values().size)
+ assertThat(child3Log).hasSize(PointerEventPass.values().size)
// Verify call values
- for (pointerEventPass in PointerEventPass.values()) {
- verify(childPointerInputFilter1)
- .onPointerEventMock(
- pointerEventOf(expectedChange1),
- pointerEventPass,
- IntSize(100, 100)
- )
- verify(childPointerInputFilter2)
- .onPointerEventMock(
- pointerEventOf(expectedChange2),
- pointerEventPass,
- IntSize(100, 100)
- )
- verify(childPointerInputFilter3)
- .onPointerEventMock(
- pointerEventOf(expectedChange3),
- pointerEventPass,
- IntSize(100, 100)
- )
- }
+
+ val expectedBounds = IntSize(100, 100)
+
+ child1Log.verifyOnPointerEventCall(
+ 0,
+ null,
+ pointerEventOf(expectedChange1),
+ PointerEventPass.Initial,
+ expectedBounds
+ )
+ child1Log.verifyOnPointerEventCall(
+ 1,
+ null,
+ pointerEventOf(expectedChange1),
+ PointerEventPass.Main,
+ expectedBounds
+ )
+ child1Log.verifyOnPointerEventCall(
+ 2,
+ null,
+ pointerEventOf(expectedChange1),
+ PointerEventPass.Final,
+ expectedBounds
+ )
+
+ child2Log.verifyOnPointerEventCall(
+ 0,
+ null,
+ pointerEventOf(expectedChange2),
+ PointerEventPass.Initial,
+ expectedBounds
+ )
+ child2Log.verifyOnPointerEventCall(
+ 1,
+ null,
+ pointerEventOf(expectedChange2),
+ PointerEventPass.Main,
+ expectedBounds
+ )
+ child2Log.verifyOnPointerEventCall(
+ 2,
+ null,
+ pointerEventOf(expectedChange2),
+ PointerEventPass.Final,
+ expectedBounds
+ )
+
+ child3Log.verifyOnPointerEventCall(
+ 0,
+ null,
+ pointerEventOf(expectedChange3),
+ PointerEventPass.Initial,
+ expectedBounds
+ )
+ child3Log.verifyOnPointerEventCall(
+ 1,
+ null,
+ pointerEventOf(expectedChange3),
+ PointerEventPass.Main,
+ expectedBounds
+ )
+ child3Log.verifyOnPointerEventCall(
+ 2,
+ null,
+ pointerEventOf(expectedChange3),
+ PointerEventPass.Final,
+ expectedBounds
+ )
}
/**
@@ -983,8 +1050,8 @@
@Test
fun process_3DownOnFloatingPointerNodeV_hitAndDispatchInfoAreCorrect() {
- val childPointerInputFilter1 = spy(MockPointerInputFilter())
- val childPointerInputFilter2 = spy(MockPointerInputFilter())
+ val childPointerInputFilter1 = PointerInputFilterMock()
+ val childPointerInputFilter2 = PointerInputFilterMock()
val childLayoutNode1 = LayoutNode(
0, 0, 100, 150,
@@ -1069,26 +1136,29 @@
// Assert
+ val log1 = childPointerInputFilter1.log.getOnPointerEventLog()
+ val log2 = childPointerInputFilter2.log.getOnPointerEventLog()
+
// Verify call count
- verify(childPointerInputFilter1, times(PointerEventPass.values().size))
- .onPointerEventMock(any(), any(), any())
- verify(childPointerInputFilter2, times(PointerEventPass.values().size))
- .onPointerEventMock(any(), any(), any())
+ assertThat(log1).hasSize(PointerEventPass.values().size)
+ assertThat(log2).hasSize(PointerEventPass.values().size)
// Verify call values
- for (pointerEventPass in PointerEventPass.values()) {
- verify(childPointerInputFilter1)
- .onPointerEventMock(
- pointerEventOf(expectedChange1, expectedChange3),
- pointerEventPass,
- IntSize(100, 150)
- )
- verify(childPointerInputFilter2)
- .onPointerEventMock(
- pointerEventOf(expectedChange2),
- pointerEventPass,
- IntSize(50, 50)
- )
+ PointerEventPass.values().forEachIndexed { index, pass ->
+ log1.verifyOnPointerEventCall(
+ index,
+ null,
+ pointerEventOf(expectedChange1, expectedChange3),
+ pass,
+ IntSize(100, 150)
+ )
+ log2.verifyOnPointerEventCall(
+ index,
+ null,
+ pointerEventOf(expectedChange2),
+ pass,
+ IntSize(50, 50)
+ )
}
}
@@ -1111,8 +1181,9 @@
*/
@Test
fun process_3DownOnFloatingPointerNodeH_hitAndDispatchInfoAreCorrect() {
- val childPointerInputFilter1 = spy(MockPointerInputFilter())
- val childPointerInputFilter2 = spy(MockPointerInputFilter())
+
+ val childPointerInputFilter1 = PointerInputFilterMock()
+ val childPointerInputFilter2 = PointerInputFilterMock()
val childLayoutNode1 = LayoutNode(
0, 0, 150, 100,
@@ -1197,26 +1268,29 @@
// Assert
+ val log1 = childPointerInputFilter1.log.getOnPointerEventLog()
+ val log2 = childPointerInputFilter2.log.getOnPointerEventLog()
+
// Verify call count
- verify(childPointerInputFilter1, times(PointerEventPass.values().size))
- .onPointerEventMock(any(), any(), any())
- verify(childPointerInputFilter2, times(PointerEventPass.values().size))
- .onPointerEventMock(any(), any(), any())
+ assertThat(log1).hasSize(PointerEventPass.values().size)
+ assertThat(log2).hasSize(PointerEventPass.values().size)
// Verify call values
- for (pointerEventPass in PointerEventPass.values()) {
- verify(childPointerInputFilter1)
- .onPointerEventMock(
- pointerEventOf(expectedChange1, expectedChange3),
- pointerEventPass,
- IntSize(150, 100)
- )
- verify(childPointerInputFilter2)
- .onPointerEventMock(
- pointerEventOf(expectedChange2),
- pointerEventPass,
- IntSize(50, 50)
- )
+ PointerEventPass.values().forEachIndexed { index, pass ->
+ log1.verifyOnPointerEventCall(
+ index,
+ null,
+ pointerEventOf(expectedChange1, expectedChange3),
+ pass,
+ IntSize(150, 100)
+ )
+ log2.verifyOnPointerEventCall(
+ index,
+ null,
+ pointerEventOf(expectedChange2),
+ pass,
+ IntSize(50, 50)
+ )
}
}
@@ -1247,10 +1321,10 @@
// Arrange
- val pointerInputFilterTopLeft = spy(MockPointerInputFilter())
- val pointerInputFilterTopRight = spy(MockPointerInputFilter())
- val pointerInputFilterBottomLeft = spy(MockPointerInputFilter())
- val pointerInputFilterBottomRight = spy(MockPointerInputFilter())
+ val pointerInputFilterTopLeft = PointerInputFilterMock()
+ val pointerInputFilterTopRight = PointerInputFilterMock()
+ val pointerInputFilterBottomLeft = PointerInputFilterMock()
+ val pointerInputFilterBottomRight = PointerInputFilterMock()
val layoutNodeTopLeft = LayoutNode(
-1, -1, 1, 1,
@@ -1415,26 +1489,32 @@
}
// Verify call values
- PointerEventPass.values().forEach { pointerEventPass ->
- verify(pointerInputFilterTopLeft).onPointerEventMock(
- eq(pointerEventOf(*expectedChangesTopLeft.toTypedArray())),
- eq(pointerEventPass),
- any()
+
+ val logTopLeft = pointerInputFilterTopLeft.log.getOnPointerEventLog()
+ val logTopRight = pointerInputFilterTopRight.log.getOnPointerEventLog()
+ val logBottomLeft = pointerInputFilterBottomLeft.log.getOnPointerEventLog()
+ val logBottomRight = pointerInputFilterBottomRight.log.getOnPointerEventLog()
+
+ PointerEventPass.values().forEachIndexed { index, pass ->
+ logTopLeft.verifyOnPointerEventCall(
+ index = index,
+ expectedEvent = pointerEventOf(*expectedChangesTopLeft.toTypedArray()),
+ expectedPass = pass
)
- verify(pointerInputFilterTopRight).onPointerEventMock(
- eq(pointerEventOf(*expectedChangesTopRight.toTypedArray())),
- eq(pointerEventPass),
- any()
+ logTopRight.verifyOnPointerEventCall(
+ index = index,
+ expectedEvent = pointerEventOf(*expectedChangesTopRight.toTypedArray()),
+ expectedPass = pass
)
- verify(pointerInputFilterBottomLeft).onPointerEventMock(
- eq(pointerEventOf(*expectedChangesBottomLeft.toTypedArray())),
- eq(pointerEventPass),
- any()
+ logBottomLeft.verifyOnPointerEventCall(
+ index = index,
+ expectedEvent = pointerEventOf(*expectedChangesBottomLeft.toTypedArray()),
+ expectedPass = pass
)
- verify(pointerInputFilterBottomRight).onPointerEventMock(
- eq(pointerEventOf(*expectedChangesBottomRight.toTypedArray())),
- eq(pointerEventPass),
- any()
+ logBottomRight.verifyOnPointerEventCall(
+ index = index,
+ expectedEvent = pointerEventOf(*expectedChangesBottomRight.toTypedArray()),
+ expectedPass = pass
)
}
}
@@ -1463,7 +1543,7 @@
fun process_rootIsOffset_onlyCorrectPointersHit() {
// Arrange
- val singlePointerInputFilter = spy(MockPointerInputFilter())
+ val singlePointerInputFilter = PointerInputFilterMock()
val layoutNode = LayoutNode(
0, 0, 2, 2,
PointerInputModifierImpl2(
@@ -1519,16 +1599,17 @@
)
}
+ val log = singlePointerInputFilter.log.getOnPointerEventLog()
+
// Verify call count
- verify(singlePointerInputFilter, times(PointerEventPass.values().size))
- .onPointerEventMock(any(), any(), any())
+ assertThat(log).hasSize(PointerEventPass.values().size)
// Verify call values
- PointerEventPass.values().forEach { pointerEventPass ->
- verify(singlePointerInputFilter).onPointerEventMock(
- eq(pointerEventOf(*expectedChanges.toTypedArray())),
- eq(pointerEventPass),
- any()
+ PointerEventPass.values().forEachIndexed { index, pass ->
+ log.verifyOnPointerEventCall(
+ index = index,
+ expectedEvent = pointerEventOf(*expectedChanges.toTypedArray()),
+ expectedPass = pass
)
}
}
@@ -1536,9 +1617,9 @@
@Test
fun process_downOn3NestedPointerInputModifiers_hitAndDispatchInfoAreCorrect() {
- val pointerInputFilter1 = spy(MockPointerInputFilter())
- val pointerInputFilter2 = spy(MockPointerInputFilter())
- val pointerInputFilter3 = spy(MockPointerInputFilter())
+ val pointerInputFilter1 = PointerInputFilterMock()
+ val pointerInputFilter2 = PointerInputFilterMock()
+ val pointerInputFilter3 = PointerInputFilterMock()
val modifier = PointerInputModifierImpl2(pointerInputFilter1) then
PointerInputModifierImpl2(pointerInputFilter2) then
@@ -1584,41 +1665,42 @@
// Assert
+ val log1 = pointerInputFilter1.log.getOnPointerEventLog()
+ val log2 = pointerInputFilter2.log.getOnPointerEventLog()
+ val log3 = pointerInputFilter3.log.getOnPointerEventLog()
+
// Verify call count
- verify(pointerInputFilter1, times(PointerEventPass.values().size))
- .onPointerEventMock(any(), any(), any())
- verify(pointerInputFilter2, times(PointerEventPass.values().size))
- .onPointerEventMock(any(), any(), any())
- verify(pointerInputFilter3, times(PointerEventPass.values().size))
- .onPointerEventMock(any(), any(), any())
+ assertThat(log1).hasSize(PointerEventPass.values().size)
+ assertThat(log2).hasSize(PointerEventPass.values().size)
+ assertThat(log3).hasSize(PointerEventPass.values().size)
// Verify call values
- for (pointerEventPass in PointerEventPass.values()) {
- verify(pointerInputFilter1)
- .onPointerEventMock(
- pointerEventOf(expectedChange),
- pointerEventPass,
- IntSize(50, 50)
- )
- verify(pointerInputFilter2)
- .onPointerEventMock(
- pointerEventOf(expectedChange),
- pointerEventPass,
- IntSize(50, 50)
- )
- verify(pointerInputFilter3)
- .onPointerEventMock(
- pointerEventOf(expectedChange),
- pointerEventPass,
- IntSize(50, 50)
- )
+ PointerEventPass.values().forEachIndexed { index, pass ->
+ log1.verifyOnPointerEventCall(
+ index = index,
+ expectedEvent = pointerEventOf(expectedChange),
+ expectedPass = pass,
+ expectedBounds = IntSize(50, 50)
+ )
+ log2.verifyOnPointerEventCall(
+ index = index,
+ expectedEvent = pointerEventOf(expectedChange),
+ expectedPass = pass,
+ expectedBounds = IntSize(50, 50)
+ )
+ log3.verifyOnPointerEventCall(
+ index = index,
+ expectedEvent = pointerEventOf(expectedChange),
+ expectedPass = pass,
+ expectedBounds = IntSize(50, 50)
+ )
}
}
@Test
fun process_downOnDeeplyNestedPointerInputModifier_hitAndDispatchInfoAreCorrect() {
- val pointerInputFilter = spy(MockPointerInputFilter())
+ val pointerInputFilter = PointerInputFilterMock()
val layoutNode1 =
LayoutNode(
@@ -1669,28 +1751,29 @@
// Assert
+ val log = pointerInputFilter.log.getOnPointerEventLog()
+
// Verify call count
- verify(pointerInputFilter, times(PointerEventPass.values().size))
- .onPointerEventMock(any(), any(), any())
+ assertThat(log).hasSize(PointerEventPass.values().size)
// Verify call values
- for (pointerEventPass in PointerEventPass.values()) {
- verify(pointerInputFilter)
- .onPointerEventMock(
- pointerEventOf(expectedChange),
- pointerEventPass,
- IntSize(499, 495)
- )
+ PointerEventPass.values().forEachIndexed { index, pass ->
+ log.verifyOnPointerEventCall(
+ index = index,
+ expectedEvent = pointerEventOf(expectedChange),
+ expectedPass = pass,
+ expectedBounds = IntSize(499, 495)
+ )
}
}
@Test
fun process_downOnComplexPointerAndLayoutNodePath_hitAndDispatchInfoAreCorrect() {
- val pointerInputFilter1 = spy(MockPointerInputFilter())
- val pointerInputFilter2 = spy(MockPointerInputFilter())
- val pointerInputFilter3 = spy(MockPointerInputFilter())
- val pointerInputFilter4 = spy(MockPointerInputFilter())
+ val pointerInputFilter1 = PointerInputFilterMock()
+ val pointerInputFilter2 = PointerInputFilterMock()
+ val pointerInputFilter3 = PointerInputFilterMock()
+ val pointerInputFilter4 = PointerInputFilterMock()
val layoutNode1 = LayoutNode(
1, 6, 500, 500,
@@ -1769,51 +1852,51 @@
// Assert
+ val log1 = pointerInputFilter1.log.getOnPointerEventLog()
+ val log2 = pointerInputFilter2.log.getOnPointerEventLog()
+ val log3 = pointerInputFilter3.log.getOnPointerEventLog()
+ val log4 = pointerInputFilter4.log.getOnPointerEventLog()
+
// Verify call count
- verify(pointerInputFilter1, times(PointerEventPass.values().size))
- .onPointerEventMock(any(), any(), any())
- verify(pointerInputFilter2, times(PointerEventPass.values().size))
- .onPointerEventMock(any(), any(), any())
- verify(pointerInputFilter3, times(PointerEventPass.values().size))
- .onPointerEventMock(any(), any(), any())
- verify(pointerInputFilter4, times(PointerEventPass.values().size))
- .onPointerEventMock(any(), any(), any())
- PointerEventPass.values()
+ assertThat(log1).hasSize(PointerEventPass.values().size)
+ assertThat(log2).hasSize(PointerEventPass.values().size)
+ assertThat(log3).hasSize(PointerEventPass.values().size)
+ assertThat(log4).hasSize(PointerEventPass.values().size)
// Verify call values
- for (pointerEventPass in PointerEventPass.values()) {
- verify(pointerInputFilter1)
- .onPointerEventMock(
- pointerEventOf(expectedChange1),
- pointerEventPass,
- IntSize(499, 494)
- )
- verify(pointerInputFilter2)
- .onPointerEventMock(
- pointerEventOf(expectedChange1),
- pointerEventPass,
- IntSize(499, 494)
- )
- verify(pointerInputFilter3)
- .onPointerEventMock(
- pointerEventOf(expectedChange2),
- pointerEventPass,
- IntSize(497, 492)
- )
- verify(pointerInputFilter4)
- .onPointerEventMock(
- pointerEventOf(expectedChange2),
- pointerEventPass,
- IntSize(497, 492)
- )
+ PointerEventPass.values().forEachIndexed { index, pass ->
+ log1.verifyOnPointerEventCall(
+ index = index,
+ expectedEvent = pointerEventOf(expectedChange1),
+ expectedPass = pass,
+ expectedBounds = IntSize(499, 494)
+ )
+ log2.verifyOnPointerEventCall(
+ index = index,
+ expectedEvent = pointerEventOf(expectedChange1),
+ expectedPass = pass,
+ expectedBounds = IntSize(499, 494)
+ )
+ log3.verifyOnPointerEventCall(
+ index = index,
+ expectedEvent = pointerEventOf(expectedChange2),
+ expectedPass = pass,
+ expectedBounds = IntSize(497, 492)
+ )
+ log4.verifyOnPointerEventCall(
+ index = index,
+ expectedEvent = pointerEventOf(expectedChange2),
+ expectedPass = pass,
+ expectedBounds = IntSize(497, 492)
+ )
}
}
@Test
fun process_downOnFullyOverlappingPointerInputModifiers_onlyTopPointerInputModifierReceives() {
- val pointerInputFilter1 = spy(MockPointerInputFilter())
- val pointerInputFilter2 = spy(MockPointerInputFilter())
+ val pointerInputFilter1 = PointerInputFilterMock()
+ val pointerInputFilter2 = PointerInputFilterMock()
val layoutNode1 = LayoutNode(
0, 0, 100, 100,
@@ -1842,14 +1925,14 @@
pointerInputEventProcessor.process(down)
// Assert
- verify(pointerInputFilter2, times(3)).onPointerEventMock(any(), any(), any())
- verify(pointerInputFilter1, never()).onPointerEventMock(any(), any(), any())
+ assertThat(pointerInputFilter2.log.getOnPointerEventLog()).hasSize(3)
+ assertThat(pointerInputFilter1.log.getOnPointerEventLog()).hasSize(0)
}
@Test
fun process_downOnPointerInputModifierInLayoutNodeWithNoSize_downNotReceived() {
- val pointerInputFilter1 = spy(MockPointerInputFilter())
+ val pointerInputFilter1 = PointerInputFilterMock()
val layoutNode1 = LayoutNode(
0, 0, 0, 0,
@@ -1868,7 +1951,7 @@
pointerInputEventProcessor.process(down)
// Assert
- verify(pointerInputFilter1, never()).onPointerEventMock(any(), any(), any())
+ assertThat(pointerInputFilter1.log.getOnPointerEventLog()).hasSize(0)
}
// Cancel Handlers
@@ -1883,7 +1966,7 @@
// Arrange
- val pointerInputFilter = spy(MockPointerInputFilter())
+ val pointerInputFilter = PointerInputFilterMock()
val layoutNode = LayoutNode(
0, 0, 500, 500,
@@ -1923,21 +2006,20 @@
// Assert
+ val log = pointerInputFilter.log.filter { it is OnPointerEventEntry || it is OnCancelEntry }
+
// Verify call count
- verify(pointerInputFilter, times(PointerEventPass.values().size))
- .onPointerEventMock(any(), any(), any())
+ assertThat(log).hasSize(PointerEventPass.values().size + 1)
// Verify call values
- inOrder(pointerInputFilter) {
- for (pass in PointerEventPass.values()) {
- verify(pointerInputFilter).onPointerEventMock(
- eq(pointerEventOf(expectedChange)),
- eq(pass),
- any()
- )
- }
- verify(pointerInputFilter).onCancel()
+ PointerEventPass.values().forEachIndexed { index, pass ->
+ log.verifyOnPointerEventCall(
+ index = index,
+ expectedEvent = pointerEventOf(expectedChange),
+ expectedPass = pass
+ )
}
+ log.verifyOnCancelCall(PointerEventPass.values().size)
}
@Test
@@ -1945,7 +2027,7 @@
// Arrange
- val pointerInputFilter = spy(MockPointerInputFilter())
+ val pointerInputFilter = PointerInputFilterMock()
val layoutNode = LayoutNode(
0, 0, 500, 500,
@@ -2041,28 +2123,30 @@
// Assert
+ val log = pointerInputFilter.log.filter { it is OnPointerEventEntry || it is OnCancelEntry }
+
// Verify call count
- verify(pointerInputFilter, times(PointerEventPass.values().size * 2))
- .onPointerEventMock(any(), any(), any())
+ assertThat(log).hasSize(PointerEventPass.values().size * 2 + 1)
// Verify call values
- inOrder(pointerInputFilter) {
- for (pass in PointerEventPass.values()) {
- verify(pointerInputFilter).onPointerEventMock(
- eq(pointerEventOf(*expectedChanges1.toTypedArray())),
- eq(pass),
- any()
- )
- }
- for (pass in PointerEventPass.values()) {
- verify(pointerInputFilter).onPointerEventMock(
- eq(pointerEventOf(*expectedChanges2.toTypedArray())),
- eq(pass),
- any()
- )
- }
- verify(pointerInputFilter).onCancel()
+ var index = 0
+ PointerEventPass.values().forEach { pass ->
+ log.verifyOnPointerEventCall(
+ index = index,
+ expectedEvent = pointerEventOf(*expectedChanges1.toTypedArray()),
+ expectedPass = pass
+ )
+ index++
}
+ PointerEventPass.values().forEach { pass ->
+ log.verifyOnPointerEventCall(
+ index = index,
+ expectedEvent = pointerEventOf(*expectedChanges2.toTypedArray()),
+ expectedPass = pass
+ )
+ index++
+ }
+ log.verifyOnCancelCall(index)
}
@Test
@@ -2070,13 +2154,13 @@
// Arrange
- val pointerInputFilter1 = spy(MockPointerInputFilter())
+ val pointerInputFilter1 = PointerInputFilterMock()
val layoutNode1 = LayoutNode(
0, 0, 199, 199,
PointerInputModifierImpl2(pointerInputFilter1)
)
- val pointerInputFilter2 = spy(MockPointerInputFilter())
+ val pointerInputFilter2 = PointerInputFilterMock()
val layoutNode2 = LayoutNode(
200, 200, 399, 399,
PointerInputModifierImpl2(pointerInputFilter2)
@@ -2145,33 +2229,32 @@
// Assert
+ val log1 =
+ pointerInputFilter1.log.filter { it is OnPointerEventEntry || it is OnCancelEntry }
+ val log2 =
+ pointerInputFilter2.log.filter { it is OnPointerEventEntry || it is OnCancelEntry }
+
// Verify call count
- verify(pointerInputFilter1, times(PointerEventPass.values().size))
- .onPointerEventMock(any(), any(), any())
- verify(pointerInputFilter2, times(PointerEventPass.values().size))
- .onPointerEventMock(any(), any(), any())
+ assertThat(log1).hasSize(PointerEventPass.values().size + 1)
+ assertThat(log2).hasSize(PointerEventPass.values().size + 1)
// Verify call values
- inOrder(pointerInputFilter1) {
- for (pass in PointerEventPass.values()) {
- verify(pointerInputFilter1).onPointerEventMock(
- eq(pointerEventOf(expectedChange1)),
- eq(pass),
- any()
- )
- }
- verify(pointerInputFilter1).onCancel()
+ var index = 0
+ PointerEventPass.values().forEach { pass ->
+ log1.verifyOnPointerEventCall(
+ index = index,
+ expectedEvent = pointerEventOf(expectedChange1),
+ expectedPass = pass
+ )
+ log2.verifyOnPointerEventCall(
+ index = index,
+ expectedEvent = pointerEventOf(expectedChange2),
+ expectedPass = pass
+ )
+ index++
}
- inOrder(pointerInputFilter2) {
- for (pass in PointerEventPass.values()) {
- verify(pointerInputFilter2).onPointerEventMock(
- eq(pointerEventOf(expectedChange2)),
- eq(pass),
- any()
- )
- }
- verify(pointerInputFilter2).onCancel()
- }
+ log1.verifyOnCancelCall(index)
+ log2.verifyOnCancelCall(index)
}
@Test
@@ -2179,7 +2262,7 @@
// Arrange
- val pointerInputFilter = spy(MockPointerInputFilter())
+ val pointerInputFilter = PointerInputFilterMock()
val layoutNode = LayoutNode(
0, 0, 500, 500,
PointerInputModifierImpl2(pointerInputFilter)
@@ -2243,28 +2326,30 @@
// Assert
+ val log = pointerInputFilter.log.filter { it is OnPointerEventEntry || it is OnCancelEntry }
+
// Verify call count
- verify(pointerInputFilter, times(PointerEventPass.values().size * 2))
- .onPointerEventMock(any(), any(), any())
+ assertThat(log).hasSize(PointerEventPass.values().size * 2 + 1)
// Verify call values
- inOrder(pointerInputFilter) {
- for (pass in PointerEventPass.values()) {
- verify(pointerInputFilter).onPointerEventMock(
- eq(pointerEventOf(expectedDown)),
- eq(pass),
- any()
- )
- }
- for (pass in PointerEventPass.values()) {
- verify(pointerInputFilter).onPointerEventMock(
- eq(pointerEventOf(expectedMove)),
- eq(pass),
- any()
- )
- }
- verify(pointerInputFilter).onCancel()
+ var index = 0
+ PointerEventPass.values().forEach { pass ->
+ log.verifyOnPointerEventCall(
+ index = index,
+ expectedEvent = pointerEventOf(expectedDown),
+ expectedPass = pass
+ )
+ index++
}
+ PointerEventPass.values().forEach { pass ->
+ log.verifyOnPointerEventCall(
+ index = index,
+ expectedEvent = pointerEventOf(expectedMove),
+ expectedPass = pass
+ )
+ index++
+ }
+ log.verifyOnCancelCall(index)
}
@Test
@@ -2272,7 +2357,7 @@
// Arrange
- val pointerInputFilter = spy(MockPointerInputFilter())
+ val pointerInputFilter = PointerInputFilterMock()
val layoutNode = LayoutNode(
0, 0, 500, 500,
PointerInputModifierImpl2(pointerInputFilter)
@@ -2311,21 +2396,22 @@
// Assert
+ val log = pointerInputFilter.log.filter { it is OnPointerEventEntry || it is OnCancelEntry }
+
// Verify call count
- verify(pointerInputFilter, times(PointerEventPass.values().size))
- .onPointerEventMock(any(), any(), any())
+ assertThat(log).hasSize(PointerEventPass.values().size + 1)
// Verify call values
- inOrder(pointerInputFilter) {
- for (pass in PointerEventPass.values()) {
- verify(pointerInputFilter).onPointerEventMock(
- eq(pointerEventOf(expectedDown)),
- eq(pass),
- any()
- )
- }
- verify(pointerInputFilter).onCancel()
+ var index = 0
+ PointerEventPass.values().forEach { pass ->
+ log.verifyOnPointerEventCall(
+ index = index,
+ expectedEvent = pointerEventOf(expectedDown),
+ expectedPass = pass
+ )
+ index++
}
+ log.verifyOnCancelCall(index)
}
@Test
@@ -2333,7 +2419,7 @@
// Arrange
- val pointerInputFilter = spy(MockPointerInputFilter())
+ val pointerInputFilter = PointerInputFilterMock()
val layoutNode = LayoutNode(
0, 0, 500, 500,
PointerInputModifierImpl2(
@@ -2399,27 +2485,30 @@
// Assert
+ val log = pointerInputFilter.log.filter { it is OnPointerEventEntry || it is OnCancelEntry }
+
// Verify call count
- verify(pointerInputFilter, times(PointerEventPass.values().size * 2))
- .onPointerEventMock(any(), any(), any())
+ assertThat(log).hasSize(PointerEventPass.values().size * 2 + 1)
// Verify call values
- inOrder(pointerInputFilter) {
- for (pass in PointerEventPass.values()) {
- verify(pointerInputFilter).onPointerEventMock(
- eq(pointerEventOf(expectedDown1)),
- eq(pass),
- any()
- )
- }
- verify(pointerInputFilter).onCancel()
- for (pass in PointerEventPass.values()) {
- verify(pointerInputFilter).onPointerEventMock(
- eq(pointerEventOf(expectedDown2)),
- eq(pass),
- any()
- )
- }
+ var index = 0
+ PointerEventPass.values().forEach { pass ->
+ log.verifyOnPointerEventCall(
+ index = index,
+ expectedEvent = pointerEventOf(expectedDown1),
+ expectedPass = pass
+ )
+ index++
+ }
+ log.verifyOnCancelCall(index)
+ index++
+ PointerEventPass.values().forEach { pass ->
+ log.verifyOnPointerEventCall(
+ index = index,
+ expectedEvent = pointerEventOf(expectedDown2),
+ expectedPass = pass
+ )
+ index++
}
}
@@ -2428,13 +2517,13 @@
// Arrange
- val childPointerInputFilter = spy(MockPointerInputFilter())
+ val childPointerInputFilter = PointerInputFilterMock()
val childLayoutNode = LayoutNode(
0, 0, 100, 100,
PointerInputModifierImpl2(childPointerInputFilter)
)
- val parentPointerInputFilter = spy(MockPointerInputFilter())
+ val parentPointerInputFilter = PointerInputFilterMock()
val parentLayoutNode: LayoutNode = LayoutNode(
0, 0, 100, 100,
PointerInputModifierImpl2(parentPointerInputFilter)
@@ -2489,21 +2578,61 @@
// Assert
+ val parentLog = parentPointerInputFilter.log.getOnPointerEventLog()
+ val childLog = childPointerInputFilter.log.getOnPointerEventLog()
+
// Verify call count
- verify(parentPointerInputFilter, times(PointerEventPass.values().size * 2))
- .onPointerEventMock(any(), any(), any())
- verify(childPointerInputFilter, times(PointerEventPass.values().size))
- .onPointerEventMock(any(), any(), any())
+ assertThat(parentLog).hasSize(PointerEventPass.values().size * 2)
+ assertThat(childLog).hasSize(PointerEventPass.values().size)
// Verify call values
- PointerEventPass.values().forEach {
- verify(parentPointerInputFilter)
- .onPointerEventMock(eq(pointerEventOf(expectedDownChange)), eq(it), any())
- verify(childPointerInputFilter)
- .onPointerEventMock(eq(pointerEventOf(expectedDownChange)), eq(it), any())
- verify(parentPointerInputFilter)
- .onPointerEventMock(eq(pointerEventOf(expectedUpChange)), eq(it), any())
- }
+
+ parentLog.verifyOnPointerEventCall(
+ index = 0,
+ expectedEvent = pointerEventOf(expectedDownChange),
+ expectedPass = PointerEventPass.Initial
+ )
+ parentLog.verifyOnPointerEventCall(
+ index = 1,
+ expectedEvent = pointerEventOf(expectedDownChange),
+ expectedPass = PointerEventPass.Main
+ )
+ parentLog.verifyOnPointerEventCall(
+ index = 2,
+ expectedEvent = pointerEventOf(expectedDownChange),
+ expectedPass = PointerEventPass.Final
+ )
+ parentLog.verifyOnPointerEventCall(
+ index = 3,
+ expectedEvent = pointerEventOf(expectedUpChange),
+ expectedPass = PointerEventPass.Initial
+ )
+ parentLog.verifyOnPointerEventCall(
+ index = 4,
+ expectedEvent = pointerEventOf(expectedUpChange),
+ expectedPass = PointerEventPass.Main
+ )
+ parentLog.verifyOnPointerEventCall(
+ index = 5,
+ expectedEvent = pointerEventOf(expectedUpChange),
+ expectedPass = PointerEventPass.Final
+ )
+
+ childLog.verifyOnPointerEventCall(
+ index = 0,
+ expectedEvent = pointerEventOf(expectedDownChange),
+ expectedPass = PointerEventPass.Initial
+ )
+ childLog.verifyOnPointerEventCall(
+ index = 1,
+ expectedEvent = pointerEventOf(expectedDownChange),
+ expectedPass = PointerEventPass.Main
+ )
+ childLog.verifyOnPointerEventCall(
+ index = 2,
+ expectedEvent = pointerEventOf(expectedDownChange),
+ expectedPass = PointerEventPass.Final
+ )
}
@Test
@@ -2511,13 +2640,13 @@
// Arrange
- val childPointerInputFilter = spy(MockPointerInputFilter())
+ val childPointerInputFilter = PointerInputFilterMock()
val childLayoutNode = LayoutNode(
0, 0, 100, 100,
PointerInputModifierImpl2(childPointerInputFilter)
)
- val parentPointerInputFilter = spy(MockPointerInputFilter())
+ val parentPointerInputFilter = PointerInputFilterMock()
val parentLayoutNode: LayoutNode = LayoutNode(
0, 0, 100, 100,
PointerInputModifierImpl2(parentPointerInputFilter)
@@ -2539,8 +2668,8 @@
pointerInputEventProcessor.process(up)
// Assert
- verify(childPointerInputFilter).onCancel()
- verify(parentPointerInputFilter, never()).onCancel()
+ assertThat(childPointerInputFilter.log.getOnCancelLog()).hasSize(1)
+ assertThat(parentPointerInputFilter.log.getOnCancelLog()).hasSize(0)
}
@Test
@@ -2548,7 +2677,7 @@
// Arrange
- val childPointerInputFilter = spy(MockPointerInputFilter())
+ val childPointerInputFilter = PointerInputFilterMock()
val childLayoutNode = LayoutNode(
0, 0, 100, 100,
PointerInputModifierImpl2(
@@ -2556,7 +2685,7 @@
)
)
- val parentPointerInputFilter = spy(MockPointerInputFilter())
+ val parentPointerInputFilter = PointerInputFilterMock()
val parentLayoutNode: LayoutNode = LayoutNode(
0, 0, 100, 100,
PointerInputModifierImpl2(
@@ -2613,21 +2742,61 @@
// Assert
+ val parentLog = parentPointerInputFilter.log.getOnPointerEventLog()
+ val childLog = childPointerInputFilter.log.getOnPointerEventLog()
+
// Verify call count
- verify(parentPointerInputFilter, times(PointerEventPass.values().size * 2))
- .onPointerEventMock(any(), any(), any())
- verify(childPointerInputFilter, times(PointerEventPass.values().size))
- .onPointerEventMock(any(), any(), any())
+ assertThat(parentLog).hasSize(PointerEventPass.values().size * 2)
+ assertThat(childLog).hasSize(PointerEventPass.values().size)
// Verify call values
- PointerEventPass.values().forEach {
- verify(parentPointerInputFilter)
- .onPointerEventMock(eq(pointerEventOf(expectedDownChange)), eq(it), any())
- verify(childPointerInputFilter)
- .onPointerEventMock(eq(pointerEventOf(expectedDownChange)), eq(it), any())
- verify(parentPointerInputFilter)
- .onPointerEventMock(eq(pointerEventOf(expectedUpChange)), eq(it), any())
- }
+
+ parentLog.verifyOnPointerEventCall(
+ index = 0,
+ expectedEvent = pointerEventOf(expectedDownChange),
+ expectedPass = PointerEventPass.Initial
+ )
+ parentLog.verifyOnPointerEventCall(
+ index = 1,
+ expectedEvent = pointerEventOf(expectedDownChange),
+ expectedPass = PointerEventPass.Main
+ )
+ parentLog.verifyOnPointerEventCall(
+ index = 2,
+ expectedEvent = pointerEventOf(expectedDownChange),
+ expectedPass = PointerEventPass.Final
+ )
+ parentLog.verifyOnPointerEventCall(
+ index = 3,
+ expectedEvent = pointerEventOf(expectedUpChange),
+ expectedPass = PointerEventPass.Initial
+ )
+ parentLog.verifyOnPointerEventCall(
+ index = 4,
+ expectedEvent = pointerEventOf(expectedUpChange),
+ expectedPass = PointerEventPass.Main
+ )
+ parentLog.verifyOnPointerEventCall(
+ index = 5,
+ expectedEvent = pointerEventOf(expectedUpChange),
+ expectedPass = PointerEventPass.Final
+ )
+
+ childLog.verifyOnPointerEventCall(
+ index = 0,
+ expectedEvent = pointerEventOf(expectedDownChange),
+ expectedPass = PointerEventPass.Initial
+ )
+ childLog.verifyOnPointerEventCall(
+ index = 1,
+ expectedEvent = pointerEventOf(expectedDownChange),
+ expectedPass = PointerEventPass.Main
+ )
+ childLog.verifyOnPointerEventCall(
+ index = 2,
+ expectedEvent = pointerEventOf(expectedDownChange),
+ expectedPass = PointerEventPass.Final
+ )
}
@Test
@@ -2635,13 +2804,13 @@
// Arrange
- val childPointerInputFilter = spy(MockPointerInputFilter())
+ val childPointerInputFilter = PointerInputFilterMock()
val childLayoutNode = LayoutNode(
0, 0, 100, 100,
PointerInputModifierImpl2(childPointerInputFilter)
)
- val parentPointerInputFilter = spy(MockPointerInputFilter())
+ val parentPointerInputFilter = PointerInputFilterMock()
val parentLayoutNode: LayoutNode = LayoutNode(
0, 0, 100, 100,
PointerInputModifierImpl2(parentPointerInputFilter)
@@ -2663,8 +2832,8 @@
pointerInputEventProcessor.process(up)
// Assert
- verify(childPointerInputFilter).onCancel()
- verify(parentPointerInputFilter, never()).onCancel()
+ assertThat(childPointerInputFilter.log.getOnCancelLog()).hasSize(1)
+ assertThat(parentPointerInputFilter.log.getOnCancelLog()).hasSize(0)
}
@Test
@@ -2687,7 +2856,7 @@
// Arrange
- val pointerInputFilter = spy(MockPointerInputFilter())
+ val pointerInputFilter = PointerInputFilterMock()
val layoutNode = LayoutNode(
0, 0, 1, 1,
@@ -2734,7 +2903,7 @@
// Arrange
- val pointerInputFilter = spy(MockPointerInputFilter())
+ val pointerInputFilter = PointerInputFilterMock()
val layoutNode = LayoutNode(
0, 0, 1, 1,
PointerInputModifierImpl2(
@@ -2764,7 +2933,7 @@
// Arrange
- val pointerInputFilter = spy(MockPointerInputFilter())
+ val pointerInputFilter = PointerInputFilterMock()
val layoutNode = LayoutNode(
0, 0, 1, 1,
PointerInputModifierImpl2(
@@ -2796,7 +2965,7 @@
// Arrange
- val pointerInputFilter = spy(MockPointerInputFilter())
+ val pointerInputFilter = PointerInputFilterMock()
val layoutNode = LayoutNode(
0, 0, 1, 1,
PointerInputModifierImpl2(
@@ -3044,23 +3213,31 @@
}
}
-open class MockPointerInputFilter : PointerInputFilter() {
-
- override fun onPointerEvent(
- pointerEvent: PointerEvent,
- pass: PointerEventPass,
- bounds: IntSize
- ) {
- onPointerEventMock(pointerEvent, pass, bounds as Any)
+private fun List<LogEntry>.verifyOnPointerEventCall(
+ index: Int,
+ expectedPif: PointerInputFilter? = null,
+ expectedEvent: PointerEvent,
+ expectedPass: PointerEventPass,
+ expectedBounds: IntSize? = null
+) {
+ val logEntry = this[index]
+ assertThat(logEntry).isInstanceOf(OnPointerEventEntry::class.java)
+ val entry = logEntry as OnPointerEventEntry
+ if (expectedPif != null) {
+ assertThat(entry.pointerInputFilter).isSameInstanceAs(expectedPif)
}
-
- override fun onCancel() {}
-
- open fun onPointerEventMock(
- pointerEvent: PointerEvent,
- pass: PointerEventPass,
- bounds: Any
- ) {
- pointerEvent.changes
+ PointerEventSubject
+ .assertThat(entry.pointerEvent)
+ .isStructurallyEqualTo(expectedEvent)
+ assertThat(entry.pass).isEqualTo(expectedPass)
+ if (expectedBounds != null) {
+ assertThat(entry.bounds).isEqualTo(expectedBounds)
}
+}
+
+private fun List<LogEntry>.verifyOnCancelCall(
+ index: Int
+) {
+ val logEntry = this[index]
+ assertThat(logEntry).isInstanceOf(OnCancelEntry::class.java)
}
\ No newline at end of file
diff --git a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/input/pointer/PointerInteropFilterTest.kt b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/input/pointer/PointerInteropFilterTest.kt
index eb19be8..57c247c 100644
--- a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/input/pointer/PointerInteropFilterTest.kt
+++ b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/input/pointer/PointerInteropFilterTest.kt
@@ -715,7 +715,9 @@
arrayOf(PointerProperties(0)),
arrayOf(PointerCoords(3f, 4f))
)
- val moveConsumed = down.moveTo(7.milliseconds, 8f, 9f).consume(1f, 0f)
+ val moveConsumed =
+ down.moveTo(7.milliseconds, 8f, 9f)
+ .apply { consumePositionChange(1f, 0f) }
val expected =
MotionEvent(
7,
@@ -772,7 +774,8 @@
)
val aMove2 = aMove1.moveTo(15.milliseconds, 8f, 9f)
- val bMoveConsumed = bDown.moveTo(15.milliseconds, 18f, 19f).consume(1f, 0f)
+ val bMoveConsumed =
+ bDown.moveTo(15.milliseconds, 18f, 19f).apply { consumePositionChange(1f, 0f) }
val expected =
MotionEvent(
@@ -1023,7 +1026,8 @@
arrayOf(PointerCoords(3f, 4f))
)
- val move1Consumed = down.moveTo(5.milliseconds, 6f, 7f).consume(0f, 1f)
+ val move1Consumed =
+ down.moveTo(5.milliseconds, 6f, 7f).apply { consumePositionChange(0f, 1f) }
val motionEvent2 =
MotionEvent(
5,
@@ -2005,7 +2009,6 @@
@Test
fun onPointerEvent_1PointerDownViewRetsFalse_nothingConsumed() {
val change = down(1, 2.milliseconds, 3f, 4f)
- val expected = change.deepCopy()
val motionEvent1 =
MotionEvent(
2,
@@ -2021,13 +2024,12 @@
pointerEventOf(change, motionEvent = motionEvent1)
)
- assertThat(change).isEqualTo(expected)
+ PointerInputChangeSubject.assertThat(change).nothingConsumed()
}
@Test
fun onPointerEvent_1PointerDownViewRetsTrue_everythingConsumed() {
val change = down(1, 2.milliseconds, 3f, 4f)
- val expected = change.deepCopy().apply { consumeDownChange() }
val motionEvent1 =
MotionEvent(
2,
@@ -2044,7 +2046,7 @@
pointerEventOf(change, motionEvent = motionEvent1)
)
- assertThat(change).isEqualTo(expected)
+ PointerInputChangeSubject.assertThat(change).downConsumed()
}
@Test
@@ -2073,14 +2075,14 @@
pointerInteropFilter.pointerInputFilter::onPointerEvent.invokeOverAllPasses(
pointerEventOf(down, motionEvent = motionEvent1)
)
- val upExpected = upActual.deepCopy().apply { consumeAllChanges() }
retVal = false
pointerInteropFilter.pointerInputFilter::onPointerEvent.invokeOverAllPasses(
pointerEventOf(upActual, motionEvent = motionEvent2)
)
- assertThat(upActual).isEqualTo(upExpected)
+ PointerInputChangeSubject.assertThat(upActual).downConsumed()
+ PointerInputChangeSubject.assertThat(upActual).positionChangeNotConsumed()
}
@Test
@@ -2096,7 +2098,6 @@
arrayOf(PointerCoords(3f, 4f))
)
val upActual = down.up(5.milliseconds)
- val expected = upActual.deepCopy().apply { consumeDownChange() }
val motionEvent2 =
MotionEvent(
5,
@@ -2116,7 +2117,7 @@
pointerEventOf(upActual, motionEvent = motionEvent2)
)
- assertThat(upActual).isEqualTo(expected)
+ PointerInputChangeSubject.assertThat(upActual).downConsumed()
}
@Test
@@ -2149,11 +2150,6 @@
retVal = true
- val expected = listOf(
- aMove.deepCopy().apply { consumeAllChanges() },
- bDown.deepCopy().apply { consumeAllChanges() }
- )
-
pointerInteropFilter.pointerInputFilter::onPointerEvent.invokeOverAllPasses(
pointerEventOf(aDown, motionEvent = motionEvent1)
)
@@ -2168,7 +2164,9 @@
// Assert
- assertThat(listOf(aMove, bDown)).isEqualTo(expected)
+ PointerInputChangeSubject.assertThat(aMove).nothingConsumed()
+ PointerInputChangeSubject.assertThat(bDown).downConsumed()
+ PointerInputChangeSubject.assertThat(bDown).positionChangeNotConsumed()
}
@Test
@@ -2201,11 +2199,6 @@
retVal = true
- val expected = listOf(
- aMove.deepCopy().apply { consumeDownChange() },
- bDown.deepCopy().apply { consumeDownChange() }
- )
-
pointerInteropFilter.pointerInputFilter::onPointerEvent.invokeOverAllPasses(
pointerEventOf(aDown, motionEvent = motionEvent1)
)
@@ -2218,7 +2211,9 @@
// Assert
- assertThat(listOf(aMove, bDown)).isEqualTo(expected)
+ PointerInputChangeSubject.assertThat(aMove).nothingConsumed()
+ PointerInputChangeSubject.assertThat(bDown).downConsumed()
+ PointerInputChangeSubject.assertThat(bDown).positionChangeNotConsumed()
}
@Test
@@ -2263,11 +2258,6 @@
retVal = true
- val expected = listOf(
- aMove2.deepCopy().apply { consumeAllChanges() },
- bUp.deepCopy().apply { consumeAllChanges() }
- )
-
pointerInteropFilter.pointerInputFilter::onPointerEvent.invokeOverAllPasses(
pointerEventOf(aDown, motionEvent = motionEvent1)
)
@@ -2284,7 +2274,9 @@
// Assert
- assertThat(listOf(aMove2, bUp)).isEqualTo(expected)
+ PointerInputChangeSubject.assertThat(aMove2).nothingConsumed()
+ PointerInputChangeSubject.assertThat(bUp).downConsumed()
+ PointerInputChangeSubject.assertThat(bUp).positionChangeNotConsumed()
}
@Test
@@ -2329,11 +2321,6 @@
retVal = true
- val expected = listOf(
- aMove2.deepCopy().apply { consumeDownChange() },
- bUp.deepCopy().apply { consumeDownChange() }
- )
-
pointerInteropFilter.pointerInputFilter::onPointerEvent.invokeOverAllPasses(
pointerEventOf(aDown, motionEvent = motionEvent1)
)
@@ -2349,7 +2336,9 @@
// Assert
- assertThat(listOf(aMove2, bUp)).isEqualTo(expected)
+ PointerInputChangeSubject.assertThat(aMove2).nothingConsumed()
+ PointerInputChangeSubject.assertThat(bUp).downConsumed()
+ PointerInputChangeSubject.assertThat(bUp).positionChangeNotConsumed()
}
@Test
@@ -2365,7 +2354,6 @@
arrayOf(PointerCoords(3f, 4f))
)
val move = down.moveTo(7.milliseconds, 8f, 9f)
- val expected = move.deepCopy().apply { consumeAllChanges() }
val motionEvent2 =
MotionEvent(
7,
@@ -2385,7 +2373,8 @@
pointerEventOf(move, motionEvent = motionEvent2)
)
- assertThat(move).isEqualTo(expected)
+ PointerInputChangeSubject.assertThat(move).downNotConsumed()
+ PointerInputChangeSubject.assertThat(move).positionChangeConsumed(Offset(5f, 5f))
}
@Test
@@ -2411,7 +2400,6 @@
arrayOf(PointerCoords(8f, 9f))
)
retVal = true
- val expected = move.deepCopy().apply { consumeAllChanges() }
pointerInteropFilter.pointerInputFilter::onPointerEvent.invokeOverAllPasses(
pointerEventOf(down, motionEvent = motionEvent1)
)
@@ -2420,7 +2408,8 @@
pointerEventOf(move, motionEvent = motionEvent2)
)
- assertThat(move).isEqualTo(expected)
+ PointerInputChangeSubject.assertThat(move).downNotConsumed()
+ PointerInputChangeSubject.assertThat(move).positionChangeConsumed(Offset(5f, 5f))
}
@Test
@@ -2477,12 +2466,6 @@
retVal = true
- val expected =
- listOf(
- aMove2.deepCopy().apply { consumeAllChanges() },
- bMove1.deepCopy().apply { consumeAllChanges() }
- )
-
pointerInteropFilter.pointerInputFilter::onPointerEvent.invokeOverAllPasses(
pointerEventOf(aDown, motionEvent = motionEvent1)
)
@@ -2499,7 +2482,10 @@
// Assert
- assertThat(listOf(aMove2, bMove1)).isEqualTo(expected)
+ PointerInputChangeSubject.assertThat(aMove2).downNotConsumed()
+ PointerInputChangeSubject.assertThat(aMove2).positionChangeConsumed(Offset(8f, 9f))
+ PointerInputChangeSubject.assertThat(bMove1).downNotConsumed()
+ PointerInputChangeSubject.assertThat(bMove1).positionChangeConsumed(Offset(18f, 19f))
}
@Test
@@ -2556,11 +2542,6 @@
retVal = true
- val expected = listOf(
- aMove2.deepCopy().apply { consumeAllChanges() },
- bMove1.deepCopy().apply { consumeAllChanges() }
- )
-
pointerInteropFilter.pointerInputFilter::onPointerEvent.invokeOverAllPasses(
pointerEventOf(aDown, motionEvent = motionEvent1)
)
@@ -2576,7 +2557,10 @@
// Assert
- assertThat(listOf(aMove2, bMove1)).isEqualTo(expected)
+ PointerInputChangeSubject.assertThat(aMove2).downNotConsumed()
+ PointerInputChangeSubject.assertThat(aMove2).positionChangeConsumed(Offset(8f, 9f))
+ PointerInputChangeSubject.assertThat(bMove1).downNotConsumed()
+ PointerInputChangeSubject.assertThat(bMove1).positionChangeConsumed(Offset(18f, 19f))
}
// Verification of no further consumption after initial consumption (because if something was
@@ -2596,7 +2580,6 @@
arrayOf(PointerCoords(3f, 4f))
)
val aMove = aDownConsumed.moveTo(5.milliseconds, 6f, 7f)
- val expected = aMove.deepCopy()
val motionEvent2 =
MotionEvent(
5,
@@ -2615,7 +2598,7 @@
pointerEventOf(aMove, motionEvent = motionEvent2)
)
- assertThat(aMove).isEqualTo(expected)
+ PointerInputChangeSubject.assertThat(aMove).nothingConsumed()
}
@Test
@@ -2646,7 +2629,6 @@
)
)
retVal = true
- val expected = aUp.deepCopy()
pointerInteropFilter.pointerInputFilter::onPointerEvent.invokeOverAllPasses(
pointerEventOf(aDownConsumed, motionEvent = motionEvent1)
@@ -2655,7 +2637,7 @@
pointerEventOf(aUp, motionEvent = motionEvent2)
)
- assertThat(aUp).isEqualTo(expected)
+ PointerInputChangeSubject.assertThat(aUp).nothingConsumed()
}
@Test
@@ -2682,8 +2664,6 @@
arrayOf(PointerCoords(3f, 4f), PointerCoords(13f, 14f))
)
- val expected = listOf(aMove1.deepCopy(), bDown.deepCopy())
-
pointerInteropFilter.pointerInputFilter::onPointerEvent.invokeOverAllPasses(
pointerEventOf(aDownConsumed, motionEvent = motionEvent1)
)
@@ -2691,7 +2671,8 @@
pointerEventOf(aMove1, bDown, motionEvent = motionEvent2)
)
- assertThat(listOf(aMove1, bDown)).isEqualTo(expected)
+ PointerInputChangeSubject.assertThat(aMove1).nothingConsumed()
+ PointerInputChangeSubject.assertThat(bDown).nothingConsumed()
}
@Test
@@ -2728,7 +2709,6 @@
arrayOf(PointerProperties(0), PointerProperties(1)),
arrayOf(PointerCoords(6f, 7f), PointerCoords(22f, 23f))
)
- val expected = listOf(aMove2.deepCopy(), bMove.deepCopy())
pointerInteropFilter.pointerInputFilter::onPointerEvent.invokeOverAllPasses(
pointerEventOf(aDownConsumed, motionEvent = motionEvent1)
@@ -2740,7 +2720,8 @@
pointerEventOf(aMove2, bMove, motionEvent = motionEvent3)
)
- assertThat(listOf(aMove2, bMove)).isEqualTo(expected)
+ PointerInputChangeSubject.assertThat(aMove2).nothingConsumed()
+ PointerInputChangeSubject.assertThat(bMove).nothingConsumed()
}
@Test
@@ -2778,7 +2759,9 @@
)
val aMove2 = aMove1.moveTo(15.milliseconds, 8f, 9f)
- val bMoveConsumed = bDown.moveTo(15.milliseconds, 18f, 19f).consume(1f, 0f)
+ val bMoveConsumed =
+ bDown.moveTo(15.milliseconds, 18f, 19f)
+ .apply { consumePositionChange(1f, 0f) }
val motionEvent3 =
MotionEvent(
7,
@@ -2795,8 +2778,6 @@
)
)
- val expected = listOf(aMove2.deepCopy(), bMoveConsumed.deepCopy())
-
pointerInteropFilter.pointerInputFilter::onPointerEvent.invokeOverAllPasses(
pointerEventOf(aDown, motionEvent = motionEvent1)
)
@@ -2810,8 +2791,9 @@
)
// Assert
-
- assertThat(listOf(aMove2, bMoveConsumed)).isEqualTo(expected)
+ PointerInputChangeSubject.assertThat(aMove2).nothingConsumed()
+ PointerInputChangeSubject.assertThat(bMoveConsumed).downNotConsumed()
+ PointerInputChangeSubject.assertThat(bMoveConsumed).positionChangeConsumed(Offset(1f, 0f))
}
@Test
@@ -2853,8 +2835,6 @@
arrayOf(PointerCoords(31f, 32f), PointerCoords(33f, 34f))
)
- val expected = listOf(aMove2.deepCopy(), bMove.deepCopy())
-
// Act
pointerInteropFilter.pointerInputFilter::onPointerEvent.invokeOverAllPasses(
pointerEventOf(aDown, motionEvent = motionEvent1)
@@ -2867,7 +2847,8 @@
)
// Assert
- assertThat(listOf(aMove2, bMove)).isEqualTo(expected)
+ PointerInputChangeSubject.assertThat(aMove2).nothingConsumed()
+ PointerInputChangeSubject.assertThat(bMove).nothingConsumed()
}
// Verifies resetting of consumption.
@@ -2908,7 +2889,6 @@
arrayOf(PointerProperties(0)),
arrayOf(PointerCoords(13f, 14f))
)
- val expected = bDown.deepCopy().apply { consumeDownChange() }
pointerInteropFilter.pointerInputFilter::onPointerEvent.invokeOverAllPasses(
pointerEventOf(aDownConsumed, motionEvent = motionEvent1)
@@ -2920,7 +2900,8 @@
pointerEventOf(bDown, motionEvent = motionEvent3)
)
- assertThat(bDown).isEqualTo(expected)
+ PointerInputChangeSubject.assertThat(bDown).downConsumed()
+ PointerInputChangeSubject.assertThat(bDown).positionChangeNotConsumed()
}
@Test
@@ -2985,8 +2966,6 @@
arrayOf(PointerCoords(53f, 54f))
)
- val expected = cDown.deepCopy().apply { consumeDownChange() }
-
// Act
pointerInteropFilter.pointerInputFilter::onPointerEvent.invokeOverAllPasses(
@@ -3007,7 +2986,8 @@
)
// Assert
- assertThat(cDown).isEqualTo(expected)
+ PointerInputChangeSubject.assertThat(cDown).downConsumed()
+ PointerInputChangeSubject.assertThat(cDown).positionChangeNotConsumed()
}
// Verification of consumption when the view rets false and then is set to return true.
@@ -3035,7 +3015,6 @@
arrayOf(PointerCoords(6f, 7f))
)
retVal = false
- val expected = aMove.deepCopy()
pointerInteropFilter.pointerInputFilter::onPointerEvent.invokeOverAllPasses(
pointerEventOf(aDown, motionEvent = motionEvent1)
@@ -3045,7 +3024,7 @@
pointerEventOf(aMove, motionEvent = motionEvent2)
)
- assertThat(aMove).isEqualTo(expected)
+ PointerInputChangeSubject.assertThat(aMove).nothingConsumed()
}
@Test
@@ -3071,7 +3050,6 @@
arrayOf(PointerCoords(3f, 4f))
)
retVal = false
- val expected = aUp.deepCopy()
pointerInteropFilter.pointerInputFilter::onPointerEvent.invokeOverAllPasses(
pointerEventOf(aDown, motionEvent = motionEvent1)
@@ -3081,7 +3059,7 @@
pointerEventOf(aUp, motionEvent = motionEvent2)
)
- assertThat(aUp).isEqualTo(expected)
+ PointerInputChangeSubject.assertThat(aUp).nothingConsumed()
}
@Test
@@ -3114,8 +3092,6 @@
retVal = false
- val expected = listOf(aMove1.deepCopy(), bDown.deepCopy())
-
// Act
pointerInteropFilter.pointerInputFilter::onPointerEvent.invokeOverAllPasses(
@@ -3128,7 +3104,8 @@
// Assert
- assertThat(listOf(aMove1, bDown)).isEqualTo(expected)
+ PointerInputChangeSubject.assertThat(aMove1).nothingConsumed()
+ PointerInputChangeSubject.assertThat(bDown).nothingConsumed()
}
@Test
@@ -3173,8 +3150,6 @@
retVal = false
- val expected = listOf(aMove2.deepCopy(), bMove1.deepCopy())
-
// Act
pointerInteropFilter.pointerInputFilter::onPointerEvent.invokeOverAllPasses(
@@ -3190,7 +3165,8 @@
// Assert
- assertThat(listOf(aMove2, bMove1)).isEqualTo(expected)
+ PointerInputChangeSubject.assertThat(aMove2).nothingConsumed()
+ PointerInputChangeSubject.assertThat(bMove1).nothingConsumed()
}
@Test
@@ -3235,8 +3211,6 @@
retVal = false
- val expected = listOf(aMove2.deepCopy(), bUp.deepCopy())
-
// Act
pointerInteropFilter.pointerInputFilter::onPointerEvent.invokeOverAllPasses(
@@ -3252,7 +3226,8 @@
// Assert
- assertThat(listOf(aMove2, bUp)).isEqualTo(expected)
+ PointerInputChangeSubject.assertThat(aMove2).nothingConsumed()
+ PointerInputChangeSubject.assertThat(bUp).nothingConsumed()
}
@Test
@@ -3306,8 +3281,6 @@
retVal = false
- val expected = listOf(bMove2.deepCopy(), cDown.deepCopy())
-
pointerInteropFilter.pointerInputFilter::onPointerEvent.invokeOverAllPasses(
pointerEventOf(aDown, motionEvent = motionEvent1)
)
@@ -3322,7 +3295,8 @@
pointerEventOf(bMove2, cDown, motionEvent = motionEvent4)
)
- assertThat(listOf(bMove2, cDown)).isEqualTo(expected)
+ PointerInputChangeSubject.assertThat(bMove2).nothingConsumed()
+ PointerInputChangeSubject.assertThat(cDown).nothingConsumed()
}
// Verification of correct passes being used
@@ -3836,7 +3810,9 @@
arrayOf(PointerProperties(0)),
arrayOf(PointerCoords(3f, 4f))
)
- val moveConsumed = down.moveTo(7.milliseconds, 8f, 9f).consume(1f, 0f)
+ val moveConsumed =
+ down.moveTo(7.milliseconds, 8f, 9f)
+ .apply { consumePositionChange(1f, 0f) }
val motionEvent2 =
MotionEvent(
7,
@@ -3895,7 +3871,8 @@
)
val aMove2 = aMove1.moveTo(15.milliseconds, 8f, 9f)
- val bMoveConsumed = bDown.moveTo(15.milliseconds, 18f, 19f).consume(1f, 0f)
+ val bMoveConsumed =
+ bDown.moveTo(15.milliseconds, 18f, 19f).apply { consumePositionChange(1f, 0f) }
val motionEvent3 =
MotionEvent(
7,
@@ -3949,14 +3926,14 @@
arrayOf(PointerProperties(0)),
arrayOf(PointerCoords(3f, 4f))
)
- val expected = down.deepCopy().apply { consumeDownChange() }
pointerInteropFilter.pointerInputFilter::onPointerEvent.invokeOverPass(
pointerEventOf(down, motionEvent = motionEvent1),
PointerEventPass.Initial
)
- assertThat(down).isEqualTo(expected)
+ PointerInputChangeSubject.assertThat(down).downConsumed()
+ PointerInputChangeSubject.assertThat(down).positionChangeNotConsumed()
}
@Test
@@ -3981,7 +3958,6 @@
arrayOf(PointerProperties(0)),
arrayOf(PointerCoords(3f, 4f))
)
- val expected = up.deepCopy().apply { consumeDownChange() }
pointerInteropFilter.pointerInputFilter::onPointerEvent.invokeOverAllPasses(
pointerEventOf(down, motionEvent = motionEvent1)
)
@@ -3991,7 +3967,8 @@
PointerEventPass.Initial
)
- assertThat(up).isEqualTo(expected)
+ PointerInputChangeSubject.assertThat(up).downConsumed()
+ PointerInputChangeSubject.assertThat(up).positionChangeNotConsumed()
}
@Test
@@ -4022,8 +3999,6 @@
arrayOf(PointerCoords(3f, 4f), PointerCoords(10f, 11f))
)
- val expected = listOf(aMove, bDown).map { it.deepCopy().apply { consumeDownChange() } }
-
pointerInteropFilter.pointerInputFilter::onPointerEvent.invokeOverAllPasses(
pointerEventOf(aDown, motionEvent = motionEvent1)
)
@@ -4037,7 +4012,9 @@
// Assert
- assertThat(listOf(aMove, bDown)).isEqualTo(expected)
+ PointerInputChangeSubject.assertThat(aMove).nothingConsumed()
+ PointerInputChangeSubject.assertThat(bDown).downConsumed()
+ PointerInputChangeSubject.assertThat(bDown).positionChangeNotConsumed()
}
@Test
@@ -4080,8 +4057,6 @@
arrayOf(PointerCoords(3f, 4f), PointerCoords(10f, 11f))
)
- val expected = listOf(aMove2, bUp).map { it.deepCopy().apply { consumeDownChange() } }
-
pointerInteropFilter.pointerInputFilter::onPointerEvent.invokeOverAllPasses(
pointerEventOf(aDown, motionEvent = motionEvent1)
)
@@ -4098,7 +4073,9 @@
// Assert
- assertThat(listOf(aMove2, bUp)).isEqualTo(expected)
+ PointerInputChangeSubject.assertThat(aMove2).nothingConsumed()
+ PointerInputChangeSubject.assertThat(bUp).downConsumed()
+ PointerInputChangeSubject.assertThat(bUp).positionChangeNotConsumed()
}
@Test
@@ -4123,8 +4100,6 @@
arrayOf(PointerProperties(0)),
arrayOf(PointerCoords(8f, 9f))
)
- val expected1 = move.deepCopy()
- val expected2 = move.deepCopy().apply { consumeAllChanges() }
pointerInteropFilter.pointerInputFilter::onPointerEvent.invokeOverAllPasses(
pointerEventOf(down, motionEvent = motionEvent1)
@@ -4136,14 +4111,15 @@
PointerEventPass.Main
)
- assertThat(move).isEqualTo(expected1)
+ PointerInputChangeSubject.assertThat(move).nothingConsumed()
pointerInteropFilter.pointerInputFilter::onPointerEvent.invokeOverPass(
pointerEventOf(move, motionEvent = motionEvent2),
PointerEventPass.Final
)
- assertThat(move).isEqualTo(expected2)
+ PointerInputChangeSubject.assertThat(move).downNotConsumed()
+ PointerInputChangeSubject.assertThat(move).positionChangeConsumed(Offset(5f, 5f))
}
@Test
diff --git a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/input/pointer/SuspendingPointerInputFilterTest.kt b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/input/pointer/SuspendingPointerInputFilterTest.kt
index 77b5259..96404d3 100644
--- a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/input/pointer/SuspendingPointerInputFilterTest.kt
+++ b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/input/pointer/SuspendingPointerInputFilterTest.kt
@@ -21,6 +21,7 @@
import androidx.compose.ui.unit.IntSize
import androidx.compose.ui.unit.Uptime
import androidx.test.filters.SmallTest
+import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.CompletableDeferred
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.flow.map
@@ -126,47 +127,56 @@
val bounds = IntSize(50, 50)
val emitter1 = PointerInputChangeEmitter(0)
val emitter2 = PointerInputChangeEmitter(1)
- val expectedChanges = listOf(
- listOf(
- emitter1.nextChange(Offset(5f, 5f)),
- emitter2.nextChange(Offset(10f, 10f))
+ val expectedEvents = listOf(
+ PointerEvent(
+ listOf(
+ emitter1.nextChange(Offset(5f, 5f)),
+ emitter2.nextChange(Offset(10f, 10f))
+ )
),
- listOf(
- emitter1.nextChange(Offset(6f, 6f)),
- emitter2.nextChange(Offset(10f, 10f), down = false)
+ PointerEvent(
+ listOf(
+ emitter1.nextChange(Offset(6f, 6f)),
+ emitter2.nextChange(Offset(10f, 10f), down = false)
+ )
),
// Synthetic cancel should look like this;
// only one pointer since the previous event's second pointer changed to up,
// the old position unchanged, 'down' changed from true to false, and the downChange
// marked as consumed.
- listOf(
- PointerInputChange(
- PointerId(0),
- current = PointerInputData(
- position = Offset(6f, 6f),
- down = false
- ),
- previous = PointerInputData(
- position = Offset(6f, 6f),
- down = true
- ),
- consumed = ConsumedData(downChange = true)
+ PointerEvent(
+ listOf(
+ PointerInputChange(
+ PointerId(0),
+ current = PointerInputData(
+ position = Offset(6f, 6f),
+ down = false
+ ),
+ previous = PointerInputData(
+ position = Offset(6f, 6f),
+ down = true
+ ),
+ consumed = ConsumedData(downChange = true)
+ )
)
)
)
- expectedChanges.take(expectedChanges.size - 1).forEach {
- filter.onPointerEvent(PointerEvent(changes = it), PointerEventPass.Main, bounds)
+ expectedEvents.take(expectedEvents.size - 1).forEach {
+ filter.onPointerEvent(it, PointerEventPass.Main, bounds)
}
filter.onCancel()
val received = withTimeout(200) {
- results.receiveAsFlow()
- .map { it.changes }
- .toList()
+ results.receiveAsFlow().toList()
}
- assertEquals(expectedChanges, received)
+ assertThat(expectedEvents).hasSize(received.size)
+
+ expectedEvents.forEachIndexed { index, expectedEvent ->
+ val actualEvent = received[index]
+ PointerEventSubject.assertThat(actualEvent).isStructurallyEqualTo(expectedEvent)
+ }
reader.cancel()
}
diff --git a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/input/pointer/TestUtils.kt b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/input/pointer/TestUtils.kt
index 2413b22..e22a920 100644
--- a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/input/pointer/TestUtils.kt
+++ b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/input/pointer/TestUtils.kt
@@ -26,6 +26,9 @@
import androidx.compose.ui.layout.LayoutCoordinates
import androidx.compose.ui.unit.IntSize
import androidx.compose.ui.unit.Uptime
+import com.google.common.truth.FailureMetadata
+import com.google.common.truth.Subject
+import com.google.common.truth.Truth
internal fun PointerInputEventData(
id: Int,
@@ -193,14 +196,6 @@
motionEvent = motionEvent
)
-internal fun PointerInputChange.deepCopy() =
- PointerInputChange(
- id,
- current.copy(),
- previous.copy(),
- consumed.copy()
- )
-
internal fun pointerEventOf(
vararg changes: PointerInputChange,
motionEvent: MotionEvent = MotionEventDouble
@@ -286,4 +281,98 @@
) : LogEntry()
internal fun internalPointerEventOf(vararg changes: PointerInputChange) =
- InternalPointerEvent(changes.toList().associateBy { it.id }.toMutableMap(), MotionEventDouble)
\ No newline at end of file
+ InternalPointerEvent(changes.toList().associateBy { it.id }.toMutableMap(), MotionEventDouble)
+
+internal class PointerEventSubject(
+ metaData: FailureMetadata,
+ val actual: PointerEvent
+) : Subject(metaData, actual) {
+ companion object {
+ private val Factory =
+ Factory<PointerEventSubject, PointerEvent> { metadata, actual ->
+ PointerEventSubject(metadata, actual)
+ }
+
+ fun assertThat(actual: PointerEvent): PointerEventSubject {
+ return Truth.assertAbout(Factory).that(actual)
+ }
+ }
+
+ fun isStructurallyEqualTo(expected: PointerEvent) {
+ check("motionEvent").that(actual.motionEvent).isEqualTo(expected.motionEvent)
+ val actualChanges = actual.changes
+ val expectedChanges = expected.changes
+ check("changes.size").that(actualChanges.size).isEqualTo(expectedChanges.size)
+ actualChanges.forEachIndexed { i, _ ->
+ check("id").that(actualChanges[i].id).isEqualTo(expectedChanges[i].id)
+ check("current").that(actualChanges[i].current).isEqualTo(expectedChanges[i].current)
+ check("previous").that(actualChanges[i].previous).isEqualTo(expectedChanges[i].previous)
+ check("consumed.downChange")
+ .that(actualChanges[i].consumed.downChange)
+ .isEqualTo(expectedChanges[i].consumed.downChange)
+ check("consumed.positionChange")
+ .that(actualChanges[i].consumed.positionChange)
+ .isEqualTo(expectedChanges[i].consumed.positionChange)
+ }
+ }
+}
+
+internal class PointerInputChangeSubject(
+ metaData: FailureMetadata,
+ val actual: PointerInputChange
+) : Subject(metaData, actual) {
+
+ companion object {
+
+ private val Factory =
+ Factory<PointerInputChangeSubject, PointerInputChange> { metadata, actual ->
+ PointerInputChangeSubject(metadata, actual)
+ }
+
+ fun assertThat(actual: PointerInputChange?): PointerInputChangeSubject {
+ return Truth.assertAbout(Factory).that(actual)
+ }
+ }
+
+ fun nothingConsumed() {
+ check("consumed.downChange").that(actual.consumed.downChange).isEqualTo(false)
+ check("consumed.positionChange").that(actual.consumed.positionChange).isEqualTo(Offset.Zero)
+ }
+
+ fun downConsumed() {
+ check("consumed.downChange").that(actual.consumed.downChange).isEqualTo(true)
+ }
+
+ fun downNotConsumed() {
+ check("consumed.downChange").that(actual.consumed.downChange).isEqualTo(false)
+ }
+
+ fun positionChangeConsumed(expected: Offset) {
+ check("consumed.positionChangeConsumed")
+ .that(actual.consumed.positionChange).isEqualTo(expected)
+ }
+
+ fun positionChangeNotConsumed() {
+ positionChangeConsumed(Offset.Zero)
+ }
+
+ fun isStructurallyEqualTo(expected: PointerInputChange) {
+ check("id").that(actual.id).isEqualTo(expected.id)
+ check("current").that(actual.current).isEqualTo(expected.current)
+ check("previous").that(actual.previous).isEqualTo(expected.previous)
+ check("consumed.downChange")
+ .that(actual.consumed.downChange)
+ .isEqualTo(expected.consumed.downChange)
+ check("consumed.positionChange")
+ .that(actual.consumed.positionChange)
+ .isEqualTo(expected.consumed.positionChange)
+ }
+}
+
+internal fun PointerInputChange.deepCopy() =
+ PointerInputChange(
+ id,
+ current.copy(),
+ previous.copy(),
+ ConsumedData(consumed.positionChange, consumed.downChange)
+ )
\ No newline at end of file
diff --git a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/window/DialogSecureFlagTest.kt b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/window/DialogSecureFlagTest.kt
index 7f4fff1..e5d91b1 100644
--- a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/window/DialogSecureFlagTest.kt
+++ b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/window/DialogSecureFlagTest.kt
@@ -27,7 +27,6 @@
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.node.ExperimentalLayoutNodeApi
-import androidx.compose.ui.selection.SimpleContainer
import androidx.compose.ui.unit.dp
import androidx.test.filters.MediumTest
import androidx.ui.test.createAndroidComposeRule
diff --git a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/window/PopupAlignmentTest.kt b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/window/PopupAlignmentTest.kt
index 85ea494..3112086 100644
--- a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/window/PopupAlignmentTest.kt
+++ b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/window/PopupAlignmentTest.kt
@@ -26,7 +26,6 @@
import androidx.compose.ui.onGloballyPositioned
import androidx.compose.ui.platform.LayoutDirectionAmbient
import androidx.compose.ui.platform.ViewAmbient
-import androidx.compose.ui.selection.SimpleContainer
import androidx.compose.ui.unit.IntBounds
import androidx.compose.ui.unit.IntOffset
import androidx.compose.ui.unit.IntSize
diff --git a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/window/PopupSecureFlagTest.kt b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/window/PopupSecureFlagTest.kt
index f970558..8bd6acd 100644
--- a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/window/PopupSecureFlagTest.kt
+++ b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/window/PopupSecureFlagTest.kt
@@ -27,7 +27,6 @@
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.node.Owner
-import androidx.compose.ui.selection.SimpleContainer
import androidx.compose.ui.unit.dp
import androidx.test.espresso.Espresso
import androidx.test.espresso.assertion.ViewAssertions
diff --git a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/window/PopupTest.kt b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/window/PopupTest.kt
index d1fecd3..afcac0f 100644
--- a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/window/PopupTest.kt
+++ b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/window/PopupTest.kt
@@ -30,7 +30,6 @@
import androidx.compose.ui.Modifier
import androidx.compose.ui.node.Owner
import androidx.compose.ui.onGloballyPositioned
-import androidx.compose.ui.selection.SimpleContainer
import androidx.compose.ui.unit.IntOffset
import androidx.compose.ui.unit.IntSize
import androidx.compose.ui.unit.dp
diff --git a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/window/PopupTestUtils.kt b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/window/PopupTestUtils.kt
index f0c2cd2..7e8479f 100644
--- a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/window/PopupTestUtils.kt
+++ b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/window/PopupTestUtils.kt
@@ -20,7 +20,18 @@
import android.view.View
import android.view.WindowManager
import androidx.activity.ComponentActivity
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Layout
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.Placeable
import androidx.compose.ui.node.Owner
+import androidx.compose.ui.unit.Constraints
+import androidx.compose.ui.unit.Dp
+import androidx.compose.ui.unit.IntSize
+import androidx.compose.ui.unit.enforce
+import androidx.compose.ui.unit.hasFixedHeight
+import androidx.compose.ui.unit.hasFixedWidth
import androidx.test.espresso.Espresso
import androidx.test.espresso.Root
import androidx.test.espresso.assertion.ViewAssertions
@@ -29,6 +40,7 @@
import org.hamcrest.Description
import org.hamcrest.Matcher
import org.hamcrest.TypeSafeMatcher
+import kotlin.math.max
// TODO(b/139861182): Remove all of this and provide helpers on rule
internal fun ComposeTestRule.popupMatches(popupTestTag: String, viewMatcher: Matcher<in View>) {
@@ -66,4 +78,61 @@
WindowManager.LayoutParams.FLAG_SECURE
)
}
-}
\ No newline at end of file
+}
+
+/**
+ * A Container Box implementation used for selection children and handle layout
+ */
+@Composable
+internal fun SimpleContainer(
+ modifier: Modifier = Modifier,
+ width: Dp? = null,
+ height: Dp? = null,
+ children: @Composable () -> Unit
+) {
+ Layout(children, modifier) { measurables, incomingConstraints ->
+ val containerConstraints = Constraints()
+ .copy(
+ width?.toIntPx() ?: 0,
+ width?.toIntPx() ?: Constraints.Infinity,
+ height?.toIntPx() ?: 0,
+ height?.toIntPx() ?: Constraints.Infinity
+ )
+ .enforce(incomingConstraints)
+ val childConstraints = containerConstraints.copy(minWidth = 0, minHeight = 0)
+ var placeable: Placeable? = null
+ val containerWidth = if (
+ containerConstraints.hasFixedWidth
+ ) {
+ containerConstraints.maxWidth
+ } else {
+ placeable = measurables.firstOrNull()?.measure(childConstraints)
+ max((placeable?.width ?: 0), containerConstraints.minWidth)
+ }
+ val containerHeight = if (
+ containerConstraints.hasFixedHeight
+ ) {
+ containerConstraints.maxHeight
+ } else {
+ if (placeable == null) {
+ placeable = measurables.firstOrNull()?.measure(childConstraints)
+ }
+ max((placeable?.height ?: 0), containerConstraints.minHeight)
+ }
+ layout(containerWidth, containerHeight) {
+ val p = placeable ?: measurables.firstOrNull()?.measure(childConstraints)
+ p?.let {
+ val position = Alignment.Center.align(
+ IntSize(
+ containerWidth - it.width,
+ containerHeight - it.height
+ )
+ )
+ it.placeRelative(
+ position.x,
+ position.y
+ )
+ }
+ }
+ }
+}
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/input/pointer/PointerEvent.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/input/pointer/PointerEvent.kt
index 2072359..c741ab1 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/input/pointer/PointerEvent.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/input/pointer/PointerEvent.kt
@@ -189,7 +189,7 @@
* @param positionChange The amount of change to the position that has been consumed.
* @param downChange True if a change to down or up has been consumed.
*/
-data class ConsumedData(
+class ConsumedData(
var positionChange: Offset = Offset.Companion.Zero,
var downChange: Boolean = false
)
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/input/pointer/PointerInputTestUtil.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/input/pointer/PointerInputTestUtil.kt
index 63e352e..91ac6d7 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/input/pointer/PointerInputTestUtil.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/input/pointer/PointerInputTestUtil.kt
@@ -73,21 +73,6 @@
consumed = ConsumedData()
)
-internal fun PointerInputChange.consume(
- dx: Float = 0f,
- dy: Float = 0f,
- downChange: Boolean = false
-) =
- copy(
- consumed = consumed.copy(
- positionChange = Offset(
- consumed.positionChange.x + dx,
- consumed.positionChange.y + dy
- ),
- downChange = consumed.downChange || downChange
- )
- )
-
/**
* A function used to react to and modify [PointerInputChange]s.
*/
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/selection/SimpleContainer.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/selection/SimpleContainer.kt
deleted file mode 100644
index d294048c..0000000
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/selection/SimpleContainer.kt
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Copyright 2020 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.
- */
-
-package androidx.compose.ui.selection
-
-import androidx.compose.runtime.Composable
-import androidx.compose.ui.Alignment
-import androidx.compose.ui.Layout
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.Placeable
-import androidx.compose.ui.unit.Constraints
-import androidx.compose.ui.unit.Dp
-import androidx.compose.ui.unit.IntSize
-import androidx.compose.ui.unit.enforce
-import androidx.compose.ui.unit.hasFixedHeight
-import androidx.compose.ui.unit.hasFixedWidth
-import kotlin.math.max
-
-/**
- * A Container Box implementation used for selection children and handle layout
- */
-@Composable
-internal fun SimpleContainer(
- modifier: Modifier = Modifier,
- width: Dp? = null,
- height: Dp? = null,
- children: @Composable () -> Unit
-) {
- Layout(children, modifier) { measurables, incomingConstraints ->
- val containerConstraints = Constraints()
- .copy(
- width?.toIntPx() ?: 0,
- width?.toIntPx() ?: Constraints.Infinity,
- height?.toIntPx() ?: 0,
- height?.toIntPx() ?: Constraints.Infinity
- )
- .enforce(incomingConstraints)
- val childConstraints = containerConstraints.copy(minWidth = 0, minHeight = 0)
- var placeable: Placeable? = null
- val containerWidth = if (
- containerConstraints.hasFixedWidth
- ) {
- containerConstraints.maxWidth
- } else {
- placeable = measurables.firstOrNull()?.measure(childConstraints)
- max((placeable?.width ?: 0), containerConstraints.minWidth)
- }
- val containerHeight = if (
- containerConstraints.hasFixedHeight
- ) {
- containerConstraints.maxHeight
- } else {
- if (placeable == null) {
- placeable = measurables.firstOrNull()?.measure(childConstraints)
- }
- max((placeable?.height ?: 0), containerConstraints.minHeight)
- }
- layout(containerWidth, containerHeight) {
- val p = placeable ?: measurables.firstOrNull()?.measure(childConstraints)
- p?.let {
- val position = Alignment.Center.align(
- IntSize(
- containerWidth - it.width,
- containerHeight - it.height
- )
- )
- it.placeRelative(
- position.x,
- position.y
- )
- }
- }
- }
-}
diff --git a/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/platform/SkijaLayer.kt b/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/platform/SkijaLayer.kt
index c53b3c3..20eb925 100644
--- a/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/platform/SkijaLayer.kt
+++ b/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/platform/SkijaLayer.kt
@@ -17,24 +17,27 @@
package androidx.compose.ui.platform
import androidx.compose.ui.DrawLayerModifier
+import androidx.compose.ui.geometry.Rect
import androidx.compose.ui.graphics.Canvas
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.DesktopCanvas
import androidx.compose.ui.graphics.Matrix
import androidx.compose.ui.graphics.Outline
+import androidx.compose.ui.graphics.Paint
import androidx.compose.ui.graphics.Path
import androidx.compose.ui.graphics.asDesktopPath
import androidx.compose.ui.graphics.nativeCanvas
import androidx.compose.ui.graphics.toArgb
+import androidx.compose.ui.graphics.toSkijaRect
import androidx.compose.ui.node.OwnedLayer
import androidx.compose.ui.unit.IntOffset
import androidx.compose.ui.unit.IntSize
import androidx.compose.ui.unit.dp
-import org.jetbrains.skija.Matrix33
+import androidx.compose.ui.unit.toBounds
+import androidx.compose.ui.unit.toRect
import org.jetbrains.skija.Picture
import org.jetbrains.skija.PictureRecorder
import org.jetbrains.skija.Point3
-import org.jetbrains.skija.Rect
import org.jetbrains.skija.ShadowUtils
class SkijaLayer(
@@ -46,6 +49,7 @@
private var size = IntSize.Zero
private var position = IntOffset.Zero
private var outlineCache = OutlineCache(owner.density, size, modifier.shape)
+ private val matrix = Matrix()
private val pictureRecorder = PictureRecorder()
private var picture: Picture? = null
private var isDestroyed = false
@@ -54,10 +58,11 @@
set(value) {
field = value
outlineCache.shape = value.shape
+ updateMatrix()
invalidate()
}
- override val layerId = 0L
+ override val layerId = lastId++
override fun destroy() {
picture?.close()
@@ -69,6 +74,7 @@
if (size != this.size) {
this.size = size
outlineCache.size = size
+ updateMatrix()
invalidate()
}
}
@@ -80,9 +86,29 @@
}
}
- // TODO(demin): calculate matrix
override fun getMatrix(matrix: Matrix) {
+ matrix.setFrom(this.matrix)
+ }
+
+ // TODO(demin): support perspective projection for rotationX/rotationY (as in Android)
+ private fun updateMatrix() {
+ val pivotX = modifier.transformOrigin.pivotFractionX * size.width
+ val pivotY = modifier.transformOrigin.pivotFractionY * size.height
+
matrix.reset()
+ matrix *= Matrix().apply {
+ translate(x = -pivotX, y = -pivotY)
+ }
+ matrix *= Matrix().apply {
+ translate(modifier.translationX, modifier.translationY)
+ rotateX(modifier.rotationX)
+ rotateY(modifier.rotationY)
+ rotateZ(modifier.rotationZ)
+ scale(modifier.scaleX, modifier.scaleY)
+ }
+ matrix *= Matrix().apply {
+ translate(x = pivotX, y = pivotY)
+ }
}
override val isValid: Boolean
@@ -99,67 +125,52 @@
override fun drawLayer(canvas: Canvas) {
outlineCache.density = owner.density
if (picture == null) {
- val pictureCanvas = pictureRecorder.beginRecording(
- Rect.makeWH(
- size.width.toFloat(),
- size.height.toFloat()
- )
- )
- performDrawLayer(DesktopCanvas(pictureCanvas))
+ val bounds = size.toBounds().toRect()
+ val pictureCanvas = pictureRecorder.beginRecording(bounds.toSkijaRect())
+ performDrawLayer(DesktopCanvas(pictureCanvas), bounds)
picture = pictureRecorder.finishRecordingAsPicture()
}
- canvas.nativeCanvas.drawPicture(
- picture,
- Matrix33.makeTranslate(position.x.toFloat(), position.y.toFloat()),
- null
- )
+
+ canvas.save()
+ canvas.concat(matrix)
+ canvas.translate(position.x.toFloat(), position.y.toFloat())
+ canvas.nativeCanvas.drawPicture(picture, null, null)
+ canvas.restore()
}
- // TODO(demin): implement alpha, rotationX, rotationY
- @OptIn(ExperimentalUnsignedTypes::class)
- private fun performDrawLayer(canvas: DesktopCanvas) {
- canvas.save()
-
- val pivotX = modifier.transformOrigin.pivotFractionX * size.width
- val pivotY = modifier.transformOrigin.pivotFractionY * size.height
-
- canvas.translate(modifier.translationX, modifier.translationY)
- canvas.translate(pivotX, pivotY)
-
- if (modifier.rotationZ != 0f) {
- canvas.rotate(modifier.rotationZ)
- }
-
- if (modifier.scaleX != 1f || modifier.scaleY != 1f) {
- canvas.scale(modifier.scaleX, modifier.scaleY)
- }
-
- canvas.translate(-pivotX, -pivotY)
-
- if (modifier.shadowElevation > 0 && modifier.alpha != 0f) {
- drawShadow(canvas)
- }
-
- if (modifier.clip && size != IntSize.Zero) {
- when (val outline = outlineCache.outline) {
- is Outline.Rectangle -> canvas.clipRect(outline.rect)
- is Outline.Rounded -> canvas.clipRoundRect(outline.roundRect)
- is Outline.Generic -> canvas.clipPath(outline.path)
+ private fun performDrawLayer(canvas: DesktopCanvas, bounds: Rect) {
+ if (modifier.alpha > 0) {
+ if (modifier.shadowElevation > 0) {
+ drawShadow(canvas)
}
- }
- if (modifier.alpha != 0f) {
+ if (modifier.alpha < 1) {
+ canvas.saveLayer(
+ bounds,
+ Paint().apply { alpha = modifier.alpha }
+ )
+ } else {
+ canvas.save()
+ }
+
+ if (modifier.clip) {
+ when (val outline = outlineCache.outline) {
+ is Outline.Rectangle -> canvas.clipRect(outline.rect)
+ is Outline.Rounded -> canvas.clipRoundRect(outline.roundRect)
+ is Outline.Generic -> canvas.clipPath(outline.path)
+ }
+ }
+
drawBlock(canvas)
+ canvas.restore()
}
-
- canvas.restore()
}
override fun updateDisplayList() = Unit
override fun updateLayerProperties() = Unit
- @ExperimentalUnsignedTypes
+ @OptIn(ExperimentalUnsignedTypes::class)
fun drawShadow(canvas: DesktopCanvas) = with (owner.density) {
val path = when (val outline = outlineCache.outline) {
is Outline.Rectangle -> Path().apply { addRect(outline.rect) }
@@ -175,8 +186,8 @@
val lightPos = Point3(0f, 0f, 600.dp.toPx())
val lightRad = 800.dp.toPx()
- val ambientAlpha = 0.039f
- val spotAlpha = 0.19f
+ val ambientAlpha = 0.039f * modifier.alpha
+ val spotAlpha = 0.19f * modifier.alpha
val ambientColor = Color.Black.copy(alpha = ambientAlpha)
val spotColor = Color.Black.copy(alpha = spotAlpha)
@@ -187,4 +198,8 @@
spotColor.toArgb(), modifier.alpha < 1f, false
)
}
+
+ companion object {
+ private var lastId = 0L
+ }
}
diff --git a/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/platform/DrawLayerTest.kt b/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/platform/DrawLayerTest.kt
index dc9f7a6..551156a 100644
--- a/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/platform/DrawLayerTest.kt
+++ b/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/platform/DrawLayerTest.kt
@@ -16,8 +16,9 @@
package androidx.compose.ui.platform
-import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.background
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.ui.Modifier
@@ -93,6 +94,70 @@
}
@Test
+ fun rotationX() {
+ val window = TestComposeWindow(width = 40, height = 40)
+
+ window.setContent {
+ Box(
+ Modifier
+ .drawLayer(rotationX = 45f)
+ .size(10f.dp, 10f.dp).background(Color.Blue)
+ )
+ Box(
+ Modifier
+ .drawLayer(
+ translationX = 20f,
+ transformOrigin = TransformOrigin(0f, 0f),
+ rotationX = 45f
+ )
+ .size(10f.dp, 10f.dp).background(Color.Blue)
+ )
+ }
+ screenshotRule.snap(window.surface)
+ }
+
+ @Test
+ fun rotationY() {
+ val window = TestComposeWindow(width = 40, height = 40)
+ window.setContent {
+ Box(
+ Modifier
+ .drawLayer(rotationY = 45f)
+ .size(10f.dp, 10f.dp).background(Color.Blue)
+ )
+ Box(
+ Modifier
+ .drawLayer(
+ translationX = 20f,
+ transformOrigin = TransformOrigin(0f, 0f),
+ rotationY = 45f
+ )
+ .size(10f.dp, 10f.dp).background(Color.Blue)
+ )
+ }
+ screenshotRule.snap(window.surface)
+ }
+
+ @Test
+ fun `nested layer transformations`() {
+ val window = TestComposeWindow(width = 40, height = 40)
+ window.setContent {
+ Box(
+ Modifier
+ .drawLayer(rotationZ = 45f, translationX = 10f)
+ .size(20f.dp, 20f.dp).background(Color.Green)
+ ) {
+ Box(
+ Modifier
+ .drawLayer(rotationZ = 45f)
+ .size(20f.dp, 20f.dp).background(Color.Blue)
+ )
+ }
+ }
+ screenshotRule.snap(window.surface)
+ }
+
+ @Test
fun clip() {
val window = TestComposeWindow(width = 40, height = 40)
window.setContent {
@@ -162,4 +227,101 @@
}
screenshotRule.snap(window.surface)
}
+
+ @Test
+ fun alpha() {
+ val window = TestComposeWindow(width = 40, height = 40)
+ window.setContent {
+ Box(
+ Modifier
+ .padding(start = 5.dp)
+ .drawLayer(
+ translationX = -5f,
+ translationY = 5f,
+ transformOrigin = TransformOrigin(0f, 0f),
+ alpha = 0.5f
+ )
+ .size(10f.dp, 10f.dp)
+ .background(Color.Green)
+ ) {
+ // This box will be clipped (because if we use alpha, we draw into
+ // intermediate buffer)
+ Box(
+ Modifier
+ .size(30f.dp, 30f.dp)
+ .background(Color.Blue)
+ )
+ }
+
+ Box(
+ Modifier
+ .padding(start = 15.dp)
+ .drawLayer(alpha = 0.5f)
+ .size(15f.dp, 15f.dp)
+ .background(Color.Red)
+ ) {
+ Box(
+ Modifier
+ .drawLayer(alpha = 0.5f)
+ .size(10f.dp, 10f.dp)
+ .background(Color.Blue)
+ )
+ }
+
+ Box(
+ Modifier
+ .drawLayer(
+ alpha = 0f
+ )
+ .size(10f.dp, 10f.dp)
+ .background(Color.Blue)
+ )
+ }
+ screenshotRule.snap(window.surface)
+ }
+
+ @Test
+ fun elevation() {
+ val window = TestComposeWindow(width = 40, height = 40)
+ window.setContent {
+ Box(
+ Modifier
+ .drawLayer(shadowElevation = 5f)
+ .size(20f.dp, 20f.dp)
+ )
+ Box(
+ Modifier
+ .drawLayer(translationX = 20f, shadowElevation = 5f)
+ .size(20f.dp, 20f.dp)
+ ) {
+ Box(
+ Modifier
+ .size(20f.dp, 20f.dp)
+ .background(Color.Blue)
+ )
+ }
+ Box(
+ Modifier
+ .drawLayer(translationY = 20f, alpha = 0.8f, shadowElevation = 5f)
+ .size(20f.dp, 20f.dp)
+ ) {
+ Box(
+ Modifier
+ .size(20f.dp, 20f.dp)
+ .background(Color.Red)
+ )
+ }
+ Box(
+ Modifier
+ .drawLayer(
+ translationX = 20f,
+ translationY = 20f,
+ shadowElevation = 5f,
+ alpha = 0.8f
+ )
+ .size(20f.dp, 20f.dp)
+ )
+ }
+ screenshotRule.snap(window.surface)
+ }
}
\ No newline at end of file
diff --git a/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/platform/SkijaLayerTest.kt b/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/platform/SkijaLayerTest.kt
new file mode 100644
index 0000000..3a2f260
--- /dev/null
+++ b/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/platform/SkijaLayerTest.kt
@@ -0,0 +1,334 @@
+/*
+ * Copyright 2020 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.
+ */
+
+package androidx.compose.ui.platform
+
+import androidx.compose.ui.DrawLayerModifier
+import androidx.compose.ui.TransformOrigin
+import androidx.compose.ui.geometry.Offset
+import androidx.compose.ui.graphics.Matrix
+import androidx.compose.ui.graphics.RectangleShape
+import androidx.compose.ui.graphics.Shape
+import androidx.compose.ui.unit.Density
+import androidx.compose.ui.unit.IntOffset
+import androidx.compose.ui.unit.IntSize
+import androidx.compose.ui.unit.round
+import org.junit.Assert.assertEquals
+import org.junit.Test
+import kotlin.math.PI
+import kotlin.math.cos
+import kotlin.math.roundToInt
+
+class SkijaLayerTest {
+ private val layer = TestSkijaLayer()
+ private val matrix = Matrix()
+ private val cos45 = cos(PI / 4)
+
+ @Test
+ fun initial() {
+ layer.getMatrix(matrix)
+
+ assertEquals(IntOffset(0, 0), matrix.map(Offset(0f, 0f)).round())
+ assertEquals(IntOffset(100, 10), matrix.map(Offset(100f, 10f)).round())
+ }
+
+ @Test
+ fun move() {
+ layer.move(IntOffset(10, 20))
+ layer.getMatrix(matrix)
+
+ assertEquals(IntOffset(0, 0), matrix.map(Offset(0f, 0f)).round())
+ assertEquals(IntOffset(100, 10), matrix.map(Offset(100f, 10f)).round())
+ }
+
+ @Test
+ fun resize() {
+ layer.resize(IntSize(100, 10))
+ layer.getMatrix(matrix)
+
+ assertEquals(IntOffset(0, 0), matrix.map(Offset(0f, 0f)).round())
+ assertEquals(IntOffset(100, 10), matrix.map(Offset(100f, 10f)).round())
+ }
+
+ @Test
+ fun `resize and move`() {
+ layer.resize(IntSize(100, 10))
+ layer.move(IntOffset(10, 20))
+ layer.getMatrix(matrix)
+
+ assertEquals(IntOffset(0, 0), matrix.map(Offset(0f, 0f)).round())
+ assertEquals(IntOffset(100, 10), matrix.map(Offset(100f, 10f)).round())
+ }
+
+ @Test
+ fun `translation, left-top origin`() {
+ layer.resize(IntSize(100, 10))
+ layer.modifier = SimpleDrawLayerModifier(
+ translationX = 10f,
+ translationY = 20f,
+ transformOrigin = TransformOrigin(0f, 0f)
+ )
+ layer.getMatrix(matrix)
+
+ assertEquals(IntOffset(10, 20), matrix.map(Offset(0f, 0f)).round())
+ assertEquals(IntOffset(110, 30), matrix.map(Offset(100f, 10f)).round())
+ }
+
+ @Test
+ fun `translation, bottom-right origin`() {
+ layer.resize(IntSize(100, 10))
+ layer.modifier = SimpleDrawLayerModifier(
+ translationX = 10f,
+ translationY = 20f,
+ transformOrigin = TransformOrigin(1f, 1f)
+ )
+ layer.getMatrix(matrix)
+
+ assertEquals(IntOffset(10, 20), matrix.map(Offset(0f, 0f)).round())
+ assertEquals(IntOffset(110, 30), matrix.map(Offset(100f, 10f)).round())
+ }
+
+ @Test
+ fun `scale, left-top origin`() {
+ layer.resize(IntSize(100, 10))
+ layer.modifier = SimpleDrawLayerModifier(
+ scaleX = 2f,
+ scaleY = 4f,
+ transformOrigin = TransformOrigin(0f, 0f)
+ )
+ layer.getMatrix(matrix)
+
+ assertEquals(IntOffset(0, 0), matrix.map(Offset(0f, 0f)).round())
+ assertEquals(IntOffset(200, 40), matrix.map(Offset(100f, 10f)).round())
+ }
+
+ @Test
+ fun `scale, bottom-right origin`() {
+ layer.resize(IntSize(100, 10))
+ layer.modifier = SimpleDrawLayerModifier(
+ scaleX = 2f,
+ scaleY = 4f,
+ transformOrigin = TransformOrigin(1f, 1f)
+ )
+ layer.getMatrix(matrix)
+
+ assertEquals(IntOffset(-100, -30), matrix.map(Offset(0f, 0f)).round())
+ assertEquals(IntOffset(100, 10), matrix.map(Offset(100f, 10f)).round())
+ }
+
+ @Test
+ fun `rotationX, left-top origin`() {
+ layer.resize(IntSize(100, 10))
+ layer.modifier = SimpleDrawLayerModifier(
+ rotationX = 45f,
+ transformOrigin = TransformOrigin(0f, 0f)
+ )
+ layer.getMatrix(matrix)
+
+ val y = (10 * cos45).roundToInt()
+ assertEquals(IntOffset(0, 0), matrix.map(Offset(0f, 0f)).round())
+ assertEquals(IntOffset(100, y), matrix.map(Offset(100f, 10f)).round())
+ }
+
+ @Test
+ fun `rotationX, bottom-right origin`() {
+ layer.resize(IntSize(100, 10))
+ layer.modifier = SimpleDrawLayerModifier(
+ rotationX = 45f,
+ transformOrigin = TransformOrigin(1f, 1f)
+ )
+ layer.getMatrix(matrix)
+
+ val y = 10 * (1 - cos45.toFloat())
+ println(matrix.map(Offset(0f, 0f)))
+ println(matrix.map(Offset(100f, 10f)))
+ assertEquals(Offset(0f, y), matrix.map(Offset(0f, 0f)))
+ assertEquals(Offset(100f, 10f), matrix.map(Offset(100f, 10f)))
+ }
+
+ @Test
+ fun `rotationY, left-top origin`() {
+ layer.resize(IntSize(100, 10))
+ layer.modifier = SimpleDrawLayerModifier(
+ rotationY = 45f,
+ transformOrigin = TransformOrigin(0f, 0f)
+ )
+ layer.getMatrix(matrix)
+
+ val x = (100 * cos45).roundToInt()
+ assertEquals(IntOffset(0, 0), matrix.map(Offset(0f, 0f)).round())
+ assertEquals(IntOffset(x, 10), matrix.map(Offset(100f, 10f)).round())
+ }
+
+ @Test
+ fun `rotationY, bottom-right origin`() {
+ layer.resize(IntSize(100, 10))
+ layer.modifier = SimpleDrawLayerModifier(
+ rotationY = 45f,
+ transformOrigin = TransformOrigin(1f, 1f)
+ )
+ layer.getMatrix(matrix)
+
+ val x = (100 * (1 - cos45)).roundToInt()
+ assertEquals(IntOffset(x, 0), matrix.map(Offset(0f, 0f)).round())
+ assertEquals(IntOffset(100, 10), matrix.map(Offset(100f, 10f)).round())
+ }
+
+ @Test
+ fun `rotationZ, left-top origin`() {
+ layer.resize(IntSize(100, 10))
+ layer.modifier = SimpleDrawLayerModifier(
+ rotationZ = 90f,
+ transformOrigin = TransformOrigin(0f, 0f)
+ )
+ layer.getMatrix(matrix)
+
+ assertEquals(IntOffset(0, 0), matrix.map(Offset(0f, 0f)).round())
+ assertEquals(IntOffset(-10, 100), matrix.map(Offset(100f, 10f)).round())
+ }
+
+ @Test
+ fun `rotationZ, bottom-right origin`() {
+ layer.resize(IntSize(100, 10))
+ layer.modifier = SimpleDrawLayerModifier(
+ rotationZ = 90f,
+ transformOrigin = TransformOrigin(1f, 1f)
+ )
+ layer.getMatrix(matrix)
+
+ assertEquals(IntOffset(110, -90), matrix.map(Offset(0f, 0f)).round())
+ assertEquals(IntOffset(100, 10), matrix.map(Offset(100f, 10f)).round())
+ }
+
+ @Test
+ fun `translation, scale, left-top origin`() {
+ layer.resize(IntSize(100, 10))
+ layer.modifier = SimpleDrawLayerModifier(
+ translationX = 60f,
+ translationY = 7f,
+ scaleX = 2f,
+ scaleY = 4f,
+ transformOrigin = TransformOrigin(0f, 0f)
+ )
+ layer.getMatrix(matrix)
+
+ assertEquals(IntOffset(0 + 60, 0 + 7), matrix.map(Offset(0f, 0f)).round())
+ assertEquals(IntOffset(100 * 2 + 60, 10 * 4 + 7), matrix.map(Offset(100f, 10f)).round())
+ }
+
+ @Test
+ fun `translation, rotationZ, left-top origin`() {
+ layer.resize(IntSize(100, 10))
+ layer.modifier = SimpleDrawLayerModifier(
+ translationX = 60f,
+ translationY = 7f,
+ rotationZ = 90f,
+ transformOrigin = TransformOrigin(0f, 0f)
+ )
+ layer.getMatrix(matrix)
+
+ assertEquals(IntOffset(0 + 60, 0 + 7), matrix.map(Offset(0f, 0f)).round())
+ assertEquals(IntOffset(-10 + 60, 100 + 7), matrix.map(Offset(100f, 10f)).round())
+ }
+
+ @Test
+ fun `translation, rotationX, left-top origin`() {
+ layer.resize(IntSize(100, 10))
+ layer.modifier = SimpleDrawLayerModifier(
+ translationX = 60f,
+ translationY = 7f,
+ rotationX = 45f,
+ transformOrigin = TransformOrigin(0f, 0f)
+ )
+ layer.getMatrix(matrix)
+
+ val y = (10 * cos45).roundToInt()
+ val translationY = (7 * cos45).roundToInt()
+ assertEquals(IntOffset(0 + 60, 0 + translationY), matrix.map(Offset(0f, 0f)).round())
+ assertEquals(IntOffset(100 + 60, y + translationY), matrix.map(Offset(100f, 10f)).round())
+ }
+
+ @Test
+ fun `translation, rotationY, left-top origin`() {
+ layer.resize(IntSize(100, 10))
+ layer.modifier = SimpleDrawLayerModifier(
+ translationX = 60f,
+ translationY = 7f,
+ rotationY = 45f,
+ transformOrigin = TransformOrigin(0f, 0f)
+ )
+ layer.getMatrix(matrix)
+
+ val x = (100 * cos45).roundToInt()
+ val translationX = (60 * cos45).roundToInt()
+ assertEquals(IntOffset(0 + translationX, 0 + 7), matrix.map(Offset(0f, 0f)).round())
+ assertEquals(IntOffset(x + translationX, 10 + 7), matrix.map(Offset(100f, 10f)).round())
+ }
+
+ @Test
+ fun `scale, rotationZ, left-top origin`() {
+ layer.resize(IntSize(100, 10))
+ layer.modifier = SimpleDrawLayerModifier(
+ scaleX = 2f,
+ scaleY = 4f,
+ rotationZ = 90f,
+ transformOrigin = TransformOrigin(0f, 0f)
+ )
+ layer.getMatrix(matrix)
+
+ assertEquals(IntOffset(0, 0), matrix.map(Offset(0f, 0f)).round())
+ assertEquals(IntOffset(-10 * 4, 100 * 2), matrix.map(Offset(100f, 10f)).round())
+ }
+
+ @Test
+ fun `translation, scale, rotationZ, left-top origin`() {
+ layer.resize(IntSize(100, 10))
+ layer.modifier = SimpleDrawLayerModifier(
+ translationX = 60f,
+ translationY = 7f,
+ scaleX = 2f,
+ scaleY = 4f,
+ rotationZ = 90f,
+ transformOrigin = TransformOrigin(0f, 0f)
+ )
+ layer.getMatrix(matrix)
+
+ assertEquals(IntOffset(0 + 60, 0 + 7), matrix.map(Offset(0f, 0f)).round())
+ assertEquals(IntOffset(-10 * 4 + 60, 100 * 2 + 7), matrix.map(Offset(100f, 10f)).round())
+ }
+
+ private fun TestSkijaLayer() = SkijaLayer(
+ density = Density(1f, 1f),
+ modifier = SimpleDrawLayerModifier(),
+ invalidateParentLayer = {},
+ drawBlock = {}
+ )
+
+ private data class SimpleDrawLayerModifier(
+ override val scaleX: Float = 1f,
+ override val scaleY: Float = 1f,
+ override val alpha: Float = 1f,
+ override val translationX: Float = 0f,
+ override val translationY: Float = 0f,
+ override val shadowElevation: Float = 0f,
+ override val rotationX: Float = 0f,
+ override val rotationY: Float = 0f,
+ override val rotationZ: Float = 0f,
+ override val transformOrigin: TransformOrigin = TransformOrigin.Center,
+ override val shape: Shape = RectangleShape,
+ override val clip: Boolean = false
+ ) : DrawLayerModifier
+}
\ No newline at end of file
diff --git a/compose/ui/ui/src/test/kotlin/androidx/compose/ui/gesture/DoubleTapGestureFilterTest.kt b/compose/ui/ui/src/test/kotlin/androidx/compose/ui/gesture/DoubleTapGestureFilterTest.kt
index 126c0a1..86d9555 100644
--- a/compose/ui/ui/src/test/kotlin/androidx/compose/ui/gesture/DoubleTapGestureFilterTest.kt
+++ b/compose/ui/ui/src/test/kotlin/androidx/compose/ui/gesture/DoubleTapGestureFilterTest.kt
@@ -23,8 +23,8 @@
import androidx.compose.ui.gesture.customevents.DelayUpMessage
import androidx.compose.ui.input.pointer.CustomEventDispatcher
import androidx.compose.ui.input.pointer.PointerId
-import androidx.compose.ui.input.pointer.consume
import androidx.compose.ui.input.pointer.consumeDownChange
+import androidx.compose.ui.input.pointer.consumePositionChange
import androidx.compose.ui.input.pointer.down
import androidx.compose.ui.input.pointer.invokeOverAllPasses
import androidx.compose.ui.input.pointer.moveTo
@@ -136,7 +136,8 @@
@Test
fun onPointerEvent_downMoveConsumedUpDownInsideTimeoutUp_onDoubleTapNotCalled() {
val down1 = down(1, 0.milliseconds)
- val moveConsumed = down1.moveTo(1.milliseconds, x = 1f).consume(dx = 1f)
+ val moveConsumed =
+ down1.moveTo(1.milliseconds, x = 1f).apply { consumePositionChange(1f, 0f) }
val up1 = moveConsumed.up(duration = 2.milliseconds)
val down2 = down(2, 101.milliseconds)
val up2 = down2.up(duration = 102.milliseconds)
@@ -156,7 +157,8 @@
val down1 = down(1, 0.milliseconds)
val up1 = down1.up(duration = 1.milliseconds)
val down2 = down(2, 100.milliseconds)
- val moveConsumed = down2.moveTo(101.milliseconds, x = 1f).consume(dx = 1f)
+ val moveConsumed =
+ down2.moveTo(101.milliseconds, x = 1f).apply { consumePositionChange(1f, 0f) }
val up2 = moveConsumed.up(duration = 102.milliseconds)
filter::onPointerEvent.invokeOverAllPasses(pointerEventOf(down1))
@@ -173,7 +175,8 @@
fun onPointerEvent_2Down1MoveConsumedUpDownInsideTimeoutUp_onDoubleTapNotCalled() {
val down1A = down(0, 0.milliseconds)
val down1B = down(1, 0.milliseconds)
- val moveConsumed1A = down1A.moveTo(1.milliseconds, x = 1f).consume(dx = 1f)
+ val moveConsumed1A =
+ down1A.moveTo(1.milliseconds, x = 1f).apply { consumePositionChange(1f, 0f) }
val move1B = down1B.moveTo(1.milliseconds)
val up1A = moveConsumed1A.up(duration = 2.milliseconds)
val up1B = move1B.up(duration = 2.milliseconds)
@@ -196,7 +199,8 @@
val up2 = down1.up(duration = 1.milliseconds)
val down2A = down(0, 100.milliseconds)
val down2B = down(1, 100.milliseconds)
- val moveConsumed2A = down2A.moveTo(101.milliseconds, x = 1f).consume(dx = 1f)
+ val moveConsumed2A =
+ down2A.moveTo(101.milliseconds, x = 1f).apply { consumePositionChange(1f, 0f) }
val move2B = down2B.moveTo(101.milliseconds)
val up2A = moveConsumed2A.up(duration = 102.milliseconds)
val up2B = move2B.up(duration = 102.milliseconds)
diff --git a/compose/ui/ui/src/test/kotlin/androidx/compose/ui/gesture/DragSlopExceededGestureFilterTest.kt b/compose/ui/ui/src/test/kotlin/androidx/compose/ui/gesture/DragSlopExceededGestureFilterTest.kt
index cce4b9f..778a789 100644
--- a/compose/ui/ui/src/test/kotlin/androidx/compose/ui/gesture/DragSlopExceededGestureFilterTest.kt
+++ b/compose/ui/ui/src/test/kotlin/androidx/compose/ui/gesture/DragSlopExceededGestureFilterTest.kt
@@ -24,8 +24,8 @@
import androidx.compose.ui.gesture.scrollorientationlocking.ScrollOrientationLocker
import androidx.compose.ui.gesture.scrollorientationlocking.ShareScrollOrientationLockerEvent
import androidx.compose.ui.input.pointer.PointerEventPass
-import androidx.compose.ui.input.pointer.consume
import androidx.compose.ui.input.pointer.consumeDownChange
+import androidx.compose.ui.input.pointer.consumePositionChange
import androidx.compose.ui.input.pointer.down
import androidx.compose.ui.input.pointer.invokeOverAllPasses
import androidx.compose.ui.input.pointer.invokeOverPass
@@ -101,7 +101,9 @@
fun onPointerEvent_downMoveFullyConsumed_canDragNotCalled() {
val down = down(0)
filter::onPointerEvent.invokeOverAllPasses(pointerEventOf(down))
- val move = down.moveBy(Duration(milliseconds = 10), 3f, 5f).consume(3f, 5f)
+ val move =
+ down.moveBy(Duration(milliseconds = 10), 3f, 5f)
+ .apply { consumePositionChange(3f, 5f) }
filter::onPointerEvent.invokeOverAllPasses(pointerEventOf(move))
assertThat(canDragDirections).isEmpty()
@@ -136,7 +138,9 @@
fun onPointerEvent_downMoveOneDimensionPartiallyConsumed_canDragCalledOnce() {
val down = down(0)
filter::onPointerEvent.invokeOverAllPasses(pointerEventOf(down))
- val move = down.moveBy(Duration(milliseconds = 10), 0f, 5f).consume(0f, 4f)
+ val move =
+ down.moveBy(Duration(milliseconds = 10), 0f, 5f)
+ .apply { consumePositionChange(0f, 4f) }
filter::onPointerEvent.invokeOverAllPasses(pointerEventOf(move))
// Twice because while under touch slop, DragGestureDetector checks during Main and
@@ -148,7 +152,9 @@
fun onPointerEvent_downMoveTwoDimensionPartiallyConsumed_canDragCalledTwice() {
val down = down(0)
filter::onPointerEvent.invokeOverAllPasses(pointerEventOf(down))
- val move = down.moveBy(Duration(milliseconds = 10), 3f, 5f).consume(2f, 4f)
+ val move =
+ down.moveBy(Duration(milliseconds = 10), 3f, 5f)
+ .apply { consumePositionChange(2f, 4f) }
filter::onPointerEvent.invokeOverAllPasses(pointerEventOf(move))
// 4 times because while under touch slop, DragGestureDetector checks during Main and
@@ -303,7 +309,9 @@
val down = down(0)
filter::onPointerEvent.invokeOverAllPasses(pointerEventOf(down))
- val move = down.moveBy(10.milliseconds, TestTouchSlop + TinyNum, 0f).consume(dx = 1f)
+ val move =
+ down.moveBy(10.milliseconds, TestTouchSlop + TinyNum, 0f)
+ .apply { consumePositionChange(1f, 0f) }
filter::onPointerEvent.invokeOverAllPasses(pointerEventOf(move))
// Assert
@@ -325,7 +333,8 @@
PointerEventPass.Main
)
)
- val move2 = move.consume(dx = (TestTouchSlop * 2f + TinyNum))
+ val move2 =
+ move.apply { consumePositionChange(TestTouchSlop * 2f + TinyNum, 0f) }
filter::onPointerEvent.invokeOverPass(
pointerEventOf(move2),
PointerEventPass.Final
@@ -684,7 +693,8 @@
val down = down(0)
filter::onPointerEvent.invokeOverAllPasses(pointerEventOf(down))
- val move = down.moveBy(10.milliseconds, 0f, 0f).consume(dx = beyondSlop)
+ val move =
+ down.moveBy(10.milliseconds, 0f, 0f).apply { consumePositionChange(beyondSlop, 0f) }
filter::onPointerEvent.invokeOverPasses(
pointerEventOf(move),
listOf(
@@ -714,7 +724,7 @@
)
)
- val moveConsumed = move.consume(dx = beyondSlop)
+ val moveConsumed = move.apply { consumePositionChange(beyondSlop, 0f) }
filter::onPointerEvent.invokeOverPasses(
pointerEventOf(moveConsumed),
PointerEventPass.Final
@@ -742,7 +752,7 @@
)
)
- val moveConsumed = move.consume(dx = -restOfSlopAndBeyond)
+ val moveConsumed = move.apply { consumePositionChange(-restOfSlopAndBeyond, 0f) }
filter::onPointerEvent.invokeOverPasses(
pointerEventOf(moveConsumed),
PointerEventPass.Final
diff --git a/compose/ui/ui/src/test/kotlin/androidx/compose/ui/gesture/LongPressGestureFilterTest.kt b/compose/ui/ui/src/test/kotlin/androidx/compose/ui/gesture/LongPressGestureFilterTest.kt
index 37b517e..2ddd50a 100644
--- a/compose/ui/ui/src/test/kotlin/androidx/compose/ui/gesture/LongPressGestureFilterTest.kt
+++ b/compose/ui/ui/src/test/kotlin/androidx/compose/ui/gesture/LongPressGestureFilterTest.kt
@@ -20,8 +20,8 @@
import androidx.compose.ui.gesture.customevents.LongPressFiredEvent
import androidx.compose.ui.input.pointer.CustomEventDispatcher
import androidx.compose.ui.input.pointer.PointerEventPass
-import androidx.compose.ui.input.pointer.consume
import androidx.compose.ui.input.pointer.consumeDownChange
+import androidx.compose.ui.input.pointer.consumePositionChange
import androidx.compose.ui.input.pointer.down
import androidx.compose.ui.input.pointer.invokeOverAllPasses
import androidx.compose.ui.input.pointer.moveBy
@@ -82,7 +82,8 @@
@Test
fun onPointerEvent_DownMoveConsumed_eventNotFired() {
val down = down(0)
- val move = down.moveBy(50.milliseconds, 1f, 1f).consume(1f, 0f)
+ val move =
+ down.moveBy(50.milliseconds, 1f, 1f).apply { consumePositionChange(1f, 0f) }
filter::onPointerEvent.invokeOverAllPasses(pointerEventOf(down))
testContext.advanceTimeBy(50, TimeUnit.MILLISECONDS)
@@ -97,7 +98,8 @@
fun onPointerEvent_2Down1MoveConsumed_eventNotFired() {
val down0 = down(0)
val down1 = down(1)
- val move0 = down0.moveBy(50.milliseconds, 1f, 1f).consume(1f, 0f)
+ val move0 =
+ down0.moveBy(50.milliseconds, 1f, 1f).apply { consumePositionChange(1f, 0f) }
val move1 = down0.moveBy(50.milliseconds, 0f, 0f)
filter::onPointerEvent.invokeOverAllPasses(pointerEventOf(down0, down1))
@@ -450,7 +452,7 @@
var pointer = down(0, 0.milliseconds)
filter::onPointerEvent.invokeOverAllPasses(pointerEventOf(pointer))
testContext.advanceTimeBy(50, TimeUnit.MILLISECONDS)
- pointer = pointer.moveTo(50.milliseconds, 5f).consume(1f)
+ pointer = pointer.moveTo(50.milliseconds, 5f).apply { consumePositionChange(1f, 0f) }
filter::onPointerEvent.invokeOverAllPasses(pointerEventOf(pointer))
// Act
diff --git a/compose/ui/ui/src/test/kotlin/androidx/compose/ui/gesture/PressIndicatorGestureFilterTest.kt b/compose/ui/ui/src/test/kotlin/androidx/compose/ui/gesture/PressIndicatorGestureFilterTest.kt
index 24b2c0e..f9ebc0b 100644
--- a/compose/ui/ui/src/test/kotlin/androidx/compose/ui/gesture/PressIndicatorGestureFilterTest.kt
+++ b/compose/ui/ui/src/test/kotlin/androidx/compose/ui/gesture/PressIndicatorGestureFilterTest.kt
@@ -18,8 +18,8 @@
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.input.pointer.PointerEventPass
-import androidx.compose.ui.input.pointer.consume
import androidx.compose.ui.input.pointer.consumeDownChange
+import androidx.compose.ui.input.pointer.consumePositionChange
import androidx.compose.ui.input.pointer.down
import androidx.compose.ui.input.pointer.invokeOverAllPasses
import androidx.compose.ui.input.pointer.invokeOverPasses
@@ -128,7 +128,7 @@
fun onPointerInput_downMoveConsumedUp_onStopNotCalled() {
var pointer = down(0, 0.milliseconds)
filter::onPointerEvent.invokeOverAllPasses(pointerEventOf(pointer))
- pointer = pointer.moveTo(100.milliseconds, 5f).consume(1f)
+ pointer = pointer.moveTo(100.milliseconds, 5f).apply { consumePositionChange(1f, 0f) }
filter::onPointerEvent.invokeOverAllPasses(pointerEventOf(pointer))
pointer = pointer.up(200.milliseconds)
filter::onPointerEvent.invokeOverAllPasses(pointerEventOf(pointer))
@@ -233,7 +233,7 @@
fun onPointerInput_downConsumedMoveConsumed_onCancelNotCalled() {
var pointer = down(0, 0.milliseconds).apply { consumeDownChange() }
filter::onPointerEvent.invokeOverAllPasses(pointerEventOf(pointer))
- pointer = pointer.moveBy(100.milliseconds, 5f).consume(1f)
+ pointer = pointer.moveBy(100.milliseconds, 5f).apply { consumePositionChange(1f, 0f) }
filter::onPointerEvent.invokeOverAllPasses(pointerEventOf(pointer))
verify(filter.onCancel!!, never()).invoke()
@@ -290,7 +290,7 @@
fun onPointerInput_downMoveConsumed_onCancelCalledOnce() {
var pointer = down(0, 0.milliseconds)
filter::onPointerEvent.invokeOverAllPasses(pointerEventOf(pointer))
- pointer = pointer.moveBy(100.milliseconds, 5f).consume(1f)
+ pointer = pointer.moveBy(100.milliseconds, 5f).apply { consumePositionChange(1f, 0f) }
filter::onPointerEvent.invokeOverAllPasses(pointerEventOf(pointer))
verify(filter.onCancel!!).invoke()
@@ -300,9 +300,9 @@
fun onPointerInput_downMoveConsumedMoveConsumed_onCancelCalledOnce() {
var pointer = down(0, 0.milliseconds)
filter::onPointerEvent.invokeOverAllPasses(pointerEventOf(pointer))
- pointer = pointer.moveBy(100.milliseconds, 5f).consume(1f)
+ pointer = pointer.moveBy(100.milliseconds, 5f).apply { consumePositionChange(1f, 0f) }
filter::onPointerEvent.invokeOverAllPasses(pointerEventOf(pointer))
- pointer = pointer.moveBy(100.milliseconds, 5f).consume(1f)
+ pointer = pointer.moveBy(100.milliseconds, 5f).apply { consumePositionChange(1f, 0f) }
filter::onPointerEvent.invokeOverAllPasses(pointerEventOf(pointer))
verify(filter.onCancel!!).invoke()
@@ -313,8 +313,8 @@
var pointer0 = down(0)
var pointer1 = down(1)
filter::onPointerEvent.invokeOverAllPasses(pointerEventOf(pointer0, pointer1))
- pointer0 = pointer0.moveBy(100.milliseconds, 5f).consume(1f)
- pointer1 = pointer1.moveBy(100.milliseconds, 5f).consume(1f)
+ pointer0 = pointer0.moveBy(100.milliseconds, 5f).apply { consumePositionChange(1f, 0f) }
+ pointer1 = pointer1.moveBy(100.milliseconds, 5f).apply { consumePositionChange(1f, 0f) }
filter::onPointerEvent.invokeOverAllPasses(pointerEventOf(pointer0, pointer1))
verify(filter.onCancel!!).invoke()
@@ -327,11 +327,11 @@
pointer0 = pointer0.moveTo(100.milliseconds)
var pointer1 = down(1, duration = 100.milliseconds)
filter::onPointerEvent.invokeOverAllPasses(pointerEventOf(pointer0, pointer1))
- pointer0 = pointer0.moveBy(100L.milliseconds, 5f).consume(5f)
+ pointer0 = pointer0.moveBy(100L.milliseconds, 5f).apply { consumePositionChange(5f, 0f) }
pointer1 = pointer1.moveBy(100L.milliseconds)
filter::onPointerEvent.invokeOverAllPasses(pointerEventOf(pointer0, pointer1))
pointer0 = pointer0.moveBy(100L.milliseconds)
- pointer1 = pointer1.moveBy(100L.milliseconds, 5f).consume(5f)
+ pointer1 = pointer1.moveBy(100L.milliseconds, 5f).apply { consumePositionChange(5f, 0f) }
filter::onPointerEvent.invokeOverAllPasses(pointerEventOf(pointer0, pointer1))
verify(filter.onCancel!!).invoke()
@@ -544,7 +544,7 @@
fun onCancel_downMoveConsumedCancel_justStartAndCancelCalledInOrderOnce() {
var pointer = down(0, 0.milliseconds)
filter::onPointerEvent.invokeOverAllPasses(pointerEventOf(pointer))
- pointer = pointer.moveTo(50.milliseconds, 1f).consume(1f)
+ pointer = pointer.moveTo(50.milliseconds, 1f).apply { consumePositionChange(1f, 0f) }
filter::onPointerEvent.invokeOverAllPasses(pointerEventOf(pointer))
filter.onCancel()
diff --git a/compose/ui/ui/src/test/kotlin/androidx/compose/ui/gesture/RawDragGestureFilterTest.kt b/compose/ui/ui/src/test/kotlin/androidx/compose/ui/gesture/RawDragGestureFilterTest.kt
index 8fa8ae4..f75ba75 100644
--- a/compose/ui/ui/src/test/kotlin/androidx/compose/ui/gesture/RawDragGestureFilterTest.kt
+++ b/compose/ui/ui/src/test/kotlin/androidx/compose/ui/gesture/RawDragGestureFilterTest.kt
@@ -23,7 +23,6 @@
import androidx.compose.ui.input.pointer.CustomEventDispatcher
import androidx.compose.ui.input.pointer.PointerEventPass
import androidx.compose.ui.input.pointer.anyPositionChangeConsumed
-import androidx.compose.ui.input.pointer.consume
import androidx.compose.ui.input.pointer.consumePositionChange
import androidx.compose.ui.input.pointer.down
import androidx.compose.ui.input.pointer.invokeOverAllPasses
@@ -105,7 +104,8 @@
filter::onPointerEvent.invokeOverAllPasses(pointerEventOf(down1))
dragStartBlocked = false
- val move1 = down1.moveBy(10.milliseconds, 1f, 1f).consume(dx = 1f, dy = 1f)
+ val move1 =
+ down1.moveBy(10.milliseconds, 1f, 1f).apply { consumePositionChange(1f, 1f) }
filter::onPointerEvent.invokeOverAllPasses(pointerEventOf(move1))
assertThat(log.filter { it.methodName == "onStart" }).isEmpty()
@@ -202,7 +202,7 @@
filter::onPointerEvent.invokeOverAllPasses(pointerEventOf(down))
dragStartBlocked = false
- val move = down.moveBy(10.milliseconds, 1f, 0f).consume(dx = 2f)
+ val move = down.moveBy(10.milliseconds, 1f, 0f).apply { consumePositionChange(2f, 0f) }
filter::onPointerEvent.invokeOverAllPasses(pointerEventOf(move))
assertThat(log.filter { it.methodName == "onStart" }).hasSize(1)
diff --git a/compose/ui/ui/src/test/kotlin/androidx/compose/ui/gesture/RawScaleGestureFilterTest.kt b/compose/ui/ui/src/test/kotlin/androidx/compose/ui/gesture/RawScaleGestureFilterTest.kt
index 8f71ec8..1b8ec4d 100644
--- a/compose/ui/ui/src/test/kotlin/androidx/compose/ui/gesture/RawScaleGestureFilterTest.kt
+++ b/compose/ui/ui/src/test/kotlin/androidx/compose/ui/gesture/RawScaleGestureFilterTest.kt
@@ -19,7 +19,7 @@
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.input.pointer.PointerEventPass
import androidx.compose.ui.input.pointer.anyPositionChangeConsumed
-import androidx.compose.ui.input.pointer.consume
+import androidx.compose.ui.input.pointer.consumePositionChange
import androidx.compose.ui.input.pointer.down
import androidx.compose.ui.input.pointer.invokeOverAllPasses
import androidx.compose.ui.input.pointer.invokeOverPasses
@@ -276,9 +276,9 @@
scaleStartBlocked = false
pointer1 =
- pointer1.moveTo(10.milliseconds, 2f, 2f).consume(-1f, -2f)
+ pointer1.moveTo(10.milliseconds, 2f, 2f).apply { consumePositionChange(-1f, -2f) }
pointer2 =
- pointer2.moveTo(10.milliseconds, 5f, 1f).consume(1f, -2f)
+ pointer2.moveTo(10.milliseconds, 5f, 1f).apply { consumePositionChange(1f, -2f) }
filter::onPointerEvent.invokeOverAllPasses(pointerEventOf(pointer1, pointer2))
assertThat(log.filter { it.methodName == "onStart" }).isEmpty()
@@ -327,7 +327,10 @@
filter::onPointerEvent.invokeOverAllPasses(pointerEventOf(pointer1, pointer2))
scaleStartBlocked = false
- pointer1 = pointer1.moveBy(10.milliseconds, dx = 0f, dy = 0f).consume(dx = -1f)
+ pointer1 =
+ pointer1.moveBy(10.milliseconds, dx = 0f, dy = 0f).apply {
+ consumePositionChange(-1f, 0f)
+ }
pointer2 = pointer2.moveBy(10.milliseconds, dx = 0f, dy = 0f)
filter::onPointerEvent.invokeOverAllPasses(pointerEventOf(pointer1, pointer2))
@@ -343,7 +346,10 @@
filter::onPointerEvent.invokeOverAllPasses(pointerEventOf(pointer1, pointer2))
scaleStartBlocked = false
- pointer1 = pointer1.moveBy(10.milliseconds, dx = 0f, dy = 0f).consume(dy = -1f)
+ pointer1 =
+ pointer1
+ .moveBy(10.milliseconds, dx = 0f, dy = 0f)
+ .apply { consumePositionChange(0f, -1f) }
pointer2 = pointer2.moveBy(10.milliseconds, dx = 0f, dy = 0f)
filter::onPointerEvent.invokeOverAllPasses(pointerEventOf(pointer1, pointer2))
diff --git a/compose/ui/ui/src/test/kotlin/androidx/compose/ui/gesture/TapGestureFilterTest.kt b/compose/ui/ui/src/test/kotlin/androidx/compose/ui/gesture/TapGestureFilterTest.kt
index f35d3c3..04e2806 100644
--- a/compose/ui/ui/src/test/kotlin/androidx/compose/ui/gesture/TapGestureFilterTest.kt
+++ b/compose/ui/ui/src/test/kotlin/androidx/compose/ui/gesture/TapGestureFilterTest.kt
@@ -23,8 +23,8 @@
import androidx.compose.ui.gesture.customevents.DelayUpMessage
import androidx.compose.ui.input.pointer.PointerEventPass
import androidx.compose.ui.input.pointer.PointerId
-import androidx.compose.ui.input.pointer.consume
import androidx.compose.ui.input.pointer.consumeDownChange
+import androidx.compose.ui.input.pointer.consumePositionChange
import androidx.compose.ui.input.pointer.down
import androidx.compose.ui.input.pointer.invokeOverAllPasses
import androidx.compose.ui.input.pointer.invokeOverPass
@@ -79,7 +79,7 @@
fun onPointerEvent_downMoveConsumedUp_onReleaseNotCalled() {
var pointer = down(0, 0.milliseconds)
filter::onPointerEvent.invokeOverAllPasses(pointerEventOf(pointer))
- pointer = pointer.moveTo(100.milliseconds, 5f).consume(5f)
+ pointer = pointer.moveTo(100.milliseconds, 5f).apply { consumePositionChange(5f, 0f) }
filter::onPointerEvent.invokeOverAllPasses(pointerEventOf(pointer))
pointer = pointer.up(200.milliseconds)
filter::onPointerEvent.invokeOverAllPasses(pointerEventOf(pointer))
diff --git a/compose/ui/ui/src/test/kotlin/androidx/compose/ui/input/pointer/PointerInputTest.kt b/compose/ui/ui/src/test/kotlin/androidx/compose/ui/input/pointer/PointerInputTest.kt
index 2a193ce..14310eb 100644
--- a/compose/ui/ui/src/test/kotlin/androidx/compose/ui/input/pointer/PointerInputTest.kt
+++ b/compose/ui/ui/src/test/kotlin/androidx/compose/ui/input/pointer/PointerInputTest.kt
@@ -20,6 +20,9 @@
import androidx.compose.ui.unit.Uptime
import androidx.compose.ui.unit.milliseconds
import androidx.test.filters.SmallTest
+import com.google.common.truth.FailureMetadata
+import com.google.common.truth.Subject
+import com.google.common.truth.Truth
import com.google.common.truth.Truth.assertThat
import org.hamcrest.CoreMatchers.`is`
import org.hamcrest.core.IsEqual.equalTo
@@ -435,18 +438,12 @@
val pointerInputChangeResult3 =
pointerInputChange1.deepCopy().apply { consumePositionChange(5f, 3f) }
- assertThat(
- pointerInputChangeResult1,
- `is`(equalTo(createPointerInputChange(8f, 16f, true, 2f, 4f, true, 5f, 0f, false)))
- )
- assertThat(
- pointerInputChangeResult2,
- `is`(equalTo(createPointerInputChange(8f, 16f, true, 2f, 4f, true, 0f, 3f, false)))
- )
- assertThat(
- pointerInputChangeResult3,
- `is`(equalTo(createPointerInputChange(8f, 16f, true, 2f, 4f, true, 5f, 3f, false)))
- )
+ PointerInputChangeSubject
+ .assertThat(pointerInputChangeResult1).positionChangeConsumed(Offset(5f, 0f))
+ PointerInputChangeSubject
+ .assertThat(pointerInputChangeResult2).positionChangeConsumed(Offset(0f, 3f))
+ PointerInputChangeSubject
+ .assertThat(pointerInputChangeResult3).positionChangeConsumed(Offset(5f, 3f))
}
@Test
@@ -461,18 +458,12 @@
val pointerInputChangeResult3 =
pointerInputChange1.deepCopy().apply { consumePositionChange(6f, 12f) }
- assertThat(
- pointerInputChangeResult1,
- `is`(equalTo(createPointerInputChange(8f, 16f, true, 2f, 4f, true, 6f, 0f, false)))
- )
- assertThat(
- pointerInputChangeResult2,
- `is`(equalTo(createPointerInputChange(8f, 16f, true, 2f, 4f, true, 0f, 12f, false)))
- )
- assertThat(
- pointerInputChangeResult3,
- `is`(equalTo(createPointerInputChange(8f, 16f, true, 2f, 4f, true, 6f, 12f, false)))
- )
+ PointerInputChangeSubject
+ .assertThat(pointerInputChangeResult1).positionChangeConsumed(Offset(6f, 0f))
+ PointerInputChangeSubject
+ .assertThat(pointerInputChangeResult2).positionChangeConsumed(Offset(0f, 12f))
+ PointerInputChangeSubject
+ .assertThat(pointerInputChangeResult3).positionChangeConsumed(Offset(6f, 12f))
}
@Test
@@ -487,18 +478,12 @@
val pointerInputChangeResult3 =
pointerInputChange1.deepCopy().apply { consumePositionChange(2f, 3f) }
- assertThat(
- pointerInputChangeResult1,
- `is`(equalTo(createPointerInputChange(8f, 16f, true, 2f, 4f, true, 3f, 5f, false)))
- )
- assertThat(
- pointerInputChangeResult2,
- `is`(equalTo(createPointerInputChange(8f, 16f, true, 2f, 4f, true, 1f, 8f, false)))
- )
- assertThat(
- pointerInputChangeResult3,
- `is`(equalTo(createPointerInputChange(8f, 16f, true, 2f, 4f, true, 3f, 8f, false)))
- )
+ PointerInputChangeSubject
+ .assertThat(pointerInputChangeResult1).positionChangeConsumed(Offset(3f, 5f))
+ PointerInputChangeSubject
+ .assertThat(pointerInputChangeResult2).positionChangeConsumed(Offset(1f, 8f))
+ PointerInputChangeSubject
+ .assertThat(pointerInputChangeResult3).positionChangeConsumed(Offset(3f, 8f))
}
@Test
@@ -511,8 +496,10 @@
val actual1 = pointerInputChange1.apply { consumeAllChanges() }
val actual2 = pointerInputChange2.apply { consumeAllChanges() }
- assertThat(actual1).isEqualTo(pointerInputChange1)
- assertThat(actual2).isEqualTo(pointerInputChange2)
+ PointerInputChangeSubject
+ .assertThat(actual1).nothingConsumed()
+ PointerInputChangeSubject
+ .assertThat(actual2).nothingConsumed()
}
@Test
@@ -525,12 +512,8 @@
val actual1 = pointerInputChange1.apply { consumeAllChanges() }
val actual2 = pointerInputChange2.apply { consumeAllChanges() }
- assertThat(actual1).isEqualTo(
- createPointerInputChange(1f, 2f, true, 1f, 2f, false, 0f, 0f, true)
- )
- assertThat(actual2).isEqualTo(
- createPointerInputChange(2f, 1f, false, 2f, 1f, true, 0f, 0f, true)
- )
+ PointerInputChangeSubject.assertThat(actual1).downConsumed()
+ PointerInputChangeSubject.assertThat(actual2).downConsumed()
}
@Test
@@ -540,9 +523,7 @@
val actual = pointerInputChange.apply { consumeAllChanges() }
- assertThat(actual).isEqualTo(
- createPointerInputChange(1f, 2f, true, 11f, 21f, true, -10f, -19f, false)
- )
+ PointerInputChangeSubject.assertThat(actual).positionChangeConsumed(Offset(-10f, -19f))
}
@Test
@@ -552,13 +533,11 @@
val actual = pointerInputChange.apply { consumeAllChanges() }
- assertThat(actual).isEqualTo(
- createPointerInputChange(1f, 2f, true, 11f, 21f, true, -10f, -19f, false)
- )
+ PointerInputChangeSubject.assertThat(actual).positionChangeConsumed(Offset(-10f, -19f))
}
@Test
- fun consumeAllChanges_allChanged_movementFullyConsumed() {
+ fun consumeAllChanges_allChanged_allConsumed() {
val pointerInputChange1 =
createPointerInputChange(1f, 2f, true, 11f, 21f, false, -3f, -5f, false)
val pointerInputChange2 =
@@ -567,12 +546,10 @@
val actual1 = pointerInputChange1.apply { consumeAllChanges() }
val actual2 = pointerInputChange2.apply { consumeAllChanges() }
- assertThat(actual1).isEqualTo(
- createPointerInputChange(1f, 2f, true, 11f, 21f, false, -10f, -19f, true)
- )
- assertThat(actual2).isEqualTo(
- createPointerInputChange(1f, 2f, false, 11f, 21f, true, -10f, -19f, true)
- )
+ PointerInputChangeSubject.assertThat(actual1).downConsumed()
+ PointerInputChangeSubject.assertThat(actual1).positionChangeConsumed(Offset(-10f, -19f))
+ PointerInputChangeSubject.assertThat(actual2).downConsumed()
+ PointerInputChangeSubject.assertThat(actual2).positionChangeConsumed(Offset(-10f, -19f))
}
// Private Helper
@@ -611,10 +588,51 @@
}
}
+private class PointerInputChangeSubject(
+ metaData: FailureMetadata,
+ val actual: PointerInputChange
+) : Subject(metaData, actual) {
+
+ companion object {
+
+ private val Factory =
+ Factory<PointerInputChangeSubject, PointerInputChange> { metadata, actual ->
+ PointerInputChangeSubject(metadata, actual)
+ }
+
+ fun assertThat(actual: PointerInputChange): PointerInputChangeSubject {
+ return Truth.assertAbout(Factory).that(actual)
+ }
+ }
+
+ fun nothingConsumed() {
+ check("consumed.downChange").that(actual.consumed.downChange).isEqualTo(false)
+ check("consumed.positionChange").that(actual.consumed.positionChange).isEqualTo(Offset.Zero)
+ }
+
+ fun downConsumed() {
+ check("consumed.downChange").that(actual.consumed.downChange).isEqualTo(true)
+ }
+
+ fun downNotConsumed() {
+ check("consumed.downChange").that(actual.consumed.downChange).isEqualTo(false)
+ }
+
+ fun positionChangeConsumed(expected: Offset) {
+ check("consumed.positionChangeConsumed")
+ .that(actual.consumed.positionChange)
+ .isEqualTo(expected)
+ }
+
+ fun positionChangeNotConsumed() {
+ positionChangeConsumed(Offset.Zero)
+ }
+}
+
private fun PointerInputChange.deepCopy() =
PointerInputChange(
id,
current.copy(),
previous.copy(),
- consumed.copy()
+ ConsumedData(consumed.positionChange, consumed.downChange)
)
\ No newline at end of file
diff --git a/development/build_log_processor.sh b/development/build_log_processor.sh
index fa46d1c..3f757b3 100755
--- a/development/build_log_processor.sh
+++ b/development/build_log_processor.sh
@@ -68,7 +68,7 @@
if "$programName" "$@" > >(tee -a "$logFile") 2>&1; then
if [ "$validateNoUnrecognizedMessagesOnSuccess" == "true" ]; then
if $SCRIPT_PATH/build_log_simplifier.py --validate $logFile >&2; then
- echo No unrecognized messages found in build log >&2
+ echo No unrecognized messages found in build log
else
echo >&2
echo "Build log validation, enabled by the argument $validateArgument, failed" >&2
diff --git a/navigation/settings.gradle b/navigation/settings.gradle
index fdeeda2..6b6da84 100644
--- a/navigation/settings.gradle
+++ b/navigation/settings.gradle
@@ -19,6 +19,8 @@
apply from: "../playground-common/playground-include-settings.gradle"
setupPlayground(this, "..")
selectProjectsFromAndroidX({ name ->
+ // Compose projects are not supported in playground yet
+ if (name.startsWith(":navigation:navigation-compose")) return false
if (name.startsWith(":navigation")) return true
if (name.startsWith(":internal-testutils-navigation")) return true
if (name.startsWith(":internal-testutils-runtime")) return true
diff --git a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspProcessingEnv.kt b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspProcessingEnv.kt
index 0788904..41d2747 100644
--- a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspProcessingEnv.kt
+++ b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspProcessingEnv.kt
@@ -70,7 +70,11 @@
}
override fun findGeneratedAnnotation(): XTypeElement? {
- TODO("Not yet implemented")
+ // this almost replicates what GeneratedAnnotations does except it doesn't check source
+ // version because we don't have that property here yet. Instead, it tries the new one
+ // first and falls back to the old one.
+ return findTypeElement("javax.annotation.processing.Generated")
+ ?: findTypeElement("javax.annotation.Generated")
}
override fun getDeclaredType(type: XTypeElement, vararg types: XType): XDeclaredType {
diff --git a/room/compiler-processing/src/test/java/androidx/room/compiler/processing/XProcessingEnvTest.kt b/room/compiler-processing/src/test/java/androidx/room/compiler/processing/XProcessingEnvTest.kt
index 0187061..2ea0df4 100644
--- a/room/compiler-processing/src/test/java/androidx/room/compiler/processing/XProcessingEnvTest.kt
+++ b/room/compiler-processing/src/test/java/androidx/room/compiler/processing/XProcessingEnvTest.kt
@@ -173,6 +173,14 @@
}
@Test
+ fun findGeneratedAnnotation() {
+ runProcessorTestIncludingKsp { invocation ->
+ val generatedAnnotation = invocation.processingEnv.findGeneratedAnnotation()
+ assertThat(generatedAnnotation?.name).isEqualTo("Generated")
+ }
+ }
+
+ @Test
fun generateCode() {
val javaSrc = Source.java(
"foo.bar.AccessGenerated",
diff --git a/wear/wear-watchface-data/api/restricted_current.txt b/wear/wear-watchface-data/api/restricted_current.txt
index 8ef12ce..7ae8729 100644
--- a/wear/wear-watchface-data/api/restricted_current.txt
+++ b/wear/wear-watchface-data/api/restricted_current.txt
@@ -225,19 +225,6 @@
field public static final android.os.Parcelable.Creator<androidx.wear.watchface.data.IdAndComplicationDetails!>! CREATOR;
}
- @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) @androidx.versionedparcelable.VersionedParcelize public final class IndicatorState implements android.os.Parcelable androidx.versionedparcelable.VersionedParcelable {
- ctor public IndicatorState(boolean, boolean, boolean, boolean, boolean, boolean);
- method public int describeContents();
- method public boolean getInAirplaneMode();
- method public boolean getInTheaterMode();
- method public boolean getIsCharging();
- method public boolean getIsConnectedToCompanion();
- method public boolean getIsGpsActive();
- method public boolean getIsKeyguardLocked();
- method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator<androidx.wear.watchface.data.IndicatorState!>! CREATOR;
- }
-
@RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) @androidx.versionedparcelable.VersionedParcelize public class RenderParametersWireFormat implements android.os.Parcelable androidx.versionedparcelable.VersionedParcelable {
ctor public RenderParametersWireFormat(int, java.util.List<androidx.wear.watchface.data.RenderParametersWireFormat.LayerParameterWireFormat!>);
method public int describeContents();
@@ -257,12 +244,10 @@
}
@RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) @androidx.versionedparcelable.VersionedParcelize public final class SystemState implements android.os.Parcelable androidx.versionedparcelable.VersionedParcelable {
- ctor public SystemState(boolean, int, int, int);
+ ctor public SystemState(boolean, int);
method public int describeContents();
method public boolean getInAmbientMode();
method public int getInterruptionFilter();
- method public int getNotificationCount();
- method public int getUnreadCount();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<androidx.wear.watchface.data.SystemState!>! CREATOR;
}
diff --git a/wear/wear-watchface-data/src/main/java/androidx/wear/watchface/data/IndicatorState.java b/wear/wear-watchface-data/src/main/java/androidx/wear/watchface/data/IndicatorState.java
deleted file mode 100644
index b7ad20b..0000000
--- a/wear/wear-watchface-data/src/main/java/androidx/wear/watchface/data/IndicatorState.java
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * Copyright 2020 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.
- */
-
-package androidx.wear.watchface.data;
-
-import android.annotation.SuppressLint;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.RestrictTo;
-import androidx.versionedparcelable.ParcelField;
-import androidx.versionedparcelable.ParcelUtils;
-import androidx.versionedparcelable.VersionedParcelable;
-import androidx.versionedparcelable.VersionedParcelize;
-
-/**
- * Data sent over AIDL for {@link IWatchFaceCommand#setIndicatorState}.
- *
- * @hide
- */
-@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX)
-@VersionedParcelize
-@SuppressLint("BanParcelableUsage") // TODO(b/169214666): Remove Parcelable
-public final class IndicatorState implements VersionedParcelable, Parcelable {
- @ParcelField(1)
- boolean mIsCharging;
-
- @ParcelField(2)
- boolean mInAirplaneMode;
-
- @ParcelField(3)
- boolean mIsConnectedToCompanion;
-
- @ParcelField(4)
- boolean mInTheaterMode;
-
- @ParcelField(5)
- boolean mIsGpsActive;
-
- @ParcelField(6)
- boolean mIsKeyguardLocked;
-
- /** Used by VersionedParcelable. */
- IndicatorState() {}
-
- public IndicatorState(
- boolean isCharging,
- boolean inAirplaneMode,
- boolean isConnectedToCompanion,
- boolean inTheaterMode,
- boolean isGpsActive,
- boolean isKeyguardLocked) {
- mIsCharging = isCharging;
- mInAirplaneMode = inAirplaneMode;
- mIsConnectedToCompanion = isConnectedToCompanion;
- mInTheaterMode = inTheaterMode;
- mIsGpsActive = isGpsActive;
- mIsKeyguardLocked = isKeyguardLocked;
- }
-
- public boolean getIsCharging() {
- return mIsCharging;
- }
-
- public boolean getInAirplaneMode() {
- return mInAirplaneMode;
- }
-
- public boolean getIsConnectedToCompanion() {
- return mIsConnectedToCompanion;
- }
-
- public boolean getInTheaterMode() {
- return mInTheaterMode;
- }
-
- public boolean getIsGpsActive() {
- return mIsGpsActive;
- }
-
- public boolean getIsKeyguardLocked() {
- return mIsKeyguardLocked;
- }
-
- /** Serializes this IndicatorState to the specified {@link Parcel}. */
- @Override
- public void writeToParcel(@NonNull Parcel parcel, int flags) {
- parcel.writeParcelable(ParcelUtils.toParcelable(this), flags);
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- public static final Parcelable.Creator<IndicatorState> CREATOR =
- new Parcelable.Creator<IndicatorState>() {
- @Override
- public IndicatorState createFromParcel(Parcel source) {
- return IndicatorStateParcelizer.read(
- ParcelUtils.fromParcelable(source.readParcelable(
- getClass().getClassLoader())));
- }
-
- @Override
- public IndicatorState[] newArray(int size) {
- return new IndicatorState[size];
- }
- };
-}
diff --git a/wear/wear-watchface-data/src/main/java/androidx/wear/watchface/data/SystemState.java b/wear/wear-watchface-data/src/main/java/androidx/wear/watchface/data/SystemState.java
index d71cf20..09ae0a2 100644
--- a/wear/wear-watchface-data/src/main/java/androidx/wear/watchface/data/SystemState.java
+++ b/wear/wear-watchface-data/src/main/java/androidx/wear/watchface/data/SystemState.java
@@ -42,24 +42,14 @@
@ParcelField(2)
int mInterruptionFilter;
- @ParcelField(3)
- int mUnreadCount;
-
- @ParcelField(4)
- int mNotificationCount;
-
/** Used by VersionedParcelable. */
SystemState() {}
public SystemState(
boolean inAmbientMode,
- int interruptionFilter,
- int unreadCount,
- int notificationCount) {
+ int interruptionFilter) {
mInAmbientMode = inAmbientMode;
mInterruptionFilter = interruptionFilter;
- mUnreadCount = unreadCount;
- mNotificationCount = notificationCount;
}
public boolean getInAmbientMode() {
@@ -70,14 +60,6 @@
return mInterruptionFilter;
}
- public int getUnreadCount() {
- return mUnreadCount;
- }
-
- public int getNotificationCount() {
- return mNotificationCount;
- }
-
/** Serializes this SystemState to the specified {@link Parcel}. */
@Override
public void writeToParcel(@NonNull Parcel parcel, int flags) {
diff --git a/wear/wear-watchface/api/current.txt b/wear/wear-watchface/api/current.txt
index 6898c51..69cfde5 100644
--- a/wear/wear-watchface/api/current.txt
+++ b/wear/wear-watchface/api/current.txt
@@ -196,7 +196,6 @@
method public androidx.wear.watchface.WatchFace.Builder setPreviewReferenceTimeMillis(long previewReferenceTimeMillis);
method public androidx.wear.watchface.WatchFace.Builder setWear2AccentColor(@ColorInt int accentColor);
method public androidx.wear.watchface.WatchFace.Builder setWear2AcceptsTapEvents(boolean acceptsTapEvents);
- method public androidx.wear.watchface.WatchFace.Builder setWear2ShowUnreadCountIndicator(boolean showUnreadCountIndicator);
method public androidx.wear.watchface.WatchFace.Builder setWear2StatusBarGravity(int statusBarGravity);
method public androidx.wear.watchface.WatchFace.Builder setWear2ViewProtectionMode(int viewProtectionMode);
}
@@ -218,13 +217,11 @@
}
public final class WatchState {
- ctor public WatchState(androidx.wear.watchface.ObservableWatchData<java.lang.Integer> interruptionFilter, androidx.wear.watchface.ObservableWatchData<java.lang.Boolean> isAmbient, androidx.wear.watchface.ObservableWatchData<java.lang.Boolean> inAirplaneMode, androidx.wear.watchface.ObservableWatchData<java.lang.Boolean> isBatteryLowAndNotCharging, androidx.wear.watchface.ObservableWatchData<java.lang.Boolean> isCharging, androidx.wear.watchface.ObservableWatchData<java.lang.Boolean> isConnectedToCompanion, androidx.wear.watchface.ObservableWatchData<java.lang.Boolean> isGpsActive, androidx.wear.watchface.ObservableWatchData<java.lang.Boolean> isKeyguardLocked, androidx.wear.watchface.ObservableWatchData<java.lang.Boolean> isInTheaterMode, androidx.wear.watchface.ObservableWatchData<java.lang.Boolean> isVisible, androidx.wear.watchface.ObservableWatchData<java.lang.Integer> notificationCount, androidx.wear.watchface.ObservableWatchData<java.lang.Integer> unreadNotificationCount, boolean hasLowBitAmbient, boolean hasBurnInProtection, int screenShape);
+ ctor public WatchState(androidx.wear.watchface.ObservableWatchData<java.lang.Integer> interruptionFilter, androidx.wear.watchface.ObservableWatchData<java.lang.Boolean> isAmbient, androidx.wear.watchface.ObservableWatchData<java.lang.Boolean> isBatteryLowAndNotCharging, androidx.wear.watchface.ObservableWatchData<java.lang.Boolean> isVisible, boolean hasLowBitAmbient, boolean hasBurnInProtection, int screenShape);
method public boolean getHasBurnInProtection();
method public boolean getHasLowBitAmbient();
method public androidx.wear.watchface.ObservableWatchData<java.lang.Integer> getInterruptionFilter();
- method public androidx.wear.watchface.ObservableWatchData<java.lang.Integer> getNotificationCount();
method public int getScreenShape();
- method public androidx.wear.watchface.ObservableWatchData<java.lang.Integer> getUnreadNotificationCount();
method public androidx.wear.watchface.ObservableWatchData<java.lang.Boolean> isAmbient();
method public androidx.wear.watchface.ObservableWatchData<java.lang.Boolean> isVisible();
property public final boolean hasBurnInProtection;
@@ -232,9 +229,7 @@
property public final androidx.wear.watchface.ObservableWatchData<java.lang.Integer> interruptionFilter;
property public final androidx.wear.watchface.ObservableWatchData<java.lang.Boolean> isAmbient;
property public final androidx.wear.watchface.ObservableWatchData<java.lang.Boolean> isVisible;
- property public final androidx.wear.watchface.ObservableWatchData<java.lang.Integer> notificationCount;
property public final int screenShape;
- property public final androidx.wear.watchface.ObservableWatchData<java.lang.Integer> unreadNotificationCount;
field public static final androidx.wear.watchface.WatchState.Companion Companion;
field public static final int SCREEN_SHAPE_RECTANGULAR = 2; // 0x2
field public static final int SCREEN_SHAPE_ROUND = 1; // 0x1
diff --git a/wear/wear-watchface/api/public_plus_experimental_current.txt b/wear/wear-watchface/api/public_plus_experimental_current.txt
index 3712fd2..dcc411b 100644
--- a/wear/wear-watchface/api/public_plus_experimental_current.txt
+++ b/wear/wear-watchface/api/public_plus_experimental_current.txt
@@ -196,7 +196,6 @@
method public androidx.wear.watchface.WatchFace.Builder setPreviewReferenceTimeMillis(long previewReferenceTimeMillis);
method public androidx.wear.watchface.WatchFace.Builder setWear2AccentColor(@ColorInt int accentColor);
method public androidx.wear.watchface.WatchFace.Builder setWear2AcceptsTapEvents(boolean acceptsTapEvents);
- method public androidx.wear.watchface.WatchFace.Builder setWear2ShowUnreadCountIndicator(boolean showUnreadCountIndicator);
method public androidx.wear.watchface.WatchFace.Builder setWear2StatusBarGravity(int statusBarGravity);
method public androidx.wear.watchface.WatchFace.Builder setWear2ViewProtectionMode(int viewProtectionMode);
}
@@ -218,13 +217,11 @@
}
public final class WatchState {
- ctor public WatchState(androidx.wear.watchface.ObservableWatchData<java.lang.Integer> interruptionFilter, androidx.wear.watchface.ObservableWatchData<java.lang.Boolean> isAmbient, androidx.wear.watchface.ObservableWatchData<java.lang.Boolean> inAirplaneMode, androidx.wear.watchface.ObservableWatchData<java.lang.Boolean> isBatteryLowAndNotCharging, androidx.wear.watchface.ObservableWatchData<java.lang.Boolean> isCharging, androidx.wear.watchface.ObservableWatchData<java.lang.Boolean> isConnectedToCompanion, androidx.wear.watchface.ObservableWatchData<java.lang.Boolean> isGpsActive, androidx.wear.watchface.ObservableWatchData<java.lang.Boolean> isKeyguardLocked, androidx.wear.watchface.ObservableWatchData<java.lang.Boolean> isInTheaterMode, androidx.wear.watchface.ObservableWatchData<java.lang.Boolean> isVisible, androidx.wear.watchface.ObservableWatchData<java.lang.Integer> notificationCount, androidx.wear.watchface.ObservableWatchData<java.lang.Integer> unreadNotificationCount, boolean hasLowBitAmbient, boolean hasBurnInProtection, int screenShape);
+ ctor public WatchState(androidx.wear.watchface.ObservableWatchData<java.lang.Integer> interruptionFilter, androidx.wear.watchface.ObservableWatchData<java.lang.Boolean> isAmbient, androidx.wear.watchface.ObservableWatchData<java.lang.Boolean> isBatteryLowAndNotCharging, androidx.wear.watchface.ObservableWatchData<java.lang.Boolean> isVisible, boolean hasLowBitAmbient, boolean hasBurnInProtection, int screenShape);
method public boolean getHasBurnInProtection();
method public boolean getHasLowBitAmbient();
method public androidx.wear.watchface.ObservableWatchData<java.lang.Integer> getInterruptionFilter();
- method public androidx.wear.watchface.ObservableWatchData<java.lang.Integer> getNotificationCount();
method public int getScreenShape();
- method public androidx.wear.watchface.ObservableWatchData<java.lang.Integer> getUnreadNotificationCount();
method public androidx.wear.watchface.ObservableWatchData<java.lang.Boolean> isAmbient();
method public androidx.wear.watchface.ObservableWatchData<java.lang.Boolean> isVisible();
property public final boolean hasBurnInProtection;
@@ -232,9 +229,7 @@
property public final androidx.wear.watchface.ObservableWatchData<java.lang.Integer> interruptionFilter;
property public final androidx.wear.watchface.ObservableWatchData<java.lang.Boolean> isAmbient;
property public final androidx.wear.watchface.ObservableWatchData<java.lang.Boolean> isVisible;
- property public final androidx.wear.watchface.ObservableWatchData<java.lang.Integer> notificationCount;
property public final int screenShape;
- property public final androidx.wear.watchface.ObservableWatchData<java.lang.Integer> unreadNotificationCount;
field public static final androidx.wear.watchface.WatchState.Companion Companion;
field public static final int SCREEN_SHAPE_RECTANGULAR = 2; // 0x2
field public static final int SCREEN_SHAPE_ROUND = 1; // 0x1
diff --git a/wear/wear-watchface/api/restricted_current.txt b/wear/wear-watchface/api/restricted_current.txt
index 05ea23d..bbae9a3 100644
--- a/wear/wear-watchface/api/restricted_current.txt
+++ b/wear/wear-watchface/api/restricted_current.txt
@@ -140,18 +140,10 @@
method public androidx.wear.watchface.WatchState asWatchState();
method public boolean getHasBurnInProtection();
method public boolean getHasLowBitAmbient();
- method public androidx.wear.watchface.MutableObservableWatchData<java.lang.Boolean> getInAirplaneMode();
method public androidx.wear.watchface.MutableObservableWatchData<java.lang.Integer> getInterruptionFilter();
- method public androidx.wear.watchface.MutableObservableWatchData<java.lang.Integer> getNotificationCount();
method public int getScreenShape();
- method public androidx.wear.watchface.MutableObservableWatchData<java.lang.Integer> getUnreadNotificationCount();
method public androidx.wear.watchface.MutableObservableWatchData<java.lang.Boolean> isAmbient();
method public androidx.wear.watchface.MutableObservableWatchData<java.lang.Boolean> isBatteryLowAndNotCharging();
- method public androidx.wear.watchface.MutableObservableWatchData<java.lang.Boolean> isCharging();
- method public androidx.wear.watchface.MutableObservableWatchData<java.lang.Boolean> isConnectedToCompanion();
- method public androidx.wear.watchface.MutableObservableWatchData<java.lang.Boolean> isGpsActive();
- method public androidx.wear.watchface.MutableObservableWatchData<java.lang.Boolean> isInTheaterMode();
- method public androidx.wear.watchface.MutableObservableWatchData<java.lang.Boolean> isKeyguardLocked();
method public androidx.wear.watchface.MutableObservableWatchData<java.lang.Boolean> isVisible();
method public void setHasBurnInProtection(boolean p);
method public void setHasLowBitAmbient(boolean p);
@@ -159,19 +151,11 @@
method public void setScreenShape(int p);
property public final boolean hasBurnInProtection;
property public final boolean hasLowBitAmbient;
- property public final androidx.wear.watchface.MutableObservableWatchData<java.lang.Boolean> inAirplaneMode;
property public final androidx.wear.watchface.MutableObservableWatchData<java.lang.Integer> interruptionFilter;
property public final androidx.wear.watchface.MutableObservableWatchData<java.lang.Boolean> isAmbient;
property public final androidx.wear.watchface.MutableObservableWatchData<java.lang.Boolean> isBatteryLowAndNotCharging;
- property public final androidx.wear.watchface.MutableObservableWatchData<java.lang.Boolean> isCharging;
- property public final androidx.wear.watchface.MutableObservableWatchData<java.lang.Boolean> isConnectedToCompanion;
- property public final androidx.wear.watchface.MutableObservableWatchData<java.lang.Boolean> isGpsActive;
- property public final androidx.wear.watchface.MutableObservableWatchData<java.lang.Boolean> isInTheaterMode;
- property public final androidx.wear.watchface.MutableObservableWatchData<java.lang.Boolean> isKeyguardLocked;
property public final androidx.wear.watchface.MutableObservableWatchData<java.lang.Boolean> isVisible;
- property public final androidx.wear.watchface.MutableObservableWatchData<java.lang.Integer> notificationCount;
property public final int screenShape;
- property public final androidx.wear.watchface.MutableObservableWatchData<java.lang.Integer> unreadNotificationCount;
}
public class ObservableWatchData<T> {
@@ -237,7 +221,6 @@
method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP) public androidx.wear.watchface.WatchFace.Builder setSystemTimeProvider(androidx.wear.watchface.WatchFace.SystemTimeProvider systemTimeProvider);
method public androidx.wear.watchface.WatchFace.Builder setWear2AccentColor(@ColorInt int accentColor);
method public androidx.wear.watchface.WatchFace.Builder setWear2AcceptsTapEvents(boolean acceptsTapEvents);
- method public androidx.wear.watchface.WatchFace.Builder setWear2ShowUnreadCountIndicator(boolean showUnreadCountIndicator);
method public androidx.wear.watchface.WatchFace.Builder setWear2StatusBarGravity(int statusBarGravity);
method public androidx.wear.watchface.WatchFace.Builder setWear2ViewProtectionMode(int viewProtectionMode);
}
@@ -275,13 +258,11 @@
}
public final class WatchState {
- ctor public WatchState(androidx.wear.watchface.ObservableWatchData<java.lang.Integer> interruptionFilter, androidx.wear.watchface.ObservableWatchData<java.lang.Boolean> isAmbient, androidx.wear.watchface.ObservableWatchData<java.lang.Boolean> inAirplaneMode, androidx.wear.watchface.ObservableWatchData<java.lang.Boolean> isBatteryLowAndNotCharging, androidx.wear.watchface.ObservableWatchData<java.lang.Boolean> isCharging, androidx.wear.watchface.ObservableWatchData<java.lang.Boolean> isConnectedToCompanion, androidx.wear.watchface.ObservableWatchData<java.lang.Boolean> isGpsActive, androidx.wear.watchface.ObservableWatchData<java.lang.Boolean> isKeyguardLocked, androidx.wear.watchface.ObservableWatchData<java.lang.Boolean> isInTheaterMode, androidx.wear.watchface.ObservableWatchData<java.lang.Boolean> isVisible, androidx.wear.watchface.ObservableWatchData<java.lang.Integer> notificationCount, androidx.wear.watchface.ObservableWatchData<java.lang.Integer> unreadNotificationCount, boolean hasLowBitAmbient, boolean hasBurnInProtection, int screenShape);
+ ctor public WatchState(androidx.wear.watchface.ObservableWatchData<java.lang.Integer> interruptionFilter, androidx.wear.watchface.ObservableWatchData<java.lang.Boolean> isAmbient, androidx.wear.watchface.ObservableWatchData<java.lang.Boolean> isBatteryLowAndNotCharging, androidx.wear.watchface.ObservableWatchData<java.lang.Boolean> isVisible, boolean hasLowBitAmbient, boolean hasBurnInProtection, int screenShape);
method public boolean getHasBurnInProtection();
method public boolean getHasLowBitAmbient();
method public androidx.wear.watchface.ObservableWatchData<java.lang.Integer> getInterruptionFilter();
- method public androidx.wear.watchface.ObservableWatchData<java.lang.Integer> getNotificationCount();
method public int getScreenShape();
- method public androidx.wear.watchface.ObservableWatchData<java.lang.Integer> getUnreadNotificationCount();
method public androidx.wear.watchface.ObservableWatchData<java.lang.Boolean> isAmbient();
method public androidx.wear.watchface.ObservableWatchData<java.lang.Boolean> isVisible();
property public final boolean hasBurnInProtection;
@@ -289,9 +270,7 @@
property public final androidx.wear.watchface.ObservableWatchData<java.lang.Integer> interruptionFilter;
property public final androidx.wear.watchface.ObservableWatchData<java.lang.Boolean> isAmbient;
property public final androidx.wear.watchface.ObservableWatchData<java.lang.Boolean> isVisible;
- property public final androidx.wear.watchface.ObservableWatchData<java.lang.Integer> notificationCount;
property public final int screenShape;
- property public final androidx.wear.watchface.ObservableWatchData<java.lang.Integer> unreadNotificationCount;
field public static final androidx.wear.watchface.WatchState.Companion Companion;
field public static final int SCREEN_SHAPE_RECTANGULAR = 2; // 0x2
field public static final int SCREEN_SHAPE_ROUND = 1; // 0x1
diff --git a/wear/wear-watchface/src/androidTest/java/androidx/wear/watchface/test/WatchFaceServiceImageTest.kt b/wear/wear-watchface/src/androidTest/java/androidx/wear/watchface/test/WatchFaceServiceImageTest.kt
index 3584b80..78f1a23 100644
--- a/wear/wear-watchface/src/androidTest/java/androidx/wear/watchface/test/WatchFaceServiceImageTest.kt
+++ b/wear/wear-watchface/src/androidTest/java/androidx/wear/watchface/test/WatchFaceServiceImageTest.kt
@@ -142,7 +142,7 @@
false,
DeviceConfig.SCREEN_SHAPE_ROUND
),
- SystemState(false, 0, 0, 0),
+ SystemState(false, 0),
null,
null
)
@@ -173,7 +173,7 @@
false,
DeviceConfig.SCREEN_SHAPE_ROUND
),
- SystemState(false, 0, 0, 0),
+ SystemState(false, 0),
null,
null
)
@@ -224,15 +224,7 @@
interactiveWatchFaceInstanceWCS.instanceId
)!!.sysUiApi
- interactiveWatchFaceInstanceSysUi.setSystemState(
- SystemState(
- ambient,
- 0,
- 0,
- 0
- )
- )
-
+ interactiveWatchFaceInstanceSysUi.setSystemState(SystemState(ambient, 0))
interactiveWatchFaceInstanceSysUi.release()
}
diff --git a/wear/wear-watchface/src/main/java/androidx/wear/watchface/WatchFace.kt b/wear/wear-watchface/src/main/java/androidx/wear/watchface/WatchFace.kt
index d20dd67..f2a30c5 100644
--- a/wear/wear-watchface/src/main/java/androidx/wear/watchface/WatchFace.kt
+++ b/wear/wear-watchface/src/main/java/androidx/wear/watchface/WatchFace.kt
@@ -178,8 +178,6 @@
@ColorInt
private var accentColor: Int = WatchFaceStyle.DEFAULT_ACCENT_COLOR
- private var showUnreadCountIndicator: Boolean = false
- private var hideNotificationIndicator: Boolean = false
private var acceptsTapEvents: Boolean = true
private var systemTimeProvider: SystemTimeProvider = object : SystemTimeProvider {
override fun getSystemTimeMillis() = System.currentTimeMillis()
@@ -247,33 +245,6 @@
}
/**
- * Sets whether to add an indicator of how many unread cards there are in the stream. The
- * indicator will be displayed next to status icons (battery state, lack of connection).
- *
- * <p>Only has an impact on devices running Wear 2.x, on other devices this is a no-op and
- * the functionality is replaced by... TODO(alexclarke): Design the replacement.
- *
- * @param showUnreadCountIndicator if true an indicator will be shown
- */
- public fun setWear2ShowUnreadCountIndicator(showUnreadCountIndicator: Boolean): Builder =
- apply { this.showUnreadCountIndicator = showUnreadCountIndicator }
-
- /**
- * Sets whether to hide the dot indicator that is displayed at the bottom of the watch face
- * if there are any unread notifications. The default value is false, but note that the
- * dot will not be displayed if the numerical unread count indicator is being shown (i.e.
- * if [getShowUnreadCountIndicator] is true).
- *
- * <p>Only has an impact on devices running Wear 2.x, on other devices this is a no-op and
- * the functionality is replaced by... TODO(alexclarke): Design the replacement.
- *
- * @param hideNotificationIndicator if true an indicator will be hidden
- * @hide
- */
- public fun setWear2HideNotificationIndicator(hideNotificationIndicator: Boolean): Builder =
- apply { this.hideNotificationIndicator = hideNotificationIndicator }
-
- /**
* Sets whether this watchface accepts tap events. The default is false.
*
* <p>Only has an impact on devices running Wear 2.x, on other devices this is a no-op and
@@ -316,8 +287,8 @@
viewProtectionMode,
statusBarGravity,
accentColor,
- showUnreadCountIndicator,
- hideNotificationIndicator,
+ false,
+ false,
acceptsTapEvents
),
componentName,
diff --git a/wear/wear-watchface/src/main/java/androidx/wear/watchface/WatchFaceService.kt b/wear/wear-watchface/src/main/java/androidx/wear/watchface/WatchFaceService.kt
index a4efd48..e4db227 100644
--- a/wear/wear-watchface/src/main/java/androidx/wear/watchface/WatchFaceService.kt
+++ b/wear/wear-watchface/src/main/java/androidx/wear/watchface/WatchFaceService.kt
@@ -63,7 +63,6 @@
import androidx.wear.watchface.data.IdAndComplicationDetails
import androidx.wear.watchface.data.DeviceConfig
import androidx.wear.watchface.data.DeviceConfig.SCREEN_SHAPE_ROUND
-import androidx.wear.watchface.data.IndicatorState
import androidx.wear.watchface.data.SystemState
import androidx.wear.watchface.style.UserStyle
import androidx.wear.watchface.style.data.UserStyleWireFormat
@@ -340,63 +339,9 @@
mutableWatchState.interruptionFilter.value = systemState.interruptionFilter
}
- if (firstSetSystemState ||
- systemState.unreadCount != mutableWatchState.unreadNotificationCount.value
- ) {
- mutableWatchState.unreadNotificationCount.value = systemState.unreadCount
- }
-
- if (firstSetSystemState ||
- systemState.notificationCount != mutableWatchState.notificationCount.value
- ) {
- mutableWatchState.notificationCount.value = systemState.notificationCount
- }
-
firstSetSystemState = false
}
- fun setIndicatorState(indicatorState: IndicatorState) {
- if (firstIndicatorState ||
- indicatorState.isCharging != mutableWatchState.isCharging.value
- ) {
- mutableWatchState.isCharging.value = indicatorState.isCharging
- }
-
- if (firstIndicatorState ||
- indicatorState.inAirplaneMode != mutableWatchState.inAirplaneMode.value
- ) {
- mutableWatchState.inAirplaneMode.value = indicatorState.inAirplaneMode
- }
-
- if (firstIndicatorState ||
- indicatorState.isConnectedToCompanion !=
- mutableWatchState.isConnectedToCompanion.value
- ) {
- mutableWatchState.isConnectedToCompanion.value =
- indicatorState.isConnectedToCompanion
- }
-
- if (firstIndicatorState ||
- indicatorState.inTheaterMode != mutableWatchState.isInTheaterMode.value
- ) {
- mutableWatchState.isInTheaterMode.value = indicatorState.inTheaterMode
- }
-
- if (firstIndicatorState ||
- indicatorState.isGpsActive != mutableWatchState.isGpsActive.value
- ) {
- mutableWatchState.isGpsActive.value = indicatorState.isGpsActive
- }
-
- if (firstIndicatorState ||
- indicatorState.isKeyguardLocked != mutableWatchState.isKeyguardLocked.value
- ) {
- mutableWatchState.isKeyguardLocked.value = indicatorState.isKeyguardLocked
- }
-
- firstIndicatorState = false
- }
-
@UiThread
fun setUserStyle(userStyle: UserStyleWireFormat) {
watchFace.onSetStyleInternal(
@@ -673,32 +618,10 @@
extras.getInt(
Constants.EXTRA_INTERRUPTION_FILTER,
mutableWatchState.interruptionFilter.getValueOr(0)
- ),
- extras.getInt(
- Constants.EXTRA_UNREAD_COUNT,
- mutableWatchState.unreadNotificationCount.getValueOr(0)
- ),
- extras.getInt(
- Constants.EXTRA_NOTIFICATION_COUNT,
- mutableWatchState.notificationCount.getValueOr(0)
)
)
)
- val statusBundle = extras.getBundle(Constants.EXTRA_INDICATOR_STATUS)
- if (statusBundle != null) {
- setIndicatorState(
- IndicatorState(
- statusBundle.getBoolean(Constants.STATUS_CHARGING),
- statusBundle.getBoolean(Constants.STATUS_AIRPLANE_MODE),
- statusBundle.getBoolean(Constants.STATUS_CONNECTED),
- statusBundle.getBoolean(Constants.STATUS_THEATER_MODE),
- statusBundle.getBoolean(Constants.STATUS_GPS_ACTIVE),
- statusBundle.getBoolean(Constants.STATUS_KEYGUARD_LOCKED)
- )
- )
- }
-
pendingBackgroundAction = null
}
diff --git a/wear/wear-watchface/src/main/java/androidx/wear/watchface/WatchState.kt b/wear/wear-watchface/src/main/java/androidx/wear/watchface/WatchState.kt
index 12f8aff..669396a 100644
--- a/wear/wear-watchface/src/main/java/androidx/wear/watchface/WatchState.kt
+++ b/wear/wear-watchface/src/main/java/androidx/wear/watchface/WatchState.kt
@@ -42,14 +42,6 @@
public val isAmbient: ObservableWatchData<Boolean>,
/**
- * Whether or not the watch is in airplane mode. Only valid if
- * [android.support.wearable.watchface.WatchFaceStyle.hideNotificationIndicator] is true.
- *
- * @hide
- */
- public val inAirplaneMode: ObservableWatchData<Boolean>,
-
- /**
* Whether or not we should conserve power due to a low battery which isn't charging. Only
* valid if [android.support.wearable.watchface.WatchFaceStyle.hideNotificationIndicator] is
* true.
@@ -58,55 +50,9 @@
*/
public val isBatteryLowAndNotCharging: ObservableWatchData<Boolean>,
- /**
- * Whether or not the watch is charging. Only valid if
- * [android.support.wearable.watchface.WatchFaceStyle.hideNotificationIndicator] is true.
- *
- * @hide
- */
- public val isCharging: ObservableWatchData<Boolean>,
-
- /**
- * Whether or not the watch is connected to the companion phone. Only valid if
- * [android.support.wearable.watchface.WatchFaceStyle.hideNotificationIndicator] is true.
- *
- * @hide
- */
- public val isConnectedToCompanion: ObservableWatchData<Boolean>,
-
- /**
- * Whether or not GPS is active on the watch. Only valid if
- * [android.support.wearable.watchface.WatchFaceStyle.hideNotificationIndicator] is true.
- *
- * @hide
- */
- public val isGpsActive: ObservableWatchData<Boolean>,
-
- /**
- * Whether or not the watch's keyguard (lock screen) is locked. Only valid if
- * [android.support.wearable.watchface.WatchFaceStyle.hideNotificationIndicator] is true.
- *
- * @hide
- */
- public val isKeyguardLocked: ObservableWatchData<Boolean>,
-
- /**
- * Whether or not the watch is in theater mode. Only valid if
- * [android.support.wearable.watchface.WatchFaceStyle.hideNotificationIndicator] is true.
- *
- * @hide
- */
- public val isInTheaterMode: ObservableWatchData<Boolean>,
-
/** Whether or not the watch face is visible. */
public val isVisible: ObservableWatchData<Boolean>,
- /** The total number of notification cards in the stream. */
- public val notificationCount: ObservableWatchData<Int>,
-
- /** The total number of unread notification cards in the stream. */
- public val unreadNotificationCount: ObservableWatchData<Int>,
-
/** Whether or not the watch hardware supports low bit ambient support. */
public val hasLowBitAmbient: Boolean,
@@ -134,20 +80,9 @@
public class MutableWatchState {
public var interruptionFilter: MutableObservableWatchData<Int> = MutableObservableWatchData()
public val isAmbient: MutableObservableWatchData<Boolean> = MutableObservableWatchData()
- public val inAirplaneMode: MutableObservableWatchData<Boolean> = MutableObservableWatchData()
public val isBatteryLowAndNotCharging: MutableObservableWatchData<Boolean> =
MutableObservableWatchData()
- public val isCharging: MutableObservableWatchData<Boolean> = MutableObservableWatchData()
- public val isConnectedToCompanion: MutableObservableWatchData<Boolean> =
- MutableObservableWatchData()
- public val isGpsActive: MutableObservableWatchData<Boolean> = MutableObservableWatchData()
- public val isKeyguardLocked: MutableObservableWatchData<Boolean> =
- MutableObservableWatchData()
- public val isInTheaterMode: MutableObservableWatchData<Boolean> = MutableObservableWatchData()
public val isVisible: MutableObservableWatchData<Boolean> = MutableObservableWatchData()
- public val notificationCount: MutableObservableWatchData<Int> = MutableObservableWatchData()
- public val unreadNotificationCount: MutableObservableWatchData<Int> =
- MutableObservableWatchData()
public var hasLowBitAmbient: Boolean = false
public var hasBurnInProtection: Boolean = false
public var screenShape: Int = 0
@@ -155,16 +90,8 @@
public fun asWatchState(): WatchState = WatchState(
interruptionFilter = interruptionFilter,
isAmbient = isAmbient,
- inAirplaneMode = inAirplaneMode,
isBatteryLowAndNotCharging = isBatteryLowAndNotCharging,
- isCharging = isCharging,
- isConnectedToCompanion = isConnectedToCompanion,
- isGpsActive = isGpsActive,
- isKeyguardLocked = isKeyguardLocked,
- isInTheaterMode = isInTheaterMode,
isVisible = isVisible,
- notificationCount = notificationCount,
- unreadNotificationCount = unreadNotificationCount,
hasLowBitAmbient = hasLowBitAmbient,
hasBurnInProtection = hasBurnInProtection,
screenShape = screenShape
diff --git a/wear/wear-watchface/src/test/java/androidx/wear/watchface/WatchFaceServiceTest.kt b/wear/wear-watchface/src/test/java/androidx/wear/watchface/WatchFaceServiceTest.kt
index ef41116..7b15c37 100644
--- a/wear/wear-watchface/src/test/java/androidx/wear/watchface/WatchFaceServiceTest.kt
+++ b/wear/wear-watchface/src/test/java/androidx/wear/watchface/WatchFaceServiceTest.kt
@@ -61,12 +61,10 @@
import org.junit.runner.RunWith
import org.mockito.ArgumentCaptor
import org.mockito.ArgumentMatchers.any
-import org.mockito.ArgumentMatchers.anyBoolean
import org.mockito.ArgumentMatchers.anyLong
import org.mockito.Mockito.`when`
import org.mockito.Mockito.doAnswer
import org.mockito.Mockito.reset
-import org.mockito.Mockito.times
import org.mockito.Mockito.validateMockitoUsage
import org.mockito.Mockito.verify
import org.robolectric.annotation.Config
@@ -935,7 +933,7 @@
false,
DeviceConfig.SCREEN_SHAPE_ROUND
),
- SystemState(false, 0, 0, 0),
+ SystemState(false, 0),
UserStyle(
hashMapOf(
colorStyleCategory to blueStyleOption,
@@ -970,7 +968,7 @@
false,
DeviceConfig.SCREEN_SHAPE_ROUND
),
- SystemState(false, 0, 0, 0),
+ SystemState(false, 0),
UserStyle(hashMapOf(watchHandStyleCategory to badStyleOption)).toWireFormat(),
null
)
@@ -981,68 +979,6 @@
}
@Test
- fun maybeUpdateStatus_issuesCorrectApiCalls() {
- initEngine(WatchFaceType.ANALOG, emptyList(), emptyList())
-
- val bundle = Bundle().apply {
- putBoolean(Constants.STATUS_CHARGING, true)
- putBoolean(Constants.STATUS_AIRPLANE_MODE, false)
- putBoolean(Constants.STATUS_CONNECTED, true)
- putBoolean(Constants.STATUS_THEATER_MODE, false)
- putBoolean(Constants.STATUS_GPS_ACTIVE, true)
- putBoolean(Constants.STATUS_KEYGUARD_LOCKED, false)
- }
-
- val isChargingObserver = mock<Observer<Boolean>>()
- val inAirplaneModeObserver = mock<Observer<Boolean>>()
- val isConnectedToCompanionObserver = mock<Observer<Boolean>>()
- val isInTheaterModeObserver = mock<Observer<Boolean>>()
- val isGpsActiveObserver = mock<Observer<Boolean>>()
- val isKeyguardLockedObserver = mock<Observer<Boolean>>()
- watchState.isCharging.addObserver(isChargingObserver)
- watchState.inAirplaneMode.addObserver(inAirplaneModeObserver)
- watchState.isConnectedToCompanion.addObserver(isConnectedToCompanionObserver)
- watchState.isInTheaterMode.addObserver(isInTheaterModeObserver)
- watchState.isGpsActive.addObserver(isGpsActiveObserver)
- watchState.isKeyguardLocked.addObserver(isKeyguardLockedObserver)
-
- // Every indicator onXyz method should be called upon the initial update.
- engineWrapper.onBackgroundAction(
- Bundle().apply {
- putBundle(Constants.EXTRA_INDICATOR_STATUS, bundle)
- }
- )
-
- verify(isChargingObserver).onChanged(true)
- verify(inAirplaneModeObserver).onChanged(false)
- verify(isConnectedToCompanionObserver).onChanged(true)
- verify(isInTheaterModeObserver).onChanged(false)
- verify(isGpsActiveObserver).onChanged(true)
- verify(isKeyguardLockedObserver).onChanged(false)
-
- reset(isChargingObserver)
- reset(inAirplaneModeObserver)
- reset(isConnectedToCompanionObserver)
- reset(isInTheaterModeObserver)
- reset(isGpsActiveObserver)
- reset(isKeyguardLockedObserver)
-
- // Check only the modified setIsCharging state leads to a call.
- bundle.putBoolean(Constants.STATUS_CHARGING, false)
- engineWrapper.onBackgroundAction(
- Bundle().apply {
- putBundle(Constants.EXTRA_INDICATOR_STATUS, bundle)
- }
- )
- verify(isChargingObserver).onChanged(false)
- verify(inAirplaneModeObserver, times(0)).onChanged(anyBoolean())
- verify(isConnectedToCompanionObserver, times(0)).onChanged(anyBoolean())
- verify(isInTheaterModeObserver, times(0)).onChanged(anyBoolean())
- verify(isGpsActiveObserver, times(0)).onChanged(anyBoolean())
- verify(isKeyguardLockedObserver, times(0)).onChanged(anyBoolean())
- }
-
- @Test
fun wear2ImmutablePropertiesSetCorrectly() {
initEngine(WatchFaceType.ANALOG, emptyList(), emptyList(), 2, true, false)
@@ -1071,7 +1007,7 @@
false,
DeviceConfig.SCREEN_SHAPE_RECTANGULAR
),
- SystemState(false, 0, 0, 0),
+ SystemState(false, 0),
UserStyle(hashMapOf(watchHandStyleCategory to badStyleOption)).toWireFormat(),
null
)