Add long-press-drag cursor move support for text fields#26001
Add long-press-drag cursor move support for text fields#26001xster merged 18 commits intoflutter:masterfrom
Conversation
jslavitz
left a comment
There was a problem hiding this comment.
Looks good, mostly just comments.
There was a problem hiding this comment.
Is there a need for a sourceTimeStamp in this gesture detector?
There was a problem hiding this comment.
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.
being underengineered is intentional. :-)
https://github.com/flutter/flutter/wiki/Style-guide-for-Flutter-repo#lazy-programming
There was a problem hiding this comment.
If the touch was canceled, do you need to call onLongPressUp here?
There was a problem hiding this comment.
I don't think we're still calling 'onLongPressUp' still. Which line were you referring to?
There was a problem hiding this comment.
Would it make sense to also include the touch delta in this class?
There was a problem hiding this comment.
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.
I think these lack of new lines in the test data are bugs
There was a problem hiding this comment.
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.
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.
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.
Recognizes a long press followed by a drag, followed by an up event.
There was a problem hiding this comment.
It doesn't have to be dragged around
There was a problem hiding this comment.
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.
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.
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.
I don't understand how your comment corresponds to my question.
There was a problem hiding this comment.
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.
shouldn't this be a DragGestureRecognizer subclass?
There was a problem hiding this comment.
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.
Presumably adding the time dimension would be what you would do in the DragGestureRecognizer subclass.
There was a problem hiding this comment.
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.
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.
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.
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.
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.
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