-
Notifications
You must be signed in to change notification settings - Fork 29.8k
Allow long-press gestures to continue even if buttons change. #127877
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
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree this is a very obscure user interaction, option 1 did sound reasonable to me and it looks like we do something similar by handling down (accepted) -> cancel in TapGestureRecognizer.
flutter/packages/flutter/lib/src/gestures/tap.dart
Lines 257 to 268 in f92f441
| @override | |
| void resolve(GestureDisposition disposition) { | |
| if (_wonArenaForPrimaryPointer && disposition == GestureDisposition.rejected) { | |
| // This can happen if the gesture has been canceled. For example, when | |
| // the pointer has exceeded the touch slop, the buttons have been changed, | |
| // or if the recognizer is disposed. | |
| assert(_sentTapDown); | |
| _checkCancel(null, 'spontaneous'); | |
| _reset(); | |
| } | |
| super.resolve(disposition); | |
| } |
But I agree with the point that it wouldn't fix current users. I wonder if in the future we want to provide the
buttons in the gesture details object so a user could potentially handle this use-case by checking if the initial down buttons are the same as the end buttons.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From testing on macOS, after this first move4, when releasing the primary button, another move event is dispatched with the buttons set as 2.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This might be outside of the scope of this PR, but when testing on macOS and web with a local example app the buttons of this final PointerUpEvent is actually 0. Is this expected?
|
Can you elaborate on what you're seeing on macOS? In general I would hope that we normalize our inputs so the same physical inputs turn into the same events at the Flutter level but that may be optimistic. I'm happy to add tests for other sequences, to make sure they all make sense. Is that what you had in mind? |
|
Using this example app with the change in this PR. import 'package:flutter/material.dart';
void main() {
runApp(const MainApp());
}
class MainApp extends StatelessWidget {
const MainApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: Center(
child: GestureDetector(
onLongPressStart: (LongPressStartDetails details) {
debugPrint('start');
},
onLongPressMoveUpdate: (LongPressMoveUpdateDetails details) {
debugPrint('move');
},
onLongPressEnd: (LongPressEndDetails details) {
debugPrint('end');
},
child: Container(
color: Colors.green,
height: 200,
width: 200,
child: const Text('Hello World!'),
),
),
),
),
);
}
}and adding some logging in For the following click sequence.
This is what I see in the logs for macOS native/and macOS chrome. I was more or less wondering if we should test that extra |
|
I can add some tests that check that sequence and others, sure. |
Previously, if you changed buttons during a long-press gesture, if it was before the gesture was accepted we would discard it, and if it was after the gesture was accepted we would silently end it without firing any of the relevant events. This silent cancelation behavior is terrible because it means there's no way for consumers to know what state they're in, so you end up with widgets that thing they're still being long-pressed even though nothing is happening. We could change the behavior in three ways, as far as I can tell: - we could send a cancel event when you change buttons. This would introduce a new kind of transition (start->cancel) which I don't think we currently require people to support. This would therefore not fix existing code and would make future code more complicated to handle a really obscure user action that it seems unlikely anyone cares about. - we could send an end event when you change buttons. This would mean the action commits, even though the user is still holding the mouse button down. This seems slightly better than the previous option but still not ideal as it means nudging the mouse button commits you even though you're still holding the button down. - we could ignore button changes after the long-press has been accepted. I implemented the last one in this PR.
|
@Renzo-Olivares PTAL |
Renzo-Olivares
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
|
I think the broken google testing may have been unrelated since it was having some issues around the time when this PR was approved. |
flutter/flutter@35085c3...bc49cd1 2023-07-06 ian@hixie.ch Allow long-press gestures to continue even if buttons change. (flutter/flutter#127877) 2023-07-06 goderbauer@google.com Enable unreachable_from_main lint - it is stable now!!1 (flutter/flutter#129854) 2023-07-06 ian@hixie.ch Update labeler to new label names (flutter/flutter#130040) 2023-07-05 47639380+Snonky@users.noreply.github.com MergeableMaterial: Fix adding a slice and separating it (flutter/flutter#128804) 2023-07-05 ian@hixie.ch Update infrastructure issue template for new priority scheme (flutter/flutter#129741) 2023-07-05 737941+loic-sharma@users.noreply.github.com Fix typo in canvas example (flutter/flutter#129879) 2023-07-05 hans.muller@gmail.com Reland Fix AnimatedList & AnimatedGrid doesn't apply MediaQuery padding #129556 (flutter/flutter#129860) 2023-07-05 ian@hixie.ch Change from "created via performance template" to "from: performance template" (flutter/flutter#130035) 2023-07-05 109253501+pdblasi-google@users.noreply.github.com Removes deprecated APIs from v2.6 in `binding.dart` and `widget_tester.dart` (flutter/flutter#129663) 2023-07-05 helinx@google.com Add new hot reload case string (flutter/flutter#130008) 2023-07-05 engine-flutter-autoroll@skia.org Manual roll Flutter Engine from 987b621eac4e to bd2e42b203e1 (32 revisions) (flutter/flutter#130023) 2023-07-05 69246223+moylanm@users.noreply.github.com Add simple unit tests for annotations.dart file (flutter/flutter#128902) 2023-07-05 gipcjs@gmail.com fix a bug when android uses CupertinoPageTransitionsBuilder... (flutter/flutter#114303) 2023-07-05 piotr.fleury@gmail.com Add .env file support for option `--dart-define-from-file` (flutter/flutter#128668) 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 bmparr@google.com,rmistry@google.com,stuartmorgan@google.com 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://bugs.chromium.org/p/skia/issues/entry?template=Autoroller+Bug Documentation for the AutoRoller is here: https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md
Previously, if you changed buttons during a long-press gesture, if it was before the gesture was accepted we would discard it, and if it was after the gesture was accepted we would silently end it without firing any of the relevant events.
This silent cancelation behavior is terrible because it means there's no way for consumers to know what state they're in, so you end up with widgets that thing they're still being long-pressed even though nothing is happening.
We could change the behavior in three ways, as far as I can tell:
we could send a cancel event when you change buttons. This would introduce a new kind of transition (start->cancel) which I don't think we currently require people to support. This would therefore not fix existing code and would make future code more complicated to handle a really obscure user action that it seems unlikely anyone cares about.
we could send an end event when you change buttons. This would mean the action commits, even though the user is still holding the mouse button down. This seems slightly better than the previous option but still not ideal as it means nudging the mouse button commits you even though you're still holding the button down.
we could ignore button changes after the long-press has been accepted.
I implemented the last one in this PR.