From ade93651ac31fc7826474a149b804366aee475ca Mon Sep 17 00:00:00 2001 From: Ian Hickson Date: Sun, 13 Dec 2015 17:08:05 -0800 Subject: [PATCH] Refactor bindings. --- examples/rendering/align_items.dart | 2 +- examples/rendering/baseline.dart | 2 +- examples/rendering/borders.dart | 2 +- examples/rendering/flex.dart | 2 +- examples/rendering/interactive_flex.dart | 46 ++- examples/rendering/justify_content.dart | 2 +- examples/rendering/render_grid.dart | 2 +- examples/rendering/render_paragraph.dart | 2 +- examples/rendering/sector_layout.dart | 2 +- examples/rendering/shadowed_box.dart | 2 +- examples/rendering/simple_autolayout.dart | 2 +- examples/rendering/spinning_flex.dart | 6 +- examples/rendering/touch_demo.dart | 2 +- examples/rendering/transform.dart | 2 +- examples/widgets/spinning_mixed.dart | 11 +- packages/flutter/lib/gestures.dart | 3 + packages/flutter/lib/rendering.dart | 1 - packages/flutter/lib/services.dart | 1 + .../flutter/lib/src/animation/ticker.dart | 4 +- packages/flutter/lib/src/gestures/arena.dart | 2 - .../flutter/lib/src/gestures/binding.dart | 94 +++++ .../flutter/lib/src/gestures/converter.dart | 183 ++++++++++ packages/flutter/lib/src/gestures/drag.dart | 39 +- .../src/{rendering => gestures}/hit_test.dart | 7 +- .../flutter/lib/src/gestures/long_press.dart | 11 +- .../flutter/lib/src/gestures/multitap.dart | 26 +- .../flutter/lib/src/gestures/recognizer.dart | 21 +- packages/flutter/lib/src/gestures/scale.dart | 12 +- packages/flutter/lib/src/gestures/tap.dart | 7 +- .../lib/src/material/material_app.dart | 4 +- packages/flutter/lib/src/material/slider.dart | 2 +- packages/flutter/lib/src/material/switch.dart | 2 +- .../flutter/lib/src/material/toggleable.dart | 2 +- .../flutter/lib/src/painting/box_painter.dart | 2 + .../lib/src/rendering/auto_layout.dart | 2 +- .../flutter/lib/src/rendering/binding.dart | 341 +++--------------- .../flutter/lib/src/rendering/object.dart | 9 +- packages/flutter/lib/src/rendering/view.dart | 2 +- .../flutter/lib/src/scheduler/scheduler.dart | 19 +- .../lib/src/services/asset_bundle.dart | 3 +- .../flutter/lib/src/services/binding.dart | 32 ++ packages/flutter/lib/src/widgets/binding.dart | 90 +++-- .../flutter/lib/src/widgets/drag_target.dart | 9 +- .../lib/src/widgets/gesture_detector.dart | 16 +- packages/flutter/lib/src/widgets/heroes.dart | 2 +- .../flutter_test/lib/src/widget_tester.dart | 23 +- .../test/engine/canvas_test_disabled.dart | 4 + packages/unit/test/engine/color_test.dart | 4 + .../test/engine/paragraph_builder_test.dart | 4 + packages/unit/test/engine/rect_test.dart | 4 + .../test/examples/sector_layout_test.dart | 4 + packages/unit/test/gestures/arena_test.dart | 4 + .../unit/test/gestures/double_tap_test.dart | 184 ++++++---- .../unit/test/gestures/long_press_test.dart | 33 +- .../unit/test/gestures/lsq_solver_test.dart | 4 + .../test/gestures/pointer_router_test.dart | 4 + packages/unit/test/gestures/scale_test.dart | 21 +- packages/unit/test/gestures/scroll_test.dart | 17 +- packages/unit/test/gestures/tap_test.dart | 90 +++-- .../test/gestures/velocity_tracker_data.dart | 4 + .../test/gestures/velocity_tracker_test.dart | 4 + packages/unit/test/harness/trivial_test.dart | 4 + .../unit/test/painting/edge_dims_test.dart | 4 + packages/unit/test/rendering/box_test.dart | 4 + packages/unit/test/rendering/flex_test.dart | 4 + packages/unit/test/rendering/grid_test.dart | 4 + packages/unit/test/rendering/image_test.dart | 4 + .../test/rendering/intrinsic_width_test.dart | 4 + .../unit/test/rendering/offstage_test.dart | 4 + .../unit/test/rendering/overflow_test.dart | 4 + .../test/rendering/positioned_box_test.dart | 4 + .../unit/test/rendering/rendering_tester.dart | 57 ++- packages/unit/test/rendering/size_test.dart | 4 + packages/unit/test/rendering/stack_test.dart | 4 + .../unit/test/rendering/viewport_test.dart | 8 +- .../unit/test/scheduler/animation_test.dart | 9 + ...test.dart => scheduler_test.dart.disabled} | 36 +- .../test/widget/animated_container_test.dart | 15 +- 78 files changed, 1035 insertions(+), 581 deletions(-) create mode 100644 packages/flutter/lib/src/gestures/binding.dart create mode 100644 packages/flutter/lib/src/gestures/converter.dart rename packages/flutter/lib/src/{rendering => gestures}/hit_test.dart (91%) create mode 100644 packages/flutter/lib/src/services/binding.dart rename packages/unit/test/scheduler/{scheduler_test.dart => scheduler_test.dart.disabled} (66%) diff --git a/examples/rendering/align_items.dart b/examples/rendering/align_items.dart index 9497f68e13d..38597f93e25 100644 --- a/examples/rendering/align_items.dart +++ b/examples/rendering/align_items.dart @@ -42,5 +42,5 @@ void main() { child: new RenderPadding(child: table, padding: new EdgeDims.symmetric(vertical: 50.0)) ); - new FlutterBinding(root: root); + new RenderingFlutterBinding(root: root); } diff --git a/examples/rendering/baseline.dart b/examples/rendering/baseline.dart index 761e79c88de..b0b47184906 100644 --- a/examples/rendering/baseline.dart +++ b/examples/rendering/baseline.dart @@ -87,5 +87,5 @@ void main() { direction: FlexDirection.vertical, alignItems: FlexAlignItems.stretch ); - new FlutterBinding(root: root); + new RenderingFlutterBinding(root: root); } diff --git a/examples/rendering/borders.dart b/examples/rendering/borders.dart index 5db29ca0375..c6aee483314 100644 --- a/examples/rendering/borders.dart +++ b/examples/rendering/borders.dart @@ -73,5 +73,5 @@ void main() { ], direction: FlexDirection.vertical ); - new FlutterBinding(root: root); + new RenderingFlutterBinding(root: root); } diff --git a/examples/rendering/flex.dart b/examples/rendering/flex.dart index 3fd3d5dc904..8d74e49f755 100644 --- a/examples/rendering/flex.dart +++ b/examples/rendering/flex.dart @@ -53,5 +53,5 @@ RenderBox buildFlexExample() { } void main() { - new FlutterBinding(root: buildFlexExample()); + new RenderingFlutterBinding(root: buildFlexExample()); } diff --git a/examples/rendering/interactive_flex.dart b/examples/rendering/interactive_flex.dart index 721ac7cd3ec..7944118a8b6 100644 --- a/examples/rendering/interactive_flex.dart +++ b/examples/rendering/interactive_flex.dart @@ -6,6 +6,7 @@ import 'dart:ui' as ui; import 'dart:math' as math; import 'dart:typed_data'; +import 'package:flutter/scheduler.dart'; import 'package:flutter/services.dart'; import 'package:flutter/rendering.dart'; import 'package:mojo/bindings.dart' as bindings; @@ -37,25 +38,32 @@ class RenderImageGrow extends RenderImage { RenderImageGrow image; -void handlePopRoute() { - activity.finishCurrentActivity(); -} +class DemoBinding extends BindingBase with Scheduler, Renderer { + DemoBinding({ RenderBox root }) { + renderView.child = root; + ui.window.onPopRoute = handlePopRoute; + ui.window.onPointerPacket = handlePointerPacket; + } -final Map touches = {}; + void handlePopRoute() { + activity.finishCurrentActivity(); + } -void handlePointerPacket(ByteData serializedPacket) { - bindings.Message message = new bindings.Message( - serializedPacket, - [], - serializedPacket.lengthInBytes, - 0 - ); - PointerPacket packet = PointerPacket.deserialize(message); + final Map touches = {}; - for (Pointer pointer in packet.pointers) { - if (pointer.type == PointerType.MOVE) - image.growth = math.max(0.0, image.growth + pointer.x - touches[pointer.pointer].x); - touches[pointer.pointer] = new Touch(pointer.x, pointer.y); + void handlePointerPacket(ByteData serializedPacket) { + bindings.Message message = new bindings.Message( + serializedPacket, + [], + serializedPacket.lengthInBytes, + 0 + ); + PointerPacket packet = PointerPacket.deserialize(message); + for (Pointer pointer in packet.pointers) { + if (pointer.type == PointerType.MOVE) + image.growth = math.max(0.0, image.growth + pointer.x - touches[pointer.pointer].x); + touches[pointer.pointer] = new Touch(pointer.x, pointer.y); + } } } @@ -74,7 +82,7 @@ void main() { // Resizeable image image = new RenderImageGrow(null, new Size(100.0, null)); - imageCache.load("https://www.dartlang.org/logos/dart-logo.png").first.then((ui.Image dartLogo) { + imageCache.load("http://flutter.io/favicon.ico").first.then((ui.Image dartLogo) { image.image = dartLogo; }); @@ -114,7 +122,5 @@ Pancetta meatball tongue tenderloin rump tail jowl boudin."""; ); updateTaskDescription('Interactive Flex', topColor); - new FlutterBinding(root: root); - ui.window.onPopRoute = handlePopRoute; - ui.window.onPointerPacket = handlePointerPacket; + new DemoBinding(root: root); } diff --git a/examples/rendering/justify_content.dart b/examples/rendering/justify_content.dart index f6fc12decd4..cea28c07183 100644 --- a/examples/rendering/justify_content.dart +++ b/examples/rendering/justify_content.dart @@ -37,5 +37,5 @@ void main() { child: new RenderPadding(child: table, padding: new EdgeDims.symmetric(vertical: 50.0)) ); - new FlutterBinding(root: root); + new RenderingFlutterBinding(root: root); } diff --git a/examples/rendering/render_grid.dart b/examples/rendering/render_grid.dart index 01403117348..86292ed8900 100644 --- a/examples/rendering/render_grid.dart +++ b/examples/rendering/render_grid.dart @@ -23,4 +23,4 @@ RenderBox buildGridExample() { return new RenderGrid(children: children, maxChildExtent: 100.0); } -main() => new FlutterBinding(root: buildGridExample()); +main() => new RenderingFlutterBinding(root: buildGridExample()); diff --git a/examples/rendering/render_paragraph.dart b/examples/rendering/render_paragraph.dart index 8eca0230b1b..61a9f4409d9 100644 --- a/examples/rendering/render_paragraph.dart +++ b/examples/rendering/render_paragraph.dart @@ -40,5 +40,5 @@ Pancetta meatball tongue tenderloin rump tail jowl boudin."""; childParentData = child.parentData; childParentData.flex = 1; - new FlutterBinding(root: root); + new RenderingFlutterBinding(root: root); } diff --git a/examples/rendering/sector_layout.dart b/examples/rendering/sector_layout.dart index a6fc547357c..db14387ef8e 100644 --- a/examples/rendering/sector_layout.dart +++ b/examples/rendering/sector_layout.dart @@ -18,5 +18,5 @@ RenderBox buildSectorExample() { } void main() { - new FlutterBinding(root: buildSectorExample()); + new RenderingFlutterBinding(root: buildSectorExample()); } diff --git a/examples/rendering/shadowed_box.dart b/examples/rendering/shadowed_box.dart index c1265df37b4..1d3a10bc6a3 100644 --- a/examples/rendering/shadowed_box.dart +++ b/examples/rendering/shadowed_box.dart @@ -18,7 +18,7 @@ void main() { var paddedBox = new RenderPadding( padding: const EdgeDims.all(50.0), child: coloredBox); - new FlutterBinding(root: new RenderDecoratedBox( + new RenderingFlutterBinding(root: new RenderDecoratedBox( decoration: const BoxDecoration( backgroundColor: const Color(0xFFFFFFFF) ), diff --git a/examples/rendering/simple_autolayout.dart b/examples/rendering/simple_autolayout.dart index 8adbb4a8c6b..17a90c35b5e 100644 --- a/examples/rendering/simple_autolayout.dart +++ b/examples/rendering/simple_autolayout.dart @@ -59,5 +59,5 @@ void main() { (p4.verticalCenter == p2.height / al.cm(2.0)) as al.Constraint, ]); - new FlutterBinding(root: root); + new RenderingFlutterBinding(root: root); } diff --git a/examples/rendering/spinning_flex.dart b/examples/rendering/spinning_flex.dart index ca85cafd6ed..7557f59ce76 100644 --- a/examples/rendering/spinning_flex.dart +++ b/examples/rendering/spinning_flex.dart @@ -5,7 +5,6 @@ import 'dart:ui' as ui; import 'package:flutter/rendering.dart'; -import 'package:flutter/scheduler.dart'; import 'lib/solid_color_box.dart'; @@ -30,9 +29,8 @@ void main() { RenderPadding root = new RenderPadding(padding: new EdgeDims.all(20.0), child: transformBox); - new FlutterBinding(root: root); - - scheduler.addPersistentFrameCallback(rotate); + new RenderingFlutterBinding(root: root) + ..addPersistentFrameCallback(rotate); } void rotate(Duration timeStamp) { diff --git a/examples/rendering/touch_demo.dart b/examples/rendering/touch_demo.dart index 029d88dc107..51ffd0b7adf 100644 --- a/examples/rendering/touch_demo.dart +++ b/examples/rendering/touch_demo.dart @@ -77,5 +77,5 @@ void main() { final StackParentData paragraphParentData = paragraph.parentData; paragraphParentData..top = 40.0 ..left = 20.0; - new FlutterBinding(root: stack); + new RenderingFlutterBinding(root: stack); } diff --git a/examples/rendering/transform.dart b/examples/rendering/transform.dart index 664b0325bf1..6a145144de4 100644 --- a/examples/rendering/transform.dart +++ b/examples/rendering/transform.dart @@ -24,5 +24,5 @@ void main() { RenderFlex flex = new RenderFlex(); flex.add(spin); - new FlutterBinding(root: flex); + new RenderingFlutterBinding(root: flex); } diff --git a/examples/widgets/spinning_mixed.dart b/examples/widgets/spinning_mixed.dart index 9a328f79fd7..f3d4b6d1709 100644 --- a/examples/widgets/spinning_mixed.dart +++ b/examples/widgets/spinning_mixed.dart @@ -6,7 +6,6 @@ import 'dart:ui' as ui; import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; -import 'package:flutter/scheduler.dart'; import 'package:flutter_rendering_examples/solid_color_box.dart'; @@ -84,11 +83,6 @@ void rotate(Duration timeStamp) { } void main() { - // Because we're going to use Widgets, we want to ensure we're using a - // WidgetFlutterBinding rather than some other kind of binding (e.g. a - // straight rendering library FlutterBinding). - WidgetFlutterBinding.ensureInitialized(); - RenderProxyBox proxy = new RenderProxyBox(); attachWidgetTreeToRenderTree(proxy); @@ -100,6 +94,7 @@ void main() { transformBox = new RenderTransform(child: flexRoot, transform: new Matrix4.identity()); RenderPadding root = new RenderPadding(padding: new EdgeDims.all(80.0), child: transformBox); - FlutterBinding.instance.renderView.child = root; - scheduler.addPersistentFrameCallback(rotate); + WidgetFlutterBinding.ensureInitialized() + ..renderView.child = root + ..addPersistentFrameCallback(rotate); } diff --git a/packages/flutter/lib/gestures.dart b/packages/flutter/lib/gestures.dart index 73aeba8049b..1dce64355c5 100644 --- a/packages/flutter/lib/gestures.dart +++ b/packages/flutter/lib/gestures.dart @@ -6,9 +6,12 @@ library gestures; export 'src/gestures/arena.dart'; +export 'src/gestures/binding.dart'; export 'src/gestures/constants.dart'; +export 'src/gestures/converter.dart'; export 'src/gestures/drag.dart'; export 'src/gestures/events.dart'; +export 'src/gestures/hit_test.dart'; export 'src/gestures/long_press.dart'; export 'src/gestures/lsq_solver.dart'; export 'src/gestures/multitap.dart'; diff --git a/packages/flutter/lib/rendering.dart b/packages/flutter/lib/rendering.dart index 08ae476b27b..a9d343745b1 100644 --- a/packages/flutter/lib/rendering.dart +++ b/packages/flutter/lib/rendering.dart @@ -16,7 +16,6 @@ export 'src/rendering/editable_paragraph.dart'; export 'src/rendering/error.dart'; export 'src/rendering/flex.dart'; export 'src/rendering/grid.dart'; -export 'src/rendering/hit_test.dart'; export 'src/rendering/image.dart'; export 'src/rendering/layer.dart'; export 'src/rendering/node.dart'; diff --git a/packages/flutter/lib/services.dart b/packages/flutter/lib/services.dart index 18e14ac8f93..c3e2962a311 100644 --- a/packages/flutter/lib/services.dart +++ b/packages/flutter/lib/services.dart @@ -13,6 +13,7 @@ library services; export 'src/services/activity.dart'; export 'src/services/asset_bundle.dart'; +export 'src/services/binding.dart'; export 'src/services/fetch.dart'; export 'src/services/image_cache.dart'; export 'src/services/image_decoder.dart'; diff --git a/packages/flutter/lib/src/animation/ticker.dart b/packages/flutter/lib/src/animation/ticker.dart index a421ba17ad7..9e4845453df 100644 --- a/packages/flutter/lib/src/animation/ticker.dart +++ b/packages/flutter/lib/src/animation/ticker.dart @@ -40,7 +40,7 @@ class Ticker { _startTime = null; if (_animationId != null) { - scheduler.cancelFrameCallbackWithId(_animationId); + Scheduler.instance.cancelFrameCallbackWithId(_animationId); _animationId = null; } @@ -74,6 +74,6 @@ class Ticker { void _scheduleTick() { assert(isTicking); assert(_animationId == null); - _animationId = scheduler.scheduleFrameCallback(_tick); + _animationId = Scheduler.instance.scheduleFrameCallback(_tick); } } diff --git a/packages/flutter/lib/src/gestures/arena.dart b/packages/flutter/lib/src/gestures/arena.dart index 663ea51a2b0..c80b3f5e905 100644 --- a/packages/flutter/lib/src/gestures/arena.dart +++ b/packages/flutter/lib/src/gestures/arena.dart @@ -64,8 +64,6 @@ class _GestureArenaState { class GestureArena { final Map _arenas = new Map(); - static final GestureArena instance = new GestureArena(); - GestureArenaEntry add(Object key, GestureArenaMember member) { _GestureArenaState state = _arenas.putIfAbsent(key, () => new _GestureArenaState()); state.add(member); diff --git a/packages/flutter/lib/src/gestures/binding.dart b/packages/flutter/lib/src/gestures/binding.dart new file mode 100644 index 00000000000..1d80be812c9 --- /dev/null +++ b/packages/flutter/lib/src/gestures/binding.dart @@ -0,0 +1,94 @@ +// Copyright 2015 The Chromium 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:typed_data'; +import 'dart:ui' as ui; + +import 'package:flutter/services.dart'; +import 'package:mojo/bindings.dart' as mojo_bindings; +import 'package:mojo/core.dart' as mojo_core; +import 'package:sky_services/pointer/pointer.mojom.dart'; + +import 'arena.dart'; +import 'converter.dart'; +import 'events.dart'; +import 'hit_test.dart'; +import 'pointer_router.dart'; + +abstract class Pointerer extends BindingBase implements HitTestTarget, HitTestable { + + void initInstances() { + super.initInstances(); + _instance = this; + ui.window.onPointerPacket = _handlePointerPacket; + } + + static Pointerer _instance; + static Pointerer get instance => _instance; + + void _handlePointerPacket(ByteData serializedPacket) { + final mojo_bindings.Message message = new mojo_bindings.Message( + serializedPacket, + [], + serializedPacket.lengthInBytes, + 0 + ); + final PointerPacket packet = PointerPacket.deserialize(message); + for (PointerEvent event in PointerEventConverter.expand(packet.pointers)) + _handlePointerEvent(event); + } + + /// A router that routes all pointer events received from the engine. + final PointerRouter pointerRouter = new PointerRouter(); + + /// The gesture arenas used for disambiguating the meaning of sequences of + /// pointer events. + final GestureArena gestureArena = new GestureArena(); + + /// State for all pointers which are currently down. + /// + /// The state of hovering pointers is not tracked because that would require + /// hit-testing on every frame. + Map _hitTests = {}; + + void _handlePointerEvent(PointerEvent event) { + if (event is PointerDownEvent) { + assert(!_hitTests.containsKey(event.pointer)); + HitTestResult result = new HitTestResult(); + hitTest(result, event.position); + _hitTests[event.pointer] = result; + } else if (event is! PointerUpEvent) { + assert(event.down == _hitTests.containsKey(event.pointer)); + if (!event.down) + return; // we currently ignore add, remove, and hover move events + } + assert(_hitTests[event.pointer] != null); + dispatchEvent(event, _hitTests[event.pointer]); + if (event is PointerUpEvent) { + assert(_hitTests.containsKey(event.pointer)); + _hitTests.remove(event.pointer); + } + } + + /// Determine which [HitTestTarget] objects are located at a given position. + void hitTest(HitTestResult result, Point position) { + result.add(new HitTestEntry(this)); + } + + /// Dispatch the given event to the path of the given hit test result + void dispatchEvent(PointerEvent event, HitTestResult result) { + assert(result != null); + for (HitTestEntry entry in result.path) + entry.target.handleEvent(event, entry); + } + + void handleEvent(PointerEvent event, HitTestEntry entry) { + pointerRouter.route(event); + if (event is PointerDownEvent) { + gestureArena.close(event.pointer); + } else if (event is PointerUpEvent) { + gestureArena.sweep(event.pointer); + } + } +} diff --git a/packages/flutter/lib/src/gestures/converter.dart b/packages/flutter/lib/src/gestures/converter.dart new file mode 100644 index 00000000000..d573768db3a --- /dev/null +++ b/packages/flutter/lib/src/gestures/converter.dart @@ -0,0 +1,183 @@ +// Copyright 2015 The Chromium 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 'package:sky_services/pointer/pointer.mojom.dart'; + +import 'events.dart'; + +class _PointerState { + _PointerState(this.lastPosition); + + int get pointer => _pointer; // The identifier used in PointerEvent objects. + int _pointer; + static int _pointerCount = 0; + void startNewPointer() { + _pointerCount += 1; + _pointer = _pointerCount; + } + + bool get down => _down; + bool _down = false; + void setDown() { + assert(!_down); + _down = true; + } + void setUp() { + assert(_down); + _down = false; + } + + Point lastPosition; +} + +class PointerEventConverter { + // Map from platform pointer identifiers to PointerEvent pointer identifiers. + static Map _pointers = {}; + + static Iterable expand(Iterable packet) sync* { + for (Pointer datum in packet) { + Point position = new Point(datum.x, datum.y); + Duration timeStamp = new Duration(microseconds: datum.timeStamp); + assert(_pointerKindMap.containsKey(datum.kind)); + PointerDeviceKind kind = _pointerKindMap[datum.kind]; + switch (datum.type) { + case PointerType.DOWN: + assert(!_pointers.containsKey(datum.pointer)); + _PointerState state = _pointers.putIfAbsent( + datum.pointer, + () => new _PointerState(position) + ); + assert(state.lastPosition == position); + state.startNewPointer(); + state.setDown(); + yield new PointerAddedEvent( + timeStamp: timeStamp, + pointer: state.pointer, + kind: kind, + position: position, + obscured: datum.obscured, + pressureMin: datum.pressureMin, + pressureMax: datum.pressureMax, + distance: datum.distance, + distanceMax: datum.distanceMax, + radiusMin: datum.radiusMin, + radiusMax: datum.radiusMax, + orientation: datum.orientation, + tilt: datum.tilt + ); + yield new PointerDownEvent( + timeStamp: timeStamp, + pointer: state.pointer, + kind: kind, + position: position, + obscured: datum.obscured, + pressure: datum.pressure, + pressureMin: datum.pressureMin, + pressureMax: datum.pressureMax, + distanceMax: datum.distanceMax, + radiusMajor: datum.radiusMajor, + radiusMinor: datum.radiusMajor, + radiusMin: datum.radiusMin, + radiusMax: datum.radiusMax, + orientation: datum.orientation, + tilt: datum.tilt + ); + break; + case PointerType.MOVE: + // If the service starts supporting hover pointers, then it must also + // start sending us ADDED and REMOVED data points. + // See also: https://github.com/flutter/flutter/issues/720 + assert(_pointers.containsKey(datum.pointer)); + _PointerState state = _pointers[datum.pointer]; + assert(state.down); + Offset offset = position - state.lastPosition; + state.lastPosition = position; + yield new PointerMoveEvent( + timeStamp: timeStamp, + pointer: state.pointer, + kind: kind, + position: position, + delta: offset, + down: state.down, + obscured: datum.obscured, + pressure: datum.pressure, + pressureMin: datum.pressureMin, + pressureMax: datum.pressureMax, + distance: datum.distance, + distanceMax: datum.distanceMax, + radiusMajor: datum.radiusMajor, + radiusMinor: datum.radiusMajor, + radiusMin: datum.radiusMin, + radiusMax: datum.radiusMax, + orientation: datum.orientation, + tilt: datum.tilt + ); + break; + case PointerType.UP: + case PointerType.CANCEL: + assert(_pointers.containsKey(datum.pointer)); + _PointerState state = _pointers[datum.pointer]; + assert(state.down); + assert(position == state.lastPosition); + state.setUp(); + if (datum.type == PointerType.UP) { + yield new PointerUpEvent( + timeStamp: timeStamp, + pointer: state.pointer, + kind: kind, + position: position, + obscured: datum.obscured, + pressureMax: datum.pressureMax, + distance: datum.distance, + distanceMax: datum.distanceMax, + radiusMin: datum.radiusMin, + radiusMax: datum.radiusMax, + orientation: datum.orientation, + tilt: datum.tilt + ); + } else { + yield new PointerCancelEvent( + timeStamp: timeStamp, + pointer: state.pointer, + kind: kind, + position: position, + obscured: datum.obscured, + pressureMin: datum.pressureMin, + pressureMax: datum.pressureMax, + distance: datum.distance, + distanceMax: datum.distanceMax, + radiusMin: datum.radiusMin, + radiusMax: datum.radiusMax, + orientation: datum.orientation, + tilt: datum.tilt + ); + } + yield new PointerRemovedEvent( + timeStamp: timeStamp, + pointer: state.pointer, + kind: kind, + obscured: datum.obscured, + pressureMin: datum.pressureMin, + pressureMax: datum.pressureMax, + distanceMax: datum.distanceMax, + radiusMin: datum.radiusMin, + radiusMax: datum.radiusMax + ); + _pointers.remove(datum.pointer); + break; + default: + // TODO(ianh): once https://github.com/flutter/flutter/issues/720 is + // done, add real support for PointerAddedEvent and PointerRemovedEvent + assert(false); + } + } + } + + static const Map _pointerKindMap = const { + PointerKind.TOUCH: PointerDeviceKind.touch, + PointerKind.MOUSE: PointerDeviceKind.mouse, + PointerKind.STYLUS: PointerDeviceKind.stylus, + PointerKind.INVERTED_STYLUS: PointerDeviceKind.invertedStylus, + }; +} diff --git a/packages/flutter/lib/src/gestures/drag.dart b/packages/flutter/lib/src/gestures/drag.dart index 885bcdc47b6..b00e20394bf 100644 --- a/packages/flutter/lib/src/gestures/drag.dart +++ b/packages/flutter/lib/src/gestures/drag.dart @@ -32,8 +32,16 @@ bool _isFlingGesture(Offset velocity) { } abstract class _DragGestureRecognizer extends OneSequenceGestureRecognizer { - _DragGestureRecognizer({ PointerRouter router, this.onStart, this.onUpdate, this.onEnd }) - : super(router: router); + _DragGestureRecognizer({ + PointerRouter router, + GestureArena gestureArena, + this.onStart, + this.onUpdate, + this.onEnd + }) : super( + router: router, + gestureArena: gestureArena + ); GestureDragStartCallback onStart; _GesturePolymorphicUpdateCallback onUpdate; @@ -120,10 +128,17 @@ abstract class _DragGestureRecognizer extends OneSequenceGest class VerticalDragGestureRecognizer extends _DragGestureRecognizer { VerticalDragGestureRecognizer({ PointerRouter router, + GestureArena gestureArena, GestureDragStartCallback onStart, GestureDragUpdateCallback onUpdate, GestureDragEndCallback onEnd - }) : super(router: router, onStart: onStart, onUpdate: onUpdate, onEnd: onEnd); + }) : super( + router: router, + gestureArena: gestureArena, + onStart: onStart, + onUpdate: onUpdate, + onEnd: onEnd + ); double get _initialPendingDragDelta => 0.0; double _getDragDelta(PointerEvent event) => event.delta.dy; @@ -133,10 +148,17 @@ class VerticalDragGestureRecognizer extends _DragGestureRecognizer { class HorizontalDragGestureRecognizer extends _DragGestureRecognizer { HorizontalDragGestureRecognizer({ PointerRouter router, + GestureArena gestureArena, GestureDragStartCallback onStart, GestureDragUpdateCallback onUpdate, GestureDragEndCallback onEnd - }) : super(router: router, onStart: onStart, onUpdate: onUpdate, onEnd: onEnd); + }) : super( + router: router, + gestureArena: gestureArena, + onStart: onStart, + onUpdate: onUpdate, + onEnd: onEnd + ); double get _initialPendingDragDelta => 0.0; double _getDragDelta(PointerEvent event) => event.delta.dx; @@ -146,10 +168,17 @@ class HorizontalDragGestureRecognizer extends _DragGestureRecognizer { class PanGestureRecognizer extends _DragGestureRecognizer { PanGestureRecognizer({ PointerRouter router, + GestureArena gestureArena, GesturePanStartCallback onStart, GesturePanUpdateCallback onUpdate, GesturePanEndCallback onEnd - }) : super(router: router, onStart: onStart, onUpdate: onUpdate, onEnd: onEnd); + }) : super( + router: router, + gestureArena: gestureArena, + onStart: onStart, + onUpdate: onUpdate, + onEnd: onEnd + ); Offset get _initialPendingDragDelta => Offset.zero; Offset _getDragDelta(PointerEvent event) => event.delta; diff --git a/packages/flutter/lib/src/rendering/hit_test.dart b/packages/flutter/lib/src/gestures/hit_test.dart similarity index 91% rename from packages/flutter/lib/src/rendering/hit_test.dart rename to packages/flutter/lib/src/gestures/hit_test.dart index 88aef26a3cb..a547d127840 100644 --- a/packages/flutter/lib/src/rendering/hit_test.dart +++ b/packages/flutter/lib/src/gestures/hit_test.dart @@ -2,7 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'package:flutter/gestures.dart'; +import 'events.dart'; + +/// An object that can hit-test pointers. +abstract class HitTestable { + void hitTest(HitTestResult result, Point position); +} /// An object that can handle events. abstract class HitTestTarget { diff --git a/packages/flutter/lib/src/gestures/long_press.dart b/packages/flutter/lib/src/gestures/long_press.dart index 4832e6d8f1f..a3010a21304 100644 --- a/packages/flutter/lib/src/gestures/long_press.dart +++ b/packages/flutter/lib/src/gestures/long_press.dart @@ -11,8 +11,15 @@ import 'recognizer.dart'; typedef void GestureLongPressCallback(); class LongPressGestureRecognizer extends PrimaryPointerGestureRecognizer { - LongPressGestureRecognizer({ PointerRouter router, this.onLongPress }) - : super(router: router, deadline: kLongPressTimeout); + LongPressGestureRecognizer({ + PointerRouter router, + GestureArena gestureArena, + this.onLongPress + }) : super( + router: router, + gestureArena: gestureArena, + deadline: kLongPressTimeout + ); GestureLongPressCallback onLongPress; diff --git a/packages/flutter/lib/src/gestures/multitap.dart b/packages/flutter/lib/src/gestures/multitap.dart index dc5e94bbd78..389fbe73ea4 100644 --- a/packages/flutter/lib/src/gestures/multitap.dart +++ b/packages/flutter/lib/src/gestures/multitap.dart @@ -58,9 +58,12 @@ class DoubleTapGestureRecognizer extends GestureRecognizer { DoubleTapGestureRecognizer({ PointerRouter router, + GestureArena gestureArena, this.onDoubleTap - }) : _router = router { + }) : _router = router, + _gestureArena = gestureArena { assert(router != null); + assert(gestureArena != null); } // Implementation notes: @@ -84,6 +87,7 @@ class DoubleTapGestureRecognizer extends GestureRecognizer { // - The gesture arena decides we have been rejected wholesale PointerRouter _router; + GestureArena _gestureArena; GestureDoubleTapCallback onDoubleTap; Timer _doubleTapTimer; @@ -98,7 +102,7 @@ class DoubleTapGestureRecognizer extends GestureRecognizer { _stopDoubleTapTimer(); _TapTracker tracker = new _TapTracker( event: event, - entry: GestureArena.instance.add(event.pointer, this) + entry: _gestureArena.add(event.pointer, this) ); _trackers[event.pointer] = tracker; tracker.startTrackingPointer(_router, handleEvent); @@ -149,6 +153,7 @@ class DoubleTapGestureRecognizer extends GestureRecognizer { void dispose() { _reset(); _router = null; + _gestureArena = null; } void _reset() { @@ -159,14 +164,14 @@ class DoubleTapGestureRecognizer extends GestureRecognizer { _TapTracker tracker = _firstTap; _firstTap = null; _reject(tracker); - GestureArena.instance.release(tracker.pointer); + _gestureArena.release(tracker.pointer); } _clearTrackers(); } void _registerFirstTap(_TapTracker tracker) { _startDoubleTapTimer(); - GestureArena.instance.hold(tracker.pointer); + _gestureArena.hold(tracker.pointer); // Note, order is important below in order for the clear -> reject logic to // work properly. _freezeTracker(tracker); @@ -226,7 +231,10 @@ class _TapGesture extends _TapTracker { Duration longTapDelay }) : gestureRecognizer = gestureRecognizer, _lastPosition = event.position, - super(event: event, entry: GestureArena.instance.add(event.pointer, gestureRecognizer)) { + super( + event: event, + entry: gestureRecognizer._gestureArena.add(event.pointer, gestureRecognizer) + ) { startTrackingPointer(gestureRecognizer.router, handleEvent); if (longTapDelay > Duration.ZERO) { _timer = new Timer(longTapDelay, () { @@ -299,18 +307,23 @@ class _TapGesture extends _TapTracker { class MultiTapGestureRecognizer extends GestureRecognizer { MultiTapGestureRecognizer({ PointerRouter router, + GestureArena gestureArena, this.onTapDown, this.onTapUp, this.onTap, this.onTapCancel, this.longTapDelay: Duration.ZERO, this.onLongTapDown - }) : _router = router { + }) : _router = router, + _gestureArena = gestureArena { assert(router != null); + assert(gestureArena != null); } PointerRouter get router => _router; PointerRouter _router; + GestureArena get gestureArena => _gestureArena; + GestureArena _gestureArena; GestureMultiTapDownCallback onTapDown; GestureMultiTapUpCallback onTapUp; GestureMultiTapCallback onTap; @@ -369,6 +382,7 @@ class MultiTapGestureRecognizer extends GestureRecognizer { // Rejection of each gesture should cause it to be removed from our map assert(_gestureMap.isEmpty); _router = null; + _gestureArena = null; } } diff --git a/packages/flutter/lib/src/gestures/recognizer.dart b/packages/flutter/lib/src/gestures/recognizer.dart index da9ac2f7c01..921dc2bd3a2 100644 --- a/packages/flutter/lib/src/gestures/recognizer.dart +++ b/packages/flutter/lib/src/gestures/recognizer.dart @@ -30,11 +30,17 @@ abstract class GestureRecognizer extends GestureArenaMember { } abstract class OneSequenceGestureRecognizer extends GestureRecognizer { - OneSequenceGestureRecognizer({ PointerRouter router }) : _router = router { + OneSequenceGestureRecognizer({ + PointerRouter router, + GestureArena gestureArena + }) : _router = router, + _gestureArena = gestureArena { assert(_router != null); + assert(_gestureArena != null); } PointerRouter _router; + GestureArena _gestureArena; final List _entries = []; final Set _trackedPointers = new Set(); @@ -58,12 +64,13 @@ abstract class OneSequenceGestureRecognizer extends GestureRecognizer { _trackedPointers.clear(); assert(_entries.isEmpty); _router = null; + _gestureArena = null; } void startTrackingPointer(int pointer) { _router.addRoute(pointer, handleEvent); _trackedPointers.add(pointer); - _entries.add(GestureArena.instance.add(pointer, this)); + _entries.add(_gestureArena.add(pointer, this)); } void stopTrackingPointer(int pointer) { @@ -87,8 +94,14 @@ enum GestureRecognizerState { } abstract class PrimaryPointerGestureRecognizer extends OneSequenceGestureRecognizer { - PrimaryPointerGestureRecognizer({ PointerRouter router, this.deadline }) - : super(router: router); + PrimaryPointerGestureRecognizer({ + PointerRouter router, + GestureArena gestureArena, + this.deadline + }) : super( + router: router, + gestureArena: gestureArena + ); final Duration deadline; diff --git a/packages/flutter/lib/src/gestures/scale.dart b/packages/flutter/lib/src/gestures/scale.dart index 45b96b8285a..e8d46347c6e 100644 --- a/packages/flutter/lib/src/gestures/scale.dart +++ b/packages/flutter/lib/src/gestures/scale.dart @@ -19,8 +19,16 @@ typedef void GestureScaleUpdateCallback(double scale, Point focalPoint); typedef void GestureScaleEndCallback(); class ScaleGestureRecognizer extends OneSequenceGestureRecognizer { - ScaleGestureRecognizer({ PointerRouter router, this.onStart, this.onUpdate, this.onEnd }) - : super(router: router); + ScaleGestureRecognizer({ + PointerRouter router, + GestureArena gestureArena, + this.onStart, + this.onUpdate, + this.onEnd + }) : super( + router: router, + gestureArena: gestureArena + ); GestureScaleStartCallback onStart; GestureScaleUpdateCallback onUpdate; diff --git a/packages/flutter/lib/src/gestures/tap.dart b/packages/flutter/lib/src/gestures/tap.dart index bd3a6a50373..0faab3f9cf1 100644 --- a/packages/flutter/lib/src/gestures/tap.dart +++ b/packages/flutter/lib/src/gestures/tap.dart @@ -19,11 +19,16 @@ typedef void GestureTapCancelCallback(); class TapGestureRecognizer extends PrimaryPointerGestureRecognizer { TapGestureRecognizer({ PointerRouter router, + GestureArena gestureArena, this.onTapDown, this.onTapUp, this.onTap, this.onTapCancel - }) : super(router: router, deadline: kPressTimeout); + }) : super( + router: router, + gestureArena: gestureArena, + deadline: kPressTimeout + ); GestureTapDownCallback onTapDown; GestureTapDownCallback onTapUp; diff --git a/packages/flutter/lib/src/material/material_app.dart b/packages/flutter/lib/src/material/material_app.dart index 3578f3c7640..8612e3ea1a5 100644 --- a/packages/flutter/lib/src/material/material_app.dart +++ b/packages/flutter/lib/src/material/material_app.dart @@ -74,11 +74,11 @@ class _MaterialAppState extends State implements BindingObserver { _navigator = new GlobalObjectKey(this); _size = ui.window.size; didChangeLocale(ui.window.locale); - FlutterBinding.instance.addObserver(this); + WidgetFlutterBinding.instance.addObserver(this); } void dispose() { - FlutterBinding.instance.removeObserver(this); + WidgetFlutterBinding.instance.removeObserver(this); super.dispose(); } diff --git a/packages/flutter/lib/src/material/slider.dart b/packages/flutter/lib/src/material/slider.dart index 5ddf74a946f..4e188238198 100644 --- a/packages/flutter/lib/src/material/slider.dart +++ b/packages/flutter/lib/src/material/slider.dart @@ -86,7 +86,7 @@ class _RenderSlider extends RenderConstrainedBox { _activeColor = activeColor, super(additionalConstraints: const BoxConstraints.tightFor(width: _kTrackWidth + 2 * _kReactionRadius, height: 2 * _kReactionRadius)) { assert(value != null && value >= 0.0 && value <= 1.0); - _drag = new HorizontalDragGestureRecognizer(router: FlutterBinding.instance.pointerRouter) + _drag = new HorizontalDragGestureRecognizer(router: Pointerer.instance.pointerRouter, gestureArena: Pointerer.instance.gestureArena) ..onStart = _handleDragStart ..onUpdate = _handleDragUpdate ..onEnd = _handleDragEnd; diff --git a/packages/flutter/lib/src/material/switch.dart b/packages/flutter/lib/src/material/switch.dart index 0e545067839..8e17741ddbe 100644 --- a/packages/flutter/lib/src/material/switch.dart +++ b/packages/flutter/lib/src/material/switch.dart @@ -115,7 +115,7 @@ class _RenderSwitch extends RenderToggleable { ) { _activeTrackColor = activeTrackColor; _inactiveTrackColor = inactiveTrackColor; - _drag = new HorizontalDragGestureRecognizer(router: FlutterBinding.instance.pointerRouter) + _drag = new HorizontalDragGestureRecognizer(router: Pointerer.instance.pointerRouter, gestureArena: Pointerer.instance.gestureArena) ..onStart = _handleDragStart ..onUpdate = _handleDragUpdate ..onEnd = _handleDragEnd; diff --git a/packages/flutter/lib/src/material/toggleable.dart b/packages/flutter/lib/src/material/toggleable.dart index 4c829a93ba1..2cf1990000a 100644 --- a/packages/flutter/lib/src/material/toggleable.dart +++ b/packages/flutter/lib/src/material/toggleable.dart @@ -29,7 +29,7 @@ abstract class RenderToggleable extends RenderConstrainedBox { assert(value != null); assert(activeColor != null); assert(inactiveColor != null); - _tap = new TapGestureRecognizer(router: FlutterBinding.instance.pointerRouter) + _tap = new TapGestureRecognizer(router: Pointerer.instance.pointerRouter, gestureArena: Pointerer.instance.gestureArena) ..onTapDown = _handleTapDown ..onTap = _handleTap ..onTapUp = _handleTapUp diff --git a/packages/flutter/lib/src/painting/box_painter.dart b/packages/flutter/lib/src/painting/box_painter.dart index ccd6ca5e8fb..c3ed68234f2 100644 --- a/packages/flutter/lib/src/painting/box_painter.dart +++ b/packages/flutter/lib/src/painting/box_painter.dart @@ -420,6 +420,8 @@ void paintImage({ double alignX, double alignY }) { + assert(canvas != null); + assert(image != null); Size outputSize = rect.size; Size inputSize = new Size(image.width.toDouble(), image.height.toDouble()); Offset sliceBorder; diff --git a/packages/flutter/lib/src/rendering/auto_layout.dart b/packages/flutter/lib/src/rendering/auto_layout.dart index d8477bbac2c..e63a4698267 100644 --- a/packages/flutter/lib/src/rendering/auto_layout.dart +++ b/packages/flutter/lib/src/rendering/auto_layout.dart @@ -220,7 +220,7 @@ class RenderAutoLayout extends RenderBox // only indicates that the value has been flushed to the variable. } - bool hitTestChildren(HitTestResult result, {Point position}) { + bool hitTestChildren(HitTestResult result, { Point position }) { return defaultHitTestChildren(result, position: position); } diff --git a/packages/flutter/lib/src/rendering/binding.dart b/packages/flutter/lib/src/rendering/binding.dart index 88641fe50f8..86b0401ed7b 100644 --- a/packages/flutter/lib/src/rendering/binding.dart +++ b/packages/flutter/lib/src/rendering/binding.dart @@ -2,265 +2,64 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:typed_data'; import 'dart:ui' as ui; import 'package:flutter/gestures.dart'; import 'package:flutter/scheduler.dart'; -import 'package:mojo/bindings.dart' as mojo_bindings; -import 'package:mojo/core.dart' as mojo_core; -import 'package:sky_services/pointer/pointer.mojom.dart'; +import 'package:flutter/services.dart'; import 'box.dart'; import 'debug.dart'; -import 'hit_test.dart'; import 'object.dart'; import 'view.dart'; -typedef void MetricListener(Size size); - -class _PointerState { - _PointerState(this.lastPosition); - - int get pointer => _pointer; // The identifier used in PointerEvent objects. - int _pointer; - static int _pointerCount = 0; - void startNewPointer() { - _pointerCount += 1; - _pointer = _pointerCount; - } - - bool get down => _down; - bool _down = false; - void setDown() { - assert(!_down); - _down = true; - } - void setUp() { - assert(_down); - _down = false; - } - - Point lastPosition; -} - -class _PointerEventConverter { - // Map from platform pointer identifiers to PointerEvent pointer identifiers. - static Map _pointers = {}; - - static Iterable expand(Iterable packet) sync* { - for (Pointer datum in packet) { - Point position = new Point(datum.x, datum.y); - Duration timeStamp = new Duration(microseconds: datum.timeStamp); - assert(_pointerKindMap.containsKey(datum.kind)); - PointerDeviceKind kind = _pointerKindMap[datum.kind]; - switch (datum.type) { - case PointerType.DOWN: - assert(!_pointers.containsKey(datum.pointer)); - _PointerState state = _pointers.putIfAbsent( - datum.pointer, - () => new _PointerState(position) - ); - assert(state.lastPosition == position); - state.startNewPointer(); - state.setDown(); - yield new PointerAddedEvent( - timeStamp: timeStamp, - pointer: state.pointer, - kind: kind, - position: position, - obscured: datum.obscured, - pressureMin: datum.pressureMin, - pressureMax: datum.pressureMax, - distance: datum.distance, - distanceMax: datum.distanceMax, - radiusMin: datum.radiusMin, - radiusMax: datum.radiusMax, - orientation: datum.orientation, - tilt: datum.tilt - ); - yield new PointerDownEvent( - timeStamp: timeStamp, - pointer: state.pointer, - kind: kind, - position: position, - obscured: datum.obscured, - pressure: datum.pressure, - pressureMin: datum.pressureMin, - pressureMax: datum.pressureMax, - distanceMax: datum.distanceMax, - radiusMajor: datum.radiusMajor, - radiusMinor: datum.radiusMajor, - radiusMin: datum.radiusMin, - radiusMax: datum.radiusMax, - orientation: datum.orientation, - tilt: datum.tilt - ); - break; - case PointerType.MOVE: - // If the service starts supporting hover pointers, then it must also - // start sending us ADDED and REMOVED data points. - // See also: https://github.com/flutter/flutter/issues/720 - assert(_pointers.containsKey(datum.pointer)); - _PointerState state = _pointers[datum.pointer]; - assert(state.down); - Offset offset = position - state.lastPosition; - state.lastPosition = position; - yield new PointerMoveEvent( - timeStamp: timeStamp, - pointer: state.pointer, - kind: kind, - position: position, - delta: offset, - down: state.down, - obscured: datum.obscured, - pressure: datum.pressure, - pressureMin: datum.pressureMin, - pressureMax: datum.pressureMax, - distance: datum.distance, - distanceMax: datum.distanceMax, - radiusMajor: datum.radiusMajor, - radiusMinor: datum.radiusMajor, - radiusMin: datum.radiusMin, - radiusMax: datum.radiusMax, - orientation: datum.orientation, - tilt: datum.tilt - ); - break; - case PointerType.UP: - case PointerType.CANCEL: - assert(_pointers.containsKey(datum.pointer)); - _PointerState state = _pointers[datum.pointer]; - assert(state.down); - assert(position == state.lastPosition); - state.setUp(); - if (datum.type == PointerType.UP) { - yield new PointerUpEvent( - timeStamp: timeStamp, - pointer: state.pointer, - kind: kind, - position: position, - obscured: datum.obscured, - pressureMax: datum.pressureMax, - distance: datum.distance, - distanceMax: datum.distanceMax, - radiusMin: datum.radiusMin, - radiusMax: datum.radiusMax, - orientation: datum.orientation, - tilt: datum.tilt - ); - } else { - yield new PointerCancelEvent( - timeStamp: timeStamp, - pointer: state.pointer, - kind: kind, - position: position, - obscured: datum.obscured, - pressureMin: datum.pressureMin, - pressureMax: datum.pressureMax, - distance: datum.distance, - distanceMax: datum.distanceMax, - radiusMin: datum.radiusMin, - radiusMax: datum.radiusMax, - orientation: datum.orientation, - tilt: datum.tilt - ); - } - yield new PointerRemovedEvent( - timeStamp: timeStamp, - pointer: state.pointer, - kind: kind, - obscured: datum.obscured, - pressureMin: datum.pressureMin, - pressureMax: datum.pressureMax, - distanceMax: datum.distanceMax, - radiusMin: datum.radiusMin, - radiusMax: datum.radiusMax - ); - _pointers.remove(datum.pointer); - break; - default: - // TODO(ianh): once https://github.com/flutter/flutter/issues/720 is - // done, add real support for PointerAddedEvent and PointerRemovedEvent - assert(false); - } - } - } - - static const Map _pointerKindMap = const { - PointerKind.TOUCH: PointerDeviceKind.touch, - PointerKind.MOUSE: PointerDeviceKind.mouse, - PointerKind.STYLUS: PointerDeviceKind.stylus, - PointerKind.INVERTED_STYLUS: PointerDeviceKind.invertedStylus, - }; -} - -class BindingObserver { - bool didPopRoute() => false; - void didChangeSize(Size size) { } - void didChangeLocale(ui.Locale locale) { } -} +export 'package:flutter/gestures.dart' show HitTestResult; /// The glue between the render tree and the Flutter engine. -class FlutterBinding extends HitTestTarget { +abstract class Renderer extends Scheduler + implements HitTestable { - FlutterBinding({ RenderBox root: null, RenderView renderViewOverride }) { - assert(_instance == null); + void initInstances() { + super.initInstances(); _instance = this; - - ui.window.onPointerPacket = _handlePointerPacket; - ui.window.onMetricsChanged = _handleMetricsChanged; - ui.window.onLocaleChanged = _handleLocaleChanged; - ui.window.onPopRoute = _handlePopRoute; - - if (renderViewOverride == null) { - _renderView = new RenderView(child: root); - _renderView.attach(); - _handleMetricsChanged(); - _renderView.scheduleInitialFrame(); - } else { - _renderView = renderViewOverride; - } - assert(_renderView != null); - scheduler.addPersistentFrameCallback(_handlePersistentFrameCallback); - - assert(_instance == this); + ui.window.onMetricsChanged = handleMetricsChanged; + initRenderView(); + addPersistentFrameCallback(_handlePersistentFrameCallback); } - /// The singleton instance of the binding. - static FlutterBinding get instance => _instance; - static FlutterBinding _instance; + static Renderer _instance; + static Renderer get instance => _instance; + + void initRenderView() { + if (renderView == null) { + renderView = new RenderView(); + renderView.scheduleInitialFrame(); + } + handleMetricsChanged(); // configures _renderView's metrics + } /// The render tree that's attached to the output surface. RenderView get renderView => _renderView; RenderView _renderView; - - final List _observers = new List(); - - void addObserver(BindingObserver observer) => _observers.add(observer); - bool removeObserver(BindingObserver observer) => _observers.remove(observer); - - void _handleMetricsChanged() { - Size size = ui.window.size; - _renderView.rootConstraints = new ViewConstraints(size: size); - for (BindingObserver observer in _observers) - observer.didChangeSize(size); + void set renderView(RenderView value) { + if (_renderView == value) + return; + if (_renderView != null) + _renderView.detach(); + _renderView = value; + if (_renderView != null) + _renderView.attach(); } - void _handleLocaleChanged() { - dispatchLocaleChanged(ui.window.locale); - } - - void dispatchLocaleChanged(ui.Locale locale) { - for (BindingObserver observer in _observers) - observer.didChangeLocale(locale); + void handleMetricsChanged() { + _renderView.rootConstraints = new ViewConstraints(size: ui.window.size); } void _handlePersistentFrameCallback(Duration timeStamp) { beginFrame(); } - /// Pump the rendering pipeline to generate a frame for the given time stamp. + /// Pump the rendering pipeline to generate a frame. void beginFrame() { RenderObject.flushLayout(); _renderView.updateCompositingBits(); @@ -268,82 +67,26 @@ class FlutterBinding extends HitTestTarget { _renderView.compositeFrame(); } - void _handlePopRoute() { - for (BindingObserver observer in _observers) { - if (observer.didPopRoute()) - return; - } - } - - void _handlePointerPacket(ByteData serializedPacket) { - final mojo_bindings.Message message = new mojo_bindings.Message( - serializedPacket, - [], - serializedPacket.lengthInBytes, - 0 - ); - final PointerPacket packet = PointerPacket.deserialize(message); - for (PointerEvent event in _PointerEventConverter.expand(packet.pointers)) - _handlePointerEvent(event); - } - - /// A router that routes all pointer events received from the engine. - final PointerRouter pointerRouter = new PointerRouter(); - - /// State for all pointers which are currently down. - /// - /// The state of hovering pointers is not tracked because that would require - /// hit-testing on every frame. - Map _hitTests = {}; - - void _handlePointerEvent(PointerEvent event) { - if (event is PointerDownEvent) { - assert(!_hitTests.containsKey(event.pointer)); - _hitTests[event.pointer] = hitTest(event.position); - } else if (event is! PointerUpEvent) { - assert(event.down == _hitTests.containsKey(event.pointer)); - if (!event.down) - return; // we currently ignore add, remove, and hover move events - } - assert(_hitTests[event.pointer] != null); - dispatchEvent(event, _hitTests[event.pointer]); - if (event is PointerUpEvent) { - assert(_hitTests.containsKey(event.pointer)); - _hitTests.remove(event.pointer); - } - } - - /// Determine which [HitTestTarget] objects are located at a given position. - HitTestResult hitTest(Point position) { - HitTestResult result = new HitTestResult(); + void hitTest(HitTestResult result, Point position) { _renderView.hitTest(result, position: position); - result.add(new HitTestEntry(this)); - return result; - } - - /// Dispatch the given event to the path of the given hit test result - void dispatchEvent(PointerEvent event, HitTestResult result) { - assert(result != null); - for (HitTestEntry entry in result.path) - entry.target.handleEvent(event, entry); - } - - void handleEvent(PointerEvent event, HitTestEntry entry) { - pointerRouter.route(event); - if (event is PointerDownEvent) { - GestureArena.instance.close(event.pointer); - } else if (event is PointerUpEvent) { - GestureArena.instance.sweep(event.pointer); - } + super.hitTest(result, position); } } /// Prints a textual representation of the entire render tree. void debugDumpRenderTree() { - debugPrint(FlutterBinding.instance.renderView.toStringDeep()); + debugPrint(Renderer.instance.renderView.toStringDeep()); } /// Prints a textual representation of the entire layer tree. void debugDumpLayerTree() { - debugPrint(FlutterBinding.instance.renderView.layer.toStringDeep()); + debugPrint(Renderer.instance.renderView.layer.toStringDeep()); +} + +/// A concrete binding for applications that use the Rendering framework +/// directly. This is the glue that binds the framework to the Flutter engine. +class RenderingFlutterBinding extends BindingBase with Scheduler, Renderer, Pointerer { + RenderingFlutterBinding({ RenderBox root }) { + renderView.child = root; + } } diff --git a/packages/flutter/lib/src/rendering/object.dart b/packages/flutter/lib/src/rendering/object.dart index 2a52f6ca015..aa21d574da1 100644 --- a/packages/flutter/lib/src/rendering/object.dart +++ b/packages/flutter/lib/src/rendering/object.dart @@ -11,12 +11,11 @@ import 'package:flutter/scheduler.dart'; import 'package:vector_math/vector_math_64.dart'; import 'debug.dart'; -import 'hit_test.dart'; import 'layer.dart'; import 'node.dart'; export 'layer.dart'; -export 'hit_test.dart'; +export 'package:flutter/gestures.dart' show HitTestEntry, HitTestResult; typedef ui.Shader ShaderCallback(Rect bounds); @@ -551,7 +550,7 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget { assert(parent == this.parent); } else { _nodesNeedingLayout.add(this); - scheduler.ensureVisualUpdate(); + Scheduler.instance.ensureVisualUpdate(); } } @@ -916,7 +915,7 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget { // ourselves without involving any other nodes. assert(_layer != null); _nodesNeedingPaint.add(this); - scheduler.ensureVisualUpdate(); + Scheduler.instance.ensureVisualUpdate(); } else if (parent is RenderObject) { // We don't have our own layer; one of our ancestors will take // care of updating the layer we're in and when they do that @@ -930,7 +929,7 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget { // then we have to paint ourselves, since nobody else can paint // us. We don't add ourselves to _nodesNeedingPaint in this // case, because the root is always told to paint regardless. - scheduler.ensureVisualUpdate(); + Scheduler.instance.ensureVisualUpdate(); } } diff --git a/packages/flutter/lib/src/rendering/view.dart b/packages/flutter/lib/src/rendering/view.dart index f6e717fd9c7..c20f23d9247 100644 --- a/packages/flutter/lib/src/rendering/view.dart +++ b/packages/flutter/lib/src/rendering/view.dart @@ -73,7 +73,7 @@ class RenderView extends RenderObject with RenderObjectWithChildMixin void scheduleInitialFrame() { scheduleInitialLayout(); scheduleInitialPaint(new TransformLayer(transform: _logicalToDeviceTransform)); - scheduler.ensureVisualUpdate(); + Scheduler.instance.ensureVisualUpdate(); } // We never call layout() on this class, so this should never get diff --git a/packages/flutter/lib/src/scheduler/scheduler.dart b/packages/flutter/lib/src/scheduler/scheduler.dart index 65cc309cae0..b1420a5af26 100644 --- a/packages/flutter/lib/src/scheduler/scheduler.dart +++ b/packages/flutter/lib/src/scheduler/scheduler.dart @@ -7,6 +7,7 @@ import 'dart:developer'; import 'dart:ui' as ui; import 'package:collection/priority_queue.dart'; +import 'package:flutter/services.dart'; /// Slows down animations by this factor to help in development. double timeDilation = 1.0; @@ -80,12 +81,18 @@ class Priority { /// the task should be run. /// /// Tasks always run in the idle time after a frame has been committed. -class Scheduler { +abstract class Scheduler extends BindingBase { /// Requires clients to use the [scheduler] singleton - Scheduler._() { + + void initInstances() { + super.initInstances(); + _instance = this; ui.window.onBeginFrame = handleBeginFrame; } + static Scheduler _instance; + static Scheduler get instance => _instance; + SchedulingStrategy schedulingStrategy = new DefaultSchedulingStrategy(); final PriorityQueue _taskQueue = new HeapPriorityQueue<_TaskEntry>( @@ -120,7 +127,7 @@ class Scheduler { if (_taskQueue.isEmpty) return; _TaskEntry entry = _taskQueue.first; - if (schedulingStrategy.shouldRunTaskWithPriority(entry.priority)) { + if (schedulingStrategy.shouldRunTaskWithPriority(priority: entry.priority, scheduler: this)) { try { (_taskQueue.removeFirst().task)(); } finally { @@ -295,17 +302,15 @@ class Scheduler { } } -final Scheduler scheduler = new Scheduler._(); - abstract class SchedulingStrategy { - bool shouldRunTaskWithPriority(int priority); + bool shouldRunTaskWithPriority({ int priority, Scheduler scheduler }); } class DefaultSchedulingStrategy implements SchedulingStrategy { // TODO(floitsch): for now we only expose the priority. It might be // interesting to provide more info (like, how long the task ran the last // time). - bool shouldRunTaskWithPriority(int priority) { + bool shouldRunTaskWithPriority({ int priority, Scheduler scheduler }) { if (scheduler.transientCallbackCount > 0) return priority >= Priority.animation._value; return true; diff --git a/packages/flutter/lib/src/services/asset_bundle.dart b/packages/flutter/lib/src/services/asset_bundle.dart index 2944c8078a0..877dd3869c0 100644 --- a/packages/flutter/lib/src/services/asset_bundle.dart +++ b/packages/flutter/lib/src/services/asset_bundle.dart @@ -100,7 +100,8 @@ class MojoAssetBundle extends AssetBundle { AssetBundle _initRootBundle() { try { AssetBundleProxy bundle = new AssetBundleProxy.fromHandle( - new core.MojoHandle(internals.takeRootBundleHandle())); + new core.MojoHandle(internals.takeRootBundleHandle()) + ); return new MojoAssetBundle(bundle); } catch (e) { return null; diff --git a/packages/flutter/lib/src/services/binding.dart b/packages/flutter/lib/src/services/binding.dart new file mode 100644 index 00000000000..c9cf8a3132f --- /dev/null +++ b/packages/flutter/lib/src/services/binding.dart @@ -0,0 +1,32 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/// Base class for mixins that provide singleton services (also known as +/// "bindings"). +/// +/// To use this class in a mixin, inherit from it and implement +/// [initInstances()]. The mixin is guaranteed to only be constructed once in +/// the lifetime of the app (more precisely, it will assert if constructed twice +/// in checked mode). +abstract class BindingBase { + BindingBase() { + assert(!_debugInitialized); + initInstances(); + assert(_debugInitialized); + } + + static bool _debugInitialized = false; + + /// The initialization method. Subclasses override this method to hook into + /// the platform and otherwise configure their services. Subclasses must call + /// "super.initInstances()". + /// + /// By convention, if the service is to be provided as a singleton, it should + /// be exposed as `MixinClassName.instance`, a static getter that returns + /// `MixinClassName._instance`, a static field that is set by + /// `initInstances()`. + void initInstances() { + assert(() { _debugInitialized = true; return true; }); + } +} diff --git a/packages/flutter/lib/src/widgets/binding.dart b/packages/flutter/lib/src/widgets/binding.dart index c07b421629c..d0e03c3b51e 100644 --- a/packages/flutter/lib/src/widgets/binding.dart +++ b/packages/flutter/lib/src/widgets/binding.dart @@ -2,35 +2,82 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import 'dart:ui' as ui; import 'dart:developer'; +import 'package:flutter/gestures.dart'; import 'package:flutter/rendering.dart'; import 'package:flutter/scheduler.dart'; +import 'package:flutter/services.dart'; import 'framework.dart'; -/// The glue that binds the widget framework to the Flutter engine. -class WidgetFlutterBinding extends FlutterBinding { +class BindingObserver { + bool didPopRoute() => false; + void didChangeSize(Size size) { } + void didChangeLocale(ui.Locale locale) { } +} - WidgetFlutterBinding() { - BuildableElement.scheduleBuildFor = scheduleBuildFor; +/// A concrete binding for applications based on the Widgets framework. +/// This is the glue that binds the framework to the Flutter engine. +class WidgetFlutterBinding extends BindingBase with Scheduler, Pointerer, Renderer { + + WidgetFlutterBinding._(); + + /// Creates and initializes the WidgetFlutterBinding. This constructor is + /// idempotent; calling it a second time will just return the + /// previously-created instance. + static WidgetFlutterBinding ensureInitialized() { + if (_instance == null) + new WidgetFlutterBinding._(); + return _instance; } - /// Ensures that there is a FlutterBinding object instantiated. - static void ensureInitialized() { - if (FlutterBinding.instance == null) - new WidgetFlutterBinding(); - assert(FlutterBinding.instance is WidgetFlutterBinding); + initInstances() { + super.initInstances(); + _instance = this; + BuildableElement.scheduleBuildFor = scheduleBuildFor; + ui.window.onLocaleChanged = handleLocaleChanged; + ui.window.onPopRoute = handlePopRoute; } /// The one static instance of this class. /// - /// Only valid after ensureInitialized() (or the WidgetFlutterBinding - /// constructor) has been called. If another FlutterBinding subclass is - /// instantiated before this one (e.g. bindings from other frameworks based on - /// the Flutter "rendering" library), then WidgetFlutterBinding.instance will - /// not be valid (and will throw in checked mode). - static WidgetFlutterBinding get instance => FlutterBinding.instance; + /// Only valid after the WidgetFlutterBinding constructor) has been called. + /// Only one binding class can be instantiated per process. If another + /// BindingBase implementation has been instantiated before this one (e.g. + /// bindings from other frameworks based on the Flutter "rendering" library), + /// then WidgetFlutterBinding.instance will not be valid (and will throw in + /// checked mode). + static WidgetFlutterBinding _instance; + static WidgetFlutterBinding get instance => _instance; + + final List _observers = new List(); + + void addObserver(BindingObserver observer) => _observers.add(observer); + bool removeObserver(BindingObserver observer) => _observers.remove(observer); + + void handleMetricsChanged() { + super.handleMetricsChanged(); + for (BindingObserver observer in _observers) + observer.didChangeSize(ui.window.size); + } + + void handleLocaleChanged() { + dispatchLocaleChanged(ui.window.locale); + } + + void dispatchLocaleChanged(ui.Locale locale) { + for (BindingObserver observer in _observers) + observer.didChangeLocale(locale); + } + + void handlePopRoute() { + for (BindingObserver observer in _observers) { + if (observer.didPopRoute()) + break; + } + } void beginFrame() { buildDirtyElements(); @@ -46,7 +93,7 @@ class WidgetFlutterBinding extends FlutterBinding { assert(!_dirtyElements.contains(element)); assert(element.dirty); if (_dirtyElements.isEmpty) - scheduler.ensureVisualUpdate(); + ensureVisualUpdate(); _dirtyElements.add(element); } @@ -93,8 +140,7 @@ class WidgetFlutterBinding extends FlutterBinding { /// Inflate the given widget and attach it to the screen. void runApp(Widget app) { - WidgetFlutterBinding.ensureInitialized(); - WidgetFlutterBinding.instance._runApp(app); + WidgetFlutterBinding.ensureInitialized()._runApp(app); } /// Print a string representation of the currently running app. @@ -157,7 +203,7 @@ class RenderObjectToWidgetElement extends RenderObjectEl Element _child; - static const _rootChild = const Object(); + static const _rootChildSlot = const Object(); void visitChildren(ElementVisitor visitor) { if (_child != null) @@ -167,19 +213,19 @@ class RenderObjectToWidgetElement extends RenderObjectEl void mount(Element parent, dynamic newSlot) { assert(parent == null); super.mount(parent, newSlot); - _child = updateChild(_child, widget.child, _rootChild); + _child = updateChild(_child, widget.child, _rootChildSlot); } void update(RenderObjectToWidgetAdapter newWidget) { super.update(newWidget); assert(widget == newWidget); - _child = updateChild(_child, widget.child, _rootChild); + _child = updateChild(_child, widget.child, _rootChildSlot); } RenderObjectWithChildMixin get renderObject => super.renderObject; void insertChildRenderObject(RenderObject child, dynamic slot) { - assert(slot == _rootChild); + assert(slot == _rootChildSlot); renderObject.child = child; } diff --git a/packages/flutter/lib/src/widgets/drag_target.dart b/packages/flutter/lib/src/widgets/drag_target.dart index 755319ed3be..592d098f6bb 100644 --- a/packages/flutter/lib/src/widgets/drag_target.dart +++ b/packages/flutter/lib/src/widgets/drag_target.dart @@ -96,6 +96,7 @@ class Draggable extends DraggableBase { GestureRecognizer createRecognizer(PointerRouter router, DragStartCallback starter) { return new MultiTapGestureRecognizer( router: router, + gestureArena: Pointerer.instance.gestureArena, onTapDown: starter ); } @@ -122,6 +123,7 @@ class LongPressDraggable extends DraggableBase { GestureRecognizer createRecognizer(PointerRouter router, DragStartCallback starter) { return new MultiTapGestureRecognizer( router: router, + gestureArena: Pointerer.instance.gestureArena, longTapDelay: kLongPressTimeout, onLongTapDown: (Point position, int pointer) { userFeedback.performHapticFeedback(HapticFeedbackType.VIRTUAL_KEY); @@ -133,7 +135,7 @@ class LongPressDraggable extends DraggableBase { class _DraggableState extends State> implements GestureArenaMember { - PointerRouter get router => FlutterBinding.instance.pointerRouter; + PointerRouter get router => Pointerer.instance.pointerRouter; void initState() { super.initState(); @@ -144,7 +146,7 @@ class _DraggableState extends State> implements GestureArena Map _activePointers = {}; void _routePointer(PointerEvent event) { - _activePointers[event.pointer] = GestureArena.instance.add(event.pointer, this); + _activePointers[event.pointer] = Pointerer.instance.gestureArena.add(event.pointer, this); _recognizer.addPointer(event); } @@ -315,7 +317,8 @@ class _DragAvatar { void update(Point globalPosition) { _lastOffset = globalPosition - dragStartPoint; _entry.markNeedsBuild(); - HitTestResult result = WidgetFlutterBinding.instance.hitTest(globalPosition + feedbackOffset); + HitTestResult result = new HitTestResult(); + WidgetFlutterBinding.instance.hitTest(result, globalPosition + feedbackOffset); _DragTargetState target = _getDragTarget(result.path); if (target == _activeTarget) return; diff --git a/packages/flutter/lib/src/widgets/gesture_detector.dart b/packages/flutter/lib/src/widgets/gesture_detector.dart index c4b94c4b195..fbad78e5751 100644 --- a/packages/flutter/lib/src/widgets/gesture_detector.dart +++ b/packages/flutter/lib/src/widgets/gesture_detector.dart @@ -121,7 +121,7 @@ class GestureDetector extends StatefulComponent { } class _GestureDetectorState extends State { - PointerRouter get _router => FlutterBinding.instance.pointerRouter; + PointerRouter get _router => Pointerer.instance.pointerRouter; TapGestureRecognizer _tap; DoubleTapGestureRecognizer _doubleTap; @@ -165,7 +165,7 @@ class _GestureDetectorState extends State { if (config.onTapDown == null && config.onTapUp == null && config.onTap == null && config.onTapCancel == null) { _tap = _ensureDisposed(_tap); } else { - _tap ??= new TapGestureRecognizer(router: _router); + _tap ??= new TapGestureRecognizer(router: _router, gestureArena: Pointerer.instance.gestureArena); _tap ..onTapDown = config.onTapDown ..onTapUp = config.onTapUp @@ -178,7 +178,7 @@ class _GestureDetectorState extends State { if (config.onDoubleTap == null) { _doubleTap = _ensureDisposed(_doubleTap); } else { - _doubleTap ??= new DoubleTapGestureRecognizer(router: _router); + _doubleTap ??= new DoubleTapGestureRecognizer(router: _router, gestureArena: Pointerer.instance.gestureArena); _doubleTap.onDoubleTap = config.onDoubleTap; } } @@ -187,7 +187,7 @@ class _GestureDetectorState extends State { if (config.onLongPress == null) { _longPress = _ensureDisposed(_longPress); } else { - _longPress ??= new LongPressGestureRecognizer(router: _router); + _longPress ??= new LongPressGestureRecognizer(router: _router, gestureArena: Pointerer.instance.gestureArena); _longPress.onLongPress = config.onLongPress; } } @@ -196,7 +196,7 @@ class _GestureDetectorState extends State { if (config.onVerticalDragStart == null && config.onVerticalDragUpdate == null && config.onVerticalDragEnd == null) { _verticalDrag = _ensureDisposed(_verticalDrag); } else { - _verticalDrag ??= new VerticalDragGestureRecognizer(router: _router); + _verticalDrag ??= new VerticalDragGestureRecognizer(router: _router, gestureArena: Pointerer.instance.gestureArena); _verticalDrag ..onStart = config.onVerticalDragStart ..onUpdate = config.onVerticalDragUpdate @@ -208,7 +208,7 @@ class _GestureDetectorState extends State { if (config.onHorizontalDragStart == null && config.onHorizontalDragUpdate == null && config.onHorizontalDragEnd == null) { _horizontalDrag = _ensureDisposed(_horizontalDrag); } else { - _horizontalDrag ??= new HorizontalDragGestureRecognizer(router: _router); + _horizontalDrag ??= new HorizontalDragGestureRecognizer(router: _router, gestureArena: Pointerer.instance.gestureArena); _horizontalDrag ..onStart = config.onHorizontalDragStart ..onUpdate = config.onHorizontalDragUpdate @@ -221,7 +221,7 @@ class _GestureDetectorState extends State { _pan = _ensureDisposed(_pan); } else { assert(_scale == null); // Scale is a superset of pan; just use scale - _pan ??= new PanGestureRecognizer(router: _router); + _pan ??= new PanGestureRecognizer(router: _router, gestureArena: Pointerer.instance.gestureArena); _pan ..onStart = config.onPanStart ..onUpdate = config.onPanUpdate @@ -234,7 +234,7 @@ class _GestureDetectorState extends State { _scale = _ensureDisposed(_scale); } else { assert(_pan == null); // Scale is a superset of pan; just use scale - _scale ??= new ScaleGestureRecognizer(router: _router); + _scale ??= new ScaleGestureRecognizer(router: _router, gestureArena: Pointerer.instance.gestureArena); _scale ..onStart = config.onScaleStart ..onUpdate = config.onScaleUpdate diff --git a/packages/flutter/lib/src/widgets/heroes.dart b/packages/flutter/lib/src/widgets/heroes.dart index feb5b058025..fdc1e41a9d2 100644 --- a/packages/flutter/lib/src/widgets/heroes.dart +++ b/packages/flutter/lib/src/widgets/heroes.dart @@ -455,7 +455,7 @@ class HeroController extends NavigatorObserver { void _checkForHeroQuest() { if (_from != null && _to != null && _from != _to) { _to.offstage = _to.performance.status != PerformanceStatus.completed; - scheduler.addPostFrameCallback(_updateQuest); + Scheduler.instance.addPostFrameCallback(_updateQuest); } } diff --git a/packages/flutter_test/lib/src/widget_tester.dart b/packages/flutter_test/lib/src/widget_tester.dart index d71b8e826b4..280e552d518 100644 --- a/packages/flutter_test/lib/src/widget_tester.dart +++ b/packages/flutter_test/lib/src/widget_tester.dart @@ -17,13 +17,15 @@ typedef Point SizeToPointFunction(Size size); class WidgetTester { WidgetTester._(FakeAsync async) - : async = async, + : binding = WidgetFlutterBinding.ensureInitialized(), + async = async, clock = async.getClock(new DateTime.utc(2015, 1, 1)) { timeDilation = 1.0; ui.window.onBeginFrame = null; runApp(new ErrorWidget()); // flush out the last build entirely } + final WidgetFlutterBinding binding; final FakeAsync async; final Clock clock; @@ -34,15 +36,16 @@ class WidgetTester { void setLocale(String languageCode, String countryCode) { ui.Locale locale = new ui.Locale(languageCode, countryCode); - FlutterBinding.instance.dispatchLocaleChanged(locale); + binding.dispatchLocaleChanged(locale); async.flushMicrotasks(); } void pump([ Duration duration ]) { if (duration != null) async.elapse(duration); - scheduler.handleBeginFrame(new Duration( - milliseconds: clock.now().millisecondsSinceEpoch)); + binding.handleBeginFrame(new Duration( + milliseconds: clock.now().millisecondsSinceEpoch) + ); async.flushMicrotasks(); } @@ -58,7 +61,7 @@ class WidgetTester { } return result; } - List get layers => _layers(FlutterBinding.instance.renderView.layer); + List get layers => _layers(binding.renderView.layer); void walkElements(ElementVisitor visitor) { @@ -66,7 +69,7 @@ class WidgetTester { visitor(element); element.visitChildren(walk); } - WidgetFlutterBinding.instance.renderViewElement.visitChildren(walk); + binding.renderViewElement.visitChildren(walk); } Element findElement(bool predicate(Element element)) { @@ -184,10 +187,14 @@ class WidgetTester { _dispatchEvent(event, _hitTest(location)); } - HitTestResult _hitTest(Point location) => WidgetFlutterBinding.instance.hitTest(location); + HitTestResult _hitTest(Point location) { + HitTestResult result = new HitTestResult(); + binding.hitTest(result, location); + return result; + } void _dispatchEvent(PointerEvent event, HitTestResult result) { - WidgetFlutterBinding.instance.dispatchEvent(event, result); + binding.dispatchEvent(event, result); } } diff --git a/packages/unit/test/engine/canvas_test_disabled.dart b/packages/unit/test/engine/canvas_test_disabled.dart index d8fe0506906..e6db08e74d1 100644 --- a/packages/unit/test/engine/canvas_test_disabled.dart +++ b/packages/unit/test/engine/canvas_test_disabled.dart @@ -1,3 +1,7 @@ +// Copyright 2015 The Chromium 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' as ui; import 'dart:ui' show Rect, Color, Paint; diff --git a/packages/unit/test/engine/color_test.dart b/packages/unit/test/engine/color_test.dart index 2a5c33fd106..f4accabf64d 100644 --- a/packages/unit/test/engine/color_test.dart +++ b/packages/unit/test/engine/color_test.dart @@ -1,3 +1,7 @@ +// Copyright 2015 The Chromium 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:test/test.dart'; diff --git a/packages/unit/test/engine/paragraph_builder_test.dart b/packages/unit/test/engine/paragraph_builder_test.dart index 7d88d407874..5f29e1260d5 100644 --- a/packages/unit/test/engine/paragraph_builder_test.dart +++ b/packages/unit/test/engine/paragraph_builder_test.dart @@ -1,3 +1,7 @@ +// Copyright 2015 The Chromium 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:test/test.dart'; diff --git a/packages/unit/test/engine/rect_test.dart b/packages/unit/test/engine/rect_test.dart index 6f9ec1adb35..874be265d2c 100644 --- a/packages/unit/test/engine/rect_test.dart +++ b/packages/unit/test/engine/rect_test.dart @@ -1,3 +1,7 @@ +// Copyright 2015 The Chromium 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:test/test.dart'; diff --git a/packages/unit/test/examples/sector_layout_test.dart b/packages/unit/test/examples/sector_layout_test.dart index fd5a05640c1..5c061a89a7c 100644 --- a/packages/unit/test/examples/sector_layout_test.dart +++ b/packages/unit/test/examples/sector_layout_test.dart @@ -1,3 +1,7 @@ +// Copyright 2015 The Chromium 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 'package:test/test.dart'; import '../rendering/rendering_tester.dart'; diff --git a/packages/unit/test/gestures/arena_test.dart b/packages/unit/test/gestures/arena_test.dart index a5b59f7746c..27b1ec22992 100644 --- a/packages/unit/test/gestures/arena_test.dart +++ b/packages/unit/test/gestures/arena_test.dart @@ -1,3 +1,7 @@ +// Copyright 2015 The Chromium 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 'package:flutter/gestures.dart'; import 'package:test/test.dart'; diff --git a/packages/unit/test/gestures/double_tap_test.dart b/packages/unit/test/gestures/double_tap_test.dart index 6ca9994dcaa..add121c2ed8 100644 --- a/packages/unit/test/gestures/double_tap_test.dart +++ b/packages/unit/test/gestures/double_tap_test.dart @@ -1,3 +1,7 @@ +// Copyright 2015 The Chromium 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 'package:flutter/gestures.dart'; import 'package:quiver/testing/async.dart'; import 'package:test/test.dart'; @@ -77,7 +81,11 @@ void main() { test('Should recognize double tap', () { PointerRouter router = new PointerRouter(); - DoubleTapGestureRecognizer tap = new DoubleTapGestureRecognizer(router: router); + GestureArena gestureArena = new GestureArena(); + DoubleTapGestureRecognizer tap = new DoubleTapGestureRecognizer( + router: router, + gestureArena: gestureArena + ); bool doubleTapRecognized = false; tap.onDoubleTap = () { @@ -85,25 +93,25 @@ void main() { }; tap.addPointer(down1); - GestureArena.instance.close(1); + gestureArena.close(1); expect(doubleTapRecognized, isFalse); router.route(down1); expect(doubleTapRecognized, isFalse); router.route(up1); expect(doubleTapRecognized, isFalse); - GestureArena.instance.sweep(1); + gestureArena.sweep(1); expect(doubleTapRecognized, isFalse); tap.addPointer(down2); - GestureArena.instance.close(2); + gestureArena.close(2); expect(doubleTapRecognized, isFalse); router.route(down2); expect(doubleTapRecognized, isFalse); router.route(up2); expect(doubleTapRecognized, isTrue); - GestureArena.instance.sweep(2); + gestureArena.sweep(2); expect(doubleTapRecognized, isTrue); tap.dispose(); @@ -111,7 +119,11 @@ void main() { test('Inter-tap distance cancels double tap', () { PointerRouter router = new PointerRouter(); - DoubleTapGestureRecognizer tap = new DoubleTapGestureRecognizer(router: router); + GestureArena gestureArena = new GestureArena(); + DoubleTapGestureRecognizer tap = new DoubleTapGestureRecognizer( + router: router, + gestureArena: gestureArena + ); bool doubleTapRecognized = false; tap.onDoubleTap = () { @@ -119,25 +131,25 @@ void main() { }; tap.addPointer(down1); - GestureArena.instance.close(1); + gestureArena.close(1); expect(doubleTapRecognized, isFalse); router.route(down1); expect(doubleTapRecognized, isFalse); router.route(up1); expect(doubleTapRecognized, isFalse); - GestureArena.instance.sweep(1); + gestureArena.sweep(1); expect(doubleTapRecognized, isFalse); tap.addPointer(down3); - GestureArena.instance.close(3); + gestureArena.close(3); expect(doubleTapRecognized, isFalse); router.route(down3); expect(doubleTapRecognized, isFalse); router.route(up3); expect(doubleTapRecognized, isFalse); - GestureArena.instance.sweep(3); + gestureArena.sweep(3); expect(doubleTapRecognized, isFalse); tap.dispose(); @@ -145,7 +157,11 @@ void main() { test('Intra-tap distance cancels double tap', () { PointerRouter router = new PointerRouter(); - DoubleTapGestureRecognizer tap = new DoubleTapGestureRecognizer(router: router); + GestureArena gestureArena = new GestureArena(); + DoubleTapGestureRecognizer tap = new DoubleTapGestureRecognizer( + router: router, + gestureArena: gestureArena + ); bool doubleTapRecognized = false; tap.onDoubleTap = () { @@ -153,7 +169,7 @@ void main() { }; tap.addPointer(down4); - GestureArena.instance.close(4); + gestureArena.close(4); expect(doubleTapRecognized, isFalse); router.route(down4); expect(doubleTapRecognized, isFalse); @@ -162,18 +178,18 @@ void main() { expect(doubleTapRecognized, isFalse); router.route(up4); expect(doubleTapRecognized, isFalse); - GestureArena.instance.sweep(4); + gestureArena.sweep(4); expect(doubleTapRecognized, isFalse); tap.addPointer(down1); - GestureArena.instance.close(1); + gestureArena.close(1); expect(doubleTapRecognized, isFalse); router.route(down2); expect(doubleTapRecognized, isFalse); router.route(up1); expect(doubleTapRecognized, isFalse); - GestureArena.instance.sweep(1); + gestureArena.sweep(1); expect(doubleTapRecognized, isFalse); tap.dispose(); @@ -181,7 +197,11 @@ void main() { test('Inter-tap delay cancels double tap', () { PointerRouter router = new PointerRouter(); - DoubleTapGestureRecognizer tap = new DoubleTapGestureRecognizer(router: router); + GestureArena gestureArena = new GestureArena(); + DoubleTapGestureRecognizer tap = new DoubleTapGestureRecognizer( + router: router, + gestureArena: gestureArena + ); bool doubleTapRecognized = false; tap.onDoubleTap = () { @@ -190,26 +210,26 @@ void main() { new FakeAsync().run((FakeAsync async) { tap.addPointer(down1); - GestureArena.instance.close(1); + gestureArena.close(1); expect(doubleTapRecognized, isFalse); router.route(down1); expect(doubleTapRecognized, isFalse); router.route(up1); expect(doubleTapRecognized, isFalse); - GestureArena.instance.sweep(1); + gestureArena.sweep(1); expect(doubleTapRecognized, isFalse); async.elapse(new Duration(milliseconds: 5000)); tap.addPointer(down2); - GestureArena.instance.close(2); + gestureArena.close(2); expect(doubleTapRecognized, isFalse); router.route(down2); expect(doubleTapRecognized, isFalse); router.route(up2); expect(doubleTapRecognized, isFalse); - GestureArena.instance.sweep(2); + gestureArena.sweep(2); expect(doubleTapRecognized, isFalse); }); @@ -218,7 +238,11 @@ void main() { test('Inter-tap delay resets double tap, allowing third tap to be a double-tap', () { PointerRouter router = new PointerRouter(); - DoubleTapGestureRecognizer tap = new DoubleTapGestureRecognizer(router: router); + GestureArena gestureArena = new GestureArena(); + DoubleTapGestureRecognizer tap = new DoubleTapGestureRecognizer( + router: router, + gestureArena: gestureArena + ); bool doubleTapRecognized = false; tap.onDoubleTap = () { @@ -227,38 +251,38 @@ void main() { new FakeAsync().run((FakeAsync async) { tap.addPointer(down1); - GestureArena.instance.close(1); + gestureArena.close(1); expect(doubleTapRecognized, isFalse); router.route(down1); expect(doubleTapRecognized, isFalse); router.route(up1); expect(doubleTapRecognized, isFalse); - GestureArena.instance.sweep(1); + gestureArena.sweep(1); expect(doubleTapRecognized, isFalse); async.elapse(new Duration(milliseconds: 5000)); tap.addPointer(down2); - GestureArena.instance.close(2); + gestureArena.close(2); expect(doubleTapRecognized, isFalse); router.route(down2); expect(doubleTapRecognized, isFalse); router.route(up2); expect(doubleTapRecognized, isFalse); - GestureArena.instance.sweep(2); + gestureArena.sweep(2); expect(doubleTapRecognized, isFalse); async.elapse(new Duration(milliseconds: 100)); tap.addPointer(down5); - GestureArena.instance.close(5); + gestureArena.close(5); expect(doubleTapRecognized, isFalse); router.route(down5); expect(doubleTapRecognized, isFalse); router.route(up5); expect(doubleTapRecognized, isTrue); - GestureArena.instance.sweep(5); + gestureArena.sweep(5); expect(doubleTapRecognized, isTrue); }); @@ -267,7 +291,11 @@ void main() { test('Intra-tap delay does not cancel double tap', () { PointerRouter router = new PointerRouter(); - DoubleTapGestureRecognizer tap = new DoubleTapGestureRecognizer(router: router); + GestureArena gestureArena = new GestureArena(); + DoubleTapGestureRecognizer tap = new DoubleTapGestureRecognizer( + router: router, + gestureArena: gestureArena + ); bool doubleTapRecognized = false; tap.onDoubleTap = () { @@ -276,7 +304,7 @@ void main() { new FakeAsync().run((FakeAsync async) { tap.addPointer(down1); - GestureArena.instance.close(1); + gestureArena.close(1); expect(doubleTapRecognized, isFalse); router.route(down1); expect(doubleTapRecognized, isFalse); @@ -284,18 +312,18 @@ void main() { async.elapse(new Duration(milliseconds: 1000)); router.route(up1); expect(doubleTapRecognized, isFalse); - GestureArena.instance.sweep(1); + gestureArena.sweep(1); expect(doubleTapRecognized, isFalse); tap.addPointer(down2); - GestureArena.instance.close(2); + gestureArena.close(2); expect(doubleTapRecognized, isFalse); router.route(down2); expect(doubleTapRecognized, isFalse); router.route(up2); expect(doubleTapRecognized, isTrue); - GestureArena.instance.sweep(2); + gestureArena.sweep(2); expect(doubleTapRecognized, isTrue); }); @@ -304,7 +332,11 @@ void main() { test('Should not recognize two overlapping taps', () { PointerRouter router = new PointerRouter(); - DoubleTapGestureRecognizer tap = new DoubleTapGestureRecognizer(router: router); + GestureArena gestureArena = new GestureArena(); + DoubleTapGestureRecognizer tap = new DoubleTapGestureRecognizer( + router: router, + gestureArena: gestureArena + ); bool doubleTapRecognized = false; tap.onDoubleTap = () { @@ -312,25 +344,25 @@ void main() { }; tap.addPointer(down1); - GestureArena.instance.close(1); + gestureArena.close(1); expect(doubleTapRecognized, isFalse); router.route(down1); expect(doubleTapRecognized, isFalse); tap.addPointer(down2); - GestureArena.instance.close(2); + gestureArena.close(2); expect(doubleTapRecognized, isFalse); router.route(down1); expect(doubleTapRecognized, isFalse); router.route(up1); expect(doubleTapRecognized, isFalse); - GestureArena.instance.sweep(1); + gestureArena.sweep(1); expect(doubleTapRecognized, isFalse); router.route(up2); expect(doubleTapRecognized, isFalse); - GestureArena.instance.sweep(2); + gestureArena.sweep(2); expect(doubleTapRecognized, isFalse); tap.dispose(); @@ -338,7 +370,11 @@ void main() { test('Should recognize one tap of group followed by second tap', () { PointerRouter router = new PointerRouter(); - DoubleTapGestureRecognizer tap = new DoubleTapGestureRecognizer(router: router); + GestureArena gestureArena = new GestureArena(); + DoubleTapGestureRecognizer tap = new DoubleTapGestureRecognizer( + router: router, + gestureArena: gestureArena + ); bool doubleTapRecognized = false; tap.onDoubleTap = () { @@ -346,36 +382,36 @@ void main() { }; tap.addPointer(down1); - GestureArena.instance.close(1); + gestureArena.close(1); expect(doubleTapRecognized, isFalse); router.route(down1); expect(doubleTapRecognized, isFalse); tap.addPointer(down2); - GestureArena.instance.close(2); + gestureArena.close(2); expect(doubleTapRecognized, isFalse); router.route(down1); expect(doubleTapRecognized, isFalse); router.route(up1); expect(doubleTapRecognized, isFalse); - GestureArena.instance.sweep(1); + gestureArena.sweep(1); expect(doubleTapRecognized, isFalse); router.route(up2); expect(doubleTapRecognized, isFalse); - GestureArena.instance.sweep(2); + gestureArena.sweep(2); expect(doubleTapRecognized, isFalse); tap.addPointer(down1); - GestureArena.instance.close(1); + gestureArena.close(1); expect(doubleTapRecognized, isFalse); router.route(down1); expect(doubleTapRecognized, isFalse); router.route(up1); expect(doubleTapRecognized, isTrue); - GestureArena.instance.sweep(1); + gestureArena.sweep(1); expect(doubleTapRecognized, isTrue); tap.dispose(); @@ -384,7 +420,11 @@ void main() { test('Should cancel on arena reject during first tap', () { PointerRouter router = new PointerRouter(); - DoubleTapGestureRecognizer tap = new DoubleTapGestureRecognizer(router: router); + GestureArena gestureArena = new GestureArena(); + DoubleTapGestureRecognizer tap = new DoubleTapGestureRecognizer( + router: router, + gestureArena: gestureArena + ); bool doubleTapRecognized = false; tap.onDoubleTap = () { @@ -393,8 +433,8 @@ void main() { tap.addPointer(down1); TestGestureArenaMember member = new TestGestureArenaMember(); - GestureArenaEntry entry = GestureArena.instance.add(1, member); - GestureArena.instance.close(1); + GestureArenaEntry entry = gestureArena.add(1, member); + gestureArena.close(1); expect(doubleTapRecognized, isFalse); router.route(down1); expect(doubleTapRecognized, isFalse); @@ -404,18 +444,18 @@ void main() { entry.resolve(GestureDisposition.accepted); expect(member.accepted, isTrue); expect(doubleTapRecognized, isFalse); - GestureArena.instance.sweep(1); + gestureArena.sweep(1); expect(doubleTapRecognized, isFalse); tap.addPointer(down2); - GestureArena.instance.close(2); + gestureArena.close(2); expect(doubleTapRecognized, isFalse); router.route(down2); expect(doubleTapRecognized, isFalse); router.route(up2); expect(doubleTapRecognized, isFalse); - GestureArena.instance.sweep(2); + gestureArena.sweep(2); expect(doubleTapRecognized, isFalse); tap.dispose(); @@ -423,7 +463,11 @@ void main() { test('Should cancel on arena reject between taps', () { PointerRouter router = new PointerRouter(); - DoubleTapGestureRecognizer tap = new DoubleTapGestureRecognizer(router: router); + GestureArena gestureArena = new GestureArena(); + DoubleTapGestureRecognizer tap = new DoubleTapGestureRecognizer( + router: router, + gestureArena: gestureArena + ); bool doubleTapRecognized = false; tap.onDoubleTap = () { @@ -432,29 +476,29 @@ void main() { tap.addPointer(down1); TestGestureArenaMember member = new TestGestureArenaMember(); - GestureArenaEntry entry = GestureArena.instance.add(1, member); - GestureArena.instance.close(1); + GestureArenaEntry entry = gestureArena.add(1, member); + gestureArena.close(1); expect(doubleTapRecognized, isFalse); router.route(down1); expect(doubleTapRecognized, isFalse); router.route(up1); expect(doubleTapRecognized, isFalse); - GestureArena.instance.sweep(1); + gestureArena.sweep(1); expect(doubleTapRecognized, isFalse); entry.resolve(GestureDisposition.accepted); expect(member.accepted, isTrue); tap.addPointer(down2); - GestureArena.instance.close(2); + gestureArena.close(2); expect(doubleTapRecognized, isFalse); router.route(down2); expect(doubleTapRecognized, isFalse); router.route(up2); expect(doubleTapRecognized, isFalse); - GestureArena.instance.sweep(2); + gestureArena.sweep(2); expect(doubleTapRecognized, isFalse); tap.dispose(); @@ -462,7 +506,11 @@ void main() { test('Should cancel on arena reject during last tap', () { PointerRouter router = new PointerRouter(); - DoubleTapGestureRecognizer tap = new DoubleTapGestureRecognizer(router: router); + GestureArena gestureArena = new GestureArena(); + DoubleTapGestureRecognizer tap = new DoubleTapGestureRecognizer( + router: router, + gestureArena: gestureArena + ); bool doubleTapRecognized = false; tap.onDoubleTap = () { @@ -471,19 +519,19 @@ void main() { tap.addPointer(down1); TestGestureArenaMember member = new TestGestureArenaMember(); - GestureArenaEntry entry = GestureArena.instance.add(1, member); - GestureArena.instance.close(1); + GestureArenaEntry entry = gestureArena.add(1, member); + gestureArena.close(1); expect(doubleTapRecognized, isFalse); router.route(down1); expect(doubleTapRecognized, isFalse); router.route(up1); expect(doubleTapRecognized, isFalse); - GestureArena.instance.sweep(1); + gestureArena.sweep(1); expect(doubleTapRecognized, isFalse); tap.addPointer(down2); - GestureArena.instance.close(2); + gestureArena.close(2); expect(doubleTapRecognized, isFalse); router.route(down2); expect(doubleTapRecognized, isFalse); @@ -493,7 +541,7 @@ void main() { router.route(up2); expect(doubleTapRecognized, isFalse); - GestureArena.instance.sweep(2); + gestureArena.sweep(2); expect(doubleTapRecognized, isFalse); tap.dispose(); @@ -501,7 +549,11 @@ void main() { test('Passive gesture should trigger on double tap cancel', () { PointerRouter router = new PointerRouter(); - DoubleTapGestureRecognizer tap = new DoubleTapGestureRecognizer(router: router); + GestureArena gestureArena = new GestureArena(); + DoubleTapGestureRecognizer tap = new DoubleTapGestureRecognizer( + router: router, + gestureArena: gestureArena + ); bool doubleTapRecognized = false; tap.onDoubleTap = () { @@ -511,15 +563,15 @@ void main() { new FakeAsync().run((FakeAsync async) { tap.addPointer(down1); TestGestureArenaMember member = new TestGestureArenaMember(); - GestureArena.instance.add(1, member); - GestureArena.instance.close(1); + gestureArena.add(1, member); + gestureArena.close(1); expect(doubleTapRecognized, isFalse); router.route(down1); expect(doubleTapRecognized, isFalse); router.route(up1); expect(doubleTapRecognized, isFalse); - GestureArena.instance.sweep(1); + gestureArena.sweep(1); expect(doubleTapRecognized, isFalse); expect(member.accepted, isFalse); diff --git a/packages/unit/test/gestures/long_press_test.dart b/packages/unit/test/gestures/long_press_test.dart index 3297ded93d8..e4c822a9764 100644 --- a/packages/unit/test/gestures/long_press_test.dart +++ b/packages/unit/test/gestures/long_press_test.dart @@ -1,3 +1,7 @@ +// Copyright 2015 The Chromium 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 'package:quiver/testing/async.dart'; import 'package:flutter/gestures.dart'; import 'package:test/test.dart'; @@ -15,7 +19,11 @@ const PointerUpEvent up = const PointerUpEvent( void main() { test('Should recognize long press', () { PointerRouter router = new PointerRouter(); - LongPressGestureRecognizer longPress = new LongPressGestureRecognizer(router: router); + GestureArena gestureArena = new GestureArena(); + LongPressGestureRecognizer longPress = new LongPressGestureRecognizer( + router: router, + gestureArena: gestureArena + ); bool longPressRecognized = false; longPress.onLongPress = () { @@ -24,7 +32,7 @@ void main() { new FakeAsync().run((FakeAsync async) { longPress.addPointer(down); - GestureArena.instance.close(5); + gestureArena.close(5); expect(longPressRecognized, isFalse); router.route(down); expect(longPressRecognized, isFalse); @@ -39,7 +47,11 @@ void main() { test('Up cancels long press', () { PointerRouter router = new PointerRouter(); - LongPressGestureRecognizer longPress = new LongPressGestureRecognizer(router: router); + GestureArena gestureArena = new GestureArena(); + LongPressGestureRecognizer longPress = new LongPressGestureRecognizer( + router: router, + gestureArena: gestureArena + ); bool longPressRecognized = false; longPress.onLongPress = () { @@ -48,7 +60,7 @@ void main() { new FakeAsync().run((FakeAsync async) { longPress.addPointer(down); - GestureArena.instance.close(5); + gestureArena.close(5); expect(longPressRecognized, isFalse); router.route(down); expect(longPressRecognized, isFalse); @@ -65,8 +77,15 @@ void main() { test('Should recognize both tap down and long press', () { PointerRouter router = new PointerRouter(); - TapGestureRecognizer tap = new TapGestureRecognizer(router: router); - LongPressGestureRecognizer longPress = new LongPressGestureRecognizer(router: router); + GestureArena gestureArena = new GestureArena(); + LongPressGestureRecognizer longPress = new LongPressGestureRecognizer( + router: router, + gestureArena: gestureArena + ); + TapGestureRecognizer tap = new TapGestureRecognizer( + router: router, + gestureArena: gestureArena + ); bool tapDownRecognized = false; tap.onTapDown = (_) { @@ -81,7 +100,7 @@ void main() { new FakeAsync().run((FakeAsync async) { tap.addPointer(down); longPress.addPointer(down); - GestureArena.instance.close(5); + gestureArena.close(5); expect(tapDownRecognized, isFalse); expect(longPressRecognized, isFalse); router.route(down); diff --git a/packages/unit/test/gestures/lsq_solver_test.dart b/packages/unit/test/gestures/lsq_solver_test.dart index 54384c6acca..08246b59e37 100644 --- a/packages/unit/test/gestures/lsq_solver_test.dart +++ b/packages/unit/test/gestures/lsq_solver_test.dart @@ -1,3 +1,7 @@ +// Copyright 2015 The Chromium 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 'package:flutter/gestures.dart'; import 'package:test/test.dart'; diff --git a/packages/unit/test/gestures/pointer_router_test.dart b/packages/unit/test/gestures/pointer_router_test.dart index 8f66fff8366..5328908db1e 100644 --- a/packages/unit/test/gestures/pointer_router_test.dart +++ b/packages/unit/test/gestures/pointer_router_test.dart @@ -1,3 +1,7 @@ +// Copyright 2015 The Chromium 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 'package:flutter_test/flutter_test.dart'; import 'package:flutter/gestures.dart'; import 'package:test/test.dart'; diff --git a/packages/unit/test/gestures/scale_test.dart b/packages/unit/test/gestures/scale_test.dart index 4916aa7b776..3684d01d941 100644 --- a/packages/unit/test/gestures/scale_test.dart +++ b/packages/unit/test/gestures/scale_test.dart @@ -1,3 +1,7 @@ +// Copyright 2015 The Chromium 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 'package:flutter_test/flutter_test.dart'; import 'package:flutter/gestures.dart'; import 'package:test/test.dart'; @@ -5,8 +9,15 @@ import 'package:test/test.dart'; void main() { test('Should recognize scale gestures', () { PointerRouter router = new PointerRouter(); - ScaleGestureRecognizer scale = new ScaleGestureRecognizer(router: router); - TapGestureRecognizer tap = new TapGestureRecognizer(router: router); + GestureArena gestureArena = new GestureArena(); + ScaleGestureRecognizer scale = new ScaleGestureRecognizer( + router: router, + gestureArena: gestureArena + ); + TapGestureRecognizer tap = new TapGestureRecognizer( + router: router, + gestureArena: gestureArena + ); bool didStartScale = false; Point updatedFocalPoint; @@ -37,7 +48,7 @@ void main() { scale.addPointer(down); tap.addPointer(down); - GestureArena.instance.close(1); + gestureArena.close(1); expect(didStartScale, isFalse); expect(updatedScale, isNull); expect(updatedFocalPoint, isNull); @@ -67,7 +78,7 @@ void main() { PointerDownEvent down2 = pointer2.down(const Point(10.0, 20.0)); scale.addPointer(down2); tap.addPointer(down2); - GestureArena.instance.close(2); + gestureArena.close(2); router.route(down2); expect(didEndScale, isTrue); @@ -100,7 +111,7 @@ void main() { PointerDownEvent down3 = pointer3.down(const Point(25.0, 35.0)); scale.addPointer(down3); tap.addPointer(down3); - GestureArena.instance.close(3); + gestureArena.close(3); router.route(down3); expect(didEndScale, isTrue); diff --git a/packages/unit/test/gestures/scroll_test.dart b/packages/unit/test/gestures/scroll_test.dart index 5280438d819..649727c5cab 100644 --- a/packages/unit/test/gestures/scroll_test.dart +++ b/packages/unit/test/gestures/scroll_test.dart @@ -1,3 +1,7 @@ +// Copyright 2015 The Chromium 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 'package:flutter_test/flutter_test.dart'; import 'package:flutter/gestures.dart'; import 'package:test/test.dart'; @@ -5,8 +9,15 @@ import 'package:test/test.dart'; void main() { test('Should recognize pan', () { PointerRouter router = new PointerRouter(); - PanGestureRecognizer pan = new PanGestureRecognizer(router: router); - TapGestureRecognizer tap = new TapGestureRecognizer(router: router); + GestureArena gestureArena = new GestureArena(); + PanGestureRecognizer pan = new PanGestureRecognizer( + router: router, + gestureArena: gestureArena + ); + TapGestureRecognizer tap = new TapGestureRecognizer( + router: router, + gestureArena: gestureArena + ); bool didStartPan = false; pan.onStart = (_) { @@ -32,7 +43,7 @@ void main() { PointerDownEvent down = pointer.down(const Point(10.0, 10.0)); pan.addPointer(down); tap.addPointer(down); - GestureArena.instance.close(5); + gestureArena.close(5); expect(didStartPan, isFalse); expect(updatedScrollDelta, isNull); expect(didEndPan, isFalse); diff --git a/packages/unit/test/gestures/tap_test.dart b/packages/unit/test/gestures/tap_test.dart index 3722e2ad597..eeff99e16c4 100644 --- a/packages/unit/test/gestures/tap_test.dart +++ b/packages/unit/test/gestures/tap_test.dart @@ -1,3 +1,7 @@ +// Copyright 2015 The Chromium 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 'package:flutter/gestures.dart'; import 'package:quiver/testing/async.dart'; import 'package:test/test.dart'; @@ -49,7 +53,11 @@ void main() { test('Should recognize tap', () { PointerRouter router = new PointerRouter(); - TapGestureRecognizer tap = new TapGestureRecognizer(router: router); + GestureArena gestureArena = new GestureArena(); + TapGestureRecognizer tap = new TapGestureRecognizer( + router: router, + gestureArena: gestureArena + ); bool tapRecognized = false; tap.onTap = () { @@ -57,14 +65,14 @@ void main() { }; tap.addPointer(down1); - GestureArena.instance.close(1); + gestureArena.close(1); expect(tapRecognized, isFalse); router.route(down1); expect(tapRecognized, isFalse); router.route(up1); expect(tapRecognized, isTrue); - GestureArena.instance.sweep(1); + gestureArena.sweep(1); expect(tapRecognized, isTrue); tap.dispose(); @@ -72,7 +80,11 @@ void main() { test('No duplicate tap events', () { PointerRouter router = new PointerRouter(); - TapGestureRecognizer tap = new TapGestureRecognizer(router: router); + GestureArena gestureArena = new GestureArena(); + TapGestureRecognizer tap = new TapGestureRecognizer( + router: router, + gestureArena: gestureArena + ); int tapsRecognized = 0; tap.onTap = () { @@ -80,25 +92,25 @@ void main() { }; tap.addPointer(down1); - GestureArena.instance.close(1); + gestureArena.close(1); expect(tapsRecognized, 0); router.route(down1); expect(tapsRecognized, 0); router.route(up1); expect(tapsRecognized, 1); - GestureArena.instance.sweep(1); + gestureArena.sweep(1); expect(tapsRecognized, 1); tap.addPointer(down1); - GestureArena.instance.close(1); + gestureArena.close(1); expect(tapsRecognized, 1); router.route(down1); expect(tapsRecognized, 1); router.route(up1); expect(tapsRecognized, 2); - GestureArena.instance.sweep(1); + gestureArena.sweep(1); expect(tapsRecognized, 2); tap.dispose(); @@ -106,7 +118,11 @@ void main() { test('Should not recognize two overlapping taps', () { PointerRouter router = new PointerRouter(); - TapGestureRecognizer tap = new TapGestureRecognizer(router: router); + GestureArena gestureArena = new GestureArena(); + TapGestureRecognizer tap = new TapGestureRecognizer( + router: router, + gestureArena: gestureArena + ); int tapsRecognized = 0; tap.onTap = () { @@ -114,13 +130,13 @@ void main() { }; tap.addPointer(down1); - GestureArena.instance.close(1); + gestureArena.close(1); expect(tapsRecognized, 0); router.route(down1); expect(tapsRecognized, 0); tap.addPointer(down2); - GestureArena.instance.close(2); + gestureArena.close(2); expect(tapsRecognized, 0); router.route(down1); expect(tapsRecognized, 0); @@ -128,12 +144,12 @@ void main() { router.route(up1); expect(tapsRecognized, 1); - GestureArena.instance.sweep(1); + gestureArena.sweep(1); expect(tapsRecognized, 1); router.route(up2); expect(tapsRecognized, 1); - GestureArena.instance.sweep(2); + gestureArena.sweep(2); expect(tapsRecognized, 1); tap.dispose(); @@ -141,7 +157,11 @@ void main() { test('Distance cancels tap', () { PointerRouter router = new PointerRouter(); - TapGestureRecognizer tap = new TapGestureRecognizer(router: router); + GestureArena gestureArena = new GestureArena(); + TapGestureRecognizer tap = new TapGestureRecognizer( + router: router, + gestureArena: gestureArena + ); bool tapRecognized = false; tap.onTap = () { @@ -153,7 +173,7 @@ void main() { }; tap.addPointer(down3); - GestureArena.instance.close(3); + gestureArena.close(3); expect(tapRecognized, isFalse); expect(tapCanceled, isFalse); router.route(down3); @@ -166,7 +186,7 @@ void main() { router.route(up3); expect(tapRecognized, isFalse); expect(tapCanceled, isTrue); - GestureArena.instance.sweep(3); + gestureArena.sweep(3); expect(tapRecognized, isFalse); expect(tapCanceled, isTrue); @@ -175,7 +195,11 @@ void main() { test('Timeout does not cancel tap', () { PointerRouter router = new PointerRouter(); - TapGestureRecognizer tap = new TapGestureRecognizer(router: router); + GestureArena gestureArena = new GestureArena(); + TapGestureRecognizer tap = new TapGestureRecognizer( + router: router, + gestureArena: gestureArena + ); bool tapRecognized = false; tap.onTap = () { @@ -184,7 +208,7 @@ void main() { new FakeAsync().run((FakeAsync async) { tap.addPointer(down1); - GestureArena.instance.close(1); + gestureArena.close(1); expect(tapRecognized, isFalse); router.route(down1); expect(tapRecognized, isFalse); @@ -193,7 +217,7 @@ void main() { expect(tapRecognized, isFalse); router.route(up1); expect(tapRecognized, isTrue); - GestureArena.instance.sweep(1); + gestureArena.sweep(1); expect(tapRecognized, isTrue); }); @@ -202,7 +226,11 @@ void main() { test('Should yield to other arena members', () { PointerRouter router = new PointerRouter(); - TapGestureRecognizer tap = new TapGestureRecognizer(router: router); + GestureArena gestureArena = new GestureArena(); + TapGestureRecognizer tap = new TapGestureRecognizer( + router: router, + gestureArena: gestureArena + ); bool tapRecognized = false; tap.onTap = () { @@ -211,16 +239,16 @@ void main() { tap.addPointer(down1); TestGestureArenaMember member = new TestGestureArenaMember(); - GestureArenaEntry entry = GestureArena.instance.add(1, member); - GestureArena.instance.hold(1); - GestureArena.instance.close(1); + GestureArenaEntry entry = gestureArena.add(1, member); + gestureArena.hold(1); + gestureArena.close(1); expect(tapRecognized, isFalse); router.route(down1); expect(tapRecognized, isFalse); router.route(up1); expect(tapRecognized, isFalse); - GestureArena.instance.sweep(1); + gestureArena.sweep(1); expect(tapRecognized, isFalse); entry.resolve(GestureDisposition.accepted); @@ -231,7 +259,11 @@ void main() { test('Should trigger on release of held arena', () { PointerRouter router = new PointerRouter(); - TapGestureRecognizer tap = new TapGestureRecognizer(router: router); + GestureArena gestureArena = new GestureArena(); + TapGestureRecognizer tap = new TapGestureRecognizer( + router: router, + gestureArena: gestureArena + ); bool tapRecognized = false; tap.onTap = () { @@ -240,16 +272,16 @@ void main() { tap.addPointer(down1); TestGestureArenaMember member = new TestGestureArenaMember(); - GestureArenaEntry entry = GestureArena.instance.add(1, member); - GestureArena.instance.hold(1); - GestureArena.instance.close(1); + GestureArenaEntry entry = gestureArena.add(1, member); + gestureArena.hold(1); + gestureArena.close(1); expect(tapRecognized, isFalse); router.route(down1); expect(tapRecognized, isFalse); router.route(up1); expect(tapRecognized, isFalse); - GestureArena.instance.sweep(1); + gestureArena.sweep(1); expect(tapRecognized, isFalse); entry.resolve(GestureDisposition.rejected); diff --git a/packages/unit/test/gestures/velocity_tracker_data.dart b/packages/unit/test/gestures/velocity_tracker_data.dart index 9f87bfcd5df..16cf2cb9d76 100644 --- a/packages/unit/test/gestures/velocity_tracker_data.dart +++ b/packages/unit/test/gestures/velocity_tracker_data.dart @@ -1,3 +1,7 @@ +// Copyright 2015 The Chromium 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 'package:flutter/gestures.dart'; const List velocityEventData = const [ diff --git a/packages/unit/test/gestures/velocity_tracker_test.dart b/packages/unit/test/gestures/velocity_tracker_test.dart index 64548c5b896..6bd13bc7ff8 100644 --- a/packages/unit/test/gestures/velocity_tracker_test.dart +++ b/packages/unit/test/gestures/velocity_tracker_test.dart @@ -1,3 +1,7 @@ +// Copyright 2015 The Chromium 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 'package:flutter/gestures.dart'; import 'package:test/test.dart'; import 'velocity_tracker_data.dart'; diff --git a/packages/unit/test/harness/trivial_test.dart b/packages/unit/test/harness/trivial_test.dart index bbca5f2afea..497571c7743 100644 --- a/packages/unit/test/harness/trivial_test.dart +++ b/packages/unit/test/harness/trivial_test.dart @@ -1,3 +1,7 @@ +// Copyright 2015 The Chromium 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 'package:test/test.dart'; void main() { diff --git a/packages/unit/test/painting/edge_dims_test.dart b/packages/unit/test/painting/edge_dims_test.dart index 5dbc3b87f2f..1c75cfb9346 100644 --- a/packages/unit/test/painting/edge_dims_test.dart +++ b/packages/unit/test/painting/edge_dims_test.dart @@ -1,3 +1,7 @@ +// Copyright 2015 The Chromium 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 'package:flutter/painting.dart'; import 'package:test/test.dart'; diff --git a/packages/unit/test/rendering/box_test.dart b/packages/unit/test/rendering/box_test.dart index 13b5bb5fb5e..2137c7febdc 100644 --- a/packages/unit/test/rendering/box_test.dart +++ b/packages/unit/test/rendering/box_test.dart @@ -1,3 +1,7 @@ +// Copyright 2015 The Chromium 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 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; import 'package:test/test.dart'; diff --git a/packages/unit/test/rendering/flex_test.dart b/packages/unit/test/rendering/flex_test.dart index 4a24006a3f4..7a5a0307720 100644 --- a/packages/unit/test/rendering/flex_test.dart +++ b/packages/unit/test/rendering/flex_test.dart @@ -1,3 +1,7 @@ +// Copyright 2015 The Chromium 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 'package:flutter/rendering.dart'; import 'package:test/test.dart'; diff --git a/packages/unit/test/rendering/grid_test.dart b/packages/unit/test/rendering/grid_test.dart index 8646ba3068f..45bd4856754 100644 --- a/packages/unit/test/rendering/grid_test.dart +++ b/packages/unit/test/rendering/grid_test.dart @@ -1,3 +1,7 @@ +// Copyright 2015 The Chromium 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 'package:flutter/rendering.dart'; import 'package:test/test.dart'; diff --git a/packages/unit/test/rendering/image_test.dart b/packages/unit/test/rendering/image_test.dart index 48996734d0e..7e369640877 100644 --- a/packages/unit/test/rendering/image_test.dart +++ b/packages/unit/test/rendering/image_test.dart @@ -1,3 +1,7 @@ +// Copyright 2015 The Chromium 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' as ui; import 'package:flutter/rendering.dart'; diff --git a/packages/unit/test/rendering/intrinsic_width_test.dart b/packages/unit/test/rendering/intrinsic_width_test.dart index de28dbab9ab..9f789e574f4 100644 --- a/packages/unit/test/rendering/intrinsic_width_test.dart +++ b/packages/unit/test/rendering/intrinsic_width_test.dart @@ -1,3 +1,7 @@ +// Copyright 2015 The Chromium 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 'package:flutter/rendering.dart'; import 'package:test/test.dart'; diff --git a/packages/unit/test/rendering/offstage_test.dart b/packages/unit/test/rendering/offstage_test.dart index 1653a42555c..af8e7c1ac21 100644 --- a/packages/unit/test/rendering/offstage_test.dart +++ b/packages/unit/test/rendering/offstage_test.dart @@ -1,3 +1,7 @@ +// Copyright 2015 The Chromium 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 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; import 'package:test/test.dart'; diff --git a/packages/unit/test/rendering/overflow_test.dart b/packages/unit/test/rendering/overflow_test.dart index c5386d7cabf..d9f7c794e73 100644 --- a/packages/unit/test/rendering/overflow_test.dart +++ b/packages/unit/test/rendering/overflow_test.dart @@ -1,3 +1,7 @@ +// Copyright 2015 The Chromium 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 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; import 'package:test/test.dart'; diff --git a/packages/unit/test/rendering/positioned_box_test.dart b/packages/unit/test/rendering/positioned_box_test.dart index 3b71b9159e2..399a05b71d8 100644 --- a/packages/unit/test/rendering/positioned_box_test.dart +++ b/packages/unit/test/rendering/positioned_box_test.dart @@ -1,3 +1,7 @@ +// Copyright 2015 The Chromium 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 'package:flutter/rendering.dart'; import 'package:test/test.dart'; diff --git a/packages/unit/test/rendering/rendering_tester.dart b/packages/unit/test/rendering/rendering_tester.dart index 2b3c217717b..58a1a63f83d 100644 --- a/packages/unit/test/rendering/rendering_tester.dart +++ b/packages/unit/test/rendering/rendering_tester.dart @@ -1,11 +1,19 @@ +// Copyright 2015 The Chromium 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 'package:flutter/gestures.dart'; import 'package:flutter/rendering.dart'; +import 'package:flutter/scheduler.dart'; +import 'package:flutter/services.dart'; const Size _kTestViewSize = const Size(800.0, 600.0); class TestRenderView extends RenderView { TestRenderView() { - attach(); rootConstraints = new ViewConstraints(size: _kTestViewSize); + } + void scheduleInitialFrame() { scheduleInitialLayout(); scheduleInitialPaint(new TransformLayer(transform: new Matrix4.identity())); } @@ -17,18 +25,37 @@ enum EnginePhase { composite } -RenderView _renderView; -RenderView get renderView => _renderView; +class TestRenderingFlutterBinding extends BindingBase with Scheduler, Renderer, Pointerer { + void initRenderView() { + if (renderView == null) { + renderView = new TestRenderView(); + renderView.scheduleInitialFrame(); + } + } + + EnginePhase phase = EnginePhase.composite; + + void beginFrame() { + RenderObject.flushLayout(); + if (phase == EnginePhase.layout) + return; + renderer.renderView.updateCompositingBits(); + RenderObject.flushPaint(); + if (phase == EnginePhase.paint) + return; + renderer.renderView.compositeFrame(); + } +} + +TestRenderingFlutterBinding _renderer; +TestRenderingFlutterBinding get renderer => _renderer; void layout(RenderBox box, { BoxConstraints constraints, EnginePhase phase: EnginePhase.layout }) { assert(box != null); // if you want to just repump the last box, call pumpFrame(). - if (renderView == null) - _renderView = new TestRenderView(); - - if (renderView.child != null) - renderView.child = null; + _renderer ??= new TestRenderingFlutterBinding(); + renderer.renderView.child = null; if (constraints != null) { box = new RenderPositionedBox( child: new RenderConstrainedBox( @@ -37,21 +64,15 @@ void layout(RenderBox box, { BoxConstraints constraints, EnginePhase phase: Engi ) ); } - - renderView.child = box; + renderer.renderView.child = box; pumpFrame(phase: phase); } void pumpFrame({ EnginePhase phase: EnginePhase.layout }) { - RenderObject.flushLayout(); - if (phase == EnginePhase.layout) - return; - renderView.updateCompositingBits(); - RenderObject.flushPaint(); - if (phase == EnginePhase.paint) - return; - renderView.compositeFrame(); + assert(renderer != null); + renderer.phase = phase; + renderer.beginFrame(); } class TestCallbackPainter extends CustomPainter { diff --git a/packages/unit/test/rendering/size_test.dart b/packages/unit/test/rendering/size_test.dart index 8d7672713a7..3a1ae6fe6d4 100644 --- a/packages/unit/test/rendering/size_test.dart +++ b/packages/unit/test/rendering/size_test.dart @@ -1,3 +1,7 @@ +// Copyright 2015 The Chromium 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 'package:flutter/rendering.dart'; import 'package:test/test.dart'; diff --git a/packages/unit/test/rendering/stack_test.dart b/packages/unit/test/rendering/stack_test.dart index 8fc40a5611b..8ca5253a438 100644 --- a/packages/unit/test/rendering/stack_test.dart +++ b/packages/unit/test/rendering/stack_test.dart @@ -1,3 +1,7 @@ +// Copyright 2015 The Chromium 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 'package:flutter/rendering.dart'; import 'package:test/test.dart'; diff --git a/packages/unit/test/rendering/viewport_test.dart b/packages/unit/test/rendering/viewport_test.dart index af1cf1640a6..bdf74ab12b4 100644 --- a/packages/unit/test/rendering/viewport_test.dart +++ b/packages/unit/test/rendering/viewport_test.dart @@ -1,3 +1,7 @@ +// Copyright 2015 The Chromium 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 'package:flutter/rendering.dart'; import 'package:test/test.dart'; @@ -26,11 +30,11 @@ void main() { HitTestResult result; result = new HitTestResult(); - renderView.hitTest(result, position: new Point(15.0, 0.0)); + renderer.renderView.hitTest(result, position: new Point(15.0, 0.0)); expect(result.path.first.target.runtimeType, equals(TestRenderView)); result = new HitTestResult(); - renderView.hitTest(result, position: new Point(15.0, 15.0)); + renderer.renderView.hitTest(result, position: new Point(15.0, 15.0)); expect(result.path.first.target, equals(green)); }); } diff --git a/packages/unit/test/scheduler/animation_test.dart b/packages/unit/test/scheduler/animation_test.dart index a7944fd082b..6472df1a0a4 100644 --- a/packages/unit/test/scheduler/animation_test.dart +++ b/packages/unit/test/scheduler/animation_test.dart @@ -1,7 +1,16 @@ +// Copyright 2015 The Chromium 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 'package:flutter/scheduler.dart'; +import 'package:flutter/services.dart'; import 'package:test/test.dart'; +class TestSchedulerBinding extends BindingBase with Scheduler { } + void main() { + Scheduler scheduler = new TestSchedulerBinding(); + test("Check for a time dilation being in effect", () { expect(timeDilation, equals(1.0)); }); diff --git a/packages/unit/test/scheduler/scheduler_test.dart b/packages/unit/test/scheduler/scheduler_test.dart.disabled similarity index 66% rename from packages/unit/test/scheduler/scheduler_test.dart rename to packages/unit/test/scheduler/scheduler_test.dart.disabled index c91444fb662..7d893e5a04e 100644 --- a/packages/unit/test/scheduler/scheduler_test.dart +++ b/packages/unit/test/scheduler/scheduler_test.dart.disabled @@ -2,43 +2,52 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +// This test is disabled because it triggers https://github.com/dart-lang/sdk/issues/25246 + import 'package:flutter/scheduler.dart'; +import 'package:flutter/services.dart'; import 'package:test/test.dart'; +class TestSchedulerBinding extends BindingBase with Scheduler { } + class TestStrategy implements SchedulingStrategy { int allowedPriority = 10000; - bool shouldRunTaskWithPriority(int priority) { + bool shouldRunTaskWithPriority({ int priority, Scheduler scheduler }) { return priority >= allowedPriority; } } void main() { test("Tasks are executed in the right order", () { - var strategy = new TestStrategy(); + Scheduler scheduler = new TestSchedulerBinding(); + TestStrategy strategy = new TestStrategy(); scheduler.schedulingStrategy = strategy; - List input = [2, 23, 23, 11, 0, 80, 3]; - List executedTasks = []; + List input = [2, 23, 23, 11, 0, 80, 3]; + List executedTasks = []; void scheduleAddingTask(int x) { scheduler.scheduleTask(() { executedTasks.add(x); }, Priority.idle + x); } - for (int x in input) { + for (int x in input) scheduleAddingTask(x); - } + strategy.allowedPriority = 100; - for (int i = 0; i < 3; i++) scheduler.handleEventLoopCallback(); + for (int i = 0; i < 3; i += 1) + scheduler.handleEventLoopCallback(); expect(executedTasks.isEmpty, isTrue); strategy.allowedPriority = 50; - for (int i = 0; i < 3; i++) scheduler.handleEventLoopCallback(); + for (int i = 0; i < 3; i += 1) + scheduler.handleEventLoopCallback(); expect(executedTasks.length, equals(1)); expect(executedTasks.single, equals(80)); executedTasks.clear(); strategy.allowedPriority = 20; - for (int i = 0; i < 3; i++) scheduler.handleEventLoopCallback(); + for (int i = 0; i < 3; i += 1) + scheduler.handleEventLoopCallback(); expect(executedTasks.length, equals(2)); expect(executedTasks[0], equals(23)); expect(executedTasks[1], equals(23)); @@ -48,21 +57,24 @@ void main() { scheduleAddingTask(19); scheduleAddingTask(5); scheduleAddingTask(97); - for (int i = 0; i < 3; i++) scheduler.handleEventLoopCallback(); + for (int i = 0; i < 3; i += 1) + scheduler.handleEventLoopCallback(); expect(executedTasks.length, equals(2)); expect(executedTasks[0], equals(99)); expect(executedTasks[1], equals(97)); executedTasks.clear(); strategy.allowedPriority = 10; - for (int i = 0; i < 3; i++) scheduler.handleEventLoopCallback(); + for (int i = 0; i < 3; i += 1) + scheduler.handleEventLoopCallback(); expect(executedTasks.length, equals(2)); expect(executedTasks[0], equals(19)); expect(executedTasks[1], equals(11)); executedTasks.clear(); strategy.allowedPriority = 1; - for (int i = 0; i < 4; i++) scheduler.handleEventLoopCallback(); + for (int i = 0; i < 4; i += 1) + scheduler.handleEventLoopCallback(); expect(executedTasks.length, equals(3)); expect(executedTasks[0], equals(5)); expect(executedTasks[1], equals(3)); diff --git a/packages/unit/test/widget/animated_container_test.dart b/packages/unit/test/widget/animated_container_test.dart index eb195c34258..e317f119626 100644 --- a/packages/unit/test/widget/animated_container_test.dart +++ b/packages/unit/test/widget/animated_container_test.dart @@ -4,7 +4,6 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:flutter/rendering.dart'; -import 'package:flutter/scheduler.dart'; import 'package:flutter/widgets.dart'; import 'package:test/test.dart'; @@ -65,9 +64,9 @@ void main() { ) ) ); - expect(scheduler.transientCallbackCount, 0); + expect(tester.binding.transientCallbackCount, 0); tester.pump(new Duration(seconds: 1)); - expect(scheduler.transientCallbackCount, 0); + expect(tester.binding.transientCallbackCount, 0); tester.pumpWidget( new AnimatedContainer( duration: const Duration(milliseconds: 200), @@ -76,9 +75,9 @@ void main() { ) ) ); - expect(scheduler.transientCallbackCount, 0); + expect(tester.binding.transientCallbackCount, 0); tester.pump(new Duration(seconds: 1)); - expect(scheduler.transientCallbackCount, 0); + expect(tester.binding.transientCallbackCount, 0); tester.pumpWidget( new AnimatedContainer( duration: const Duration(milliseconds: 200), @@ -87,9 +86,9 @@ void main() { ) ) ); - expect(scheduler.transientCallbackCount, 1); // this is the only time an animation should have started! + expect(tester.binding.transientCallbackCount, 1); // this is the only time an animation should have started! tester.pump(new Duration(seconds: 1)); - expect(scheduler.transientCallbackCount, 0); + expect(tester.binding.transientCallbackCount, 0); tester.pumpWidget( new AnimatedContainer( duration: const Duration(milliseconds: 200), @@ -98,7 +97,7 @@ void main() { ) ) ); - expect(scheduler.transientCallbackCount, 0); + expect(tester.binding.transientCallbackCount, 0); }); }); }