net.peanuuutz.fork.ui.foundation.input.PointerFocusHandler.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of fork-ui Show documentation
Show all versions of fork-ui Show documentation
Comprehensive API designed for Minecraft modders
The newest version!
package net.peanuuutz.fork.ui.foundation.input
import androidx.compose.runtime.Stable
import kotlinx.coroutines.isActive
import net.peanuuutz.fork.ui.ui.context.focus.FocusRequester
import net.peanuuutz.fork.ui.ui.context.pointer.MouseButton
import net.peanuuutz.fork.ui.ui.context.pointer.PointerEvent
import net.peanuuutz.fork.ui.ui.context.pointer.PointerTapEvent
import net.peanuuutz.fork.ui.ui.context.pointer.isUnconsumed
import net.peanuuutz.fork.ui.ui.modifier.Modifier
import net.peanuuutz.fork.ui.ui.modifier.ModifierNodeElement
import net.peanuuutz.fork.ui.ui.modifier.input.SuspendingPointerInputModifierNode
import net.peanuuutz.fork.ui.ui.modifier.input.filter
import net.peanuuutz.fork.ui.ui.node.BranchingModifierNode
import net.peanuuutz.fork.ui.ui.node.PointerEventPass
import net.peanuuutz.fork.ui.ui.node.PointerInputModifierNode
@Stable
fun Modifier.pointerFocusHandler(
focusRequester: FocusRequester,
isEnabled: Boolean = true
): Modifier {
if (!isEnabled) {
return this
}
return this then PointerFocusHandlerModifier(focusRequester)
}
// ======== Internal ========
private data class PointerFocusHandlerModifier(
val focusRequester: FocusRequester
) : ModifierNodeElement() {
override fun create(): PointerFocusHandlerModifierNode {
return PointerFocusHandlerModifierNode(focusRequester)
}
override fun update(node: PointerFocusHandlerModifierNode) {
node.focusRequester = focusRequester
}
}
private class PointerFocusHandlerModifierNode(
var focusRequester: FocusRequester
) : BranchingModifierNode(), PointerInputModifierNode {
private val pointerInputHandler: SuspendingPointerInputModifierNode = branch {
SuspendingPointerInputModifierNode {
receive {
while (listenerContext.isActive) {
val event = filter { event ->
event.button == MouseButton.Left &&
event.isPressed &&
event.isUnconsumed
}
if (event.isCaptured) {
focusRequester.requestFocus()
}
}
}
}
}
override fun onPointerEvent(pass: PointerEventPass, pointerEvent: PointerEvent) {
pointerInputHandler.onPointerEvent(pass, pointerEvent)
}
}