Skip to content

Conversation

chunhtai
Copy link
Contributor

@chunhtai chunhtai commented Dec 14, 2021

Support for mouse drag selection and mobile selection

#81839

design doc: http://flutter.dev/go/global-selection

Pre-launch Checklist

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

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

@flutter-dashboard flutter-dashboard bot added a: text input Entering text in a text field or keyboard related problems f: gestures flutter/packages/flutter/gestures repository. f: routes Navigator, Router, and related APIs. f: scrolling Viewports, list views, slivers, etc. framework flutter/packages/flutter repository. See also f: labels. labels Dec 14, 2021
Copy link
Member

@goderbauer goderbauer left a comment

Choose a reason for hiding this comment

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

Haven't reviewed it all, just some comments from an initial read-through.


/// Called when the selectables this widget collected has changed.
///
/// Use this method to extract the collected selectables in the subtree.
Copy link
Member

Choose a reason for hiding this comment

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

document that the selectables are given in screen order in the list?


DragSelectionStartEvent? _currentDragStart;

/// Updates the selectables this updater manages.
Copy link
Member

Choose a reason for hiding this comment

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

Document that it expects the selectables in screen order (I think?)

/// Gets the list selectables this updater is responsible for updating.
///
/// The subclasses is responsible for updating the selection when the
/// selectables in the list has changed.
Copy link
Member

Choose a reason for hiding this comment

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

document expected order?

}

