DelayUpEvent.kt
/*
* 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.gesture.customevents
import androidx.compose.ui.gesture.DoubleTapGestureFilter
import androidx.compose.ui.gesture.TapGestureFilter
import androidx.compose.ui.input.pointer.CustomEvent
import androidx.compose.ui.input.pointer.PointerId
import androidx.compose.ui.input.pointer.PointerInputFilter
/**
* Dispatched by a [PointerInputFilter] when it wants other [PointerInputFilter]s to delay
* "responding to up events" (calling callbacks because, for example, a finger lifted off of the
* screen).
*
* Senders and receivers of this message must follow a strict contract such that disambiguation
* between multiple [PointerInputFilter]s in regards tapping multiple times works correctly and
* only one responds correctly at a time. See [DelayUpMessage] for details.
*
* Note: This system and contract currently only works to disambiguate between
* [DoubleTapGestureFilter] and [TapGestureFilter]. Further multiple tap has not yet been
* implemented.
*
* @param message The [DelayUpMessage] being sent.
* @param pointers The pointers whose up events are being requested to be delayed.
*/
@Suppress("EqualsOrHashCode")
data class DelayUpEvent(var message: DelayUpMessage, val pointers: Set<PointerId>) : CustomEvent {
// Only generating hash code with immutable property.
override fun hashCode(): Int {
return pointers.hashCode()
}
}
/**
* The types of messages that can be dispatched.
*/
enum class DelayUpMessage {
/**
* Reports that future "up events" should not result in any normally related callbacks at
* this time.
*
* When a [PointerInputFilter] dispatches this message, it must later dispatch
* [DelayedUpConsumed] or [DelayedUpNotConsumed], even when it is about to be removed from
* the hierarchy.
*
* As an example of how this works in practice. When a [DoubleTapGestureFilter] sees the
* last finger leave the screen, it dispatches this message. When [TapGestureFilter]
* receives this message, it knows not to fire its [TapGestureFilter.onTap] callback when it
* later also sees the last finger leave the screen.
*/
DelayUp,
/**
* Reports that previously delayed "up events" have been consumed by another
* [PointerInputFilter] and thus the receiving [PointerInputFilter] should not fire any
* associated callbacks.
*
* When this message is received, the delaying relationship is concluded and the next message
* that can be sent is [DelayUp].
*
* Continuing the example above, if a new finger "touches" the [DoubleTapGestureFilter]
* before a timer expires, [DoubleTapGestureFilter] will dispatch this message so that
* [TapGestureFilter] knows to stop waiting to possibly call [TapGestureFilter.onTap].
*/
DelayedUpConsumed,
/**
* Reports that a receiver can now respond to previously delayed up events.
*
* If a receiver does so, they must change the message to DelayedUpConsumed so that when the
* associated [DelayUpEvent] is dispatched to other future [PointerInputFilter]s, they don't
* also respond to the delayed event.
*
* When this message is received, the delaying relationship is concluded and the next message
* that can be sent is [DelayUp].
*
* Continuing the example above, if a timer expires before a new finger "touches" the
* [DoubleTapGestureFilter], it will dispatch this message such that [TapGestureFilter] will
* know it can fire its [TapGestureFilter.onTap] callback. When it does so, it should change
* the message to [DelayedUpConsumed] so that any other possible [PointerInputFilter]s will
* not fire their callbacks associated with the "up" event.
*/
DelayedUpNotConsumed
}