Multi-touch & gestes
Lisez les gestes trackpad et tactiles du backend Tao via les pointer events Compose, ou via le flux de gestes brut.
Le backend Tao relaie le flux de gestes du système vers les pointer events Compose : les
pincements, rotations et scrolls trackpad atteignent votre UI via les APIs d'entrée Compose
standard. Quand vous avez besoin des données de geste non traitées, TaoWindow expose aussi le
flux trackpad brut.
Ajouter la dépendance
La prise en charge des gestes est incluse dans le backend Tao. Aucun artefact supplémentaire n'est nécessaire.
dependencies {
implementation("dev.nucleusframework:nucleus.decorated-window-tao:2.0.7")
}Lire les gestes depuis Compose
La plupart du traitement des gestes passe par Compose. Les entrées trackpad et tactiles
arrivent sous forme de PointerInputChange ; detectTransformGestures et les autres modifiers
d'entrée fonctionnent donc sans code spécifique à Tao :
import androidx.compose.foundation.gestures.detectTransformGestures
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.input.pointer.pointerInput
@Composable
fun ZoomCanvas() {
var scale by remember { mutableStateOf(1f) }
Box(
Modifier
.fillMaxSize()
.pointerInput(Unit) {
detectTransformGestures { _, _, zoom, _ ->
scale *= zoom
}
},
)
}Chaque PointerInputChange porte aussi la source d'entrée et la pression, ce qui vous permet de
réagir selon la manière dont l'événement a été produit :
import androidx.compose.ui.input.pointer.PointerType
Modifier.pointerInput(Unit) {
awaitPointerEventScope {
while (true) {
val change = awaitPointerEvent().changes.first()
val source = change.type // PointerType.Mouse | Touch | Stylus | Eraser
val pressure = change.pressure // 0f si le périphérique ne rapporte pas de pression
// Réagir selon source / pression.
}
}
}Lire le flux de gestes brut
Pour distinguer directement le type et la phase d'un geste — par exemple séparer un pincement
d'un scroll à deux doigts — enregistrez un TrackpadGestureListener sur le TaoWindow courant :
import dev.nucleusframework.window.tao.LocalTaoWindow
import dev.nucleusframework.window.tao.TaoTrackpadGesture
import dev.nucleusframework.window.tao.TaoTrackpadPhase
val window = LocalTaoWindow.current
window?.onTrackpadGesture { kind, phase, xFixed, yFixed, valueFixed ->
if (kind == TaoTrackpadGesture.MAGNIFY && phase == TaoTrackpadPhase.CHANGED) {
val ratio = valueFixed / 10_000f // delta de magnify sous forme de ratio
// Appliquez le delta de zoom.
}
}Le callback reçoit des entiers en virgule fixe : xFixed et yFixed sont des pixels physiques
relatifs à la vue, multipliés par 1024, et valueFixed est le delta multiplié par 10000 (un
ratio pour magnify, des degrés pour rotate).
onTrackpadGesture remplace le listener précédemment enregistré au lieu d'en ajouter un.
Enregistrez un seul listener par fenêtre.
Fonctionnement
Sur chaque plateforme, Tao s'abonne à la source de gestes native haute résolution — NSEvent
magnify et rotate sur macOS, l'entrée des touchpads de précision sur Windows, et le protocole
de gestes du pointeur Wayland sur Linux. Le pont Rust remet ces événements en forme et les livre
à la JVM via un format unique, que le scene host convertit en pointer events Compose.
Le TrackpadGestureListener brut se place sur ce même flux, avant la synthèse des pointer events.
macOS et Linux émettent magnify, rotate et smart-magnify ; Windows n'émet que magnify. Il n'existe
pas de source native sur les autres configurations, où le listener ne se déclenche donc pas.
Référence de l'API
Enregistrer un listener de gestes
// dev.nucleusframework.window.tao.TaoWindow
fun onTrackpadGesture(listener: TrackpadGestureListener)
fun interface TrackpadGestureListener {
fun onGesture(
kind: Int, // valeur TaoTrackpadGesture
phase: Int, // valeur TaoTrackpadPhase
xFixed: Int, // pixels physiques × 1024, relatifs à la vue
yFixed: Int,
valueFixed: Int, // delta × 10000 (ratio pour magnify, degrés pour rotate)
)
}Récupérez la fenêtre via LocalTaoWindow.current, qui vaut null en dehors d'une fenêtre Tao.
Constantes de gestes
object TaoTrackpadGesture {
const val MAGNIFY: Int = 0
const val ROTATE: Int = 1
const val SMART_MAGNIFY: Int = 2
}
object TaoTrackpadPhase {
const val BEGAN: Int = 0
const val CHANGED: Int = 1
const val ENDED: Int = 2
const val CANCELLED: Int = 3
}Infos pointer sur chaque changement
// androidx.compose.ui.input.pointer.PointerInputChange
val type: PointerType // Mouse | Touch | Stylus | Eraser
val pressure: Float // 0f si le périphérique ne rapporte pas de pression
val position: Offset // position sub-pixel
val scrollDelta: Offset // molette et scroll trackpadEt ensuite
- Stylet — pression et inclinaison des périphériques stylet.
- Wayland — comportement d'entrée et de fenêtrage spécifique à Linux.
- Fenêtre décorée — la fenêtre Tao et sa barre de titre.
- Backend Tao — ce que fournit le backend Tao.