Skip to content

GestureDetector isn't added to Arena in certain situations for some reason #113177

@Lasslos

Description

@Lasslos

I am trying to make a Widget that acts like the Google Calendar Week View, a ListView that can be pinch-zoomed as soon as a second pointer enters. Therefore, I created a RawGestureDetector that is supposed to declare Victory in the Arena as soon as two or more pointers are on the screen, however, when putting down one pointer and then adding a second one, without removing the first one, the GestureDetector is not even added to the arena.
I don't know if my approach is the correct one, so I would be happy to see a suggestion why I am having this issue or how to do it differently.

Steps to Reproduce

  1. Execute flutter run on the code sample
  2. Click with one pointer and then after that, click with a second pointer leaving the first on the screen
  3. In the console you will see that the GestureArena doesnt even consider my second RawGestureDetector.

Expected results:

My RawGestureDetector declaring victory in the second arena

Actual results:

My RawGestureDetector not even added to the Arena:

I/flutter (13717): Gesture arena 8    ❙ ★ Opening new gesture arena.
I/flutter (13717): Gesture arena 8    ❙ Adding: PinchToZoomGestureRecognizer#f9b77
I/flutter (13717): Gesture arena 8    ❙ Adding: VerticalDragGestureRecognizer#07525(start behavior: start)
I/flutter (13717): Gesture arena 8    ❙ Closing with 2 members.
I/flutter (13717): Gesture arena 8    ❙ Accepting: VerticalDragGestureRecognizer#07525(start behavior: start)
I/flutter (13717): Gesture arena 8    ❙ Self-declared winner: VerticalDragGestureRecognizer#07525(start behavior: start)
D/EGL_emulation(13717): app_time_stats: avg=781.66ms min=5.34ms max=12373.45ms count=16
I/flutter (13717): Gesture arena 9    ❙ ★ Opening new gesture arena.
I/flutter (13717): Gesture arena 9    ❙ Adding: VerticalDragGestureRecognizer#07525(start behavior: start)
I/flutter (13717): Gesture arena 9    ❙ Accepting: VerticalDragGestureRecognizer#07525(start behavior: start)
I/flutter (13717): Gesture arena 9    ❙ Closing with 1 member.
I/flutter (13717): Gesture arena 9    ❙ Default winner: VerticalDragGestureRecognizer#07525(start behavior: start)
Code sample

Widget for Tests:

import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';

void main() {
  debugPrintGestureArenaDiagnostics = true;
  runApp(const MaterialApp(home: MyApp()));
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SingleChildScrollView(
        child: RawGestureDetector(
          gestures: <Type, GestureRecognizerFactory>{
            PinchToZoomGestureRecognizer: GestureRecognizerFactoryWithHandlers<
                PinchToZoomGestureRecognizer>(
                  () => PinchToZoomGestureRecognizer(
                onScaleStart: () {},
                onScaleUpdate: () {},
                onScaleEnd: () {},
              ),
                  (instance) {},
            ),
          },
          child: Container(
            width: MediaQuery.of(context).size.width,
            decoration: const BoxDecoration(
              color: Colors.blueGrey,
            ),
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.center,
              mainAxisAlignment: MainAxisAlignment.spaceEvenly,
              children: List.generate(
                100,
                (index) => Text("Item $index"),
              ),
            ),
          ),
        ),
      ),
    );
  }
}

GestureRecognizer:

class PinchToZoomGestureRecognizer extends OneSequenceGestureRecognizer {
  final void Function() onScaleStart;
  final void Function() onScaleUpdate;
  final void Function() onScaleEnd;

  PinchToZoomGestureRecognizer({
    required this.onScaleStart,
    required this.onScaleUpdate,
    required this.onScaleEnd,
  });

  @override
  String get debugDescription => '$runtimeType';

  Map<int, Offset> pointerPositionMap = {};

