这是indexloc提供的服务,不要输入任何密码
Skip to content

MouseRegion enter/exit event can be triggered with button pressed #81148

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Apr 30, 2021

Conversation

xu-baolin
Copy link
Member

Fixes #69458
Fixes #80942

The doc says that event can be triggered with or without buttons pressed:

  /// Triggered when a mouse pointer has entered this widget.
  ///
  /// This callback is triggered when the pointer, with or without buttons
  /// pressed, has started to be contained by the region of this widget. More
  /// specifically, the callback is triggered by the following cases:

Code Sample

  testWidgets('onEnter and onExit can be triggered with mouse buttons pressed', (WidgetTester tester) async {
    PointerEnterEvent? enter;
    PointerExitEvent? exit;
    await tester.pumpWidget(Center(
      child: MouseRegion(
        child: Container(
          color: const Color.fromARGB(0xff, 0xff, 0x00, 0x00),
          width: 100.0,
          height: 100.0,
        ),
        onEnter: (PointerEnterEvent details) => enter = details,
        onExit: (PointerExitEvent details) => exit = details,
      ),
    ));

    final TestGesture gesture = await tester.createGesture(kind: PointerDeviceKind.mouse, buttons: kPrimaryMouseButton);
    await gesture.addPointer(location: Offset.zero);
    await gesture.down(Offset.zero); // Press the mouse button.
    addTearDown(gesture.removePointer);
    await tester.pump();
    enter = null;
    exit = null;
    // Trigger the enter event.
    await gesture.moveTo(const Offset(400.0, 300.0));
    expect(enter, isNotNull);
    expect(enter!.position, equals(const Offset(400.0, 300.0)));
    expect(enter!.localPosition, equals(const Offset(50.0, 50.0)));
    expect(exit, isNull);

    // Trigger the exit event.
    await gesture.moveTo(const Offset(1.0, 1.0));
    expect(exit, isNotNull);
    expect(exit!.position, equals(const Offset(1.0, 1.0)));
    expect(exit!.localPosition, equals(const Offset(-349.0, -249.0)));
  });

@flutter-dashboard flutter-dashboard bot added the framework flutter/packages/flutter repository. See also f: labels. label Apr 25, 2021
@google-cla google-cla bot added the cla: yes label Apr 25, 2021
// the pointer went down, rather than do hit detection each time we get
// such an event.
hitTestResult = _hitTests[event.pointer];
if (event.kind == PointerDeviceKind.mouse) {
Copy link
Member Author

@xu-baolin xu-baolin Apr 25, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, I want to replace all the logic with this, but I can't fully evaluate the impact, so I limit the changes to mouse operations.

    } else if (event.down) {
      assert(_hitTests.containsKey(event.pointer));
      hitTestResult = HitTestResult();
      hitTest(hitTestResult, event.position);
      _hitTests[event.pointer] = hitTestResult;
    }

@xu-baolin xu-baolin requested review from goderbauer and removed request for gspencergoog April 28, 2021 05:43
@dkwingsmt
Copy link
Contributor

dkwingsmt commented Apr 28, 2021

Thanks for the fix, although I don't think this is the best way to fix it. You changed to whom the Move events are dispatched to fix enter/exit. In the current event model, the hover/down/up/move events are independent from enter/exit. The root cause of this problem is how the target annotation for MouseTracker are calculated.

My proposal is to change RenderingBinding.dispatchEvent to:

  @override // from GestureBinding
  void dispatchEvent(PointerEvent event, HitTestResult? hitTestResult) {
    if (hitTestResult != null ||
        event is PointerAddedEvent ||
        event is PointerRemovedEvent) {
      assert(event.position != null);
      _mouseTracker!.updateWithEvent(event, () =>
        (event.down || hitTestResult == null) ? renderView.hitTestMouseTrackers(event.position) : hitTestResult
      );
    }
    super.dispatchEvent(event, hitTestResult);
  }

(Feel free to incorporate this change to your PR if you agree :) Although a little more comment to explain would be preferrable.)

Copy link
Contributor

@dkwingsmt dkwingsmt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@fluttergithubbot fluttergithubbot merged commit ace61f0 into flutter:master Apr 30, 2021
dkwingsmt added a commit that referenced this pull request Apr 30, 2021
dkwingsmt added a commit that referenced this pull request Apr 30, 2021
@ToyWalrus
Copy link

Just curious, what caused this PR to be reverted?

@xu-baolin
Copy link
Member Author

Just curious, what caused this PR to be reverted?

Still investigating, we will try to reland this ASAP.

dkwingsmt added a commit to dkwingsmt/flutter that referenced this pull request May 24, 2021
dkwingsmt added a commit that referenced this pull request Jun 12, 2021
…ssed (#83253)

* Revert "Revert "MouseRegion enter/exit event can be triggered with button pressed (#81148)" (#81557)"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
framework flutter/packages/flutter repository. See also f: labels.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

MouseRegion rebuilds every time when the pointer does not tap up MouseRegion does not behave properly while dragging a Draggable over a MouseRegion
4 participants