feat: stylus support (#12196)

Signed-off-by: fufesou <linlong1266@gmail.com>
This commit is contained in:
fufesou
2025-07-01 13:13:41 +08:00
committed by GitHub
parent 5faf0ad3cf
commit f26d2a7b84
2 changed files with 31 additions and 20 deletions

View File

@@ -111,9 +111,13 @@ class _RawTouchGestureDetectorRegionState
); );
} }
bool isNotTouchBasedDevice() {
return !kTouchBasedDeviceKinds.contains(lastDeviceKind);
}
onTapDown(TapDownDetails d) async { onTapDown(TapDownDetails d) async {
lastDeviceKind = d.kind; lastDeviceKind = d.kind;
if (lastDeviceKind != PointerDeviceKind.touch) { if (isNotTouchBasedDevice()) {
return; return;
} }
if (handleTouch) { if (handleTouch) {
@@ -126,7 +130,7 @@ class _RawTouchGestureDetectorRegionState
onTapUp(TapUpDetails d) async { onTapUp(TapUpDetails d) async {
final TapDownDetails? lastTapDownDetails = _lastTapDownDetails; final TapDownDetails? lastTapDownDetails = _lastTapDownDetails;
_lastTapDownDetails = null; _lastTapDownDetails = null;
if (lastDeviceKind != PointerDeviceKind.touch) { if (isNotTouchBasedDevice()) {
return; return;
} }
if (handleTouch) { if (handleTouch) {
@@ -142,7 +146,7 @@ class _RawTouchGestureDetectorRegionState
} }
onTap() async { onTap() async {
if (lastDeviceKind != PointerDeviceKind.touch) { if (isNotTouchBasedDevice()) {
return; return;
} }
if (!handleTouch) { if (!handleTouch) {
@@ -153,7 +157,7 @@ class _RawTouchGestureDetectorRegionState
onDoubleTapDown(TapDownDetails d) async { onDoubleTapDown(TapDownDetails d) async {
lastDeviceKind = d.kind; lastDeviceKind = d.kind;
if (lastDeviceKind != PointerDeviceKind.touch) { if (isNotTouchBasedDevice()) {
return; return;
} }
if (handleTouch) { if (handleTouch) {
@@ -163,7 +167,7 @@ class _RawTouchGestureDetectorRegionState
} }
onDoubleTap() async { onDoubleTap() async {
if (lastDeviceKind != PointerDeviceKind.touch) { if (isNotTouchBasedDevice()) {
return; return;
} }
if (ffiModel.touchMode && ffi.cursorModel.lastIsBlocked) { if (ffiModel.touchMode && ffi.cursorModel.lastIsBlocked) {
@@ -179,7 +183,7 @@ class _RawTouchGestureDetectorRegionState
onLongPressDown(LongPressDownDetails d) async { onLongPressDown(LongPressDownDetails d) async {
lastDeviceKind = d.kind; lastDeviceKind = d.kind;
if (lastDeviceKind != PointerDeviceKind.touch) { if (isNotTouchBasedDevice()) {
return; return;
} }
if (handleTouch) { if (handleTouch) {
@@ -198,7 +202,7 @@ class _RawTouchGestureDetectorRegionState
} }
onLongPressUp() async { onLongPressUp() async {
if (lastDeviceKind != PointerDeviceKind.touch) { if (isNotTouchBasedDevice()) {
return; return;
} }
if (handleTouch) { if (handleTouch) {
@@ -208,7 +212,7 @@ class _RawTouchGestureDetectorRegionState
// for mobiles // for mobiles
onLongPress() async { onLongPress() async {
if (lastDeviceKind != PointerDeviceKind.touch) { if (isNotTouchBasedDevice()) {
return; return;
} }
if (!ffi.ffiModel.isPeerMobile) { if (!ffi.ffiModel.isPeerMobile) {
@@ -228,7 +232,7 @@ class _RawTouchGestureDetectorRegionState
} }
onLongPressMoveUpdate(LongPressMoveUpdateDetails d) async { onLongPressMoveUpdate(LongPressMoveUpdateDetails d) async {
if (!ffiModel.isPeerMobile || lastDeviceKind != PointerDeviceKind.touch) { if (!ffiModel.isPeerMobile || isNotTouchBasedDevice()) {
return; return;
} }
if (handleTouch) { if (handleTouch) {
@@ -241,7 +245,7 @@ class _RawTouchGestureDetectorRegionState
onDoubleFinerTapDown(TapDownDetails d) async { onDoubleFinerTapDown(TapDownDetails d) async {
lastDeviceKind = d.kind; lastDeviceKind = d.kind;
if (lastDeviceKind != PointerDeviceKind.touch) { if (isNotTouchBasedDevice()) {
return; return;
} }
_doubleFinerTapPosition = d.localPosition; _doubleFinerTapPosition = d.localPosition;
@@ -250,7 +254,7 @@ class _RawTouchGestureDetectorRegionState
onDoubleFinerTap(TapDownDetails d) async { onDoubleFinerTap(TapDownDetails d) async {
lastDeviceKind = d.kind; lastDeviceKind = d.kind;
if (lastDeviceKind != PointerDeviceKind.touch) { if (isNotTouchBasedDevice()) {
return; return;
} }
@@ -266,7 +270,7 @@ class _RawTouchGestureDetectorRegionState
onHoldDragStart(DragStartDetails d) async { onHoldDragStart(DragStartDetails d) async {
lastDeviceKind = d.kind; lastDeviceKind = d.kind;
if (lastDeviceKind != PointerDeviceKind.touch) { if (isNotTouchBasedDevice()) {
return; return;
} }
if (!handleTouch) { if (!handleTouch) {
@@ -275,7 +279,7 @@ class _RawTouchGestureDetectorRegionState
} }
onHoldDragUpdate(DragUpdateDetails d) async { onHoldDragUpdate(DragUpdateDetails d) async {
if (lastDeviceKind != PointerDeviceKind.touch) { if (isNotTouchBasedDevice()) {
return; return;
} }
if (!handleTouch) { if (!handleTouch) {
@@ -284,7 +288,7 @@ class _RawTouchGestureDetectorRegionState
} }
onHoldDragEnd(DragEndDetails d) async { onHoldDragEnd(DragEndDetails d) async {
if (lastDeviceKind != PointerDeviceKind.touch) { if (isNotTouchBasedDevice()) {
return; return;
} }
if (!handleTouch) { if (!handleTouch) {
@@ -296,7 +300,7 @@ class _RawTouchGestureDetectorRegionState
final TapDownDetails? lastTapDownDetails = _lastTapDownDetails; final TapDownDetails? lastTapDownDetails = _lastTapDownDetails;
_lastTapDownDetails = null; _lastTapDownDetails = null;
lastDeviceKind = d.kind ?? lastDeviceKind; lastDeviceKind = d.kind ?? lastDeviceKind;
if (lastDeviceKind != PointerDeviceKind.touch) { if (isNotTouchBasedDevice()) {
return; return;
} }
if (handleTouch) { if (handleTouch) {
@@ -342,7 +346,7 @@ class _RawTouchGestureDetectorRegionState
} }
onOneFingerPanUpdate(DragUpdateDetails d) async { onOneFingerPanUpdate(DragUpdateDetails d) async {
if (lastDeviceKind != PointerDeviceKind.touch) { if (isNotTouchBasedDevice()) {
return; return;
} }
if (ffi.cursorModel.shouldBlock(d.localPosition.dx, d.localPosition.dy)) { if (ffi.cursorModel.shouldBlock(d.localPosition.dx, d.localPosition.dy)) {
@@ -356,7 +360,7 @@ class _RawTouchGestureDetectorRegionState
onOneFingerPanEnd(DragEndDetails d) async { onOneFingerPanEnd(DragEndDetails d) async {
_touchModePanStarted = false; _touchModePanStarted = false;
if (lastDeviceKind != PointerDeviceKind.touch) { if (isNotTouchBasedDevice()) {
return; return;
} }
if (isDesktop || isWebDesktop) { if (isDesktop || isWebDesktop) {
@@ -370,13 +374,13 @@ class _RawTouchGestureDetectorRegionState
// scale + pan event // scale + pan event
onTwoFingerScaleStart(ScaleStartDetails d) { onTwoFingerScaleStart(ScaleStartDetails d) {
_lastTapDownDetails = null; _lastTapDownDetails = null;
if (lastDeviceKind != PointerDeviceKind.touch) { if (isNotTouchBasedDevice()) {
return; return;
} }
} }
onTwoFingerScaleUpdate(ScaleUpdateDetails d) async { onTwoFingerScaleUpdate(ScaleUpdateDetails d) async {
if (lastDeviceKind != PointerDeviceKind.touch) { if (isNotTouchBasedDevice()) {
return; return;
} }
if ((isDesktop || isWebDesktop)) { if ((isDesktop || isWebDesktop)) {
@@ -401,7 +405,7 @@ class _RawTouchGestureDetectorRegionState
} }
onTwoFingerScaleEnd(ScaleEndDetails d) async { onTwoFingerScaleEnd(ScaleEndDetails d) async {
if (lastDeviceKind != PointerDeviceKind.touch) { if (isNotTouchBasedDevice()) {
return; return;
} }
if ((isDesktop || isWebDesktop)) { if ((isDesktop || isWebDesktop)) {

View File

@@ -1,3 +1,4 @@
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_hbb/common.dart'; import 'package:flutter_hbb/common.dart';
import 'package:flutter_hbb/models/state_model.dart'; import 'package:flutter_hbb/models/state_model.dart';
@@ -336,6 +337,12 @@ const kRemoteImageQualityCustom = 'custom';
const kIgnoreDpi = true; const kIgnoreDpi = true;
const Set<PointerDeviceKind> kTouchBasedDeviceKinds = {
PointerDeviceKind.touch,
PointerDeviceKind.stylus,
PointerDeviceKind.invertedStylus,
};
// ================================ mobile ================================ // ================================ mobile ================================
// Magic numbers, maybe need to avoid it or use a better way to get them. // Magic numbers, maybe need to avoid it or use a better way to get them.