Skip to content

Conversation

@timcreatedit
Copy link
Contributor

Reopened after revert in #147658

Another test was added in the meantime to draggable_test.dart that didn't call gesture.up(). I added this call to the test and now all tests pass.


Original Description (#145647):

We changed the coordinates used to position the Draggable feedback by transforming them into the Overlays coordinate space. This has no influence on any untransformed Overlay, most Flutter apps should be not affected.
This PR fixes the positioning of the feedback in transformed context (see #145639 for before video):

Screenshot.2024-03-23.at.20.30.06.mp4

Pre-launch Checklist

If you need help, consider asking for advice on the #hackers-new channel on Discord.

@github-actions github-actions bot added the framework flutter/packages/flutter repository. See also f: labels. label May 24, 2024
@justinmc justinmc requested review from dkwingsmt and justinmc May 24, 2024 21:09
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!

Copy link
Contributor

@justinmc justinmc left a comment

Choose a reason for hiding this comment

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

LGTM 👍. Thanks for following up after the revert.

I wish we had an automated way to catch this lack of .up calls. I was just asking @polina-c about this.


// Finish gesture to release resources.
await gesture.up();
await tester.pumpAndSettle();
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit: Should this be pump? Just noticing that it's usually pump elsewhere. Same for the two new tests below.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good point, works just as well with pump! I think I just copied the three lines from the test right above the ones I added without thinking too much about it. Fixed!

@timcreatedit timcreatedit requested a review from justinmc May 28, 2024 21:57
@dkwingsmt
Copy link
Contributor

I wish we had an automated way to catch this lack of .up calls. I was just asking @polina-c about this.

When I worked on mouse we immediately add gesture.up to tear down after the startGesture. Not sure if it works here.

However a bigger problem for me is that, the error seems to be triggered by the case where the dragging widget is unmounted during a drag, which is a totally normal case. Will this case trigger error in prod? If so we should fix this case instead of avoiding them in the tests.

@dkwingsmt
Copy link
Contributor

dkwingsmt commented May 28, 2024

Ok, I've tested that this will trigger error if the root widget (which supposedly provides the overlay) is take away during the drag.

Reproduction:

  1. Apply this PR (or simply access the context during _DragAvatar.updateDrag
  void updateDrag(Offset globalPosition) {
    final RenderBox box = overlayState.context.findRenderObject()! as RenderBox;
    final Offset overlaySpaceOffset = box.globalToLocal(globalPosition);
    print(overlaySpaceOffset - dragStartPoint);
  1. Run the following app:
import 'package:flutter/material.dart';

class Main extends StatefulWidget {

  @override
  _MainState createState() => _MainState();
}

class _MainState extends State<Main> {
  bool _show = true;

  @override
  Widget build(BuildContext context) {
    return !_show ? Container() : MaterialApp(
      home: ListView(
        scrollDirection: Axis.horizontal,
        children: <Widget>[
          DragTarget<int>(
            builder: (BuildContext context, List<int?> data, List<dynamic> rejects) {
              return const Text('Target');
            },
            onAcceptWithDetails: (DragTargetDetails<int> _) {
            },
          ),
          Container(width: 400.0),
          Draggable<int>(
            data: 1,
            feedback: Text('H'),
            onDragStarted: () {
              Future<void>.delayed(Duration(seconds: 2)).then((_) {
                setState(() {
                  _show = false;
                });
              });
            },
            childWhenDragging: SizedBox(),
            axis: Axis.horizontal,
            child: Text('H'),
          ),
        ],
      ),
    );
  }
}

void main() {
  runApp(Main());
}
  1. Drag the H and hold for 2 seconds before moving

Throws error:


══╡ EXCEPTION CAUGHT BY GESTURE LIBRARY ╞═══════════════════════════════════════════════════════════
The following assertion was thrown while routing a pointer event:
This widget has been unmounted, so the State no longer has a context (and should be considered
defunct).
Consider canceling any active work during "dispose" or using the "mounted" getter to determine if
the State is still active.

When the exception was thrown, this was the stack:
#0      State.context.<anonymous closure> (package:flutter/src/widgets/framework.dart:951:9)
#1      State.context (package:flutter/src/widgets/framework.dart:957:6)
#2      _DragAvatar.updateDrag (package:flutter/src/widgets/drag_target.dart:857:40)
#3      _DragAvatar.update (package:flutter/src/widgets/drag_target.dart:839:5)
#4      MultiDragPointerState._move (package:flutter/src/gestures/multidrag.dart:100:16)
#5      MultiDragGestureRecognizer._handleEvent (package:flutter/src/gestures/multidrag.dart:267:13)
#6      PointerRouter._dispatch (package:flutter/src/gestures/pointer_router.dart:98:12)
#7      PointerRouter._dispatchEventToRoutes.<anonymous closure> (package:flutter/src/gestures/pointer_router.dart:143:9)
#8      _LinkedHashMapMixin.forEach (dart:collection-patch/compact_hash.dart:633:13)
#9      PointerRouter._dispatchEventToRoutes (package:flutter/src/gestures/pointer_router.dart:141:18)
#10     PointerRouter.route (package:flutter/src/gestures/pointer_router.dart:127:7)
#11     GestureBinding.handleEvent (package:flutter/src/gestures/binding.dart:495:19)
#12     GestureBinding.dispatchEvent (package:flutter/src/gestures/binding.dart:475:22)
#13     RendererBinding.dispatchEvent (package:flutter/src/rendering/binding.dart:450:11)
#14     GestureBinding._handlePointerEventImmediately (package:flutter/src/gestures/binding.dart:420:7)
#15     GestureBinding.handlePointerEvent (package:flutter/src/gestures/binding.dart:383:5)
#16     GestureBinding._flushPointerEventQueue (package:flutter/src/gestures/binding.dart:330:7)
#17     GestureBinding._handlePointerDataPacket (package:flutter/src/gestures/binding.dart:299:9)
#18     _invoke1 (dart:ui/hooks.dart:328:13)
#19     PlatformDispatcher._dispatchPointerDataPacket (dart:ui/platform_dispatcher.dart:442:7)
#20     _dispatchPointerDataPacket (dart:ui/hooks.dart:262:31)

router: Instance of 'PointerRouter'
route: Closure: (PointerEvent) => void from Function '_handleEvent@171470698':.
event: PointerMoveEvent#dc09b(position: Offset(379.5, 32.1))
════════════════════════════════════════════════════════════════════════════════════════════════════

Another exception was thrown: This widget has been unmounted, so the State no longer has a context (and should be considered defunct). 

We should probably fix this error instead of patching the tests.

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.

See comment

@timcreatedit
Copy link
Contributor Author

Thanks for finding this, that's very insightful. As I mentioned on the other PR it didn't quite sit right with me that the test failures were triggered by the changes. I will take a look at this again!

@timcreatedit
Copy link
Contributor Author

@dkwingsmt I added a new test that verifies the behaviour you found when unmounting, and added a mounted check to the context access in _DragAvatar.updateDrag. Now the test passes. Do you want me to revert the changes I made to other tests, or do we still want to finish the gestures there? I reckon since unmounting is now covered by a test, we might as well leave it in?

Thanks again for your help!

@timcreatedit timcreatedit requested a review from dkwingsmt June 12, 2024 08:45
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, thanks for working on this!

@dkwingsmt
Copy link
Contributor

I would prefer removing the gesture.ups in existing tests since they are unneeded changes (for the PR) and unneeded lines (for the tests), but I'm not strong on this.

Awesome test for the graceful unmounting, BTW!

Copy link
Contributor

@justinmc justinmc left a comment

Choose a reason for hiding this comment

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

LGTM, but see the analyzer failure.

@timcreatedit timcreatedit force-pushed the draggable-feedback-positioning branch from 01ab09b to 5d331e1 Compare June 19, 2024 13:28
@timcreatedit
Copy link
Contributor Author

I would prefer removing the gesture.ups in existing tests since they are unneeded changes (for the PR) and unneeded lines (for the tests), but I'm not strong on this.

Awesome test for the graceful unmounting, BTW!

Removed them all! Thanks :)

@timcreatedit
Copy link
Contributor Author

LGTM, but see the analyzer failure.

@justinmc Ready, it's all green 🌿

@timcreatedit
Copy link
Contributor Author

@dkwingsmt @justinmc Just wanted to touch base again, is there anything you still need from me?

@dkwingsmt dkwingsmt merged commit f5b671a into flutter:master Jun 28, 2024
@dkwingsmt
Copy link
Contributor

Nope. Here we go! Thanks for the work!

engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Jun 28, 2024
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Jun 28, 2024
auto-submit bot pushed a commit to flutter/packages that referenced this pull request Jun 29, 2024
Manual roll requested by [email protected]

flutter/flutter@15f95ce...651a17d

2024-06-28 [email protected] Roll Flutter Engine from a78f5ce743ce to 2f7e9ab27493 (11 revisions) (flutter/flutter#151002)
2024-06-28 [email protected] Draggable feedback positioning (flutter/flutter#149040)
2024-06-28 [email protected] Add support for type-safe plugin apply (flutter/flutter#150958)
2024-06-28 [email protected] Use caret syntax with flutter create command (flutter/flutter#150920)
2024-06-28 [email protected] Roll Packages from 03f5f6d to 412ec46 (12 revisions) (flutter/flutter#150985)
2024-06-28 [email protected] [flutter_tools] Include more details in structured errors sent to a DAP client (flutter/flutter#150698)
2024-06-28 [email protected] Roll Flutter Engine from 94591ffb20df to a78f5ce743ce (1 revision) (flutter/flutter#150972)

If this roll has caused a breakage, revert this CL and stop the roller
using the controls here:
https://autoroll.skia.org/r/flutter-packages
Please CC [email protected],[email protected],[email protected] on the revert to ensure that a human
is aware of the problem.

To file a bug in Packages: https://github.com/flutter/flutter/issues/new/choose

To report a problem with the AutoRoller itself, please file a bug:
https://issues.skia.org/issues/new?component=1389291&template=1850622

Documentation for the AutoRoller is here:
https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md
@polina-c polina-c mentioned this pull request Jul 1, 2024
victorsanni pushed a commit to victorsanni/flutter that referenced this pull request Jul 8, 2024
Reopened after revert in flutter#147658

Another test was added in the meantime to `draggable_test.dart` that
didn't call `gesture.up()`. I added this call to the test and now all
tests pass.

---
# Original Description (flutter#145647):
We changed the coordinates used to position the `Draggable` feedback by
transforming them into the `Overlay`s coordinate space. This has no
influence on any untransformed `Overlay`, most Flutter apps should be
not affected.
This PR fixes the positioning of the feedback in transformed context
(see flutter#145639 for before video):


https://github.com/flutter/flutter/assets/42270125/df34e198-0667-453d-a27a-a79b2e2825a1

- fixes flutter#145639 

## Pre-launch Checklist

- [X] I read the [Contributor Guide] and followed the process outlined
there for submitting PRs.
- [X] I read the [Tree Hygiene] wiki page, which explains my
responsibilities.
- [X] I read and followed the [Flutter Style Guide], including [Features
we expect every widget to implement].
- [X] I signed the [CLA].
- [X] I listed at least one issue that this PR fixes in the description
above.
- [x] I updated/added relevant documentation (doc comments with `///`).
- [x] I added new tests to check the change I am making, or this PR is
[test-exempt].
- [x] I followed the [breaking change policy] and added [Data Driven
Fixes] where supported.
- [x] All existing and new tests are passing.

If you need help, consider asking for advice on the #hackers-new channel
on [Discord].

<!-- Links -->
[Contributor Guide]:
https://github.com/flutter/flutter/wiki/Tree-hygiene#overview
[Tree Hygiene]: https://github.com/flutter/flutter/wiki/Tree-hygiene
[test-exempt]:
https://github.com/flutter/flutter/wiki/Tree-hygiene#tests
[Flutter Style Guide]:
https://github.com/flutter/flutter/wiki/Style-guide-for-Flutter-repo
[Features we expect every widget to implement]:
https://github.com/flutter/flutter/wiki/Style-guide-for-Flutter-repo#features-we-expect-every-widget-to-implement
[CLA]: https://cla.developers.google.com/
[flutter/tests]: https://github.com/flutter/tests
[breaking change policy]:
https://github.com/flutter/flutter/wiki/Tree-hygiene#handling-breaking-changes
[Discord]: https://github.com/flutter/flutter/wiki/Chat
[Data Driven Fixes]:
https://github.com/flutter/flutter/wiki/Data-driven-Fixes

---------

Co-authored-by: Jesper Bellenbaum <[email protected]>
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Aug 6, 2024
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.

Draggable Feedback is positioned incorrectly when the Overlay is scaled

4 participants