Commit 7d11cfa4 authored by Adam Barth's avatar Adam Barth

Merge pull request #1056 from abarth/event_ordering

Events should bubble up the tree
parents 3f217243 f5102d11
...@@ -52,17 +52,16 @@ class HitTestResult { ...@@ -52,17 +52,16 @@ class HitTestResult {
/// The list of [HitTestEntry] objects recorded during the hit test. /// The list of [HitTestEntry] objects recorded during the hit test.
/// ///
/// The first entry in the path is the least specific, typically the one at /// The first entry in the path is the most specific, typically the one at
/// the root of tree being hit tested. Event propagation starts with the most /// the leaf of tree being hit tested. Event propagation starts with the most
/// specific (i.e., last) entry and proceeds in reverse order through the /// specific (i.e., first) entry and proceeds in order through the path.
/// path.
final List<HitTestEntry> path; final List<HitTestEntry> path;
/// Add a [HitTestEntry] to the path. /// Add a [HitTestEntry] to the path.
/// ///
/// The new entry is added at the end of the path, which means entries should /// The new entry is added at the end of the path, which means entries should
/// be added in order from last specific to most specific, typically during a /// be added in order from most specific to least specific, typically during a
/// downward walk in the tree being hit tested. /// upward walk in the tree being hit tested.
void add(HitTestEntry entry) { void add(HitTestEntry entry) {
path.add(entry); path.add(entry);
} }
......
...@@ -136,15 +136,15 @@ class SkyBinding extends HitTestTarget { ...@@ -136,15 +136,15 @@ class SkyBinding extends HitTestTarget {
HitTestResult hitTest(Point position) { HitTestResult hitTest(Point position) {
HitTestResult result = new HitTestResult(); HitTestResult result = new HitTestResult();
result.add(new BindingHitTestEntry(this, result));
_renderView.hitTest(result, position: position); _renderView.hitTest(result, position: position);
result.add(new BindingHitTestEntry(this, result));
return result; return result;
} }
EventDisposition dispatchEvent(sky.Event event, HitTestResult result) { EventDisposition dispatchEvent(sky.Event event, HitTestResult result) {
assert(result != null); assert(result != null);
EventDisposition disposition = EventDisposition.ignored; EventDisposition disposition = EventDisposition.ignored;
for (HitTestEntry entry in result.path.reversed) { for (HitTestEntry entry in result.path) {
EventDisposition entryDisposition = entry.target.handleEvent(event, entry); EventDisposition entryDisposition = entry.target.handleEvent(event, entry);
if (entryDisposition == EventDisposition.consumed) if (entryDisposition == EventDisposition.consumed)
return EventDisposition.consumed; return EventDisposition.consumed;
......
...@@ -81,11 +81,8 @@ class RenderView extends RenderObject with RenderObjectWithChildMixin<RenderBox> ...@@ -81,11 +81,8 @@ class RenderView extends RenderObject with RenderObjectWithChildMixin<RenderBox>
} }
bool hitTest(HitTestResult result, { Point position }) { bool hitTest(HitTestResult result, { Point position }) {
if (child != null) { if (child != null)
Rect childBounds = Point.origin & child.size; child.hitTest(result, position: position);
if (childBounds.contains(position))
child.hitTest(result, position: position);
}
result.add(new HitTestEntry(this)); result.add(new HitTestEntry(this));
return true; return true;
} }
......
...@@ -1366,7 +1366,7 @@ class WidgetSkyBinding extends SkyBinding { ...@@ -1366,7 +1366,7 @@ class WidgetSkyBinding extends SkyBinding {
EventDisposition handleEvent(sky.Event event, BindingHitTestEntry entry) { EventDisposition handleEvent(sky.Event event, BindingHitTestEntry entry) {
EventDisposition disposition = EventDisposition.ignored; EventDisposition disposition = EventDisposition.ignored;
for (HitTestEntry entry in entry.result.path.reversed) { for (HitTestEntry entry in entry.result.path) {
if (entry.target is! RenderObject) if (entry.target is! RenderObject)
continue; continue;
for (Widget target in RenderObjectWrapper.getWidgetsForRenderObject(entry.target)) { for (Widget target in RenderObjectWrapper.getWidgetsForRenderObject(entry.target)) {
......
import 'package:sky/widgets.dart';
import 'package:test/test.dart';
import 'widget_tester.dart';
void main() {
test('Events bubble up the tree', () {
WidgetTester tester = new WidgetTester();
List<String> log = new List<String>();
tester.pumpFrame(() {
return new Listener(
onPointerDown: (_) {
log.add('top');
},
child: new Listener(
onPointerDown: (_) {
log.add('middle');
},
child: new DecoratedBox(
decoration: const BoxDecoration(),
child: new Listener(
onPointerDown: (_) {
log.add('bottom');
},
child: new Text('X')
)
)
)
);
});
tester.tap(tester.findText('X'));
expect(log, equals([
'bottom',
'middle',
'top',
]));
});
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment