Add viewId to PointerEvents (#128287)
Follow-up to https://github.com/flutter/engine/pull/42493.
This commit is contained in:
parent
31e3ae89db
commit
cff67336d0
@ -288,7 +288,7 @@ mixin GestureBinding on BindingBase implements HitTestable, HitTestDispatcher, H
|
||||
// We convert pointer data to logical pixels so that e.g. the touch slop can be
|
||||
// defined in a device-independent manner.
|
||||
try {
|
||||
_pendingPointerEvents.addAll(PointerEventConverter.expand(packet.data, platformDispatcher.implicitView!.devicePixelRatio));
|
||||
_pendingPointerEvents.addAll(PointerEventConverter.expand(packet.data, _devicePixelRatioForView));
|
||||
if (!locked) {
|
||||
_flushPointerEventQueue();
|
||||
}
|
||||
@ -302,6 +302,10 @@ mixin GestureBinding on BindingBase implements HitTestable, HitTestDispatcher, H
|
||||
}
|
||||
}
|
||||
|
||||
double? _devicePixelRatioForView(int viewId) {
|
||||
return platformDispatcher.view(id: viewId)?.devicePixelRatio;
|
||||
}
|
||||
|
||||
/// Dispatch a [PointerCancelEvent] for the given pointer soon.
|
||||
///
|
||||
/// The pointer event will be dispatched before the next pointer event and
|
||||
@ -368,7 +372,7 @@ mixin GestureBinding on BindingBase implements HitTestable, HitTestDispatcher, H
|
||||
if (event is PointerDownEvent || event is PointerSignalEvent || event is PointerHoverEvent || event is PointerPanZoomStartEvent) {
|
||||
assert(!_hitTests.containsKey(event.pointer), 'Pointer of ${event.toString(minLevel: DiagnosticLevel.debug)} unexpectedly has a HitTestResult associated with it.');
|
||||
hitTestResult = HitTestResult();
|
||||
hitTest(hitTestResult, event.position);
|
||||
hitTestInView(hitTestResult, event.position, event.viewId);
|
||||
if (event is PointerDownEvent || event is PointerPanZoomStartEvent) {
|
||||
_hitTests[event.pointer] = hitTestResult;
|
||||
}
|
||||
@ -401,12 +405,22 @@ mixin GestureBinding on BindingBase implements HitTestable, HitTestDispatcher, H
|
||||
}
|
||||
}
|
||||
|
||||
/// Determine which [HitTestTarget] objects are located at a given position.
|
||||
/// Determine which [HitTestTarget] objects are located at a given position in
|
||||
/// the specified view.
|
||||
@override // from HitTestable
|
||||
void hitTest(HitTestResult result, Offset position) {
|
||||
void hitTestInView(HitTestResult result, Offset position, int viewId) {
|
||||
result.add(HitTestEntry(this));
|
||||
}
|
||||
|
||||
@override // from HitTestable
|
||||
@Deprecated(
|
||||
'Use hitTestInView and specify the view to hit test. '
|
||||
'This feature was deprecated after v3.11.0-20.0.pre.',
|
||||
)
|
||||
void hitTest(HitTestResult result, Offset position) {
|
||||
hitTestInView(result, position, platformDispatcher.implicitView!.viewId);
|
||||
}
|
||||
|
||||
/// Dispatch an event to [pointerRouter] and the path of a hit test result.
|
||||
///
|
||||
/// The `event` is routed to [pointerRouter]. If the `hitTestResult` is not
|
||||
|
@ -32,6 +32,18 @@ int _synthesiseDownButtons(int buttons, PointerDeviceKind kind) {
|
||||
}
|
||||
}
|
||||
|
||||
/// Signature for a callback that returns the device pixel ratio of a
|
||||
/// [FlutterView] identified by the provided `viewId`.
|
||||
///
|
||||
/// Returns null if no view with the provided ID exists.
|
||||
///
|
||||
/// Used by [PointerEventConverter.expand].
|
||||
///
|
||||
/// See also:
|
||||
///
|
||||
/// * [FlutterView.devicePixelRatio] for an explanation of device pixel ratio.
|
||||
typedef DevicePixelRatioGetter = double? Function(int viewId);
|
||||
|
||||
/// Converts from engine pointer data to framework pointer events.
|
||||
///
|
||||
/// This takes [PointerDataPacket] objects, as received from the engine via
|
||||
@ -45,10 +57,15 @@ abstract final class PointerEventConverter {
|
||||
/// [dart:ui.FlutterView.devicePixelRatio]) is used to convert the incoming data
|
||||
/// from physical coordinates to logical pixels. See the discussion at
|
||||
/// [PointerEvent] for more details on the [PointerEvent] coordinate space.
|
||||
static Iterable<PointerEvent> expand(Iterable<ui.PointerData> data, double devicePixelRatio) {
|
||||
static Iterable<PointerEvent> expand(Iterable<ui.PointerData> data, DevicePixelRatioGetter devicePixelRatioForView) {
|
||||
return data
|
||||
.where((ui.PointerData datum) => datum.signalKind != ui.PointerSignalKind.unknown)
|
||||
.map<PointerEvent?>((ui.PointerData datum) {
|
||||
final double? devicePixelRatio = devicePixelRatioForView(datum.viewId);
|
||||
if (devicePixelRatio == null) {
|
||||
// View doesn't exist anymore.
|
||||
return null;
|
||||
}
|
||||
final Offset position = Offset(datum.physicalX, datum.physicalY) / devicePixelRatio;
|
||||
final Offset delta = Offset(datum.physicalDeltaX, datum.physicalDeltaY) / devicePixelRatio;
|
||||
final double radiusMinor = _toLogicalPixels(datum.radiusMinor, devicePixelRatio);
|
||||
@ -62,6 +79,7 @@ abstract final class PointerEventConverter {
|
||||
switch (datum.change) {
|
||||
case ui.PointerChange.add:
|
||||
return PointerAddedEvent(
|
||||
viewId: datum.viewId,
|
||||
timeStamp: timeStamp,
|
||||
kind: kind,
|
||||
device: datum.device,
|
||||
@ -79,6 +97,7 @@ abstract final class PointerEventConverter {
|
||||
);
|
||||
case ui.PointerChange.hover:
|
||||
return PointerHoverEvent(
|
||||
viewId: datum.viewId,
|
||||
timeStamp: timeStamp,
|
||||
kind: kind,
|
||||
device: datum.device,
|
||||
@ -102,6 +121,7 @@ abstract final class PointerEventConverter {
|
||||
);
|
||||
case ui.PointerChange.down:
|
||||
return PointerDownEvent(
|
||||
viewId: datum.viewId,
|
||||
timeStamp: timeStamp,
|
||||
pointer: datum.pointerIdentifier,
|
||||
kind: kind,
|
||||
@ -124,6 +144,7 @@ abstract final class PointerEventConverter {
|
||||
);
|
||||
case ui.PointerChange.move:
|
||||
return PointerMoveEvent(
|
||||
viewId: datum.viewId,
|
||||
timeStamp: timeStamp,
|
||||
pointer: datum.pointerIdentifier,
|
||||
kind: kind,
|
||||
@ -149,6 +170,7 @@ abstract final class PointerEventConverter {
|
||||
);
|
||||
case ui.PointerChange.up:
|
||||
return PointerUpEvent(
|
||||
viewId: datum.viewId,
|
||||
timeStamp: timeStamp,
|
||||
pointer: datum.pointerIdentifier,
|
||||
kind: kind,
|
||||
@ -172,6 +194,7 @@ abstract final class PointerEventConverter {
|
||||
);
|
||||
case ui.PointerChange.cancel:
|
||||
return PointerCancelEvent(
|
||||
viewId: datum.viewId,
|
||||
timeStamp: timeStamp,
|
||||
pointer: datum.pointerIdentifier,
|
||||
kind: kind,
|
||||
@ -194,6 +217,7 @@ abstract final class PointerEventConverter {
|
||||
);
|
||||
case ui.PointerChange.remove:
|
||||
return PointerRemovedEvent(
|
||||
viewId: datum.viewId,
|
||||
timeStamp: timeStamp,
|
||||
kind: kind,
|
||||
device: datum.device,
|
||||
@ -208,6 +232,7 @@ abstract final class PointerEventConverter {
|
||||
);
|
||||
case ui.PointerChange.panZoomStart:
|
||||
return PointerPanZoomStartEvent(
|
||||
viewId: datum.viewId,
|
||||
timeStamp: timeStamp,
|
||||
pointer: datum.pointerIdentifier,
|
||||
device: datum.device,
|
||||
@ -221,6 +246,7 @@ abstract final class PointerEventConverter {
|
||||
final Offset panDelta =
|
||||
Offset(datum.panDeltaX, datum.panDeltaY) / devicePixelRatio;
|
||||
return PointerPanZoomUpdateEvent(
|
||||
viewId: datum.viewId,
|
||||
timeStamp: timeStamp,
|
||||
pointer: datum.pointerIdentifier,
|
||||
device: datum.device,
|
||||
@ -234,6 +260,7 @@ abstract final class PointerEventConverter {
|
||||
);
|
||||
case ui.PointerChange.panZoomEnd:
|
||||
return PointerPanZoomEndEvent(
|
||||
viewId: datum.viewId,
|
||||
timeStamp: timeStamp,
|
||||
pointer: datum.pointerIdentifier,
|
||||
device: datum.device,
|
||||
@ -249,6 +276,7 @@ abstract final class PointerEventConverter {
|
||||
final Offset scrollDelta =
|
||||
Offset(datum.scrollDeltaX, datum.scrollDeltaY) / devicePixelRatio;
|
||||
return PointerScrollEvent(
|
||||
viewId: datum.viewId,
|
||||
timeStamp: timeStamp,
|
||||
kind: kind,
|
||||
device: datum.device,
|
||||
@ -258,6 +286,7 @@ abstract final class PointerEventConverter {
|
||||
);
|
||||
case ui.PointerSignalKind.scrollInertiaCancel:
|
||||
return PointerScrollInertiaCancelEvent(
|
||||
viewId: datum.viewId,
|
||||
timeStamp: timeStamp,
|
||||
kind: kind,
|
||||
device: datum.device,
|
||||
@ -266,6 +295,7 @@ abstract final class PointerEventConverter {
|
||||
);
|
||||
case ui.PointerSignalKind.scale:
|
||||
return PointerScaleEvent(
|
||||
viewId: datum.viewId,
|
||||
timeStamp: timeStamp,
|
||||
kind: kind,
|
||||
device: datum.device,
|
||||
|
@ -2,7 +2,6 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
|
||||
import 'dart:ui' show Offset, PointerDeviceKind;
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
@ -245,6 +244,7 @@ abstract class PointerEvent with Diagnosticable {
|
||||
/// Abstract const constructor. This constructor enables subclasses to provide
|
||||
/// const constructors so that they can be used in const expressions.
|
||||
const PointerEvent({
|
||||
this.viewId = 0,
|
||||
this.embedderId = 0,
|
||||
this.timeStamp = Duration.zero,
|
||||
this.pointer = 0,
|
||||
@ -273,6 +273,9 @@ abstract class PointerEvent with Diagnosticable {
|
||||
this.original,
|
||||
});
|
||||
|
||||
/// The ID of the [FlutterView] which this event originated from.
|
||||
final int viewId;
|
||||
|
||||
/// Unique identifier that ties the [PointerEvent] to the embedder event that created it.
|
||||
///
|
||||
/// No two pointer events can have the same [embedderId] on platforms that set it.
|
||||
@ -536,6 +539,7 @@ abstract class PointerEvent with Diagnosticable {
|
||||
/// Calling this method on a transformed event will return a new transformed
|
||||
/// event based on the current [transform] and the provided properties.
|
||||
PointerEvent copyWith({
|
||||
int? viewId,
|
||||
Duration? timeStamp,
|
||||
int? pointer,
|
||||
PointerDeviceKind? kind,
|
||||
@ -619,7 +623,6 @@ abstract class PointerEvent with Diagnosticable {
|
||||
// A mixin that adds implementation for [debugFillProperties] and [toStringFull]
|
||||
// to [PointerEvent].
|
||||
mixin _PointerEventDescription on PointerEvent {
|
||||
|
||||
@override
|
||||
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
|
||||
super.debugFillProperties(properties);
|
||||
@ -650,6 +653,7 @@ mixin _PointerEventDescription on PointerEvent {
|
||||
properties.add(FlagProperty('obscured', value: obscured, ifTrue: 'obscured', level: DiagnosticLevel.debug));
|
||||
properties.add(FlagProperty('synthesized', value: synthesized, ifTrue: 'synthesized', level: DiagnosticLevel.debug));
|
||||
properties.add(IntProperty('embedderId', embedderId, defaultValue: 0, level: DiagnosticLevel.debug));
|
||||
properties.add(IntProperty('viewId', viewId, defaultValue: 0, level: DiagnosticLevel.debug));
|
||||
}
|
||||
|
||||
/// Returns a complete textual description of this event.
|
||||
@ -666,7 +670,6 @@ abstract class _AbstractPointerEvent implements PointerEvent { }
|
||||
// matrix. It defers all field getters to the original event, except for
|
||||
// [localPosition] and [localDelta], which are calculated when first used.
|
||||
abstract class _TransformedPointerEvent extends _AbstractPointerEvent with Diagnosticable, _PointerEventDescription {
|
||||
|
||||
@override
|
||||
PointerEvent get original;
|
||||
|
||||
@ -758,11 +761,15 @@ abstract class _TransformedPointerEvent extends _AbstractPointerEvent with Diagn
|
||||
untransformedEndPosition: position,
|
||||
transformedEndPosition: localPosition,
|
||||
);
|
||||
|
||||
@override
|
||||
int get viewId => original.viewId;
|
||||
}
|
||||
|
||||
mixin _CopyPointerAddedEvent on PointerEvent {
|
||||
@override
|
||||
PointerAddedEvent copyWith({
|
||||
int? viewId,
|
||||
Duration? timeStamp,
|
||||
int? pointer,
|
||||
PointerDeviceKind? kind,
|
||||
@ -787,6 +794,7 @@ mixin _CopyPointerAddedEvent on PointerEvent {
|
||||
int? embedderId,
|
||||
}) {
|
||||
return PointerAddedEvent(
|
||||
viewId: viewId ?? this.viewId,
|
||||
timeStamp: timeStamp ?? this.timeStamp,
|
||||
kind: kind ?? this.kind,
|
||||
device: device ?? this.device,
|
||||
@ -814,6 +822,7 @@ class PointerAddedEvent extends PointerEvent with _PointerEventDescription, _Cop
|
||||
///
|
||||
/// All of the arguments must be non-null.
|
||||
const PointerAddedEvent({
|
||||
super.viewId,
|
||||
super.timeStamp,
|
||||
super.pointer,
|
||||
super.kind,
|
||||
@ -858,6 +867,7 @@ class _TransformedPointerAddedEvent extends _TransformedPointerEvent with _CopyP
|
||||
mixin _CopyPointerRemovedEvent on PointerEvent {
|
||||
@override
|
||||
PointerRemovedEvent copyWith({
|
||||
int? viewId,
|
||||
Duration? timeStamp,
|
||||
int? pointer,
|
||||
PointerDeviceKind? kind,
|
||||
@ -882,6 +892,7 @@ mixin _CopyPointerRemovedEvent on PointerEvent {
|
||||
int? embedderId,
|
||||
}) {
|
||||
return PointerRemovedEvent(
|
||||
viewId: viewId ?? this.viewId,
|
||||
timeStamp: timeStamp ?? this.timeStamp,
|
||||
kind: kind ?? this.kind,
|
||||
device: device ?? this.device,
|
||||
@ -906,6 +917,7 @@ class PointerRemovedEvent extends PointerEvent with _PointerEventDescription, _C
|
||||
///
|
||||
/// All of the arguments must be non-null.
|
||||
const PointerRemovedEvent({
|
||||
super.viewId,
|
||||
super.timeStamp,
|
||||
super.pointer,
|
||||
super.kind,
|
||||
@ -948,6 +960,7 @@ class _TransformedPointerRemovedEvent extends _TransformedPointerEvent with _Cop
|
||||
mixin _CopyPointerHoverEvent on PointerEvent {
|
||||
@override
|
||||
PointerHoverEvent copyWith({
|
||||
int? viewId,
|
||||
Duration? timeStamp,
|
||||
int? pointer,
|
||||
PointerDeviceKind? kind,
|
||||
@ -972,6 +985,7 @@ mixin _CopyPointerHoverEvent on PointerEvent {
|
||||
int? embedderId,
|
||||
}) {
|
||||
return PointerHoverEvent(
|
||||
viewId: viewId ?? this.viewId,
|
||||
timeStamp: timeStamp ?? this.timeStamp,
|
||||
kind: kind ?? this.kind,
|
||||
device: device ?? this.device,
|
||||
@ -1013,6 +1027,7 @@ class PointerHoverEvent extends PointerEvent with _PointerEventDescription, _Cop
|
||||
///
|
||||
/// All of the arguments must be non-null.
|
||||
const PointerHoverEvent({
|
||||
super.viewId,
|
||||
super.timeStamp,
|
||||
super.kind,
|
||||
super.pointer,
|
||||
@ -1064,6 +1079,7 @@ class _TransformedPointerHoverEvent extends _TransformedPointerEvent with _CopyP
|
||||
mixin _CopyPointerEnterEvent on PointerEvent {
|
||||
@override
|
||||
PointerEnterEvent copyWith({
|
||||
int? viewId,
|
||||
Duration? timeStamp,
|
||||
int? pointer,
|
||||
PointerDeviceKind? kind,
|
||||
@ -1088,6 +1104,7 @@ mixin _CopyPointerEnterEvent on PointerEvent {
|
||||
int? embedderId,
|
||||
}) {
|
||||
return PointerEnterEvent(
|
||||
viewId: viewId ?? this.viewId,
|
||||
timeStamp: timeStamp ?? this.timeStamp,
|
||||
kind: kind ?? this.kind,
|
||||
device: device ?? this.device,
|
||||
@ -1129,6 +1146,7 @@ class PointerEnterEvent extends PointerEvent with _PointerEventDescription, _Cop
|
||||
///
|
||||
/// All of the arguments must be non-null.
|
||||
const PointerEnterEvent({
|
||||
super.viewId,
|
||||
super.timeStamp,
|
||||
super.pointer,
|
||||
super.kind,
|
||||
@ -1162,6 +1180,7 @@ class PointerEnterEvent extends PointerEvent with _PointerEventDescription, _Cop
|
||||
///
|
||||
/// This is used by the [MouseTracker] to synthesize enter events.
|
||||
factory PointerEnterEvent.fromMouseEvent(PointerEvent event) => PointerEnterEvent(
|
||||
viewId: event.viewId,
|
||||
timeStamp: event.timeStamp,
|
||||
pointer: event.pointer,
|
||||
kind: event.kind,
|
||||
@ -1210,6 +1229,7 @@ class _TransformedPointerEnterEvent extends _TransformedPointerEvent with _CopyP
|
||||
mixin _CopyPointerExitEvent on PointerEvent {
|
||||
@override
|
||||
PointerExitEvent copyWith({
|
||||
int? viewId,
|
||||
Duration? timeStamp,
|
||||
int? pointer,
|
||||
PointerDeviceKind? kind,
|
||||
@ -1234,6 +1254,7 @@ mixin _CopyPointerExitEvent on PointerEvent {
|
||||
int? embedderId,
|
||||
}) {
|
||||
return PointerExitEvent(
|
||||
viewId: viewId ?? this.viewId,
|
||||
timeStamp: timeStamp ?? this.timeStamp,
|
||||
kind: kind ?? this.kind,
|
||||
device: device ?? this.device,
|
||||
@ -1275,6 +1296,7 @@ class PointerExitEvent extends PointerEvent with _PointerEventDescription, _Copy
|
||||
///
|
||||
/// All of the arguments must be non-null.
|
||||
const PointerExitEvent({
|
||||
super.viewId,
|
||||
super.timeStamp,
|
||||
super.kind,
|
||||
super.pointer,
|
||||
@ -1306,6 +1328,7 @@ class PointerExitEvent extends PointerEvent with _PointerEventDescription, _Copy
|
||||
///
|
||||
/// This is used by the [MouseTracker] to synthesize exit events.
|
||||
factory PointerExitEvent.fromMouseEvent(PointerEvent event) => PointerExitEvent(
|
||||
viewId: event.viewId,
|
||||
timeStamp: event.timeStamp,
|
||||
pointer: event.pointer,
|
||||
kind: event.kind,
|
||||
@ -1355,6 +1378,7 @@ class _TransformedPointerExitEvent extends _TransformedPointerEvent with _CopyPo
|
||||
mixin _CopyPointerDownEvent on PointerEvent {
|
||||
@override
|
||||
PointerDownEvent copyWith({
|
||||
int? viewId,
|
||||
Duration? timeStamp,
|
||||
int? pointer,
|
||||
PointerDeviceKind? kind,
|
||||
@ -1379,6 +1403,7 @@ mixin _CopyPointerDownEvent on PointerEvent {
|
||||
int? embedderId,
|
||||
}) {
|
||||
return PointerDownEvent(
|
||||
viewId: viewId ?? this.viewId,
|
||||
timeStamp: timeStamp ?? this.timeStamp,
|
||||
pointer: pointer ?? this.pointer,
|
||||
kind: kind ?? this.kind,
|
||||
@ -1413,6 +1438,7 @@ class PointerDownEvent extends PointerEvent with _PointerEventDescription, _Copy
|
||||
///
|
||||
/// All of the arguments must be non-null.
|
||||
const PointerDownEvent({
|
||||
super.viewId,
|
||||
super.timeStamp,
|
||||
super.pointer,
|
||||
super.kind,
|
||||
@ -1463,6 +1489,7 @@ class _TransformedPointerDownEvent extends _TransformedPointerEvent with _CopyPo
|
||||
mixin _CopyPointerMoveEvent on PointerEvent {
|
||||
@override
|
||||
PointerMoveEvent copyWith({
|
||||
int? viewId,
|
||||
Duration? timeStamp,
|
||||
int? pointer,
|
||||
PointerDeviceKind? kind,
|
||||
@ -1487,6 +1514,7 @@ mixin _CopyPointerMoveEvent on PointerEvent {
|
||||
int? embedderId,
|
||||
}) {
|
||||
return PointerMoveEvent(
|
||||
viewId: viewId ?? this.viewId,
|
||||
timeStamp: timeStamp ?? this.timeStamp,
|
||||
pointer: pointer ?? this.pointer,
|
||||
kind: kind ?? this.kind,
|
||||
@ -1526,6 +1554,7 @@ class PointerMoveEvent extends PointerEvent with _PointerEventDescription, _Copy
|
||||
///
|
||||
/// All of the arguments must be non-null.
|
||||
const PointerMoveEvent({
|
||||
super.viewId,
|
||||
super.timeStamp,
|
||||
super.pointer,
|
||||
super.kind,
|
||||
@ -1580,6 +1609,7 @@ class _TransformedPointerMoveEvent extends _TransformedPointerEvent with _CopyPo
|
||||
mixin _CopyPointerUpEvent on PointerEvent {
|
||||
@override
|
||||
PointerUpEvent copyWith({
|
||||
int? viewId,
|
||||
Duration? timeStamp,
|
||||
int? pointer,
|
||||
PointerDeviceKind? kind,
|
||||
@ -1605,6 +1635,7 @@ mixin _CopyPointerUpEvent on PointerEvent {
|
||||
int? embedderId,
|
||||
}) {
|
||||
return PointerUpEvent(
|
||||
viewId: viewId ?? this.viewId,
|
||||
timeStamp: timeStamp ?? this.timeStamp,
|
||||
pointer: pointer ?? this.pointer,
|
||||
kind: kind ?? this.kind,
|
||||
@ -1640,6 +1671,7 @@ class PointerUpEvent extends PointerEvent with _PointerEventDescription, _CopyPo
|
||||
///
|
||||
/// All of the arguments must be non-null.
|
||||
const PointerUpEvent({
|
||||
super.viewId,
|
||||
super.timeStamp,
|
||||
super.pointer,
|
||||
super.kind,
|
||||
@ -1705,6 +1737,7 @@ abstract class PointerSignalEvent extends PointerEvent {
|
||||
/// Abstract const constructor. This constructor enables subclasses to provide
|
||||
/// const constructors so that they can be used in const expressions.
|
||||
const PointerSignalEvent({
|
||||
super.viewId,
|
||||
super.timeStamp,
|
||||
super.pointer,
|
||||
super.kind = PointerDeviceKind.mouse,
|
||||
@ -1720,6 +1753,7 @@ mixin _CopyPointerScrollEvent on PointerEvent {
|
||||
|
||||
@override
|
||||
PointerScrollEvent copyWith({
|
||||
int? viewId,
|
||||
Duration? timeStamp,
|
||||
int? pointer,
|
||||
PointerDeviceKind? kind,
|
||||
@ -1744,6 +1778,7 @@ mixin _CopyPointerScrollEvent on PointerEvent {
|
||||
int? embedderId,
|
||||
}) {
|
||||
return PointerScrollEvent(
|
||||
viewId: viewId ?? this.viewId,
|
||||
timeStamp: timeStamp ?? this.timeStamp,
|
||||
kind: kind ?? this.kind,
|
||||
device: device ?? this.device,
|
||||
@ -1770,6 +1805,7 @@ class PointerScrollEvent extends PointerSignalEvent with _PointerEventDescriptio
|
||||
///
|
||||
/// All of the arguments must be non-null.
|
||||
const PointerScrollEvent({
|
||||
super.viewId,
|
||||
super.timeStamp,
|
||||
super.kind,
|
||||
super.device,
|
||||
@ -1821,6 +1857,7 @@ class _TransformedPointerScrollEvent extends _TransformedPointerEvent with _Copy
|
||||
mixin _CopyPointerScrollInertiaCancelEvent on PointerEvent {
|
||||
@override
|
||||
PointerScrollInertiaCancelEvent copyWith({
|
||||
int? viewId,
|
||||
Duration? timeStamp,
|
||||
int? pointer,
|
||||
PointerDeviceKind? kind,
|
||||
@ -1845,6 +1882,7 @@ mixin _CopyPointerScrollInertiaCancelEvent on PointerEvent {
|
||||
int? embedderId,
|
||||
}) {
|
||||
return PointerScrollInertiaCancelEvent(
|
||||
viewId: viewId ?? this.viewId,
|
||||
timeStamp: timeStamp ?? this.timeStamp,
|
||||
kind: kind ?? this.kind,
|
||||
device: device ?? this.device,
|
||||
@ -1870,6 +1908,7 @@ class PointerScrollInertiaCancelEvent extends PointerSignalEvent with _PointerEv
|
||||
///
|
||||
/// All of the arguments must be non-null.
|
||||
const PointerScrollInertiaCancelEvent({
|
||||
super.viewId,
|
||||
super.timeStamp,
|
||||
super.kind,
|
||||
super.device,
|
||||
@ -1905,6 +1944,7 @@ mixin _CopyPointerScaleEvent on PointerEvent {
|
||||
|
||||
@override
|
||||
PointerScaleEvent copyWith({
|
||||
int? viewId,
|
||||
Duration? timeStamp,
|
||||
int? pointer,
|
||||
PointerDeviceKind? kind,
|
||||
@ -1930,6 +1970,7 @@ mixin _CopyPointerScaleEvent on PointerEvent {
|
||||
double? scale,
|
||||
}) {
|
||||
return PointerScaleEvent(
|
||||
viewId: viewId ?? this.viewId,
|
||||
timeStamp: timeStamp ?? this.timeStamp,
|
||||
kind: kind ?? this.kind,
|
||||
device: device ?? this.device,
|
||||
@ -1956,6 +1997,7 @@ class PointerScaleEvent extends PointerSignalEvent with _PointerEventDescription
|
||||
///
|
||||
/// All of the arguments must be non-null.
|
||||
const PointerScaleEvent({
|
||||
super.viewId,
|
||||
super.timeStamp,
|
||||
super.kind,
|
||||
super.device,
|
||||
@ -1995,6 +2037,7 @@ class _TransformedPointerScaleEvent extends _TransformedPointerEvent with _CopyP
|
||||
mixin _CopyPointerPanZoomStartEvent on PointerEvent {
|
||||
@override
|
||||
PointerPanZoomStartEvent copyWith({
|
||||
int? viewId,
|
||||
Duration? timeStamp,
|
||||
int? pointer,
|
||||
PointerDeviceKind? kind,
|
||||
@ -2020,6 +2063,7 @@ mixin _CopyPointerPanZoomStartEvent on PointerEvent {
|
||||
}) {
|
||||
assert(kind == null || identical(kind, PointerDeviceKind.trackpad));
|
||||
return PointerPanZoomStartEvent(
|
||||
viewId: viewId ?? this.viewId,
|
||||
timeStamp: timeStamp ?? this.timeStamp,
|
||||
device: device ?? this.device,
|
||||
position: position ?? this.position,
|
||||
@ -2039,6 +2083,7 @@ class PointerPanZoomStartEvent extends PointerEvent with _PointerEventDescriptio
|
||||
///
|
||||
/// All of the arguments must be non-null.
|
||||
const PointerPanZoomStartEvent({
|
||||
super.viewId,
|
||||
super.timeStamp,
|
||||
super.device,
|
||||
super.pointer,
|
||||
@ -2085,6 +2130,7 @@ mixin _CopyPointerPanZoomUpdateEvent on PointerEvent {
|
||||
|
||||
@override
|
||||
PointerPanZoomUpdateEvent copyWith({
|
||||
int? viewId,
|
||||
Duration? timeStamp,
|
||||
int? pointer,
|
||||
PointerDeviceKind? kind,
|
||||
@ -2116,6 +2162,7 @@ mixin _CopyPointerPanZoomUpdateEvent on PointerEvent {
|
||||
}) {
|
||||
assert(kind == null || identical(kind, PointerDeviceKind.trackpad));
|
||||
return PointerPanZoomUpdateEvent(
|
||||
viewId: viewId ?? this.viewId,
|
||||
timeStamp: timeStamp ?? this.timeStamp,
|
||||
device: device ?? this.device,
|
||||
position: position ?? this.position,
|
||||
@ -2139,6 +2186,7 @@ class PointerPanZoomUpdateEvent extends PointerEvent with _PointerEventDescripti
|
||||
///
|
||||
/// All of the arguments must be non-null.
|
||||
const PointerPanZoomUpdateEvent({
|
||||
super.viewId,
|
||||
super.timeStamp,
|
||||
super.device,
|
||||
super.pointer,
|
||||
@ -2212,6 +2260,7 @@ class _TransformedPointerPanZoomUpdateEvent extends _TransformedPointerEvent wit
|
||||
mixin _CopyPointerPanZoomEndEvent on PointerEvent {
|
||||
@override
|
||||
PointerPanZoomEndEvent copyWith({
|
||||
int? viewId,
|
||||
Duration? timeStamp,
|
||||
int? pointer,
|
||||
PointerDeviceKind? kind,
|
||||
@ -2237,6 +2286,7 @@ mixin _CopyPointerPanZoomEndEvent on PointerEvent {
|
||||
}) {
|
||||
assert(kind == null || identical(kind, PointerDeviceKind.trackpad));
|
||||
return PointerPanZoomEndEvent(
|
||||
viewId: viewId ?? this.viewId,
|
||||
timeStamp: timeStamp ?? this.timeStamp,
|
||||
device: device ?? this.device,
|
||||
position: position ?? this.position,
|
||||
@ -2256,6 +2306,7 @@ class PointerPanZoomEndEvent extends PointerEvent with _PointerEventDescription,
|
||||
///
|
||||
/// All of the arguments must be non-null.
|
||||
const PointerPanZoomEndEvent({
|
||||
super.viewId,
|
||||
super.timeStamp,
|
||||
super.device,
|
||||
super.pointer,
|
||||
@ -2289,6 +2340,7 @@ class _TransformedPointerPanZoomEndEvent extends _TransformedPointerEvent with _
|
||||
mixin _CopyPointerCancelEvent on PointerEvent {
|
||||
@override
|
||||
PointerCancelEvent copyWith({
|
||||
int? viewId,
|
||||
Duration? timeStamp,
|
||||
int? pointer,
|
||||
PointerDeviceKind? kind,
|
||||
@ -2313,6 +2365,7 @@ mixin _CopyPointerCancelEvent on PointerEvent {
|
||||
int? embedderId,
|
||||
}) {
|
||||
return PointerCancelEvent(
|
||||
viewId: viewId ?? this.viewId,
|
||||
timeStamp: timeStamp ?? this.timeStamp,
|
||||
pointer: pointer ?? this.pointer,
|
||||
kind: kind ?? this.kind,
|
||||
@ -2347,6 +2400,7 @@ class PointerCancelEvent extends PointerEvent with _PointerEventDescription, _Co
|
||||
///
|
||||
/// All of the arguments must be non-null.
|
||||
const PointerCancelEvent({
|
||||
super.viewId,
|
||||
super.timeStamp,
|
||||
super.pointer,
|
||||
super.kind,
|
||||
|
@ -16,11 +16,16 @@ export 'events.dart' show PointerEvent;
|
||||
|
||||
/// An object that can hit-test pointers.
|
||||
abstract interface class HitTestable {
|
||||
/// Check whether the given position hits this object.
|
||||
///
|
||||
/// If this given position hits this object, consider adding a [HitTestEntry]
|
||||
/// to the given hit test result.
|
||||
/// Deprecated. Use [hitTestInView] instead.
|
||||
@Deprecated(
|
||||
'Use hitTestInView and specify the view to hit test. '
|
||||
'This feature was deprecated after v3.11.0-20.0.pre.',
|
||||
)
|
||||
void hitTest(HitTestResult result, Offset position);
|
||||
|
||||
/// Fills the provided [HitTestResult] with [HitTestEntry]s for objects that
|
||||
/// are hit at the given `position` in the view identified by `viewId`.
|
||||
void hitTestInView(HitTestResult result, Offset position, int viewId);
|
||||
}
|
||||
|
||||
/// An object that can dispatch events.
|
||||
|
@ -54,6 +54,7 @@ class PointerEventResampler {
|
||||
int buttons,
|
||||
) {
|
||||
return PointerHoverEvent(
|
||||
viewId: event.viewId,
|
||||
timeStamp: timeStamp,
|
||||
kind: event.kind,
|
||||
device: event.device,
|
||||
@ -86,6 +87,7 @@ class PointerEventResampler {
|
||||
int buttons,
|
||||
) {
|
||||
return PointerMoveEvent(
|
||||
viewId: event.viewId,
|
||||
timeStamp: timeStamp,
|
||||
pointer: pointerIdentifier,
|
||||
kind: event.kind,
|
||||
|
@ -519,9 +519,10 @@ mixin RendererBinding on BindingBase, ServicesBinding, SchedulerBinding, Gesture
|
||||
}
|
||||
|
||||
@override
|
||||
void hitTest(HitTestResult result, Offset position) {
|
||||
void hitTestInView(HitTestResult result, Offset position, int viewId) {
|
||||
assert(viewId == renderView.flutterView.viewId);
|
||||
renderView.hitTest(result, position: position);
|
||||
super.hitTest(result, position);
|
||||
super.hitTestInView(result, position, viewId);
|
||||
}
|
||||
|
||||
Future<void> _forceRepaint() {
|
||||
|
@ -103,6 +103,8 @@ class RenderView extends RenderObject with RenderObjectWithChildMixin<RenderBox>
|
||||
markNeedsLayout();
|
||||
}
|
||||
|
||||
/// The [FlutterView] into which this [RenderView] will render.
|
||||
ui.FlutterView get flutterView => _view;
|
||||
final ui.FlutterView _view;
|
||||
|
||||
/// Whether Flutter should automatically compute the desired system UI.
|
||||
|
@ -13,6 +13,7 @@ import 'debug.dart';
|
||||
import 'framework.dart';
|
||||
import 'media_query.dart';
|
||||
import 'overlay.dart';
|
||||
import 'view.dart';
|
||||
|
||||
/// Signature for determining whether the given data will be accepted by a [DragTarget].
|
||||
///
|
||||
@ -497,6 +498,7 @@ class _DraggableState<T extends Object> extends State<Draggable<T>> {
|
||||
feedbackOffset: widget.feedbackOffset,
|
||||
ignoringFeedbackSemantics: widget.ignoringFeedbackSemantics,
|
||||
ignoringFeedbackPointer: widget.ignoringFeedbackPointer,
|
||||
viewId: View.of(context).viewId,
|
||||
onDragUpdate: (DragUpdateDetails details) {
|
||||
if (mounted && widget.onDragUpdate != null) {
|
||||
widget.onDragUpdate!(details);
|
||||
@ -756,6 +758,7 @@ class _DragAvatar<T extends Object> extends Drag {
|
||||
this.onDragEnd,
|
||||
required this.ignoringFeedbackSemantics,
|
||||
required this.ignoringFeedbackPointer,
|
||||
required this.viewId,
|
||||
}) : _position = initialPosition {
|
||||
_entry = OverlayEntry(builder: _build);
|
||||
overlayState.insert(_entry!);
|
||||
@ -772,6 +775,7 @@ class _DragAvatar<T extends Object> extends Drag {
|
||||
final OverlayState overlayState;
|
||||
final bool ignoringFeedbackSemantics;
|
||||
final bool ignoringFeedbackPointer;
|
||||
final int viewId;
|
||||
|
||||
_DragTargetState<Object>? _activeTarget;
|
||||
final List<_DragTargetState<Object>> _enteredTargets = <_DragTargetState<Object>>[];
|
||||
@ -804,7 +808,7 @@ class _DragAvatar<T extends Object> extends Drag {
|
||||
_lastOffset = globalPosition - dragStartPoint;
|
||||
_entry!.markNeedsBuild();
|
||||
final HitTestResult result = HitTestResult();
|
||||
WidgetsBinding.instance.hitTest(result, globalPosition + feedbackOffset);
|
||||
WidgetsBinding.instance.hitTestInView(result, globalPosition + feedbackOffset, viewId);
|
||||
|
||||
final List<_DragTargetState<Object>> targets = _getDragTargets(result.path).toList();
|
||||
|
||||
|
@ -5018,7 +5018,7 @@ class _ScribbleFocusableState extends State<_ScribbleFocusable> implements Scrib
|
||||
}
|
||||
final Rect intersection = calculatedBounds.intersect(rect);
|
||||
final HitTestResult result = HitTestResult();
|
||||
WidgetsBinding.instance.hitTest(result, intersection.center);
|
||||
WidgetsBinding.instance.hitTestInView(result, intersection.center, View.of(context).viewId);
|
||||
return result.path.any((HitTestEntry entry) => entry.target == renderEditable);
|
||||
}
|
||||
|
||||
|
@ -39,39 +39,47 @@ void main() {
|
||||
final ui.PointerDataPacket packet = ui.PointerDataPacket(
|
||||
data: <ui.PointerData>[
|
||||
ui.PointerData(
|
||||
viewId: tester.view.viewId,
|
||||
change: ui.PointerChange.add,
|
||||
timeStamp: epoch,
|
||||
),
|
||||
ui.PointerData(
|
||||
viewId: tester.view.viewId,
|
||||
change: ui.PointerChange.down,
|
||||
timeStamp: epoch,
|
||||
),
|
||||
ui.PointerData(
|
||||
viewId: tester.view.viewId,
|
||||
change: ui.PointerChange.move,
|
||||
physicalX: 15.0,
|
||||
timeStamp: epoch + const Duration(milliseconds: 10),
|
||||
),
|
||||
ui.PointerData(
|
||||
viewId: tester.view.viewId,
|
||||
change: ui.PointerChange.move,
|
||||
physicalX: 30.0,
|
||||
timeStamp: epoch + const Duration(milliseconds: 20),
|
||||
),
|
||||
ui.PointerData(
|
||||
viewId: tester.view.viewId,
|
||||
change: ui.PointerChange.move,
|
||||
physicalX: 45.0,
|
||||
timeStamp: epoch + const Duration(milliseconds: 30),
|
||||
),
|
||||
ui.PointerData(
|
||||
viewId: tester.view.viewId,
|
||||
change: ui.PointerChange.move,
|
||||
physicalX: 50.0,
|
||||
timeStamp: epoch + const Duration(milliseconds: 40),
|
||||
),
|
||||
ui.PointerData(
|
||||
viewId: tester.view.viewId,
|
||||
change: ui.PointerChange.up,
|
||||
physicalX: 60.0,
|
||||
timeStamp: epoch + const Duration(milliseconds: 40),
|
||||
),
|
||||
ui.PointerData(
|
||||
viewId: tester.view.viewId,
|
||||
change: ui.PointerChange.remove,
|
||||
physicalX: 60.0,
|
||||
timeStamp: epoch + const Duration(milliseconds: 40),
|
||||
|
@ -175,7 +175,7 @@ void main() {
|
||||
],
|
||||
);
|
||||
|
||||
final List<PointerEvent> events = PointerEventConverter.expand(packet.data, devicePixelRatio).toList();
|
||||
final List<PointerEvent> events = PointerEventConverter.expand(packet.data, (int viewId) => devicePixelRatio).toList();
|
||||
|
||||
expect(events.length, 5);
|
||||
expect(events[0], isA<PointerAddedEvent>());
|
||||
@ -191,7 +191,7 @@ void main() {
|
||||
ui.PointerData(change: ui.PointerChange.add, device: 24),
|
||||
],
|
||||
);
|
||||
List<PointerEvent> events = PointerEventConverter.expand(packet.data, devicePixelRatio).toList();
|
||||
List<PointerEvent> events = PointerEventConverter.expand(packet.data, (int viewId) => devicePixelRatio).toList();
|
||||
|
||||
expect(events.length, 1);
|
||||
expect(events[0], isA<PointerAddedEvent>());
|
||||
@ -207,7 +207,7 @@ void main() {
|
||||
ui.PointerData(signalKind: ui.PointerSignalKind.scroll, device: 24, scrollDeltaY: double.negativeInfinity, scrollDeltaX: 10),
|
||||
],
|
||||
);
|
||||
events = PointerEventConverter.expand(packet.data, devicePixelRatio).toList();
|
||||
events = PointerEventConverter.expand(packet.data, (int viewId) => devicePixelRatio).toList();
|
||||
expect(events.length, 0);
|
||||
|
||||
// Send packet with a valid scroll event.
|
||||
@ -217,12 +217,12 @@ void main() {
|
||||
],
|
||||
);
|
||||
// Make sure PointerEventConverter can expand when device pixel ratio is valid.
|
||||
events = PointerEventConverter.expand(packet.data, devicePixelRatio).toList();
|
||||
events = PointerEventConverter.expand(packet.data, (int viewId) => devicePixelRatio).toList();
|
||||
expect(events.length, 1);
|
||||
expect(events[0], isA<PointerScrollEvent>());
|
||||
|
||||
// Make sure PointerEventConverter returns none when device pixel ratio is invalid.
|
||||
events = PointerEventConverter.expand(packet.data, 0).toList();
|
||||
events = PointerEventConverter.expand(packet.data, (int viewId) => 0).toList();
|
||||
expect(events.length, 0);
|
||||
});
|
||||
|
||||
@ -234,7 +234,7 @@ void main() {
|
||||
],
|
||||
);
|
||||
|
||||
final List<PointerEvent> events = PointerEventConverter.expand(packet.data, devicePixelRatio).toList();
|
||||
final List<PointerEvent> events = PointerEventConverter.expand(packet.data, (int viewId) => devicePixelRatio).toList();
|
||||
|
||||
expect(events.length, 2);
|
||||
expect(events[0], isA<PointerAddedEvent>());
|
||||
@ -253,7 +253,7 @@ void main() {
|
||||
],
|
||||
);
|
||||
|
||||
final List<PointerEvent> events = PointerEventConverter.expand(packet.data, devicePixelRatio).toList();
|
||||
final List<PointerEvent> events = PointerEventConverter.expand(packet.data, (int viewId) => devicePixelRatio).toList();
|
||||
|
||||
expect(events.length, 5);
|
||||
expect(events[0], isA<PointerAddedEvent>());
|
||||
@ -280,7 +280,7 @@ void main() {
|
||||
],
|
||||
);
|
||||
|
||||
final List<PointerEvent> events = PointerEventConverter.expand(packet.data, devicePixelRatio).toList();
|
||||
final List<PointerEvent> events = PointerEventConverter.expand(packet.data, (int viewId) => devicePixelRatio).toList();
|
||||
|
||||
expect(events.length, 5);
|
||||
expect(events[0], isA<PointerAddedEvent>());
|
||||
@ -312,7 +312,7 @@ void main() {
|
||||
],
|
||||
);
|
||||
|
||||
final List<PointerEvent> events = PointerEventConverter.expand(packet.data, devicePixelRatio).toList();
|
||||
final List<PointerEvent> events = PointerEventConverter.expand(packet.data, (int viewId) => devicePixelRatio).toList();
|
||||
|
||||
expect(events.length, 5);
|
||||
expect(events[0], isA<PointerAddedEvent>());
|
||||
@ -341,7 +341,7 @@ void main() {
|
||||
],
|
||||
);
|
||||
|
||||
final List<PointerEvent> events = PointerEventConverter.expand(packet.data, devicePixelRatio).toList();
|
||||
final List<PointerEvent> events = PointerEventConverter.expand(packet.data, (int viewId) => devicePixelRatio).toList();
|
||||
|
||||
expect(events.length, 5);
|
||||
expect(events[0], isA<PointerAddedEvent>());
|
||||
@ -371,7 +371,7 @@ void main() {
|
||||
],
|
||||
);
|
||||
|
||||
final List<PointerEvent> events = PointerEventConverter.expand(packet.data, devicePixelRatio).toList();
|
||||
final List<PointerEvent> events = PointerEventConverter.expand(packet.data, (int viewId) => devicePixelRatio).toList();
|
||||
|
||||
expect(events.length, 5);
|
||||
expect(events[0], isA<PointerAddedEvent>());
|
||||
@ -429,4 +429,33 @@ void main() {
|
||||
FlutterError.onError = FlutterError.presentError;
|
||||
}
|
||||
});
|
||||
|
||||
test('PointerEventConverter processes view IDs', () {
|
||||
const int startID = 987654;
|
||||
const List<ui.PointerData> data = <ui.PointerData>[
|
||||
ui.PointerData(viewId: startID + 0, change: ui.PointerChange.cancel), // ignore: avoid_redundant_argument_values
|
||||
ui.PointerData(viewId: startID + 1, change: ui.PointerChange.add),
|
||||
ui.PointerData(viewId: startID + 2, change: ui.PointerChange.remove),
|
||||
ui.PointerData(viewId: startID + 3, change: ui.PointerChange.hover),
|
||||
ui.PointerData(viewId: startID + 4, change: ui.PointerChange.down),
|
||||
ui.PointerData(viewId: startID + 5, change: ui.PointerChange.move),
|
||||
ui.PointerData(viewId: startID + 6, change: ui.PointerChange.up),
|
||||
ui.PointerData(viewId: startID + 7, change: ui.PointerChange.panZoomStart),
|
||||
ui.PointerData(viewId: startID + 8, change: ui.PointerChange.panZoomUpdate),
|
||||
ui.PointerData(viewId: startID + 9, change: ui.PointerChange.panZoomEnd),
|
||||
];
|
||||
|
||||
final List<int> viewIds = <int>[];
|
||||
double devicePixelRatioGetter(int viewId) {
|
||||
viewIds.add(viewId);
|
||||
return viewId / 10.0;
|
||||
}
|
||||
|
||||
final List<PointerEvent> events = PointerEventConverter.expand(data, devicePixelRatioGetter).toList();
|
||||
|
||||
final List<int> expectedViewIds = List<int>.generate(10, (int index) => startID + index);
|
||||
expect(viewIds, expectedViewIds);
|
||||
expect(events, hasLength(10));
|
||||
expect(events.map((PointerEvent event) => event.viewId), expectedViewIds);
|
||||
});
|
||||
}
|
||||
|
@ -1192,7 +1192,8 @@ abstract class WidgetController {
|
||||
/// Forwards the given location to the binding's hitTest logic.
|
||||
HitTestResult hitTestOnBinding(Offset location) {
|
||||
final HitTestResult result = HitTestResult();
|
||||
binding.hitTest(result, location);
|
||||
// TODO(goderbauer): Support multiple views in flutter_test pointer event handling, https://github.com/flutter/flutter/issues/128281
|
||||
binding.hitTest(result, location); // ignore: deprecated_member_use
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -1313,7 +1314,8 @@ abstract class WidgetController {
|
||||
final Offset location = box.localToGlobal(sizeToPoint(box.size));
|
||||
if (warnIfMissed) {
|
||||
final HitTestResult result = HitTestResult();
|
||||
binding.hitTest(result, location);
|
||||
// TODO(goderbauer): Support multiple views in flutter_test pointer event handling, https://github.com/flutter/flutter/issues/128281
|
||||
binding.hitTest(result, location); // ignore: deprecated_member_use
|
||||
bool found = false;
|
||||
for (final HitTestEntry entry in result.path) {
|
||||
if (entry.target == box) {
|
||||
|
@ -642,7 +642,8 @@ class _HitTestableFinder extends ChainedFinder {
|
||||
final RenderBox box = candidate.renderObject! as RenderBox;
|
||||
final Offset absoluteOffset = box.localToGlobal(alignment.alongSize(box.size));
|
||||
final HitTestResult hitResult = HitTestResult();
|
||||
WidgetsBinding.instance.hitTest(hitResult, absoluteOffset);
|
||||
// TODO(goderbauer): Support multiple views in flutter_test pointer event handling, https://github.com/flutter/flutter/issues/128281
|
||||
WidgetsBinding.instance.hitTest(hitResult, absoluteOffset); // ignore: deprecated_member_use
|
||||
for (final HitTestEntry entry in hitResult.path) {
|
||||
if (entry.target == candidate.renderObject) {
|
||||
yield candidate;
|
||||
|
@ -167,8 +167,8 @@ class TestPlatformDispatcher implements PlatformDispatcher {
|
||||
: null;
|
||||
}
|
||||
|
||||
final Map<Object, TestFlutterView> _testViews = <Object, TestFlutterView>{};
|
||||
final Map<Object, TestDisplay> _testDisplays = <Object, TestDisplay>{};
|
||||
final Map<int, TestFlutterView> _testViews = <int, TestFlutterView>{};
|
||||
final Map<int, TestDisplay> _testDisplays = <int, TestDisplay>{};
|
||||
|
||||
@override
|
||||
VoidCallback? get onMetricsChanged => _platformDispatcher.onMetricsChanged;
|
||||
@ -510,6 +510,9 @@ class TestPlatformDispatcher implements PlatformDispatcher {
|
||||
@override
|
||||
Iterable<TestFlutterView> get views => _testViews.values;
|
||||
|
||||
@override
|
||||
FlutterView? view({required int id}) => _testViews[id];
|
||||
|
||||
@override
|
||||
Iterable<TestDisplay> get displays => _testDisplays.values;
|
||||
|
||||
|
@ -153,6 +153,10 @@ void main() {
|
||||
retrieveTestBinding(tester).platformDispatcher.localesTestValue = defaultLocales;
|
||||
});
|
||||
|
||||
testWidgets('TestPlatformDispatcher.view getter returns the implicit view', (WidgetTester tester) async {
|
||||
expect(WidgetsBinding.instance.platformDispatcher.view(id: tester.view.viewId), same(tester.view));
|
||||
});
|
||||
|
||||
// TODO(pdblasi-google): Removed this group of tests when the Display API is stable and supported on all platforms.
|
||||
group('TestPlatformDispatcher with unsupported Display API', () {
|
||||
testWidgets('can initialize with empty displays', (WidgetTester tester) async {
|
||||
|
Loading…
x
Reference in New Issue
Block a user