Unverified Commit cff67336 authored by Michael Goderbauer's avatar Michael Goderbauer Committed by GitHub

Add viewId to PointerEvents (#128287)

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