/// Copies the selected contents of all the selectables.
Object? copy() {
Copy link
Member

Choose a reason for hiding this comment

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

Should this be typed String?? Seems to be the only possible return type?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It may not be the case if we support multimedia, but i guess we can change that later?


/// Initialize the selection of the selectable children.
///
/// The goal is to find which selectable child the selection starts on
Copy link
Member

Choose a reason for hiding this comment

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

missing .

@goderbauer
Copy link
Member

This looks pretty interesting. It's nice to see that we can do this without adding things to RenderObject.

What wasn't clear to me from my initial read-through is why we need SelectionResult.next/SelectionResult.previous. Why can that not just be determined based on the rect of a Selectable?

late final SelectionResult result;
if (event is DragSelectionEvent) {
if (event is DragSelectionStartEvent) {
_dragSelectionStartInGlobalCoordinate = event.offset;
Copy link
Member

@goderbauer goderbauer Dec 14, 2021

Choose a reason for hiding this comment

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

Wouldn't we want to hold on to the start point in local coordinates und use that for the calculations in _updateDragSelection?

I am thinking about a scenario where you start the selection with a pointer down in a large body of text and while the pointer is down you scroll a surrounding scrollable. I think that scroll needs to extend the selection and the selection needs to start at the letter that the pointer touched when it cam down first. Due to the scroll, that letter will have moved in the global coordinate system, though.

/// should start before all of its children. Returns [SelectionResult.next]
/// if the selection should start after all of its children.
SelectionResult _initSelection(DragSelectionUpdateEvent event) {
for (int index = 0; index < selectables.length; index += 1){
Copy link
Member

Choose a reason for hiding this comment

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

nit: space before {

@chunhtai
Copy link
Contributor Author

chunhtai commented Dec 14, 2021

This looks pretty interesting. It's nice to see that we can do this without adding things to RenderObject.

What wasn't clear to me from my initial read-through is why we need SelectionResult.next/SelectionResult.previous. Why can that not just be determined based on the rect of a Selectable?

The biggest concern is select to scroll. Imagine a container with 3 child [A, B, C]. If B is scrollable and the drag selection goes to C, IMO we can't send update event to C until B finishes scrolling. We can also makes B returns some kind of flag to tell the container not to proceed and get rid of SelectionResult, but I think the current implementation is more systematic since there maybe more cases where selectable itself has opinion on the selection order.

The other concern is keyboard selection. Imagine developer press shit+ down, how does the container know which selectable should be the new selection edge. With SelectionResult, the selectable itself can tell the container whether the shift down should reach the next selectable or not.

@skia-gold
Copy link

Gold has detected about 1 new digest(s) on patchset 9.
View them at https://flutter-gold.skia.org/cl/github/95226

@chunhtai chunhtai force-pushed the inherited-selection branch from 1387fce to bfab82c Compare December 30, 2021 23:23
@skia-gold
Copy link

Gold has detected about 2 new digest(s) on patchset 10.
View them at https://flutter-gold.skia.org/cl/github/95226

@skia-gold
Copy link

Gold has detected about 1 new digest(s) on patchset 11.
View them at https://flutter-gold.skia.org/cl/github/95226

@skia-gold
Copy link

Gold has detected about 1 new digest(s) on patchset 12.
View them at https://flutter-gold.skia.org/cl/github/95226

@chunhtai chunhtai force-pushed the inherited-selection branch 6 times, most recently from 523b432 to 2cf4f8e Compare January 18, 2022 21:44
@chunhtai chunhtai force-pushed the inherited-selection branch 2 times, most recently from 9425c57 to 01d68b6 Compare January 26, 2022 01:03
@chunhtai chunhtai marked this pull request as ready for review January 27, 2022 01:14
@flutter-dashboard flutter-dashboard bot added the f: material design flutter/packages/flutter/material repository. label Jan 27, 2022
@chunhtai chunhtai requested a review from goderbauer January 27, 2022 01:14
@chunhtai
Copy link
Contributor Author

please ignore the failing test for now, It is because I want to hide the selection specific logic in RenderParagraph by making a private subclass of it, and it failed the describe node test. I am thinking whether there is way around it or i will have to expose the API

@chunhtai
Copy link
Contributor Author

I will add more tests. This PR now supports both mouse selection and mobile selection. I figure i may need to tear up bunch of API in Selectable to separate both them into two PR, which may make it hard to comprehend. So I keep them in the same PR.

@chunhtai
Copy link
Contributor Author

also cc @jonahwilliams

Copy link
Member

@goderbauer goderbauer left a comment

Choose a reason for hiding this comment

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

Overall this LGTM after the last few comments are addressed.

}
}
}
if (widget.registrar != null)
Copy link
Member

Choose a reason for hiding this comment

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

What if it changes from non-null to null?

Copy link
Contributor Author

@chunhtai chunhtai May 24, 2022

Choose a reason for hiding this comment

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

It will be handled in didUpdateWidget

selection = const TextSelection.collapsed(offset: 1);
break;
}
textEditingValue = TextEditingValue(text: '__', selection: selection);
Copy link
Member

Choose a reason for hiding this comment

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

Let's add some TODO comments here explaining that.

Copy link
Member

@goderbauer goderbauer left a comment

Choose a reason for hiding this comment

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

LGTM

@nilsreichardt
Copy link
Contributor

nilsreichardt commented May 24, 2022

Right clicking a word selects the word, but I think it shouldn't. In a TextField, right clicking just sets the cursor.

From #95226 (review)

@justinmc On macOS this not true for web (I don't know how Windows it handels):

Screen.Recording.2022-05-25.at.00.46.29.mov

(I used the flutter.dev website)

@justinmc
Copy link
Contributor

@nilsreichardt Good catch. I think we're doing those gestures in another PR so we'll have to get this right there.

@nilsreichardt
Copy link
Contributor

@justinmc Yes, I also opened a few issue for the SelectionArea widget which can be implemented in separated PRs 👍 My intention with the comment was the current selection behavior of SelectionArea is correct (right click and the word becomes selected) ✅

camsim99 pushed a commit to camsim99/flutter that referenced this pull request Aug 10, 2022
* Support global selection

* addressing comments

* add new test

* Addressing review comments

* update

* addressing comments

* addressing comments

* Addressing comments

* fix build
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Aug 30, 2022
engine-flutter-autoroll added a commit to engine-flutter-autoroll/plugins that referenced this pull request Aug 30, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
a: text input Entering text in a text field or keyboard related problems f: gestures flutter/packages/flutter/gestures repository. f: material design flutter/packages/flutter/material repository. f: routes Navigator, Router, and related APIs. f: scrolling Viewports, list views, slivers, etc. framework flutter/packages/flutter repository. See also f: labels.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants