Skip to content

Conversation

@xster
Copy link
Member

@xster xster commented Jan 3, 2019

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

@xster xster requested review from HansMuller and jslavitz January 3, 2019 07:15
@zoechi zoechi added a: text input Entering text in a text field or keyboard related problems framework flutter/packages/flutter repository. See also f: labels. f: material design flutter/packages/flutter/material repository. f: cupertino flutter/packages/flutter/cupertino repository labels Jan 3, 2019
Copy link
Contributor

@jslavitz jslavitz left a 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.

Copy link
Contributor

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?

Copy link
Member Author

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.

Copy link
Contributor

Choose a reason for hiding this comment

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

Copy link
Contributor

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?

Copy link
Member Author

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?

Copy link
Contributor

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?

Copy link
Member Author

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.

@xster xster force-pushed the long-press-drag branch 2 times, most recently from f4575ee to 3953929 Compare January 15, 2019 09:52
Copy link
Member Author

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

Copy link
Contributor

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.

Copy link
Member Author

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.

Copy link
Contributor

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"?

Copy link
Member Author

Choose a reason for hiding this comment

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

ah good point. Linked

Copy link
Contributor

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.

Copy link
Member Author

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

Copy link
Contributor

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.

@xster
Copy link
Member Author

xster commented Jan 16, 2019

GitHub notifications is pretty wonky. @HansMuller ready for another look.

@xster
Copy link
Member Author

xster commented Feb 7, 2019

@HansMuller this is ready for another look.
@goderbauer I didn't merge the 2 long press recognizers as we talked about. Unfortunately, the existing long press recognizer's callback signature is too spartan to make use of them. Rather than breaking that API, which would be a bit more significant, I just left the newly created one.

&& _getDistance(event) > postAcceptSlopTolerance;

if (event is PointerMoveEvent && (isPreAcceptSlopPastTolerance || isPostAcceptSlopPastTolerance)) {
resolve(GestureDisposition.rejected);
Copy link
Contributor

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?

Copy link
Member Author

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.

Copy link
Contributor

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.

Copy link
Member Author

Choose a reason for hiding this comment

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

If isPostAcceptSlopPastTolerance is 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 {
Copy link
Contributor

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?

Copy link
Member Author

@xster xster Feb 7, 2019

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

Copy link
Contributor

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.

Copy link
Member Author

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.

Copy link
Contributor

@HansMuller HansMuller left a 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.

@xster
Copy link
Member Author

xster commented Feb 8, 2019

@Hixie can you see if you have additional comments?

@xster
Copy link
Member Author

xster commented Feb 12, 2019

I'm landing this to unblock follow up PRs. Let me know if you have additional comments @Hixie and I'll address them.

@xster xster merged commit 892c891 into flutter:master Feb 12, 2019
@xster xster deleted the long-press-drag branch February 12, 2019 23:10
@xster xster changed the title Add long-press-drag cursor move support on iOS Add long-press-drag cursor move support for text fields Feb 13, 2019
void rejectGesture(int pointer) {
void acceptGesture(int pointer) {
// Ignore state 'ready' here because that would happen if this recognizer
// won by a sweep.
Copy link
Contributor

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)) {
Copy link
Contributor

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.

Copy link
Member Author

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,
Copy link
Contributor

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.

@Hixie
Copy link
Contributor

Hixie commented Feb 15, 2019

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.

@xster
Copy link
Member Author

xster commented Feb 16, 2019

#28032 to revert for more discussions.

@xster
Copy link
Member Author

xster commented Feb 20, 2019

Some notes from offline chat:

  • Change the various name references to not conflate with anything from the gesture arena ("accept" and "reject") since in the gesture arena sense, the arena is done once someone accepts.
  • Rename to not have the word 'drag' in the recognizer since it's not a conventional drag gesture.
  • Consider adding new callbacks to the non-drag long press to get around not breaking APIs with existing callback signatures that don't have enough data to work with.

xster added a commit to xster/flutter that referenced this pull request Feb 21, 2019
mdebbar pushed a commit to mdebbar/flutter that referenced this pull request Feb 21, 2019
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Aug 7, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

a: text input Entering text in a text field or keyboard related problems c: API break Backwards-incompatible API changes f: cupertino flutter/packages/flutter/cupertino repository f: material design flutter/packages/flutter/material repository. framework flutter/packages/flutter repository. See also f: labels.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

It's not possible to move the cursor in a text field by dragging

6 participants