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
2cdf2f00
Unverified
Commit
2cdf2f00
authored
Oct 05, 2020
by
Tong Mu
Committed by
GitHub
Oct 05, 2020
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Treat hover events as normal pointer events, and bring them back to Listener (#63834)
parent
2cdec258
Changes
15
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
15 changed files
with
167 additions
and
747 deletions
+167
-747
binding.dart
packages/flutter/lib/src/gestures/binding.dart
+4
-5
binding.dart
packages/flutter/lib/src/rendering/binding.dart
+0
-1
mouse_tracking.dart
packages/flutter/lib/src/rendering/mouse_tracking.dart
+0
-31
platform_view.dart
packages/flutter/lib/src/rendering/platform_view.dart
+3
-7
proxy_box.dart
packages/flutter/lib/src/rendering/proxy_box.dart
+23
-13
platform_views.dart
packages/flutter/lib/src/services/platform_views.dart
+4
-0
basic.dart
packages/flutter/lib/src/widgets/basic.dart
+33
-64
gesture_binding_test.dart
packages/flutter/test/gestures/gesture_binding_test.dart
+4
-1
mouse_tracking_test.dart
packages/flutter/test/rendering/mouse_tracking_test.dart
+1
-1
mouse_tracking_test_utils.dart
...ges/flutter/test/rendering/mouse_tracking_test_utils.dart
+0
-1
platform_view_test.dart
packages/flutter/test/rendering/platform_view_test.dart
+13
-0
listener_deprecated_test.dart
packages/flutter/test/widgets/listener_deprecated_test.dart
+0
-586
listener_test.dart
packages/flutter/test/widgets/listener_test.dart
+28
-0
mouse_region_test.dart
packages/flutter/test/widgets/mouse_region_test.dart
+50
-14
test_pointer.dart
packages/flutter_test/lib/src/test_pointer.dart
+4
-23
No files found.
packages/flutter/lib/src/gestures/binding.dart
View file @
2cdf2f00
...
...
@@ -270,7 +270,7 @@ mixin GestureBinding on BindingBase implements HitTestable, HitTestDispatcher, H
void
handlePointerEvent
(
PointerEvent
event
)
{
assert
(!
locked
);
HitTestResult
?
hitTestResult
;
if
(
event
is
PointerDownEvent
||
event
is
PointerSignalEvent
)
{
if
(
event
is
PointerDownEvent
||
event
is
PointerSignalEvent
||
event
is
PointerHoverEvent
)
{
assert
(!
_hitTests
.
containsKey
(
event
.
pointer
));
hitTestResult
=
HitTestResult
();
hitTest
(
hitTestResult
,
event
.
position
);
...
...
@@ -298,7 +298,6 @@ mixin GestureBinding on BindingBase implements HitTestable, HitTestDispatcher, H
return
true
;
}());
if
(
hitTestResult
!=
null
||
event
is
PointerHoverEvent
||
event
is
PointerAddedEvent
||
event
is
PointerRemovedEvent
)
{
assert
(
event
.
position
!=
null
);
...
...
@@ -318,8 +317,8 @@ mixin GestureBinding on BindingBase implements HitTestable, HitTestDispatcher, H
/// null, the event is also sent to every [HitTestTarget] in the entries of the
/// given [HitTestResult]. Any exceptions from the handlers are caught.
///
/// The `hitTestResult` argument may only be null for [Pointer
HoverEvent]s,
/// [Pointer
AddedEvent]s, or [Pointer
RemovedEvent]s.
/// The `hitTestResult` argument may only be null for [Pointer
AddedEvent]s or
/// [PointerRemovedEvent]s.
@override
// from HitTestDispatcher
void
dispatchEvent
(
PointerEvent
event
,
HitTestResult
?
hitTestResult
)
{
assert
(!
locked
);
...
...
@@ -327,7 +326,7 @@ mixin GestureBinding on BindingBase implements HitTestable, HitTestDispatcher, H
// [PointerAddedEvent], or [PointerRemovedEvent]. These events are specially
// routed here; other events will be routed through the `handleEvent` below.
if
(
hitTestResult
==
null
)
{
assert
(
event
is
Pointer
HoverEvent
||
event
is
Pointer
AddedEvent
||
event
is
PointerRemovedEvent
);
assert
(
event
is
PointerAddedEvent
||
event
is
PointerRemovedEvent
);
try
{
pointerRouter
.
route
(
event
);
}
catch
(
exception
,
stack
)
{
...
...
packages/flutter/lib/src/rendering/binding.dart
View file @
2cdf2f00
...
...
@@ -259,7 +259,6 @@ mixin RendererBinding on BindingBase, ServicesBinding, SchedulerBinding, Gesture
@override
// from GestureBinding
void
dispatchEvent
(
PointerEvent
event
,
HitTestResult
?
hitTestResult
)
{
if
(
hitTestResult
!=
null
||
event
is
PointerHoverEvent
||
event
is
PointerAddedEvent
||
event
is
PointerRemovedEvent
)
{
assert
(
event
.
position
!=
null
);
...
...
packages/flutter/lib/src/rendering/mouse_tracking.dart
View file @
2cdf2f00
...
...
@@ -53,7 +53,6 @@ class MouseTrackerAnnotation with Diagnosticable {
/// All arguments are optional. The [cursor] must not be null.
const
MouseTrackerAnnotation
({
this
.
onEnter
,
this
.
onHover
,
this
.
onExit
,
this
.
cursor
=
MouseCursor
.
defer
,
})
:
assert
(
cursor
!=
null
);
...
...
@@ -72,16 +71,6 @@ class MouseTrackerAnnotation with Diagnosticable {
/// * [MouseRegion.onEnter], which uses this callback.
final
PointerEnterEventListener
?
onEnter
;
/// Triggered when a mouse pointer has moved onto or within the region without
/// buttons pressed.
///
/// This callback is not triggered by the movement of an annotation.
///
/// See also:
///
/// * [MouseRegion.onHover], which uses this callback.
final
PointerHoverEventListener
?
onHover
;
/// Triggered when a mouse pointer, with or without buttons pressed, has
/// exited the region.
///
...
...
@@ -482,8 +471,6 @@ abstract class BaseMouseTracker extends ChangeNotifier {
mixin
_MouseTrackerEventMixin
on
BaseMouseTracker
{
// Handles device update and dispatches mouse event callbacks.
static
void
_handleDeviceUpdateMouseEvents
(
MouseTrackerUpdateDetails
details
)
{
final
PointerEvent
?
previousEvent
=
details
.
previousEvent
;
final
PointerEvent
?
triggeringEvent
=
details
.
triggeringEvent
;
final
PointerEvent
latestEvent
=
details
.
latestEvent
;
final
LinkedHashMap
<
MouseTrackerAnnotation
,
Matrix4
>
lastAnnotations
=
details
.
lastAnnotations
;
...
...
@@ -514,24 +501,6 @@ mixin _MouseTrackerEventMixin on BaseMouseTracker {
if
(
annotation
.
onEnter
!=
null
)
annotation
.
onEnter
!(
baseEnterEvent
.
transformed
(
nextAnnotations
[
annotation
]));
}
// Send hover events to annotations that are in next, in reverse visual
// order. The reverse visual order is chosen only because of the simplicity
// by keeping the hover events aligned with enter events.
if
(
triggeringEvent
is
PointerHoverEvent
)
{
final
Offset
?
hoverPositionBeforeUpdate
=
previousEvent
is
PointerHoverEvent
?
previousEvent
.
position
:
null
;
final
bool
pointerHasMoved
=
hoverPositionBeforeUpdate
==
null
||
hoverPositionBeforeUpdate
!=
triggeringEvent
.
position
;
// If the hover event follows a non-hover event, or has moved since the
// last hover, then trigger the hover callback on all annotations.
// Otherwise, trigger the hover callback only on annotations that it
// newly enters.
final
Iterable
<
MouseTrackerAnnotation
>
hoveringAnnotations
=
pointerHasMoved
?
nextAnnotations
.
keys
.
toList
().
reversed
:
enteringAnnotations
;
for
(
final
MouseTrackerAnnotation
annotation
in
hoveringAnnotations
)
{
if
(
annotation
.
onHover
!=
null
)
{
annotation
.
onHover
!(
triggeringEvent
.
transformed
(
nextAnnotations
[
annotation
]));
}
}
}
}
@protected
...
...
packages/flutter/lib/src/rendering/platform_view.dart
View file @
2cdf2f00
...
...
@@ -723,13 +723,6 @@ mixin _PlatformViewGestureMixin on RenderBox implements MouseTrackerAnnotation {
@override
PointerEnterEventListener
?
get
onEnter
=>
null
;
@override
PointerHoverEventListener
get
onHover
=>
_handleHover
;
void
_handleHover
(
PointerHoverEvent
event
)
{
if
(
_handlePointerEvent
!=
null
)
_handlePointerEvent
!(
event
);
}
@override
PointerExitEventListener
?
get
onExit
=>
null
;
...
...
@@ -741,6 +734,9 @@ mixin _PlatformViewGestureMixin on RenderBox implements MouseTrackerAnnotation {
if
(
event
is
PointerDownEvent
)
{
_gestureRecognizer
!.
addPointer
(
event
);
}
if
(
event
is
PointerHoverEvent
)
{
_handlePointerEvent
?.
call
(
event
);
}
}
@override
...
...
packages/flutter/lib/src/rendering/proxy_box.dart
View file @
2cdf2f00
...
...
@@ -2662,10 +2662,10 @@ typedef PointerSignalEventListener = void Function(PointerSignalEvent event);
/// Calls callbacks in response to common pointer events.
///
/// It responds to events that can construct gestures, such as when the
/// pointer is p
ressed, moved,
then released or canceled.
/// pointer is p
ointer is pressed and moved, and
then released or canceled.
///
/// It does not respond to events that are exclusive to mouse, such as when the
/// mouse enters
, exits or hover
s a region without pressing any buttons. For
/// mouse enters
and exit
s a region without pressing any buttons. For
/// these events, use [RenderMouseRegion].
///
/// If it has a child, defers to the child for sizing behavior.
...
...
@@ -2679,6 +2679,7 @@ class RenderPointerListener extends RenderProxyBoxWithHitTestBehavior {
this
.
onPointerDown
,
this
.
onPointerMove
,
this
.
onPointerUp
,
this
.
onPointerHover
,
this
.
onPointerCancel
,
this
.
onPointerSignal
,
HitTestBehavior
behavior
=
HitTestBehavior
.
deferToChild
,
...
...
@@ -2697,6 +2698,9 @@ class RenderPointerListener extends RenderProxyBoxWithHitTestBehavior {
/// contact with the screen.
PointerUpEventListener
?
onPointerUp
;
/// Called when a pointer that has not an [onPointerDown] changes position.
PointerHoverEventListener
?
onPointerHover
;
/// Called when the input from a pointer that triggered an [onPointerDown] is
/// no longer directed towards this receiver.
PointerCancelEventListener
?
onPointerCancel
;
...
...
@@ -2712,16 +2716,18 @@ class RenderPointerListener extends RenderProxyBoxWithHitTestBehavior {
@override
void
handleEvent
(
PointerEvent
event
,
HitTestEntry
entry
)
{
assert
(
debugHandleEvent
(
event
,
entry
));
if
(
onPointerDown
!=
null
&&
event
is
PointerDownEvent
)
return
onPointerDown
!(
event
);
if
(
onPointerMove
!=
null
&&
event
is
PointerMoveEvent
)
return
onPointerMove
!(
event
);
if
(
onPointerUp
!=
null
&&
event
is
PointerUpEvent
)
return
onPointerUp
!(
event
);
if
(
onPointerCancel
!=
null
&&
event
is
PointerCancelEvent
)
return
onPointerCancel
!(
event
);
if
(
onPointerSignal
!=
null
&&
event
is
PointerSignalEvent
)
return
onPointerSignal
!(
event
);
if
(
event
is
PointerDownEvent
)
return
onPointerDown
?.
call
(
event
);
if
(
event
is
PointerMoveEvent
)
return
onPointerMove
?.
call
(
event
);
if
(
event
is
PointerUpEvent
)
return
onPointerUp
?.
call
(
event
);
if
(
event
is
PointerHoverEvent
)
return
onPointerHover
?.
call
(
event
);
if
(
event
is
PointerCancelEvent
)
return
onPointerCancel
?.
call
(
event
);
if
(
event
is
PointerSignalEvent
)
return
onPointerSignal
?.
call
(
event
);
}
@override
...
...
@@ -2733,6 +2739,7 @@ class RenderPointerListener extends RenderProxyBoxWithHitTestBehavior {
'down'
:
onPointerDown
,
'move'
:
onPointerMove
,
'up'
:
onPointerUp
,
'hover'
:
onPointerHover
,
'cancel'
:
onPointerCancel
,
'signal'
:
onPointerSignal
,
},
...
...
@@ -2821,7 +2828,10 @@ class RenderMouseRegion extends RenderProxyBox implements MouseTrackerAnnotation
@override
PointerEnterEventListener
?
onEnter
;
@override
/// Triggered when a pointer has moved onto or within the region without
/// buttons pressed.
///
/// This callback is not triggered by the movement of the object.
PointerHoverEventListener
?
onHover
;
@override
...
...
packages/flutter/lib/src/services/platform_views.dart
View file @
2cdf2f00
...
...
@@ -848,6 +848,10 @@ abstract class AndroidViewController extends PlatformViewController {
/// for description of the parameters.
@override
Future
<
void
>
dispatchPointerEvent
(
PointerEvent
event
)
async
{
if
(
event
is
PointerHoverEvent
)
{
return
;
}
if
(
event
is
PointerDownEvent
)
{
_motionEventConverter
.
handlePointerDownEvent
(
event
);
}
...
...
packages/flutter/lib/src/widgets/basic.dart
View file @
2cdf2f00
...
...
@@ -5812,27 +5812,8 @@ class Listener extends StatelessWidget {
Key
?
key
,
this
.
onPointerDown
,
this
.
onPointerMove
,
// We have to ignore the lint rule here in order to use deprecated
// parameters and keep backward compatibility.
// TODO(tongmu): After it goes stable, remove these 3 parameters from Listener
// and Listener should no longer need an intermediate class _PointerListener.
// https://github.com/flutter/flutter/issues/36085
@Deprecated
(
'Use MouseRegion.onEnter instead. See MouseRegion.opaque for behavioral difference. '
'This feature was deprecated after v1.10.14.'
)
this
.
onPointerEnter
,
@Deprecated
(
'Use MouseRegion.onExit instead. See MouseRegion.opaque for behavioral difference. '
'This feature was deprecated after v1.10.14.'
)
this
.
onPointerExit
,
@Deprecated
(
'Use MouseRegion.onHover instead. See MouseRegion.opaque for behavioral difference. '
'This feature was deprecated after v1.10.14.'
)
this
.
onPointerHover
,
this
.
onPointerUp
,
this
.
onPointerHover
,
this
.
onPointerCancel
,
this
.
onPointerSignal
,
this
.
behavior
=
HitTestBehavior
.
deferToChild
,
...
...
@@ -5849,15 +5830,9 @@ class Listener extends StatelessWidget {
/// Called when a pointer that triggered an [onPointerDown] changes position.
final
PointerMoveEventListener
?
onPointerMove
;
/// Called when a pointer enters the region for this widget.
///
/// This is only fired for pointers which report their location when not down
/// (e.g. mouse pointers, but not most touch pointers).
///
/// If this is a mouse pointer, this will fire when the mouse pointer enters
/// the region defined by this widget, or when the widget appears under the
/// pointer.
final
PointerEnterEventListener
?
onPointerEnter
;
/// Called when a pointer that triggered an [onPointerDown] is no longer in
/// contact with the screen.
final
PointerUpEventListener
?
onPointerUp
;
/// Called when a pointer that has not triggered an [onPointerDown] changes
/// position.
...
...
@@ -5866,20 +5841,6 @@ class Listener extends StatelessWidget {
/// (e.g. mouse pointers, but not most touch pointers).
final
PointerHoverEventListener
?
onPointerHover
;
/// Called when a pointer leaves the region for this widget.
///
/// This is only fired for pointers which report their location when not down
/// (e.g. mouse pointers, but not most touch pointers).
///
/// If this is a mouse pointer, this will fire when the mouse pointer leaves
/// the region defined by this widget, or when the widget disappears from
/// under the pointer.
final
PointerExitEventListener
?
onPointerExit
;
/// Called when a pointer that triggered an [onPointerDown] is no longer in
/// contact with the screen.
final
PointerUpEventListener
?
onPointerUp
;
/// Called when the input from a pointer that triggered an [onPointerDown] is
/// no longer directed towards this receiver.
final
PointerCancelEventListener
?
onPointerCancel
;
...
...
@@ -5904,28 +5865,18 @@ class Listener extends StatelessWidget {
@override
Widget
build
(
BuildContext
context
)
{
Widget
?
result
=
_child
;
if
(
onPointerEnter
!=
null
||
onPointerExit
!=
null
||
onPointerHover
!=
null
)
{
result
=
MouseRegion
(
onEnter:
onPointerEnter
,
onExit:
onPointerExit
,
onHover:
onPointerHover
,
opaque:
false
,
child:
result
,
);
}
result
=
_PointerListener
(
// TODO(dkwingsmt): Remove the extra wrapper, and make `Listener` a
// StatelessWidget. https://github.com/flutter/flutter/issues/65586
return
_PointerListener
(
onPointerDown:
onPointerDown
,
onPointerUp:
onPointerUp
,
onPointerMove:
onPointerMove
,
onPointerHover:
onPointerHover
,
onPointerCancel:
onPointerCancel
,
onPointerSignal:
onPointerSignal
,
behavior:
behavior
,
child:
result
,
child:
_child
,
);
return
result
;
}
}
...
...
@@ -5935,6 +5886,7 @@ class _PointerListener extends SingleChildRenderObjectWidget {
this
.
onPointerDown
,
this
.
onPointerMove
,
this
.
onPointerUp
,
this
.
onPointerHover
,
this
.
onPointerCancel
,
this
.
onPointerSignal
,
this
.
behavior
=
HitTestBehavior
.
deferToChild
,
...
...
@@ -5945,6 +5897,7 @@ class _PointerListener extends SingleChildRenderObjectWidget {
final
PointerDownEventListener
?
onPointerDown
;
final
PointerMoveEventListener
?
onPointerMove
;
final
PointerUpEventListener
?
onPointerUp
;
final
PointerHoverEventListener
?
onPointerHover
;
final
PointerCancelEventListener
?
onPointerCancel
;
final
PointerSignalEventListener
?
onPointerSignal
;
final
HitTestBehavior
behavior
;
...
...
@@ -5955,6 +5908,7 @@ class _PointerListener extends SingleChildRenderObjectWidget {
onPointerDown:
onPointerDown
,
onPointerMove:
onPointerMove
,
onPointerUp:
onPointerUp
,
onPointerHover:
onPointerHover
,
onPointerCancel:
onPointerCancel
,
onPointerSignal:
onPointerSignal
,
behavior:
behavior
,
...
...
@@ -5967,6 +5921,7 @@ class _PointerListener extends SingleChildRenderObjectWidget {
..
onPointerDown
=
onPointerDown
..
onPointerMove
=
onPointerMove
..
onPointerUp
=
onPointerUp
..
onPointerHover
=
onPointerHover
..
onPointerCancel
=
onPointerCancel
..
onPointerSignal
=
onPointerSignal
..
behavior
=
behavior
;
...
...
@@ -5987,11 +5942,15 @@ class _PointerListener extends SingleChildRenderObjectWidget {
}
}
/// A widget that tracks the movement of mice
, even when no button is pressed
.
/// A widget that tracks the movement of mice.
///
/// It does not listen to events that can construct gestures, such as when the
/// pointer is pressed, moved, then released or canceled. For these events,
/// use [Listener], or more preferably, [GestureDetector].
/// [MouseRegion] is used
/// when it is needed to compare the list of objects that a mouse pointer is
/// hovering over betweeen this frame and the last frame. This means entering
/// events, exiting events, and mouse cursors.
///
/// To listen to general pointer events, use [Listener], or more preferably,
/// [GestureDetector].
///
/// ## Layout behavior
///
...
...
@@ -6110,13 +6069,23 @@ class MouseRegion extends StatefulWidget {
/// internally implemented.
final
PointerEnterEventListener
?
onEnter
;
/// Triggered when a
mouse pointer has moved onto or within the
widget without
/// Triggered when a
pointer moves into a position within this
widget without
/// buttons pressed.
///
/// This callback is not triggered by the movement of an annotation.
/// Usually this is only fired for pointers which report their location when
/// not down (e.g. mouse pointers). Certain devices also fire this event on
/// single taps in accessibility mode.
///
/// This callback is not triggered by the movement of the widget.
///
/// The time that this callback is triggered is during the callback of a
/// pointer event, which is always between frames.
///
/// See also:
///
/// * [Listener.onPointerHover], which does the same job. Prefer using
/// [Listener.onPointerHover], since hover events are similar to other regular
/// events.
final
PointerHoverEventListener
?
onHover
;
/// Triggered when a mouse pointer has exited this widget when the widget is
...
...
packages/flutter/test/gestures/gesture_binding_test.dart
View file @
2cdf2f00
...
...
@@ -105,7 +105,10 @@ void main() {
_binding
.
callback
=
events
.
add
;
ui
.
window
.
onPointerDataPacket
(
packet
);
expect
(
events
.
length
,
0
);
expect
(
events
.
length
,
3
);
expect
(
events
[
0
],
isA
<
PointerHoverEvent
>());
expect
(
events
[
1
],
isA
<
PointerHoverEvent
>());
expect
(
events
[
2
],
isA
<
PointerHoverEvent
>());
expect
(
pointerRouterEvents
.
length
,
6
,
reason:
'pointerRouterEvents contains:
$pointerRouterEvents
'
);
expect
(
pointerRouterEvents
[
0
],
isA
<
PointerAddedEvent
>());
...
...
packages/flutter/test/rendering/mouse_tracking_test.dart
View file @
2cdf2f00
...
...
@@ -546,7 +546,7 @@ void main() {
ui
.
window
.
onPointerDataPacket
(
ui
.
PointerDataPacket
(
data:
<
ui
.
PointerData
>[
_pointerData
(
PointerChange
.
hover
,
const
Offset
(
0.0
,
10.0
)),
]));
expect
(
logs
,
<
String
>[
'enterA'
,
'enterB'
,
'hover
A'
,
'hoverB
'
]);
expect
(
logs
,
<
String
>[
'enterA'
,
'enterB'
,
'hover
B'
,
'hoverA
'
]);
logs
.
clear
();
// Moves out of A within one frame.
...
...
packages/flutter/test/rendering/mouse_tracking_test_utils.dart
View file @
2cdf2f00
...
...
@@ -77,7 +77,6 @@ class TestAnnotationTarget with Diagnosticable implements MouseTrackerAnnotation
@override
final
PointerEnterEventListener
?
onEnter
;
@override
final
PointerHoverEventListener
?
onHover
;
@override
...
...
packages/flutter/test/rendering/platform_view_test.dart
View file @
2cdf2f00
...
...
@@ -87,6 +87,19 @@ void main() {
expect
(
fakePlatformViewController
.
dispatchedPointerEvents
,
isNotEmpty
);
});
test
(
'touch hover events are dispatched via PlatformViewController.dispatchPointerEvent'
,
()
{
layout
(
platformViewRenderBox
);
pumpFrame
(
phase:
EnginePhase
.
flushSemantics
);
ui
.
window
.
onPointerDataPacket
(
ui
.
PointerDataPacket
(
data:
<
ui
.
PointerData
>[
_pointerData
(
ui
.
PointerChange
.
add
,
const
Offset
(
0
,
0
)),
_pointerData
(
ui
.
PointerChange
.
hover
,
const
Offset
(
10
,
10
)),
_pointerData
(
ui
.
PointerChange
.
remove
,
const
Offset
(
10
,
10
)),
]));
expect
(
fakePlatformViewController
.
dispatchedPointerEvents
,
isNotEmpty
);
});
},
skip:
isBrowser
);
// TODO(yjbanov): fails on Web with obscured stack trace: https://github.com/flutter/flutter/issues/42770
}
...
...
packages/flutter/test/widgets/listener_deprecated_test.dart
deleted
100644 → 0
View file @
2cdec258
This diff is collapsed.
Click to expand it.
packages/flutter/test/widgets/listener_test.dart
View file @
2cdf2f00
...
...
@@ -49,6 +49,34 @@ void main() {
]));
});
testWidgets
(
'Detects hover events from touch devices'
,
(
WidgetTester
tester
)
async
{
final
List
<
String
>
log
=
<
String
>[];
await
tester
.
pumpWidget
(
Center
(
child:
SizedBox
(
width:
300
,
height:
300
,
child:
Listener
(
onPointerHover:
(
_
)
{
log
.
add
(
'bottom'
);
},
child:
const
Text
(
'X'
,
textDirection:
TextDirection
.
ltr
),
),
),
),
);
final
TestGesture
gesture
=
await
tester
.
createGesture
();
await
gesture
.
addPointer
();
addTearDown
(
gesture
.
removePointer
);
await
gesture
.
moveTo
(
tester
.
getCenter
(
find
.
byType
(
Listener
)));
expect
(
log
,
equals
(<
String
>[
'bottom'
,
]));
});
group
(
'transformed events'
,
()
{
testWidgets
(
'simple offset for touch/signal'
,
(
WidgetTester
tester
)
async
{
final
List
<
PointerEvent
>
events
=
<
PointerEvent
>[];
...
...
packages/flutter/test/widgets/mouse_region_test.dart
View file @
2cdf2f00
...
...
@@ -125,7 +125,8 @@ void main() {
PointerExitEvent
exit
;
await
tester
.
pumpWidget
(
Center
(
child:
MouseRegion
(
child:
const
SizedBox
(
child:
Container
(
color:
const
Color
.
fromARGB
(
0xff
,
0xff
,
0x00
,
0x00
),
width:
100.0
,
height:
100.0
,
),
...
...
@@ -372,6 +373,37 @@ void main() {
expect
(
exit
.
localPosition
,
equals
(
const
Offset
(
50
,
50
)));
});
testWidgets
(
'detects hover from touch devices'
,
(
WidgetTester
tester
)
async
{
PointerEnterEvent
enter
;
PointerHoverEvent
move
;
PointerExitEvent
exit
;
await
tester
.
pumpWidget
(
Center
(
child:
MouseRegion
(
child:
Container
(
color:
const
Color
.
fromARGB
(
0xff
,
0xff
,
0x00
,
0x00
),
width:
100.0
,
height:
100.0
,
),
onEnter:
(
PointerEnterEvent
details
)
=>
enter
=
details
,
onHover:
(
PointerHoverEvent
details
)
=>
move
=
details
,
onExit:
(
PointerExitEvent
details
)
=>
exit
=
details
,
),
));
final
TestGesture
gesture
=
await
tester
.
createGesture
(
kind:
PointerDeviceKind
.
touch
);
await
gesture
.
addPointer
(
location:
Offset
.
zero
);
addTearDown
(
gesture
.
removePointer
);
await
tester
.
pump
();
move
=
null
;
enter
=
null
;
exit
=
null
;
await
gesture
.
moveTo
(
const
Offset
(
400.0
,
300.0
));
expect
(
move
,
isNotNull
);
expect
(
move
.
position
,
equals
(
const
Offset
(
400.0
,
300.0
)));
expect
(
move
.
localPosition
,
equals
(
const
Offset
(
50.0
,
50.0
)));
expect
(
enter
,
isNull
);
expect
(
exit
,
isNull
);
});
testWidgets
(
'Hover works with nested listeners'
,
(
WidgetTester
tester
)
async
{
final
UniqueKey
key1
=
UniqueKey
();
final
UniqueKey
key2
=
UniqueKey
();
...
...
@@ -589,8 +621,12 @@ void main() {
}
await
tester
.
pumpWidget
(
hoverableContainer
(
onEnter:
(
PointerEnterEvent
details
)
{
logs
.
add
(
'enter1'
);
},
onHover:
(
PointerHoverEvent
details
)
{
logs
.
add
(
'hover1'
);
},
onEnter:
(
PointerEnterEvent
details
)
{
logs
.
add
(
'enter1'
);
},
onHover:
(
PointerHoverEvent
details
)
{
logs
.
add
(
'hover1'
);
},
onExit:
(
PointerExitEvent
details
)
{
logs
.
add
(
'exit1'
);
},
));
...
...
@@ -1178,31 +1214,31 @@ void main() {
// Move to the overlapping area.
await
gesture
.
moveTo
(
const
Offset
(
75
,
75
));
await
tester
.
pumpAndSettle
();
expect
(
logs
,
<
String
>[
'enterA'
,
'enterB'
,
'enterC'
,
'hover
A'
,
'hoverB'
,
'hoverC
'
]);
expect
(
logs
,
<
String
>[
'enterA'
,
'enterB'
,
'enterC'
,
'hover
C'
,
'hoverB'
,
'hoverA
'
]);
logs
.
clear
();
// Move to the B only area.
await
gesture
.
moveTo
(
const
Offset
(
25
,
75
));
await
tester
.
pumpAndSettle
();
expect
(
logs
,
<
String
>[
'exitC'
,
'hover
A'
,
'hoverB
'
]);
expect
(
logs
,
<
String
>[
'exitC'
,
'hover
B'
,
'hoverA
'
]);
logs
.
clear
();
// Move back to the overlapping area.
await
gesture
.
moveTo
(
const
Offset
(
75
,
75
));
await
tester
.
pumpAndSettle
();
expect
(
logs
,
<
String
>[
'enterC'
,
'hover
A'
,
'hoverB'
,
'hoverC
'
]);
expect
(
logs
,
<
String
>[
'enterC'
,
'hover
C'
,
'hoverB'
,
'hoverA
'
]);
logs
.
clear
();
// Move to the C only area.
await
gesture
.
moveTo
(
const
Offset
(
125
,
75
));
await
tester
.
pumpAndSettle
();
expect
(
logs
,
<
String
>[
'exitB'
,
'hover
A'
,
'hoverC
'
]);
expect
(
logs
,
<
String
>[
'exitB'
,
'hover
C'
,
'hoverA
'
]);
logs
.
clear
();
// Move back to the overlapping area.
await
gesture
.
moveTo
(
const
Offset
(
75
,
75
));
await
tester
.
pumpAndSettle
();
expect
(
logs
,
<
String
>[
'enterB'
,
'hover
A'
,
'hoverB'
,
'hoverC
'
]);
expect
(
logs
,
<
String
>[
'enterB'
,
'hover
C'
,
'hoverB'
,
'hoverA
'
]);
logs
.
clear
();
// Move out.
...
...
@@ -1226,31 +1262,31 @@ void main() {
// Move to the overlapping area.
await
gesture
.
moveTo
(
const
Offset
(
75
,
75
));
await
tester
.
pumpAndSettle
();
expect
(
logs
,
<
String
>[
'enterA'
,
'enterC'
,
'hover
A'
,
'hoverC
'
]);
expect
(
logs
,
<
String
>[
'enterA'
,
'enterC'
,
'hover
C'
,
'hoverA
'
]);
logs
.
clear
();
// Move to the B only area.
await
gesture
.
moveTo
(
const
Offset
(
25
,
75
));
await
tester
.
pumpAndSettle
();
expect
(
logs
,
<
String
>[
'exitC'
,
'enterB'
,
'hover
A'
,
'hoverB
'
]);
expect
(
logs
,
<
String
>[
'exitC'
,
'enterB'
,
'hover
B'
,
'hoverA
'
]);
logs
.
clear
();
// Move back to the overlapping area.
await
gesture
.
moveTo
(
const
Offset
(
75
,
75
));
await
tester
.
pumpAndSettle
();
expect
(
logs
,
<
String
>[
'exitB'
,
'enterC'
,
'hover
A'
,
'hoverC
'
]);
expect
(
logs
,
<
String
>[
'exitB'
,
'enterC'
,
'hover
C'
,
'hoverA
'
]);
logs
.
clear
();
// Move to the C only area.
await
gesture
.
moveTo
(
const
Offset
(
125
,
75
));
await
tester
.
pumpAndSettle
();
expect
(
logs
,
<
String
>[
'hover
A'
,
'hoverC
'
]);
expect
(
logs
,
<
String
>[
'hover
C'
,
'hoverA
'
]);
logs
.
clear
();
// Move back to the overlapping area.
await
gesture
.
moveTo
(
const
Offset
(
75
,
75
));
await
tester
.
pumpAndSettle
();
expect
(
logs
,
<
String
>[
'hover
A'
,
'hoverC
'
]);
expect
(
logs
,
<
String
>[
'hover
C'
,
'hoverA
'
]);
logs
.
clear
();
// Move out.
...
...
@@ -1274,7 +1310,7 @@ void main() {
// Move to the overlapping area.
await
gesture
.
moveTo
(
const
Offset
(
75
,
75
));
await
tester
.
pumpAndSettle
();
expect
(
logs
,
<
String
>[
'enterA'
,
'enterC'
,
'hover
A'
,
'hoverC
'
]);
expect
(
logs
,
<
String
>[
'enterA'
,
'enterC'
,
'hover
C'
,
'hoverA
'
]);
logs
.
clear
();
// Move out.
...
...
packages/flutter_test/lib/src/test_pointer.dart
View file @
2cdf2f00
...
...
@@ -25,11 +25,7 @@ class TestPointer {
this
.
kind
=
PointerDeviceKind
.
touch
,
int
?
device
,
int
buttons
=
kPrimaryButton
,
])
:
assert
(
kind
!=
null
),
assert
(
pointer
!=
null
),
assert
(
buttons
!=
null
),
_buttons
=
buttons
{
])
:
_buttons
=
buttons
{
switch
(
kind
)
{
case
PointerDeviceKind
.
mouse
:
_device
=
device
??
1
;
...
...
@@ -211,7 +207,6 @@ class TestPointer {
Duration
timeStamp
=
Duration
.
zero
,
Offset
?
location
,
})
{
assert
(
timeStamp
!=
null
);
_location
=
location
??
_location
;
return
PointerAddedEvent
(
timeStamp:
timeStamp
,
...
...
@@ -230,7 +225,6 @@ class TestPointer {
Duration
timeStamp
=
Duration
.
zero
,
Offset
?
location
,
})
{
assert
(
timeStamp
!=
null
);
_location
=
location
??
_location
;
return
PointerRemovedEvent
(
timeStamp:
timeStamp
,
...
...
@@ -251,13 +245,10 @@ class TestPointer {
Offset
newLocation
,
{
Duration
timeStamp
=
Duration
.
zero
,
})
{
assert
(
newLocation
!=
null
);
assert
(
timeStamp
!=
null
);
assert
(
!
isDown
,
'Hover events can only be generated when the pointer is up. To '
'simulate movement when the pointer is down, use move() instead.'
);
assert
(
kind
!=
PointerDeviceKind
.
touch
,
"Touch pointers can't generate hover events"
);
final
Offset
delta
=
location
!=
null
?
newLocation
-
location
!
:
Offset
.
zero
;
_location
=
newLocation
;
return
PointerHoverEvent
(
...
...
@@ -278,8 +269,6 @@ class TestPointer {
Offset
scrollDelta
,
{
Duration
timeStamp
=
Duration
.
zero
,
})
{
assert
(
scrollDelta
!=
null
);
assert
(
timeStamp
!=
null
);
assert
(
kind
!=
PointerDeviceKind
.
touch
,
"Touch pointers can't generate pointer signal events"
);
assert
(
location
!=
null
);
return
PointerScrollEvent
(
...
...
@@ -327,11 +316,7 @@ class TestGesture {
PointerDeviceKind
kind
=
PointerDeviceKind
.
touch
,
int
?
device
,
int
buttons
=
kPrimaryButton
,
})
:
assert
(
dispatcher
!=
null
),
assert
(
pointer
!=
null
),
assert
(
kind
!=
null
),
assert
(
buttons
!=
null
),
_dispatcher
=
dispatcher
,
})
:
_dispatcher
=
dispatcher
,
_pointer
=
TestPointer
(
pointer
,
kind
,
device
,
buttons
);
/// Dispatch a pointer down event at the given `downLocation`, caching the
...
...
@@ -380,8 +365,7 @@ class TestGesture {
/// Send a move event moving the pointer by the given offset.
///
/// If the pointer is down, then a move event is dispatched. If the pointer is
/// up, then a hover event is dispatched. Touch devices are not able to send
/// hover events.
/// up, then a hover event is dispatched.
Future
<
void
>
moveBy
(
Offset
offset
,
{
Duration
timeStamp
=
Duration
.
zero
})
{
assert
(
_pointer
.
location
!=
null
);
return
moveTo
(
_pointer
.
location
!
+
offset
,
timeStamp:
timeStamp
);
...
...
@@ -390,15 +374,12 @@ class TestGesture {
/// Send a move event moving the pointer to the given location.
///
/// If the pointer is down, then a move event is dispatched. If the pointer is
/// up, then a hover event is dispatched. Touch devices are not able to send
/// hover events.
/// up, then a hover event is dispatched.
Future
<
void
>
moveTo
(
Offset
location
,
{
Duration
timeStamp
=
Duration
.
zero
})
{
return
TestAsyncUtils
.
guard
<
void
>(()
{
if
(
_pointer
.
_isDown
)
{
return
_dispatcher
(
_pointer
.
move
(
location
,
timeStamp:
timeStamp
));
}
else
{
assert
(
_pointer
.
kind
!=
PointerDeviceKind
.
touch
,
'Touch device move events can only be sent if the pointer is down.'
);
return
_dispatcher
(
_pointer
.
hover
(
location
,
timeStamp:
timeStamp
));
}
});
...
...
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