All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.peanuuutz.fork.ui.foundation.input.PointerFocusHandler.kt Maven / Gradle / Ivy

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)
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy