From 45f2c589875444a2767f280a69fbb947c620689d Mon Sep 17 00:00:00 2001 From: Adam Barth Date: Thu, 27 Aug 2015 15:02:35 -0700 Subject: [PATCH] Add PointerRouter This patch is the first step towards implementing gestures. The pointer router allows the gesture detectors to hook in at the end of the pointer event propagation chain. Related to #145 --- packages/flutter/lib/base/pointer_router.dart | 40 +++++++++++++++++++ .../flutter/lib/rendering/sky_binding.dart | 4 ++ packages/flutter/lib/widgets/drag_target.dart | 3 ++ packages/flutter/lib/widgets/framework.dart | 2 + 4 files changed, 49 insertions(+) create mode 100644 packages/flutter/lib/base/pointer_router.dart diff --git a/packages/flutter/lib/base/pointer_router.dart b/packages/flutter/lib/base/pointer_router.dart new file mode 100644 index 0000000000..5b12864d62 --- /dev/null +++ b/packages/flutter/lib/base/pointer_router.dart @@ -0,0 +1,40 @@ +// 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:sky' as sky; + +import 'package:sky/base/hit_test.dart'; + +typedef void _Route(sky.PointerEvent event); + +class PointerRouter extends HitTestTarget { + final Map> _routeMap = new Map>(); + + void addRoute(int pointer, _Route route) { + List<_Route> routes = _routeMap.putIfAbsent(pointer, () => new List<_Route>()); + assert(!routes.contains(route)); + routes.add(route); + } + + void removeRoute(int pointer, _Route route) { + assert(_routeMap.containsKey(pointer)); + List<_Route> routes = _routeMap[pointer]; + assert(routes.contains(route)); + routes.remove(route); + if (routes.isEmpty) + _routeMap.remove(pointer); + } + + EventDisposition handleEvent(sky.Event e, HitTestEntry entry) { + if (e is! sky.PointerEvent) + return EventDisposition.ignored; + sky.PointerEvent event = e; + List<_Route> routes = _routeMap[event.pointer]; + if (routes == null) + return EventDisposition.ignored; + for (_Route route in new List<_Route>.from(routes)) + route(event); + return EventDisposition.processed; + } +} diff --git a/packages/flutter/lib/rendering/sky_binding.dart b/packages/flutter/lib/rendering/sky_binding.dart index 5eca6e8f34..0a4b0f689e 100644 --- a/packages/flutter/lib/rendering/sky_binding.dart +++ b/packages/flutter/lib/rendering/sky_binding.dart @@ -4,6 +4,7 @@ import 'dart:sky' as sky; +import 'package:sky/base/pointer_router.dart'; import 'package:sky/base/hit_test.dart'; import 'package:sky/base/scheduler.dart' as scheduler; import 'package:sky/rendering/box.dart'; @@ -92,6 +93,8 @@ class SkyBinding { } } + final PointerRouter pointerRouter = new PointerRouter(); + Map _stateForPointer = new Map(); PointerState _createStateForPointer(sky.PointerEvent event, Point position) { @@ -127,6 +130,7 @@ class SkyBinding { HitTestResult hitTest(Point position) { HitTestResult result = new HitTestResult(); + result.add(new HitTestEntry(pointerRouter)); _renderView.hitTest(result, position: position); return result; } diff --git a/packages/flutter/lib/widgets/drag_target.dart b/packages/flutter/lib/widgets/drag_target.dart index d7d6d5d1c3..63e8c1ec95 100644 --- a/packages/flutter/lib/widgets/drag_target.dart +++ b/packages/flutter/lib/widgets/drag_target.dart @@ -5,6 +5,7 @@ import 'dart:collection'; import 'package:sky/base/hit_test.dart'; +import 'package:sky/rendering/object.dart'; import 'package:sky/rendering/sky_binding.dart'; import 'package:sky/widgets/basic.dart'; import 'package:sky/widgets/framework.dart'; @@ -80,6 +81,8 @@ class DragController { DragTarget _getDragTarget(List path) { for (HitTestEntry entry in path.reversed) { + if (entry.target is! RenderObject) + continue; for (Widget widget in RenderObjectWrapper.getWidgetsForRenderObject(entry.target)) { if (widget is DragTarget) return widget; diff --git a/packages/flutter/lib/widgets/framework.dart b/packages/flutter/lib/widgets/framework.dart index 5859650745..9617933d27 100644 --- a/packages/flutter/lib/widgets/framework.dart +++ b/packages/flutter/lib/widgets/framework.dart @@ -1282,6 +1282,8 @@ class WidgetSkyBinding extends SkyBinding { if (disposition == EventDisposition.consumed) return EventDisposition.consumed; for (HitTestEntry entry in result.path.reversed) { + if (entry.target is! RenderObject) + continue; for (Widget target in RenderObjectWrapper.getWidgetsForRenderObject(entry.target)) { if (target is Listener) { EventDisposition targetDisposition = target._handleEvent(event);