Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in
Toggle navigation
F
Front-End
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
abdullh.alsoleman
Front-End
Commits
da8695d3
Unverified
Commit
da8695d3
authored
Jul 13, 2020
by
Tong Mu
Committed by
GitHub
Jul 13, 2020
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Mouse events report correct local positions (#61190)
parent
067d3da8
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
115 additions
and
71 deletions
+115
-71
mouse_cursor.dart
packages/flutter/lib/src/rendering/mouse_cursor.dart
+2
-3
mouse_tracking.dart
packages/flutter/lib/src/rendering/mouse_tracking.dart
+41
-35
view.dart
packages/flutter/lib/src/rendering/view.dart
+5
-3
mouse_tracking_cursor_test.dart
...es/flutter/test/rendering/mouse_tracking_cursor_test.dart
+9
-2
mouse_tracking_test.dart
packages/flutter/test/rendering/mouse_tracking_test.dart
+44
-23
proxy_box_test.dart
packages/flutter/test/rendering/proxy_box_test.dart
+2
-1
mouse_region_test.dart
packages/flutter/test/widgets/mouse_region_test.dart
+12
-4
No files found.
packages/flutter/lib/src/rendering/mouse_cursor.dart
View file @
da8695d3
...
@@ -5,7 +5,6 @@
...
@@ -5,7 +5,6 @@
// @dart = 2.8
// @dart = 2.8
import
'dart:async'
;
import
'dart:async'
;
import
'dart:collection'
show
LinkedHashSet
;
import
'package:flutter/foundation.dart'
;
import
'package:flutter/foundation.dart'
;
import
'package:flutter/gestures.dart'
;
import
'package:flutter/gestures.dart'
;
...
@@ -52,7 +51,7 @@ mixin MouseTrackerCursorMixin on BaseMouseTracker {
...
@@ -52,7 +51,7 @@ mixin MouseTrackerCursorMixin on BaseMouseTracker {
// The `annotations` is the current annotations that the device is hovering in
// The `annotations` is the current annotations that the device is hovering in
// visual order from front the back.
// visual order from front the back.
// The return value is never null.
// The return value is never null.
MouseCursor
_findFirstCursor
(
LinkedHashSet
<
MouseTrackerAnnotation
>
annotations
)
{
MouseCursor
_findFirstCursor
(
Iterable
<
MouseTrackerAnnotation
>
annotations
)
{
return
_DeferringMouseCursor
.
firstNonDeferred
(
return
_DeferringMouseCursor
.
firstNonDeferred
(
annotations
.
map
((
MouseTrackerAnnotation
annotation
)
=>
annotation
.
cursor
),
annotations
.
map
((
MouseTrackerAnnotation
annotation
)
=>
annotation
.
cursor
),
)
??
SystemMouseCursors
.
basic
;
)
??
SystemMouseCursors
.
basic
;
...
@@ -68,7 +67,7 @@ mixin MouseTrackerCursorMixin on BaseMouseTracker {
...
@@ -68,7 +67,7 @@ mixin MouseTrackerCursorMixin on BaseMouseTracker {
}
}
final
MouseCursorSession
lastSession
=
_lastSession
[
device
];
final
MouseCursorSession
lastSession
=
_lastSession
[
device
];
final
MouseCursor
nextCursor
=
_findFirstCursor
(
details
.
nextAnnotations
);
final
MouseCursor
nextCursor
=
_findFirstCursor
(
details
.
nextAnnotations
.
keys
);
if
(
lastSession
?.
cursor
==
nextCursor
)
if
(
lastSession
?.
cursor
==
nextCursor
)
return
;
return
;
...
...
packages/flutter/lib/src/rendering/mouse_tracking.dart
View file @
da8695d3
...
@@ -4,13 +4,15 @@
...
@@ -4,13 +4,15 @@
// @dart = 2.8
// @dart = 2.8
import
'dart:collection'
show
LinkedHash
Set
;
import
'dart:collection'
show
LinkedHash
Map
;
import
'dart:ui'
;
import
'dart:ui'
;
import
'package:flutter/foundation.dart'
;
import
'package:flutter/foundation.dart'
;
import
'package:flutter/gestures.dart'
;
import
'package:flutter/gestures.dart'
;
import
'package:flutter/scheduler.dart'
;
import
'package:flutter/scheduler.dart'
;
import
'package:vector_math/vector_math_64.dart'
show
Matrix4
;
import
'mouse_cursor.dart'
;
import
'mouse_cursor.dart'
;
import
'object.dart'
;
import
'object.dart'
;
...
@@ -132,7 +134,7 @@ class MouseTrackerAnnotation with Diagnosticable {
...
@@ -132,7 +134,7 @@ class MouseTrackerAnnotation with Diagnosticable {
///
///
/// It is used by the [BaseMouseTracker] to fetch annotations for the mouse
/// It is used by the [BaseMouseTracker] to fetch annotations for the mouse
/// position.
/// position.
typedef
MouseDetectorAnnotationFinder
=
Iterable
<
MouseTrackerAnnotation
>
Function
(
Offset
offset
);
typedef
MouseDetectorAnnotationFinder
=
LinkedHashMap
<
MouseTrackerAnnotation
,
Matrix4
>
Function
(
Offset
offset
);
// Various states of a connected mouse device used by [BaseMouseTracker].
// Various states of a connected mouse device used by [BaseMouseTracker].
class
_MouseState
{
class
_MouseState
{
...
@@ -143,13 +145,13 @@ class _MouseState {
...
@@ -143,13 +145,13 @@ class _MouseState {
// The list of annotations that contains this device.
// The list of annotations that contains this device.
//
//
// It uses [LinkedHash
Set
] to keep the insertion order.
// It uses [LinkedHash
Map
] to keep the insertion order.
LinkedHash
Set
<
MouseTrackerAnnotation
>
get
annotations
=>
_annotations
;
LinkedHash
Map
<
MouseTrackerAnnotation
,
Matrix4
>
get
annotations
=>
_annotations
;
LinkedHash
Set
<
MouseTrackerAnnotation
>
_annotations
=
LinkedHashSet
<
MouseTrackerAnnotation
>();
LinkedHash
Map
<
MouseTrackerAnnotation
,
Matrix4
>
_annotations
=
LinkedHashMap
<
MouseTrackerAnnotation
,
Matrix4
>();
LinkedHash
Set
<
MouseTrackerAnnotation
>
replaceAnnotations
(
LinkedHashSet
<
MouseTrackerAnnotation
>
value
)
{
LinkedHash
Map
<
MouseTrackerAnnotation
,
Matrix4
>
replaceAnnotations
(
LinkedHashMap
<
MouseTrackerAnnotation
,
Matrix4
>
value
)
{
assert
(
value
!=
null
);
assert
(
value
!=
null
);
final
LinkedHash
Set
<
MouseTrackerAnnotation
>
previous
=
_annotations
;
final
LinkedHash
Map
<
MouseTrackerAnnotation
,
Matrix4
>
previous
=
_annotations
;
_annotations
=
value
;
_annotations
=
value
;
return
previous
;
return
previous
;
}
}
...
@@ -215,12 +217,12 @@ class MouseTrackerUpdateDetails with Diagnosticable {
...
@@ -215,12 +217,12 @@ class MouseTrackerUpdateDetails with Diagnosticable {
/// The annotations that the device is hovering before the update.
/// The annotations that the device is hovering before the update.
///
///
/// It is never null.
/// It is never null.
final
LinkedHash
Set
<
MouseTrackerAnnotation
>
lastAnnotations
;
final
LinkedHash
Map
<
MouseTrackerAnnotation
,
Matrix4
>
lastAnnotations
;
/// The annotations that the device is hovering after the update.
/// The annotations that the device is hovering after the update.
///
///
/// It is never null.
/// It is never null.
final
LinkedHash
Set
<
MouseTrackerAnnotation
>
nextAnnotations
;
final
LinkedHash
Map
<
MouseTrackerAnnotation
,
Matrix4
>
nextAnnotations
;
/// The last event that the device observed before the update.
/// The last event that the device observed before the update.
///
///
...
@@ -259,8 +261,8 @@ class MouseTrackerUpdateDetails with Diagnosticable {
...
@@ -259,8 +261,8 @@ class MouseTrackerUpdateDetails with Diagnosticable {
properties
.
add
(
IntProperty
(
'device'
,
device
));
properties
.
add
(
IntProperty
(
'device'
,
device
));
properties
.
add
(
DiagnosticsProperty
<
PointerEvent
>(
'previousEvent'
,
previousEvent
));
properties
.
add
(
DiagnosticsProperty
<
PointerEvent
>(
'previousEvent'
,
previousEvent
));
properties
.
add
(
DiagnosticsProperty
<
PointerEvent
>(
'triggeringEvent'
,
triggeringEvent
));
properties
.
add
(
DiagnosticsProperty
<
PointerEvent
>(
'triggeringEvent'
,
triggeringEvent
));
properties
.
add
(
DiagnosticsProperty
<
Set
<
MouseTrackerAnnotation
>>(
'lastAnnotations'
,
lastAnnotations
));
properties
.
add
(
DiagnosticsProperty
<
Map
<
MouseTrackerAnnotation
,
Matrix4
>>(
'lastAnnotations'
,
lastAnnotations
));
properties
.
add
(
DiagnosticsProperty
<
Set
<
MouseTrackerAnnotation
>>(
'nextAnnotations'
,
nextAnnotations
));
properties
.
add
(
DiagnosticsProperty
<
Map
<
MouseTrackerAnnotation
,
Matrix4
>>(
'nextAnnotations'
,
nextAnnotations
));
}
}
}
}
...
@@ -418,16 +420,17 @@ class BaseMouseTracker extends ChangeNotifier {
...
@@ -418,16 +420,17 @@ class BaseMouseTracker extends ChangeNotifier {
||
lastEvent
.
position
!=
event
.
position
;
||
lastEvent
.
position
!=
event
.
position
;
}
}
// Find the annotations that is hovered by the device of the `state`.
// Find the annotations that is hovered by the device of the `state`, and
// their respective global transform matrices.
//
//
// If the device is not connected
, an empty set is returned without calling
// If the device is not connected
or not a mouse, an empty map is returned
// `annotationFinder`.
//
without calling
`annotationFinder`.
LinkedHash
Set
<
MouseTrackerAnnotation
>
_findAnnotations
(
_MouseState
state
)
{
LinkedHash
Map
<
MouseTrackerAnnotation
,
Matrix4
>
_findAnnotations
(
_MouseState
state
)
{
final
Offset
globalPosition
=
state
.
latestEvent
.
position
;
final
Offset
globalPosition
=
state
.
latestEvent
.
position
;
final
int
device
=
state
.
device
;
final
int
device
=
state
.
device
;
return
(
_mouseStates
.
containsKey
(
device
))
if
(!
_mouseStates
.
containsKey
(
device
))
?
LinkedHashSet
<
MouseTrackerAnnotation
>.
from
(
annotationFinder
(
globalPosition
))
return
<
MouseTrackerAnnotation
,
Matrix4
>{}
as
LinkedHashMap
<
MouseTrackerAnnotation
,
Matrix4
>;
:
<
MouseTrackerAnnotation
>{}
as
LinkedHashSet
<
MouseTrackerAnnotation
>
;
return
annotationFinder
(
globalPosition
)
;
}
}
/// A callback that is called on the update of a device.
/// A callback that is called on the update of a device.
...
@@ -485,8 +488,8 @@ class BaseMouseTracker extends ChangeNotifier {
...
@@ -485,8 +488,8 @@ class BaseMouseTracker extends ChangeNotifier {
final
_MouseState
targetState
=
_mouseStates
[
device
]
??
existingState
;
final
_MouseState
targetState
=
_mouseStates
[
device
]
??
existingState
;
final
PointerEvent
lastEvent
=
targetState
.
replaceLatestEvent
(
event
);
final
PointerEvent
lastEvent
=
targetState
.
replaceLatestEvent
(
event
);
final
LinkedHash
Set
<
MouseTrackerAnnotation
>
nextAnnotations
=
_findAnnotations
(
targetState
);
final
LinkedHash
Map
<
MouseTrackerAnnotation
,
Matrix4
>
nextAnnotations
=
_findAnnotations
(
targetState
);
final
LinkedHash
Set
<
MouseTrackerAnnotation
>
lastAnnotations
=
targetState
.
replaceAnnotations
(
nextAnnotations
);
final
LinkedHash
Map
<
MouseTrackerAnnotation
,
Matrix4
>
lastAnnotations
=
targetState
.
replaceAnnotations
(
nextAnnotations
);
handleDeviceUpdate
(
MouseTrackerUpdateDetails
.
byPointerEvent
(
handleDeviceUpdate
(
MouseTrackerUpdateDetails
.
byPointerEvent
(
lastAnnotations:
lastAnnotations
,
lastAnnotations:
lastAnnotations
,
...
@@ -506,8 +509,8 @@ class BaseMouseTracker extends ChangeNotifier {
...
@@ -506,8 +509,8 @@ class BaseMouseTracker extends ChangeNotifier {
_deviceUpdatePhase
(()
{
_deviceUpdatePhase
(()
{
for
(
final
_MouseState
dirtyState
in
_mouseStates
.
values
)
{
for
(
final
_MouseState
dirtyState
in
_mouseStates
.
values
)
{
final
PointerEvent
lastEvent
=
dirtyState
.
latestEvent
;
final
PointerEvent
lastEvent
=
dirtyState
.
latestEvent
;
final
LinkedHash
Set
<
MouseTrackerAnnotation
>
nextAnnotations
=
_findAnnotations
(
dirtyState
);
final
LinkedHash
Map
<
MouseTrackerAnnotation
,
Matrix4
>
nextAnnotations
=
_findAnnotations
(
dirtyState
);
final
LinkedHash
Set
<
MouseTrackerAnnotation
>
lastAnnotations
=
dirtyState
.
replaceAnnotations
(
nextAnnotations
);
final
LinkedHash
Map
<
MouseTrackerAnnotation
,
Matrix4
>
lastAnnotations
=
dirtyState
.
replaceAnnotations
(
nextAnnotations
);
handleDeviceUpdate
(
MouseTrackerUpdateDetails
.
byNewFrame
(
handleDeviceUpdate
(
MouseTrackerUpdateDetails
.
byNewFrame
(
lastAnnotations:
lastAnnotations
,
lastAnnotations:
lastAnnotations
,
...
@@ -531,8 +534,8 @@ mixin _MouseTrackerEventMixin on BaseMouseTracker {
...
@@ -531,8 +534,8 @@ mixin _MouseTrackerEventMixin on BaseMouseTracker {
final
PointerEvent
triggeringEvent
=
details
.
triggeringEvent
;
final
PointerEvent
triggeringEvent
=
details
.
triggeringEvent
;
final
PointerEvent
latestEvent
=
details
.
latestEvent
;
final
PointerEvent
latestEvent
=
details
.
latestEvent
;
final
LinkedHash
Set
<
MouseTrackerAnnotation
>
lastAnnotations
=
details
.
lastAnnotations
;
final
LinkedHash
Map
<
MouseTrackerAnnotation
,
Matrix4
>
lastAnnotations
=
details
.
lastAnnotations
;
final
LinkedHash
Set
<
MouseTrackerAnnotation
>
nextAnnotations
=
details
.
nextAnnotations
;
final
LinkedHash
Map
<
MouseTrackerAnnotation
,
Matrix4
>
nextAnnotations
=
details
.
nextAnnotations
;
// Order is important for mouse event callbacks. The `findAnnotations`
// Order is important for mouse event callbacks. The `findAnnotations`
// returns annotations in the visual order from front to back. We call
// returns annotations in the visual order from front to back. We call
...
@@ -542,19 +545,22 @@ mixin _MouseTrackerEventMixin on BaseMouseTracker {
...
@@ -542,19 +545,22 @@ mixin _MouseTrackerEventMixin on BaseMouseTracker {
// Send exit events to annotations that are in last but not in next, in
// Send exit events to annotations that are in last but not in next, in
// visual order.
// visual order.
final
Iterable
<
MouseTrackerAnnotation
>
exitingAnnotations
=
lastAnnotations
.
difference
(
nextAnnotations
);
final
PointerExitEvent
baseExitEvent
=
PointerExitEvent
.
fromMouseEvent
(
latestEvent
);
for
(
final
MouseTrackerAnnotation
annotation
in
exitingAnnotations
)
{
lastAnnotations
.
forEach
((
MouseTrackerAnnotation
annotation
,
Matrix4
transform
)
{
if
(
annotation
.
onExit
!=
null
)
if
(!
nextAnnotations
.
containsKey
(
annotation
))
annotation
.
onExit
(
PointerExitEvent
.
fromMouseEvent
(
latestEvent
));
if
(
annotation
.
onExit
!=
null
)
}
annotation
.
onExit
(
baseExitEvent
.
transformed
(
lastAnnotations
[
annotation
]));
});
// Send enter events to annotations that are not in last but in next, in
// Send enter events to annotations that are not in last but in next, in
// reverse visual order.
// reverse visual order.
final
Iterable
<
MouseTrackerAnnotation
>
enteringAnnotations
=
final
List
<
MouseTrackerAnnotation
>
enteringAnnotations
=
nextAnnotations
.
keys
.
where
(
nextAnnotations
.
difference
(
lastAnnotations
).
toList
().
reversed
;
(
MouseTrackerAnnotation
annotation
)
=>
!
lastAnnotations
.
containsKey
(
annotation
),
for
(
final
MouseTrackerAnnotation
annotation
in
enteringAnnotations
)
{
).
toList
();
final
PointerEnterEvent
baseEnterEvent
=
PointerEnterEvent
.
fromMouseEvent
(
latestEvent
);
for
(
final
MouseTrackerAnnotation
annotation
in
enteringAnnotations
.
reversed
)
{
if
(
annotation
.
onEnter
!=
null
)
if
(
annotation
.
onEnter
!=
null
)
annotation
.
onEnter
(
PointerEnterEvent
.
fromMouseEvent
(
latestEvent
));
annotation
.
onEnter
(
baseEnterEvent
.
transformed
(
nextAnnotations
[
annotation
]
));
}
}
// Send hover events to annotations that are in next, in reverse visual
// Send hover events to annotations that are in next, in reverse visual
...
@@ -567,10 +573,10 @@ mixin _MouseTrackerEventMixin on BaseMouseTracker {
...
@@ -567,10 +573,10 @@ mixin _MouseTrackerEventMixin on BaseMouseTracker {
// last hover, then trigger the hover callback on all annotations.
// last hover, then trigger the hover callback on all annotations.
// Otherwise, trigger the hover callback only on annotations that it
// Otherwise, trigger the hover callback only on annotations that it
// newly enters.
// newly enters.
final
Iterable
<
MouseTrackerAnnotation
>
hoveringAnnotations
=
pointerHasMoved
?
nextAnnotations
.
toList
().
reversed
:
enteringAnnotations
;
final
Iterable
<
MouseTrackerAnnotation
>
hoveringAnnotations
=
pointerHasMoved
?
nextAnnotations
.
keys
.
toList
().
reversed
:
enteringAnnotations
;
for
(
final
MouseTrackerAnnotation
annotation
in
hoveringAnnotations
)
{
for
(
final
MouseTrackerAnnotation
annotation
in
hoveringAnnotations
)
{
if
(
annotation
.
onHover
!=
null
)
{
if
(
annotation
.
onHover
!=
null
)
{
annotation
.
onHover
(
triggeringEvent
);
annotation
.
onHover
(
triggeringEvent
.
transformed
(
nextAnnotations
[
annotation
])
);
}
}
}
}
}
}
...
...
packages/flutter/lib/src/rendering/view.dart
View file @
da8695d3
...
@@ -4,6 +4,7 @@
...
@@ -4,6 +4,7 @@
// @dart = 2.8
// @dart = 2.8
import
'dart:collection'
show
LinkedHashMap
;
import
'dart:developer'
;
import
'dart:developer'
;
import
'dart:io'
show
Platform
;
import
'dart:io'
show
Platform
;
import
'dart:ui'
as
ui
show
Scene
,
SceneBuilder
,
Window
;
import
'dart:ui'
as
ui
show
Scene
,
SceneBuilder
,
Window
;
...
@@ -198,7 +199,7 @@ class RenderView extends RenderObject with RenderObjectWithChildMixin<RenderBox>
...
@@ -198,7 +199,7 @@ class RenderView extends RenderObject with RenderObjectWithChildMixin<RenderBox>
///
///
/// * [Layer.findAllAnnotations], which is used by this method to find all
/// * [Layer.findAllAnnotations], which is used by this method to find all
/// [AnnotatedRegionLayer]s annotated for mouse tracking.
/// [AnnotatedRegionLayer]s annotated for mouse tracking.
Iterable
<
MouseTrackerAnnotation
>
hitTestMouseTrackers
(
Offset
position
)
{
LinkedHashMap
<
MouseTrackerAnnotation
,
Matrix4
>
hitTestMouseTrackers
(
Offset
position
)
{
// Layer hit testing is done using device pixels, so we have to convert
// Layer hit testing is done using device pixels, so we have to convert
// the logical coordinates of the event location back to device pixels
// the logical coordinates of the event location back to device pixels
// here.
// here.
...
@@ -206,10 +207,11 @@ class RenderView extends RenderObject with RenderObjectWithChildMixin<RenderBox>
...
@@ -206,10 +207,11 @@ class RenderView extends RenderObject with RenderObjectWithChildMixin<RenderBox>
if
(
child
!=
null
)
if
(
child
!=
null
)
child
.
hitTest
(
result
,
position:
position
);
child
.
hitTest
(
result
,
position:
position
);
result
.
add
(
HitTestEntry
(
this
));
result
.
add
(
HitTestEntry
(
this
));
final
List
<
MouseTrackerAnnotation
>
annotations
=
<
MouseTrackerAnnotation
>[];
final
LinkedHashMap
<
MouseTrackerAnnotation
,
Matrix4
>
annotations
=
<
MouseTrackerAnnotation
,
Matrix4
>{}
as
LinkedHashMap
<
MouseTrackerAnnotation
,
Matrix4
>;
for
(
final
HitTestEntry
entry
in
result
.
path
)
{
for
(
final
HitTestEntry
entry
in
result
.
path
)
{
if
(
entry
.
target
is
MouseTrackerAnnotation
)
{
if
(
entry
.
target
is
MouseTrackerAnnotation
)
{
annotations
.
add
(
entry
.
target
as
MouseTrackerAnnotation
)
;
annotations
[
entry
.
target
as
MouseTrackerAnnotation
]
=
entry
.
transform
;
}
}
}
}
return
annotations
;
return
annotations
;
...
...
packages/flutter/test/rendering/mouse_tracking_cursor_test.dart
View file @
da8695d3
...
@@ -4,6 +4,7 @@
...
@@ -4,6 +4,7 @@
// @dart = 2.8
// @dart = 2.8
import
'dart:collection'
show
LinkedHashMap
;
import
'dart:ui'
as
ui
;
import
'dart:ui'
as
ui
;
import
'dart:ui'
show
PointerChange
;
import
'dart:ui'
show
PointerChange
;
...
@@ -25,12 +26,14 @@ void _ensureTestGestureBinding() {
...
@@ -25,12 +26,14 @@ void _ensureTestGestureBinding() {
assert
(
GestureBinding
.
instance
!=
null
);
assert
(
GestureBinding
.
instance
!=
null
);
}
}
typedef
SimpleAnnotationFinder
=
Iterable
<
MouseTrackerAnnotation
>
Function
(
Offset
offset
);
void
main
(
)
{
void
main
(
)
{
MethodCallHandler
_methodCallHandler
;
MethodCallHandler
_methodCallHandler
;
// Only one of `logCursors` and `cursorHandler` should be specified.
// Only one of `logCursors` and `cursorHandler` should be specified.
void
_setUpMouseTracker
({
void
_setUpMouseTracker
({
MouseDetector
AnnotationFinder
annotationFinder
,
Simple
AnnotationFinder
annotationFinder
,
List
<
_CursorUpdateDetails
>
logCursors
,
List
<
_CursorUpdateDetails
>
logCursors
,
MethodCallHandler
cursorHandler
,
MethodCallHandler
cursorHandler
,
})
{
})
{
...
@@ -43,7 +46,11 @@ void main() {
...
@@ -43,7 +46,11 @@ void main() {
:
cursorHandler
;
:
cursorHandler
;
final
MouseTracker
mouseTracker
=
MouseTracker
(
final
MouseTracker
mouseTracker
=
MouseTracker
(
GestureBinding
.
instance
.
pointerRouter
,
GestureBinding
.
instance
.
pointerRouter
,
annotationFinder
,
(
Offset
offset
)
=>
LinkedHashMap
<
MouseTrackerAnnotation
,
Matrix4
>.
fromEntries
(
annotationFinder
(
offset
).
map
(
(
MouseTrackerAnnotation
annotation
)
=>
MapEntry
<
MouseTrackerAnnotation
,
Matrix4
>(
annotation
,
Matrix4
.
identity
()),
),
),
);
);
RendererBinding
.
instance
.
initMouseTracker
(
mouseTracker
);
RendererBinding
.
instance
.
initMouseTracker
(
mouseTracker
);
}
}
...
...
packages/flutter/test/rendering/mouse_tracking_test.dart
View file @
da8695d3
...
@@ -4,6 +4,7 @@
...
@@ -4,6 +4,7 @@
// @dart = 2.8
// @dart = 2.8
import
'dart:collection'
show
LinkedHashMap
;
import
'dart:ui'
as
ui
;
import
'dart:ui'
as
ui
;
import
'dart:ui'
show
PointerChange
;
import
'dart:ui'
show
PointerChange
;
...
@@ -13,6 +14,7 @@ import 'package:flutter/rendering.dart';
...
@@ -13,6 +14,7 @@ import 'package:flutter/rendering.dart';
import
'package:flutter/gestures.dart'
;
import
'package:flutter/gestures.dart'
;
import
'package:flutter/scheduler.dart'
;
import
'package:flutter/scheduler.dart'
;
import
'package:flutter/services.dart'
;
import
'package:flutter/services.dart'
;
import
'package:vector_math/vector_math_64.dart'
show
Matrix4
;
import
'../flutter_test_alternative.dart'
;
import
'../flutter_test_alternative.dart'
;
...
@@ -65,11 +67,29 @@ void _ensureTestGestureBinding() {
...
@@ -65,11 +67,29 @@ void _ensureTestGestureBinding() {
assert
(
GestureBinding
.
instance
!=
null
);
assert
(
GestureBinding
.
instance
!=
null
);
}
}
@immutable
class
AnnotationEntry
{
AnnotationEntry
(
this
.
annotation
,
[
Matrix4
transform
])
:
transform
=
transform
??
Matrix4
.
identity
();
final
MouseTrackerAnnotation
annotation
;
final
Matrix4
transform
;
}
typedef
SimpleAnnotationFinder
=
Iterable
<
AnnotationEntry
>
Function
(
Offset
offset
);
void
main
(
)
{
void
main
(
)
{
void
_setUpMouseAnnotationFinder
(
MouseDetector
AnnotationFinder
annotationFinder
)
{
void
_setUpMouseAnnotationFinder
(
Simple
AnnotationFinder
annotationFinder
)
{
final
MouseTracker
mouseTracker
=
MouseTracker
(
final
MouseTracker
mouseTracker
=
MouseTracker
(
GestureBinding
.
instance
.
pointerRouter
,
GestureBinding
.
instance
.
pointerRouter
,
annotationFinder
,
(
Offset
offset
)
=>
LinkedHashMap
<
MouseTrackerAnnotation
,
Matrix4
>.
fromEntries
(
annotationFinder
(
offset
).
map
(
(
AnnotationEntry
entry
)
=>
MapEntry
<
MouseTrackerAnnotation
,
Matrix4
>(
entry
.
annotation
,
entry
.
transform
,
),
),
),
);
);
RendererBinding
.
instance
.
initMouseTracker
(
mouseTracker
);
RendererBinding
.
instance
.
initMouseTracker
(
mouseTracker
);
}
}
...
@@ -96,7 +116,7 @@ void main() {
...
@@ -96,7 +116,7 @@ void main() {
);
);
_setUpMouseAnnotationFinder
(
_setUpMouseAnnotationFinder
(
(
Offset
position
)
sync
*
{
(
Offset
position
)
sync
*
{
yield
annotation
;
yield
AnnotationEntry
(
annotation
)
;
},
},
);
);
return
annotation
;
return
annotation
;
...
@@ -312,7 +332,7 @@ void main() {
...
@@ -312,7 +332,7 @@ void main() {
);
);
_setUpMouseAnnotationFinder
((
Offset
position
)
sync
*
{
_setUpMouseAnnotationFinder
((
Offset
position
)
sync
*
{
if
(
isInHitRegion
)
{
if
(
isInHitRegion
)
{
yield
annotation
;
yield
AnnotationEntry
(
annotation
,
Matrix4
.
translationValues
(
10
,
20
,
0
))
;
}
}
});
});
...
@@ -334,7 +354,7 @@ void main() {
...
@@ -334,7 +354,7 @@ void main() {
_binding
.
flushPostFrameCallbacks
(
Duration
.
zero
);
_binding
.
flushPostFrameCallbacks
(
Duration
.
zero
);
expect
(
events
,
_equalToEventsOnCriticalFields
(<
PointerEvent
>[
expect
(
events
,
_equalToEventsOnCriticalFields
(<
PointerEvent
>[
const
PointerEnterEvent
(
position:
Offset
(
0
.0
,
100.
0
)),
const
PointerEnterEvent
(
position:
Offset
(
0
,
100
),
localPosition:
Offset
(
10
,
12
0
)),
]));
]));
events
.
clear
();
events
.
clear
();
...
@@ -345,7 +365,7 @@ void main() {
...
@@ -345,7 +365,7 @@ void main() {
_binding
.
flushPostFrameCallbacks
(
Duration
.
zero
);
_binding
.
flushPostFrameCallbacks
(
Duration
.
zero
);
expect
(
events
,
_equalToEventsOnCriticalFields
(<
PointerEvent
>[
expect
(
events
,
_equalToEventsOnCriticalFields
(<
PointerEvent
>[
const
PointerExitEvent
(
position:
Offset
(
0.0
,
100.0
)),
const
PointerExitEvent
(
position:
Offset
(
0.0
,
100.0
)
,
localPosition:
Offset
(
10
,
120
)
),
]));
]));
expect
(
_binding
.
postFrameCallbacks
,
hasLength
(
0
));
expect
(
_binding
.
postFrameCallbacks
,
hasLength
(
0
));
});
});
...
@@ -360,7 +380,7 @@ void main() {
...
@@ -360,7 +380,7 @@ void main() {
);
);
_setUpMouseAnnotationFinder
((
Offset
position
)
sync
*
{
_setUpMouseAnnotationFinder
((
Offset
position
)
sync
*
{
if
(
isInHitRegion
)
{
if
(
isInHitRegion
)
{
yield
annotation
;
yield
AnnotationEntry
(
annotation
,
Matrix4
.
translationValues
(
10
,
20
,
0
))
;
}
}
});
});
...
@@ -380,7 +400,7 @@ void main() {
...
@@ -380,7 +400,7 @@ void main() {
_binding
.
flushPostFrameCallbacks
(
Duration
.
zero
);
_binding
.
flushPostFrameCallbacks
(
Duration
.
zero
);
expect
(
events
,
_equalToEventsOnCriticalFields
(<
PointerEvent
>[
expect
(
events
,
_equalToEventsOnCriticalFields
(<
PointerEvent
>[
const
PointerEnterEvent
(
position:
Offset
(
0.0
,
100.0
)),
const
PointerEnterEvent
(
position:
Offset
(
0.0
,
100.0
)
,
localPosition:
Offset
(
10
,
120
)
),
]));
]));
events
.
clear
();
events
.
clear
();
...
@@ -394,7 +414,7 @@ void main() {
...
@@ -394,7 +414,7 @@ void main() {
_binding
.
flushPostFrameCallbacks
(
Duration
.
zero
);
_binding
.
flushPostFrameCallbacks
(
Duration
.
zero
);
expect
(
events
,
_equalToEventsOnCriticalFields
(<
PointerEvent
>[
expect
(
events
,
_equalToEventsOnCriticalFields
(<
PointerEvent
>[
const
PointerExitEvent
(
position:
Offset
(
0.0
,
100.0
)),
const
PointerExitEvent
(
position:
Offset
(
0.0
,
100.0
)
,
localPosition:
Offset
(
10
,
120
)
),
]));
]));
expect
(
_binding
.
postFrameCallbacks
,
hasLength
(
0
));
expect
(
_binding
.
postFrameCallbacks
,
hasLength
(
0
));
});
});
...
@@ -409,7 +429,7 @@ void main() {
...
@@ -409,7 +429,7 @@ void main() {
);
);
_setUpMouseAnnotationFinder
((
Offset
position
)
sync
*
{
_setUpMouseAnnotationFinder
((
Offset
position
)
sync
*
{
if
(
isInHitRegion
)
{
if
(
isInHitRegion
)
{
yield
annotation
;
yield
AnnotationEntry
(
annotation
,
Matrix4
.
translationValues
(
10
,
20
,
0
))
;
}
}
});
});
...
@@ -423,7 +443,7 @@ void main() {
...
@@ -423,7 +443,7 @@ void main() {
expect
(
_binding
.
postFrameCallbacks
,
hasLength
(
0
));
expect
(
_binding
.
postFrameCallbacks
,
hasLength
(
0
));
expect
(
events
,
_equalToEventsOnCriticalFields
(<
PointerEvent
>[
expect
(
events
,
_equalToEventsOnCriticalFields
(<
PointerEvent
>[
const
PointerEnterEvent
(
position:
Offset
(
0.0
,
100.0
)),
const
PointerEnterEvent
(
position:
Offset
(
0.0
,
100.0
)
,
localPosition:
Offset
(
10
,
120
)
),
]));
]));
events
.
clear
();
events
.
clear
();
...
@@ -433,7 +453,7 @@ void main() {
...
@@ -433,7 +453,7 @@ void main() {
]));
]));
expect
(
_binding
.
postFrameCallbacks
,
hasLength
(
0
));
expect
(
_binding
.
postFrameCallbacks
,
hasLength
(
0
));
expect
(
events
,
_equalToEventsOnCriticalFields
(<
PointerEvent
>[
expect
(
events
,
_equalToEventsOnCriticalFields
(<
PointerEvent
>[
const
PointerExitEvent
(
position:
Offset
(
0.0
,
100.0
)),
const
PointerExitEvent
(
position:
Offset
(
0.0
,
100.0
)
,
localPosition:
Offset
(
10
,
120
)
),
]));
]));
});
});
...
@@ -447,7 +467,7 @@ void main() {
...
@@ -447,7 +467,7 @@ void main() {
);
);
_setUpMouseAnnotationFinder
((
Offset
position
)
sync
*
{
_setUpMouseAnnotationFinder
((
Offset
position
)
sync
*
{
if
(
isInHitRegion
)
{
if
(
isInHitRegion
)
{
yield
annotation
;
yield
AnnotationEntry
(
annotation
,
Matrix4
.
translationValues
(
10
,
20
,
0
))
;
}
}
});
});
...
@@ -466,8 +486,8 @@ void main() {
...
@@ -466,8 +486,8 @@ void main() {
]));
]));
expect
(
_binding
.
postFrameCallbacks
,
hasLength
(
0
));
expect
(
_binding
.
postFrameCallbacks
,
hasLength
(
0
));
expect
(
events
,
_equalToEventsOnCriticalFields
(<
PointerEvent
>[
expect
(
events
,
_equalToEventsOnCriticalFields
(<
PointerEvent
>[
const
PointerEnterEvent
(
position:
Offset
(
0.0
,
100.0
)),
const
PointerEnterEvent
(
position:
Offset
(
0.0
,
100.0
)
,
localPosition:
Offset
(
10
,
120
)
),
const
PointerHoverEvent
(
position:
Offset
(
0.0
,
100.0
)),
const
PointerHoverEvent
(
position:
Offset
(
0.0
,
100.0
)
,
localPosition:
Offset
(
10
,
120
)
),
]));
]));
events
.
clear
();
events
.
clear
();
...
@@ -478,7 +498,7 @@ void main() {
...
@@ -478,7 +498,7 @@ void main() {
]));
]));
expect
(
_binding
.
postFrameCallbacks
,
hasLength
(
0
));
expect
(
_binding
.
postFrameCallbacks
,
hasLength
(
0
));
expect
(
events
,
_equalToEventsOnCriticalFields
(<
PointerEvent
>[
expect
(
events
,
_equalToEventsOnCriticalFields
(<
PointerEvent
>[
const
PointerExitEvent
(
position:
Offset
(
200.0
,
100.0
)),
const
PointerExitEvent
(
position:
Offset
(
200.0
,
100.0
)
,
localPosition:
Offset
(
210
,
120
)
),
]));
]));
});
});
...
@@ -506,9 +526,9 @@ void main() {
...
@@ -506,9 +526,9 @@ void main() {
);
);
_setUpMouseAnnotationFinder
((
Offset
position
)
sync
*
{
_setUpMouseAnnotationFinder
((
Offset
position
)
sync
*
{
if
(
isInHitRegionOne
)
if
(
isInHitRegionOne
)
yield
annotation1
;
yield
AnnotationEntry
(
annotation1
)
;
else
if
(
isInHitRegionTwo
)
else
if
(
isInHitRegionTwo
)
yield
annotation2
;
yield
AnnotationEntry
(
annotation2
)
;
});
});
isInHitRegionOne
=
false
;
isInHitRegionOne
=
false
;
...
@@ -546,8 +566,8 @@ void main() {
...
@@ -546,8 +566,8 @@ void main() {
_setUpMouseAnnotationFinder
((
Offset
position
)
sync
*
{
_setUpMouseAnnotationFinder
((
Offset
position
)
sync
*
{
// Children's annotations come before parents'.
// Children's annotations come before parents'.
if
(
isInB
)
{
if
(
isInB
)
{
yield
annotationB
;
yield
AnnotationEntry
(
annotationB
)
;
yield
annotationA
;
yield
AnnotationEntry
(
annotationA
)
;
}
}
});
});
...
@@ -598,9 +618,9 @@ void main() {
...
@@ -598,9 +618,9 @@ void main() {
);
);
_setUpMouseAnnotationFinder
((
Offset
position
)
sync
*
{
_setUpMouseAnnotationFinder
((
Offset
position
)
sync
*
{
if
(
isInA
)
{
if
(
isInA
)
{
yield
annotationA
;
yield
AnnotationEntry
(
annotationA
)
;
}
else
if
(
isInB
)
{
}
else
if
(
isInB
)
{
yield
annotationB
;
yield
AnnotationEntry
(
annotationB
)
;
}
}
});
});
...
@@ -676,7 +696,8 @@ class _EventCriticalFieldsMatcher extends Matcher {
...
@@ -676,7 +696,8 @@ class _EventCriticalFieldsMatcher extends Matcher {
if
(!(
if
(!(
_matchesField
(
matchState
,
'kind'
,
actual
.
kind
,
PointerDeviceKind
.
mouse
)
&&
_matchesField
(
matchState
,
'kind'
,
actual
.
kind
,
PointerDeviceKind
.
mouse
)
&&
_matchesField
(
matchState
,
'position'
,
actual
.
position
,
_expected
.
position
)
&&
_matchesField
(
matchState
,
'position'
,
actual
.
position
,
_expected
.
position
)
&&
_matchesField
(
matchState
,
'device'
,
actual
.
device
,
_expected
.
device
)
_matchesField
(
matchState
,
'device'
,
actual
.
device
,
_expected
.
device
)
&&
_matchesField
(
matchState
,
'localPosition'
,
actual
.
localPosition
,
_expected
.
localPosition
)
))
{
))
{
return
false
;
return
false
;
}
}
...
...
packages/flutter/test/rendering/proxy_box_test.dart
View file @
da8695d3
...
@@ -4,6 +4,7 @@
...
@@ -4,6 +4,7 @@
// @dart = 2.8
// @dart = 2.8
import
'dart:collection'
show
LinkedHashMap
;
import
'dart:typed_data'
;
import
'dart:typed_data'
;
import
'dart:ui'
as
ui
show
Gradient
,
Image
,
ImageFilter
;
import
'dart:ui'
as
ui
show
Gradient
,
Image
,
ImageFilter
;
...
@@ -492,7 +493,7 @@ void main() {
...
@@ -492,7 +493,7 @@ void main() {
test
(
'RenderMouseRegion can change properties when detached'
,
()
{
test
(
'RenderMouseRegion can change properties when detached'
,
()
{
renderer
.
initMouseTracker
(
MouseTracker
(
renderer
.
initMouseTracker
(
MouseTracker
(
renderer
.
pointerRouter
,
renderer
.
pointerRouter
,
(
_
)
=>
<
MouseTrackerAnnotation
>[]
,
(
_
)
=>
<
MouseTrackerAnnotation
,
Matrix4
>{}
as
LinkedHashMap
<
MouseTrackerAnnotation
,
Matrix4
>
,
));
));
final
RenderMouseRegion
object
=
RenderMouseRegion
();
final
RenderMouseRegion
object
=
RenderMouseRegion
();
object
object
...
...
packages/flutter/test/widgets/mouse_region_test.dart
View file @
da8695d3
...
@@ -112,8 +112,10 @@ void main() {
...
@@ -112,8 +112,10 @@ void main() {
await
gesture
.
moveTo
(
const
Offset
(
400.0
,
300.0
));
await
gesture
.
moveTo
(
const
Offset
(
400.0
,
300.0
));
expect
(
move
,
isNotNull
);
expect
(
move
,
isNotNull
);
expect
(
move
.
position
,
equals
(
const
Offset
(
400.0
,
300.0
)));
expect
(
move
.
position
,
equals
(
const
Offset
(
400.0
,
300.0
)));
expect
(
move
.
localPosition
,
equals
(
const
Offset
(
50.0
,
50.0
)));
expect
(
enter
,
isNotNull
);
expect
(
enter
,
isNotNull
);
expect
(
enter
.
position
,
equals
(
const
Offset
(
400.0
,
300.0
)));
expect
(
enter
.
position
,
equals
(
const
Offset
(
400.0
,
300.0
)));
expect
(
enter
.
localPosition
,
equals
(
const
Offset
(
50.0
,
50.0
)));
expect
(
exit
,
isNull
);
expect
(
exit
,
isNull
);
});
});
...
@@ -145,6 +147,7 @@ void main() {
...
@@ -145,6 +147,7 @@ void main() {
expect
(
enter
,
isNull
);
expect
(
enter
,
isNull
);
expect
(
exit
,
isNotNull
);
expect
(
exit
,
isNotNull
);
expect
(
exit
.
position
,
equals
(
const
Offset
(
1.0
,
1.0
)));
expect
(
exit
.
position
,
equals
(
const
Offset
(
1.0
,
1.0
)));
expect
(
exit
.
localPosition
,
equals
(
const
Offset
(-
349.0
,
-
249.0
)));
});
});
testWidgets
(
'triggers pointer enter when a mouse is connected'
,
(
WidgetTester
tester
)
async
{
testWidgets
(
'triggers pointer enter when a mouse is connected'
,
(
WidgetTester
tester
)
async
{
...
@@ -170,6 +173,7 @@ void main() {
...
@@ -170,6 +173,7 @@ void main() {
expect
(
move
,
isNull
);
expect
(
move
,
isNull
);
expect
(
enter
,
isNotNull
);
expect
(
enter
,
isNotNull
);
expect
(
enter
.
position
,
equals
(
const
Offset
(
400.0
,
300.0
)));
expect
(
enter
.
position
,
equals
(
const
Offset
(
400.0
,
300.0
)));
expect
(
enter
.
localPosition
,
equals
(
const
Offset
(
50.0
,
50.0
)));
expect
(
exit
,
isNull
);
expect
(
exit
,
isNull
);
});
});
...
@@ -203,6 +207,7 @@ void main() {
...
@@ -203,6 +207,7 @@ void main() {
expect
(
enter
,
isNull
);
expect
(
enter
,
isNull
);
expect
(
exit
,
isNotNull
);
expect
(
exit
,
isNotNull
);
expect
(
exit
.
position
,
equals
(
const
Offset
(
400.0
,
300.0
)));
expect
(
exit
.
position
,
equals
(
const
Offset
(
400.0
,
300.0
)));
expect
(
exit
.
localPosition
,
equals
(
const
Offset
(
50.0
,
50.0
)));
exit
=
null
;
exit
=
null
;
await
tester
.
pump
();
await
tester
.
pump
();
expect
(
move
,
isNull
);
expect
(
move
,
isNull
);
...
@@ -243,6 +248,7 @@ void main() {
...
@@ -243,6 +248,7 @@ void main() {
expect
(
move
,
isNull
);
expect
(
move
,
isNull
);
expect
(
enter
,
isNotNull
);
expect
(
enter
,
isNotNull
);
expect
(
enter
.
position
,
equals
(
const
Offset
(
400.0
,
300.0
)));
expect
(
enter
.
position
,
equals
(
const
Offset
(
400.0
,
300.0
)));
expect
(
enter
.
localPosition
,
equals
(
const
Offset
(
50.0
,
50.0
)));
expect
(
exit
,
isNull
);
expect
(
exit
,
isNull
);
});
});
...
@@ -285,7 +291,7 @@ void main() {
...
@@ -285,7 +291,7 @@ void main() {
PointerHoverEvent
move
;
PointerHoverEvent
move
;
PointerExitEvent
exit
;
PointerExitEvent
exit
;
await
tester
.
pumpWidget
(
Container
(
await
tester
.
pumpWidget
(
Container
(
alignment:
Alignment
.
center
,
alignment:
Alignment
.
topLeft
,
child:
MouseRegion
(
child:
MouseRegion
(
child:
const
SizedBox
(
child:
const
SizedBox
(
width:
100.0
,
width:
100.0
,
...
@@ -297,14 +303,14 @@ void main() {
...
@@ -297,14 +303,14 @@ void main() {
),
),
));
));
final
TestGesture
gesture
=
await
tester
.
createGesture
(
kind:
PointerDeviceKind
.
mouse
);
final
TestGesture
gesture
=
await
tester
.
createGesture
(
kind:
PointerDeviceKind
.
mouse
);
await
gesture
.
addPointer
(
location:
const
Offset
(
1.0
,
1.0
));
await
gesture
.
addPointer
(
location:
const
Offset
(
401.0
,
30
1.0
));
addTearDown
(
gesture
.
removePointer
);
addTearDown
(
gesture
.
removePointer
);
await
tester
.
pump
();
await
tester
.
pump
();
expect
(
enter
,
isNull
);
expect
(
enter
,
isNull
);
expect
(
move
,
isNull
);
expect
(
move
,
isNull
);
expect
(
exit
,
isNull
);
expect
(
exit
,
isNull
);
await
tester
.
pumpWidget
(
Container
(
await
tester
.
pumpWidget
(
Container
(
alignment:
Alignment
.
topLeft
,
alignment:
Alignment
.
center
,
child:
MouseRegion
(
child:
MouseRegion
(
child:
const
SizedBox
(
child:
const
SizedBox
(
width:
100.0
,
width:
100.0
,
...
@@ -317,7 +323,8 @@ void main() {
...
@@ -317,7 +323,8 @@ void main() {
));
));
await
tester
.
pump
();
await
tester
.
pump
();
expect
(
enter
,
isNotNull
);
expect
(
enter
,
isNotNull
);
expect
(
enter
.
position
,
equals
(
const
Offset
(
1.0
,
1.0
)));
expect
(
enter
.
position
,
equals
(
const
Offset
(
401.0
,
301.0
)));
expect
(
enter
.
localPosition
,
equals
(
const
Offset
(
51.0
,
51.0
)));
expect
(
move
,
isNull
);
expect
(
move
,
isNull
);
expect
(
exit
,
isNull
);
expect
(
exit
,
isNull
);
});
});
...
@@ -362,6 +369,7 @@ void main() {
...
@@ -362,6 +369,7 @@ void main() {
expect
(
move
,
isNull
);
expect
(
move
,
isNull
);
expect
(
exit
,
isNotNull
);
expect
(
exit
,
isNotNull
);
expect
(
exit
.
position
,
equals
(
const
Offset
(
400
,
300
)));
expect
(
exit
.
position
,
equals
(
const
Offset
(
400
,
300
)));
expect
(
exit
.
localPosition
,
equals
(
const
Offset
(
50
,
50
)));
});
});
testWidgets
(
'Hover works with nested listeners'
,
(
WidgetTester
tester
)
async
{
testWidgets
(
'Hover works with nested listeners'
,
(
WidgetTester
tester
)
async
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment