-
Notifications
You must be signed in to change notification settings - Fork 29.8k
Add long-press-drag cursor move support for text fields #26001
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
jslavitz
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.
Looks good, mostly just comments.
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.
Is there a need for a sourceTimeStamp in this gesture detector?
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.
Not right now but I feel like our gesture classes are a bit relatively under-engineered for a low level API. I'm keeping it mostly consistent with the drag details which this is comparable to.
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.
being underengineered is intentional. :-)
https://github.com/flutter/flutter/wiki/Style-guide-for-Flutter-repo#lazy-programming
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.
If the touch was canceled, do you need to call onLongPressUp here?
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 don't think we're still calling 'onLongPressUp' still. Which line were you referring to?
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.
Would it make sense to also include the touch delta in this class?
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.
Did you mean something similar to DragUpdateDetails? Chatted with Hans a bit and I feel like providing absolute values is better than providing relative to relative values. It's a lot easier to go from one way to the other than the reverse.
f4575ee to
3953929
Compare
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 think these lack of new lines in the test data are bugs
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.
Did the tests start failing?
I don't think this should be changed. It looks like tests that used kThreeLines set the font size to 34, which would cause the text field to insert soft breaks at the ends of the lines.
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.
No but rather the test has always been passing by pure coincidence where we weren't actually dragging the handle in some parts of the test that tried to exercise it. Though the outcome was the same when the drag was done on the textfield behind it which scrolled nevertheless.
Looking at the existing usages of kThreeLines and kMoreThanFourLines also seem to expect that the beginning of lines match the beginnings of each test lines.
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.
triggered from => triggered by?
Not sure what this is referring to exactly. Maybe a "See also" that sheds some light on "proxied events"?
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.
ah good point. Linked
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.
Recognizes a long press followed by a drag, followed by an up event.
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.
It doesn't have to be dragged around
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.
Did the tests start failing?
I don't think this should be changed. It looks like tests that used kThreeLines set the font size to 34, which would cause the text field to insert soft breaks at the ends of the lines.
02331c0 to
10d0c4c
Compare
|
GitHub notifications is pretty wonky. @HansMuller ready for another look. |
|
@HansMuller this is ready for another look. |
| && _getDistance(event) > postAcceptSlopTolerance; | ||
|
|
||
| if (event is PointerMoveEvent && (isPreAcceptSlopPastTolerance || isPostAcceptSlopPastTolerance)) { | ||
| resolve(GestureDisposition.rejected); |
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 don't understand. If isPostAcceptSlopPastTolerance is true, then we know we've already been accepted, so what does it mean to reject it?
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 don't have a strong opinion about this. I'm mostly leaning towards not introducing more API breaks in this PR since it was the existing behaviour (whether the gesture was accepted or not). Rejecting an accepted gesture makes future events not go through, such as the up event.
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 don't understand how your comment corresponds to my question.
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.
If
isPostAcceptSlopPastToleranceis true, then we know we've already been accepted
Yes
so what does it mean to reject it?
In the existing implementation,
if (event is PointerMoveEvent && _getDistance(event) > kTouchSlop) {
resolve(GestureDisposition.rejected);causes the recognizer to stop emitting post-accept events such as the up event. I leaned towards not altering that behavior and left it in this PR though we can make that change if we feel that we have a strong reason to.
| /// | ||
| /// * [LongPressGestureRecognizer], which cancels its gesture if a drag event | ||
| /// occurs at any point during the long-press. | ||
| class LongPressDragGestureRecognizer extends PrimaryPointerGestureRecognizer { |
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.
shouldn't this be a DragGestureRecognizer subclass?
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.
The DragGestureRecognizer is unconcerned with the time dimension which is important here. Perhaps both PrimaryPointerGestureRecognizer and/or DragGestureRecognizer can be refactored to be mixins, though that would break more APIs
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.
Presumably adding the time dimension would be what you would do in the DragGestureRecognizer subclass.
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.
We could add a time component to DragGestureRecognizer or a move component to PrimaryPointerGestureRecognizer. I don't feel strongly either way. We can modify DragGestureRecognizer and have this subclass it instead if you prefer.
Ideally, the time and position components would both come in via mixins. We can also just not change either subclasses and do it here directly but we'd have to repeat that work for some of the other gestures that are coming up such as double tap drag.
HansMuller
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
Looks like there's still feedback from Ian to deal with.
|
@Hixie can you see if you have additional comments? |
|
I'm landing this to unblock follow up PRs. Let me know if you have additional comments @Hixie and I'll address them. |
| void rejectGesture(int pointer) { | ||
| void acceptGesture(int pointer) { | ||
| // Ignore state 'ready' here because that would happen if this recognizer | ||
| // won by a sweep. |
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 comment doesn't make much sense to me
| void rejectGesture(int pointer) { | ||
| if (pointer == primaryPointer | ||
| && (state == GestureRecognizerState.possible || | ||
| state == GestureRecognizerState.accepted)) { |
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 think we should assert that we're not accepted here. it doesn't make sense to reject when you're accepted.
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.
It's the existing behavior since there are no knowledge of acceptance in this class yet. We're moving a step closer in this PR but I haven't changed this behavior.
| possible, | ||
|
|
||
| /// The gesture has been definitively accepted by the recognizer. | ||
| accepted, |
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 am not convinced about adding this. I don't really understand what it gives us.
|
Sorry about not getting back promptly. In general, please don't land things until you get a clear indication from everyone who has left comments that they are happy. |
|
#28032 to revert for more discussions. |
|
Some notes from offline chat:
|
Add long press drag recognizer as a separate recognizer to the normal long press which gets canceled if moved.
Use on iOS to move cursor.
Long press drag on Android, which moves word selections rather than a collapsed cursor, will be a different PR.
Fixes #20693.
Is API breaking since it adds a new GestureRecognizerState enum though I doubt anyone uses it.
Left #26394 for Android