Skip to content

Commit a5ae18b

Browse files
authored
[web] Fix pointer events for Wacom pen (flutter#24719)
1 parent aa3bb5e commit a5ae18b

2 files changed

Lines changed: 73 additions & 15 deletions

File tree

lib/web_ui/lib/src/engine/pointer_binding.dart

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -510,7 +510,7 @@ class _PointerAdapter extends _BaseAdapter with _WheelEventListenerMixin {
510510
@override
511511
void setup() {
512512
_addPointerEventListener('pointerdown', (html.PointerEvent event) {
513-
final int device = event.pointerId!;
513+
final int device = _getPointerId(event);
514514
final List<ui.PointerData> pointerData = <ui.PointerData>[];
515515
final _ButtonSanitizer sanitizer = _ensureSanitizer(device);
516516
final _SanitizedDetails? up =
@@ -528,7 +528,7 @@ class _PointerAdapter extends _BaseAdapter with _WheelEventListenerMixin {
528528
});
529529

530530
_addPointerEventListener('pointermove', (html.PointerEvent event) {
531-
final int device = event.pointerId!;
531+
final int device = _getPointerId(event);
532532
final _ButtonSanitizer sanitizer = _ensureSanitizer(device);
533533
final List<ui.PointerData> pointerData = <ui.PointerData>[];
534534
final List<html.PointerEvent> expandedEvents = _expandEvents(event);
@@ -544,7 +544,7 @@ class _PointerAdapter extends _BaseAdapter with _WheelEventListenerMixin {
544544
}, acceptOutsideGlasspane: true);
545545

546546
_addPointerEventListener('pointerup', (html.PointerEvent event) {
547-
final int device = event.pointerId!;
547+
final int device = _getPointerId(event);
548548
final List<ui.PointerData> pointerData = <ui.PointerData>[];
549549
final _SanitizedDetails? details = _getSanitizer(device).sanitizeUpEvent(buttons: event.buttons);
550550
_removePointerIfUnhoverable(event);
@@ -557,7 +557,7 @@ class _PointerAdapter extends _BaseAdapter with _WheelEventListenerMixin {
557557
// A browser fires cancel event if it concludes the pointer will no longer
558558
// be able to generate events (example: device is deactivated)
559559
_addPointerEventListener('pointercancel', (html.PointerEvent event) {
560-
final int device = event.pointerId!;
560+
final int device = _getPointerId(event);
561561
final List<ui.PointerData> pointerData = <ui.PointerData>[];
562562
final _SanitizedDetails details = _getSanitizer(device).sanitizeCancelEvent();
563563
_removePointerIfUnhoverable(event);
@@ -581,10 +581,6 @@ class _PointerAdapter extends _BaseAdapter with _WheelEventListenerMixin {
581581
assert(event != null); // ignore: unnecessary_null_comparison
582582
assert(details != null); // ignore: unnecessary_null_comparison
583583
final ui.PointerDeviceKind kind = _pointerTypeToDeviceKind(event.pointerType!);
584-
// We force `device: _mouseDeviceId` on mouse pointers because Wheel events
585-
// might come before any PointerEvents, and since wheel events don't contain
586-
// pointerId we always assign `device: _mouseDeviceId` to them.
587-
final int device = kind == ui.PointerDeviceKind.mouse ? _mouseDeviceId : event.pointerId!;
588584
final double tilt = _computeHighestTilt(event);
589585
final Duration timeStamp = _BaseAdapter._eventTimeStampToDuration(event.timeStamp!);
590586
_pointerDataConverter.convert(
@@ -593,7 +589,7 @@ class _PointerAdapter extends _BaseAdapter with _WheelEventListenerMixin {
593589
timeStamp: timeStamp,
594590
kind: kind,
595591
signalKind: ui.PointerSignalKind.none,
596-
device: device,
592+
device: _getPointerId(event),
597593
physicalX: event.client.x.toDouble() * ui.window.devicePixelRatio,
598594
physicalY: event.client.y.toDouble() * ui.window.devicePixelRatio,
599595
buttons: details.buttons,
@@ -632,6 +628,14 @@ class _PointerAdapter extends _BaseAdapter with _WheelEventListenerMixin {
632628
}
633629
}
634630

631+
int _getPointerId(html.PointerEvent event) {
632+
// We force `device: _mouseDeviceId` on mouse pointers because Wheel events
633+
// might come before any PointerEvents, and since wheel events don't contain
634+
// pointerId we always assign `device: _mouseDeviceId` to them.
635+
final ui.PointerDeviceKind kind = _pointerTypeToDeviceKind(event.pointerType!);
636+
return kind == ui.PointerDeviceKind.mouse ? _mouseDeviceId : event.pointerId!;
637+
}
638+
635639
/// Tilt angle is -90 to + 90. Take maximum deflection and convert to radians.
636640
double _computeHighestTilt(html.PointerEvent e) =>
637641
(e.tiltX!.abs() > e.tiltY!.abs() ? e.tiltX : e.tiltY)!.toDouble() /

lib/web_ui/test/engine/pointer_binding_test.dart

Lines changed: 60 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2090,6 +2090,60 @@ void testMain() {
20902090
},
20912091
);
20922092

2093+
_testEach<_PointerEventContext>(
2094+
[
2095+
_PointerEventContext(),
2096+
],
2097+
'handles random pointer id on up events',
2098+
(_PointerEventContext context) {
2099+
PointerBinding.instance.debugOverrideDetector(context);
2100+
// This happens with pens that are simulated with mouse events
2101+
// (e.g. Wacom). It sends events with the pointer type "mouse", and
2102+
// assigns a random pointer ID to each event.
2103+
//
2104+
// For more info, see: https://github.com/flutter/flutter/issues/75559
2105+
2106+
List<ui.PointerDataPacket> packets = <ui.PointerDataPacket>[];
2107+
ui.window.onPointerDataPacket = (ui.PointerDataPacket packet) {
2108+
packets.add(packet);
2109+
};
2110+
2111+
glassPane.dispatchEvent(context.mouseDown(
2112+
pointerId: 12,
2113+
button: 0,
2114+
buttons: 1,
2115+
clientX: 10.0,
2116+
clientY: 10.0,
2117+
));
2118+
2119+
expect(packets, hasLength(1));
2120+
expect(packets.single.data, hasLength(2));
2121+
2122+
expect(packets.single.data[0].change, equals(ui.PointerChange.add));
2123+
expect(packets.single.data[0].synthesized, equals(true));
2124+
expect(packets.single.data[1].change, equals(ui.PointerChange.down));
2125+
packets.clear();
2126+
2127+
expect(
2128+
() {
2129+
glassPane.dispatchEvent(context.mouseUp(
2130+
pointerId: 41,
2131+
button: 0,
2132+
buttons: 0,
2133+
clientX: 10.0,
2134+
clientY: 10.0,
2135+
));
2136+
},
2137+
returnsNormally,
2138+
);
2139+
2140+
expect(packets, hasLength(1));
2141+
expect(packets.single.data, hasLength(1));
2142+
2143+
expect(packets.single.data[0].change, equals(ui.PointerChange.up));
2144+
},
2145+
);
2146+
20932147
// TOUCH ADAPTER
20942148

20952149
_testEach(
@@ -2537,9 +2591,9 @@ class _PointerEventContext extends _BasicEventContext
25372591

25382592
@override
25392593
html.Event mouseDown(
2540-
{double clientX, double clientY, int button, int buttons}) {
2594+
{double clientX, double clientY, int button, int buttons, int pointerId = 1}) {
25412595
return _downWithFullDetails(
2542-
pointer: 1,
2596+
pointer: pointerId,
25432597
buttons: buttons,
25442598
button: button,
25452599
clientX: clientX,
@@ -2581,9 +2635,9 @@ class _PointerEventContext extends _BasicEventContext
25812635

25822636
@override
25832637
html.Event mouseMove(
2584-
{double clientX, double clientY, int button, int buttons}) {
2638+
{double clientX, double clientY, int button, int buttons, int pointerId = 1}) {
25852639
return _moveWithFullDetails(
2586-
pointer: 1,
2640+
pointer: pointerId,
25872641
buttons: buttons,
25882642
button: button,
25892643
clientX: clientX,
@@ -2623,9 +2677,9 @@ class _PointerEventContext extends _BasicEventContext
26232677
}
26242678

26252679
@override
2626-
html.Event mouseUp({double clientX, double clientY, int button, int buttons}) {
2680+
html.Event mouseUp({double clientX, double clientY, int button, int buttons, int pointerId = 1}) {
26272681
return _upWithFullDetails(
2628-
pointer: 1,
2682+
pointer: pointerId,
26292683
button: button,
26302684
buttons: buttons,
26312685
clientX: clientX,

0 commit comments

Comments
 (0)