-
Notifications
You must be signed in to change notification settings - Fork 6k
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
add pointer data santizing in flutter web engine #14082
Conversation
expect(packets[0].data[1].physicalY, equals(10.0)); | ||
expect(packets[0].data[1].physicalDeltaX, equals(0.0)); | ||
expect(packets[0].data[1].physicalDeltaY, equals(0.0)); | ||
// Scroll event will fire twice |
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 seeing this weird behavior which I am not sure it is by design or not. glassPane.dispatchEvent(html.WheelEvent(..)) will actually fire two scroll event back to back to glassPaneElement listener
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.
/cc @mdebbar
Hmm, could we possibly have the pointer binding double-subscribed on the glasspane?
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 seems like the some tests do not clear the subscription in between test. It will fire more event if i ran the entire test suite
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 yes, if it's over-firing in tests, then some tests are probably not cleaning up after themselves.
@@ -15,23 +15,17 @@ class PointerBinding { | |||
static PointerBinding get instance => _instance; | |||
static PointerBinding _instance; | |||
|
|||
// Set of pointerIds that are added before routing hover and mouse wheel |
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 no longer need to guess whether the framework will synthesize an add or not, because it won't.
@@ -490,34 +470,6 @@ Duration _eventTimeStampToDuration(num milliseconds) { | |||
return Duration(milliseconds: ms, microseconds: micro); | |||
} | |||
|
|||
void _ensureMouseDeviceAdded(List<ui.PointerData> data, double clientX, |
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.
synthesizing logic is moved to pointer_converter.dart
Did you mean "It is now"? |
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.
@mdebbar should definitely review this. I'll have a second look at it tomorrow.
expect(packets[0].data[1].physicalY, equals(10.0)); | ||
expect(packets[0].data[1].physicalDeltaX, equals(0.0)); | ||
expect(packets[0].data[1].physicalDeltaY, equals(0.0)); | ||
// Scroll event will fire twice |
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.
/cc @mdebbar
Hmm, could we possibly have the pointer binding double-subscribed on the glasspane?
class _PointerState { | ||
_PointerState(this.x, this.y); | ||
|
||
int get pointer => _pointer; // The identifier used in framework hit test. |
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 should probably be a dartdoc comment.
_PointerState _ensureStateForPointer(ui.PointerData datum, double x, double y) { | ||
return _pointers.putIfAbsent( | ||
datum.device, | ||
() => _PointerState(x, y), |
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.
nit: indentation is off.
|
||
/// Convert the given list pointer data into a sequence of framework-compatible | ||
/// pointer data. | ||
Iterable<ui.PointerData> convert(List<ui.PointerData> data) sync* { |
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 understand that this is how the Flutter framework used to implement this. But on the web, sync*
is expensive and we try to avoid it. Are there any downsides if we change this method to mutate the data
list in-place instead of generating a new iterable? (we might also rename the method to make it clear that it mutates the list in-place).
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.
sync* is expensive everywhere, if we're doing it on dart:ui it should be removed
yield _synthesizeFrom(datum, ui.PointerChange.add); | ||
yield _synthesizeFrom(datum, ui.PointerChange.down); | ||
} | ||
assert(state.down); |
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'm probably missing something here, but it seems like this assertion always fails if alreadyAdded
is false. We could do one of two things:
- Do
state.down = true;
when we synthesizePointerChange.down
above. - Disallow
PointerChange.move
if the pointer hasn't already been added.
I'm in favor of option 2, but I'm open for discussing it further.
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.
oh I missing a state.down=true. I added this part when i was confused at #14082 (comment)
I should remove this synthesizing all together
Is this a fix for flutter/flutter#45510? |
@tvolkert yes |
} | ||
|
||
List<ui.PointerData> _convertWheelEventToPointerData( | ||
html.WheelEvent 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 moved all these helper function to baseadapter abstract class
void _addWheelEventListener(void listener(html.WheelEvent e)) { | ||
final dynamic eventOptions = js_util.newObject(); | ||
js_util.setProperty(eventOptions, 'passive', false); | ||
js_util.callMethod(PointerBinding.instance.domRenderer.glassPaneElement, |
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 is a bit confusing to me. If we will call preventDefault, why don't we just use capture = true, and then we can just use the more generic function BaseAdapter. _addEventListener?
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'm not sure I understand.
The browser by default sets passive=true
on scroll
and wheel
event listeners. So we need to explicitly set it to passive=false
to be able to call event.preventDefault()
. This is independent from capture
.
cc @ferhatb who implemented wheel 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.
If we use usecapture= true, we don't have to call event.preventDefault()?
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.
Calling event.preventDefault()
is necessary regardless of the value of useCapture
.
useCapture
controls when your listener gets called. If it's true, your listener is called before your children. If it's false, your children are called before your listener.
event.preventDefault
tells the browser to not perform the default behavior for that event (which in this case is scrolling). We want Flutter to handle the scrolling, so we prevent the browser from doing any kind of scrolling.
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 just check we can still call preventdefault if we have usecapture = true, and from the api documentation of usecapture I can't see why we dont want to use it.
The reason why I want to move away from js_util.callMethod is that i am having trouble remove the listener afterward.
I updated it so that add wheel listener goes through BaseAdapter._addEventListener as well. Let me know if I missed something.
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.
offline discussion: we have to use js interop to remove the wheel event listener (js_util.callMethod(glassPane, 'removeEventListener', ...)
).
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.
fixed
@mdebbar this is ready for re-review |
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 if LGT @mdebbar
2a12939
to
71a1504
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.
…ine#14082) (#46049) git@github.com:flutter/engine.git/compare/90e28c027c0b...3e6d6bc git log 90e28c0..3e6d6bc --first-parent --oneline 2019-12-04 47866232+chunhtai@users.noreply.github.com add pointer data santizing in flutter web engine (#14082) If this roll has caused a breakage, revert this CL and stop the roller using the controls here: https://autoroll.skia.org/r/flutter-engine-flutter-autoroll Please CC chinmaygarde@google.com on the revert to ensure that a human is aware of the problem. 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/+/master/autoroll/README.md
Great! Thank you soo much @chunhtai ❤️ |
Framework moved the pointer data sanitization and metrics-related calculation to engine side.
It is now engine's responsibility to provide those metrics and clean pointer data stream.
This pr implements those calculation and sanitization in flutter web engine.
Fixes flutter/flutter#45510