From ebf5b44fb34bcb9e55bfceee86410118e7c0c222 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 --- sky/packages/sky/lib/base/pointer_router.dart | 40 +++++++++++++++++++ .../sky/lib/rendering/sky_binding.dart | 4 ++ sky/packages/sky/lib/widgets/drag_target.dart | 3 ++ sky/packages/sky/lib/widgets/framework.dart | 2 + 4 files changed, 49 insertions(+) create mode 100644 sky/packages/sky/lib/base/pointer_router.dart diff --git a/sky/packages/sky/lib/base/pointer_router.dart b/sky/packages/sky/lib/base/pointer_router.dart new file mode 100644 index 00000000000..5b12864d623 --- /dev/null +++ b/sky/packages/sky/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/sky/packages/sky/lib/rendering/sky_binding.dart b/sky/packages/sky/lib/rendering/sky_binding.dart index 5eca6e8f34f..0a4b0f689e1 100644 --- a/sky/packages/sky/lib/rendering/sky_binding.dart +++ b/sky/packages/sky/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/sky/packages/sky/lib/widgets/drag_target.dart b/sky/packages/sky/lib/widgets/drag_target.dart index d7d6d5d1c3c..63e8c1ec951 100644 --- a/sky/packages/sky/lib/widgets/drag_target.dart +++ b/sky/packages/sky/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/sky/packages/sky/lib/widgets/framework.dart b/sky/packages/sky/lib/widgets/framework.dart index 58596507459..9617933d279 100644 --- a/sky/packages/sky/lib/widgets/framework.dart +++ b/sky/packages/sky/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);