  @override
  void addAllowedPointer(PointerEvent event) {
    startTrackingPointer(event.pointer);
    pointerPositionMap[event.pointer] = event.position;
    if (pointerPositionMap.length >= 2) {
      resolve(GestureDisposition.accepted);
    }
  }
  @override
  void handleEvent(PointerEvent event) {
    if (event is PointerMoveEvent) {
      pointerPositionMap[event.pointer] = event.position;
      return;
    } else if (event is PointerDownEvent) {
      pointerPositionMap[event.pointer] = event.position;
    } else if (event is PointerUpEvent || event is PointerCancelEvent) {
      stopTrackingPointer(event.pointer);
      pointerPositionMap.remove(event.pointer);
    }

    if (pointerPositionMap.length >= 2) {
      resolve(GestureDisposition.accepted);
    }
  }

  @override
  void didStopTrackingLastPointer(int pointer) {
    resolve(GestureDisposition.rejected);
  }
}
flutter doctor -v
[✓] Flutter (Channel stable, 3.0.5, on Microsoft Windows [Version 10.0.19044.2006], locale de-DE)
    • Flutter version 3.0.5 at C:\Users\Laslo\flutter
    • Upstream repository https://github.com/flutter/flutter.git
    • Framework revision f1875d570e (3 months ago), 2022-07-13 11:24:16 -0700
    • Engine revision e85ea0e79c
    • Dart version 2.17.6
    • DevTools version 2.12.2

[!] Android toolchain - develop for Android devices (Android SDK version 33.0.0)
    • Android SDK at C:\Users\Laslo\AppData\Local\Android\sdk
    ✗ cmdline-tools component is missing
      Run `path/to/sdkmanager --install "cmdline-tools;latest"`
      See https://developer.android.com/studio/command-line for more details.
    ✗ Android license status unknown.
      Run `flutter doctor --android-licenses` to accept the SDK licenses.
      See https://flutter.dev/docs/get-started/install/windows#android-setup for more details.

[✓] Chrome - develop for the web
    • Chrome at C:\Program Files (x86)\Google\Chrome\Application\chrome.exe

[✗] Visual Studio - develop for Windows
    ✗ Visual Studio not installed; this is necessary for Windows development.
      Download at https://visualstudio.microsoft.com/downloads/.
      Please install the "Desktop development with C++" workload, including all of its default components

[!] Android Studio (not installed)
    • Android Studio not found; download from https://developer.android.com/studio/index.html
      (or visit https://flutter.dev/docs/get-started/install/windows#android-setup for detailed instructions).

[✓] IntelliJ IDEA Ultimate Edition (version 2022.2)
    • IntelliJ at C:\Users\Laslo\AppData\Local\JetBrains\Toolbox\apps\IDEA-U\ch-0\222.4345.14
    • Flutter plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin version 222.4167.21

[✓] VS Code (version 1.71.2)
    • VS Code at C:\Users\Laslo\AppData\Local\Programs\Microsoft VS Code
    • Flutter extension can be installed from:
      🔨 https://marketplace.visualstudio.com/items?itemName=Dart-Code.flutter

[✓] Connected device (3 available)
    • Windows (desktop) • windows • windows-x64    • Microsoft Windows [Version 10.0.19044.2006]
    • Chrome (web)      • chrome  • web-javascript • Google Chrome 105.0.5195.127
    • Edge (web)        • edge    • web-javascript • Microsoft Edge 105.0.1343.33

[✓] HTTP Host Availability
    • All required HTTP hosts are available

! Doctor found issues in 3 categories.

Metadata

Metadata

Assignees

No one assigned

    Labels

    f: gesturesflutter/packages/flutter/gestures repository.found in release: 3.3Found to occur in 3.3found in release: 3.5Found to occur in 3.5frameworkflutter/packages/flutter repository. See also f: labels.has reproducible stepsThe issue has been confirmed reproducible and is ready to work onr: invalidIssue is closed as not valid

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions