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
9e2e0ef3
Unverified
Commit
9e2e0ef3
authored
Jul 23, 2020
by
Ming Lyu (CareF)
Committed by
GitHub
Jul 23, 2020
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
implement handlePointerEventRecord for LiveWidgetController (#61266)
parent
e91b8339
Changes
2
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
165 additions
and
3 deletions
+165
-3
controller.dart
packages/flutter_test/lib/src/controller.dart
+82
-3
live_widget_controller_test.dart
packages/flutter_test/test/live_widget_controller_test.dart
+83
-0
No files found.
packages/flutter_test/lib/src/controller.dart
View file @
9e2e0ef3
...
...
@@ -4,6 +4,7 @@
import
'dart:async'
;
import
'package:clock/clock.dart'
;
import
'package:flutter/gestures.dart'
;
import
'package:flutter/rendering.dart'
;
import
'package:flutter/widgets.dart'
;
...
...
@@ -718,8 +719,86 @@ class LiveWidgetController extends WidgetController {
@override
Future
<
List
<
Duration
>>
handlePointerEventRecord
(
List
<
PointerEventRecord
>
records
)
{
// TODO(CareF): This will be implemented after we decide what should be the
// correct pumping strategy.
throw
UnimplementedError
;
assert
(
records
!=
null
);
assert
(
records
.
isNotEmpty
);
return
TestAsyncUtils
.
guard
<
List
<
Duration
>>(()
async
{
// hitTestHistory is an equivalence of _hitTests in [GestureBinding],
// used as state for all pointers which are currently down.
final
Map
<
int
,
HitTestResult
>
hitTestHistory
=
<
int
,
HitTestResult
>{};
final
List
<
Duration
>
handleTimeStampDiff
=
<
Duration
>[];
DateTime
startTime
;
for
(
final
PointerEventRecord
record
in
records
)
{
final
DateTime
now
=
clock
.
now
();
startTime
??=
now
;
// So that the first event is promised to receive a zero timeDiff
final
Duration
timeDiff
=
record
.
timeDelay
-
now
.
difference
(
startTime
);
if
(
timeDiff
.
isNegative
)
{
// This happens when something (e.g. GC) takes a long time during the
// processing of the events.
// Flush all past events
handleTimeStampDiff
.
add
(-
timeDiff
);
for
(
final
PointerEvent
event
in
record
.
events
)
{
_handlePointerEvent
(
event
,
hitTestHistory
);
}
}
else
{
await
Future
<
void
>.
delayed
(
timeDiff
);
handleTimeStampDiff
.
add
(
// Recalculating the time diff for getting exact time when the event
// packet is sent. For a perfect Future.delayed like the one in a
// fake async this new diff should be zero.
clock
.
now
().
difference
(
startTime
)
-
record
.
timeDelay
,
);
for
(
final
PointerEvent
event
in
record
.
events
)
{
_handlePointerEvent
(
event
,
hitTestHistory
);
}
}
}
// This makes sure that a gesture is completed, with no more pointers
// active.
assert
(
hitTestHistory
.
isEmpty
);
return
handleTimeStampDiff
;
});
}
// This method is almost identical to [GestureBinding._handlePointerEvent]
// to replicate the bahavior of the real binding.
void
_handlePointerEvent
(
PointerEvent
event
,
Map
<
int
,
HitTestResult
>
_hitTests
)
{
HitTestResult
hitTestResult
;
if
(
event
is
PointerDownEvent
||
event
is
PointerSignalEvent
)
{
assert
(!
_hitTests
.
containsKey
(
event
.
pointer
));
hitTestResult
=
HitTestResult
();
binding
.
hitTest
(
hitTestResult
,
event
.
position
);
if
(
event
is
PointerDownEvent
)
{
_hitTests
[
event
.
pointer
]
=
hitTestResult
;
}
assert
(()
{
if
(
debugPrintHitTestResults
)
debugPrint
(
'
$event
:
$hitTestResult
'
);
return
true
;
}());
}
else
if
(
event
is
PointerUpEvent
||
event
is
PointerCancelEvent
)
{
hitTestResult
=
_hitTests
.
remove
(
event
.
pointer
);
}
else
if
(
event
.
down
)
{
// Because events that occur with the pointer down (like
// PointerMoveEvents) should be dispatched to the same place that their
// initial PointerDownEvent was, we want to re-use the path we found when
// the pointer went down, rather than do hit detection each time we get
// such an event.
hitTestResult
=
_hitTests
[
event
.
pointer
];
}
assert
(()
{
if
(
debugPrintMouseHoverEvents
&&
event
is
PointerHoverEvent
)
debugPrint
(
'
$event
'
);
return
true
;
}());
if
(
hitTestResult
!=
null
||
event
is
PointerHoverEvent
||
event
is
PointerAddedEvent
||
event
is
PointerRemovedEvent
)
{
binding
.
dispatchEvent
(
event
,
hitTestResult
);
}
}
}
packages/flutter_test/test/live_widget_controller_test.dart
0 → 100644
View file @
9e2e0ef3
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import
'dart:ui'
;
import
'package:flutter/material.dart'
;
import
'package:flutter/gestures.dart'
;
import
'package:flutter/scheduler.dart'
;
import
'package:flutter_test/flutter_test.dart'
;
Future
<
void
>
main
()
async
{
test
(
'Input event array on LiveWidgetController'
,
()
async
{
final
List
<
String
>
logs
=
<
String
>[];
runApp
(
MaterialApp
(
home:
Listener
(
onPointerDown:
(
PointerDownEvent
event
)
=>
logs
.
add
(
'down
${event.buttons}
'
),
onPointerMove:
(
PointerMoveEvent
event
)
=>
logs
.
add
(
'move
${event.buttons}
'
),
onPointerUp:
(
PointerUpEvent
event
)
=>
logs
.
add
(
'up
${event.buttons}
'
),
child:
const
Text
(
'test'
),
),
),
);
await
SchedulerBinding
.
instance
.
endOfFrame
;
final
WidgetController
controller
=
LiveWidgetController
(
WidgetsBinding
.
instance
);
final
Offset
location
=
controller
.
getCenter
(
find
.
text
(
'test'
));
final
List
<
PointerEventRecord
>
records
=
<
PointerEventRecord
>[
PointerEventRecord
(
Duration
.
zero
,
<
PointerEvent
>[
// Typically PointerAddedEvent is not used in testers, but for records
// captured on a device it is usually what start a gesture.
PointerAddedEvent
(
timeStamp:
Duration
.
zero
,
position:
location
,
),
PointerDownEvent
(
timeStamp:
Duration
.
zero
,
position:
location
,
buttons:
kSecondaryMouseButton
,
pointer:
1
,
),
]),
...<
PointerEventRecord
>[
for
(
Duration
t
=
const
Duration
(
milliseconds:
5
);
t
<
const
Duration
(
milliseconds:
80
);
t
+=
const
Duration
(
milliseconds:
16
))
PointerEventRecord
(
t
,
<
PointerEvent
>[
PointerMoveEvent
(
timeStamp:
t
-
const
Duration
(
milliseconds:
1
),
position:
location
,
buttons:
kSecondaryMouseButton
,
pointer:
1
,
)
])
],
PointerEventRecord
(
const
Duration
(
milliseconds:
80
),
<
PointerEvent
>[
PointerUpEvent
(
timeStamp:
const
Duration
(
milliseconds:
79
),
position:
location
,
buttons:
kSecondaryMouseButton
,
pointer:
1
,
)
])
];
final
List
<
Duration
>
timeDiffs
=
await
controller
.
handlePointerEventRecord
(
records
);
expect
(
timeDiffs
.
length
,
records
.
length
);
for
(
final
Duration
diff
in
timeDiffs
)
{
// Allow some freedom of time delay in real world.
assert
(
diff
.
inMilliseconds
>
-
1
);
}
const
String
b
=
'
$kSecondaryMouseButton
'
;
expect
(
logs
.
first
,
'down
$b
'
);
for
(
int
i
=
1
;
i
<
logs
.
length
-
1
;
i
++)
{
expect
(
logs
[
i
],
'move
$b
'
);
}
expect
(
logs
.
last
,
'up
$b
'
);
});
}
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