Merge pull request #659 from eseidelGoogle/analyzer

Fix analyzer warnings
diff --git a/examples/game/lib/sprite_widget.dart b/examples/game/lib/sprite_widget.dart
index 9f58a02..7ddb51e 100644
--- a/examples/game/lib/sprite_widget.dart
+++ b/examples/game/lib/sprite_widget.dart
@@ -24,14 +24,14 @@
   ///     var mySpriteWidget = new SpriteWidget(mySpriteTree, SpriteBoxTransformMode.fixedHeight);
   SpriteWidget(this.rootNode, [this.transformMode = SpriteBoxTransformMode.letterbox]);
 
-  SpriteBox get root => super.root;
+  SpriteBox get renderObject => super.renderObject;
 
   SpriteBox createNode() => new SpriteBox(rootNode, transformMode);
 
   void syncRenderObject(SpriteWidget old) {
     super.syncRenderObject(old);
 
-    root.rootNode = rootNode;
-    root.transformMode = transformMode;
+    renderObject.rootNode = rootNode;
+    renderObject.transformMode = transformMode;
   }
 }
diff --git a/examples/widgets/drag_and_drop.dart b/examples/widgets/drag_and_drop.dart
new file mode 100644
index 0000000..7c2f00f
--- /dev/null
+++ b/examples/widgets/drag_and_drop.dart
@@ -0,0 +1,151 @@
+// 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/theme/colors.dart' as colors;
+import 'package:sky/widgets.dart';
+
+final double kTop = 10.0 + sky.view.paddingTop;
+final double kLeft = 10.0;
+
+class DragData {
+  DragData(this.text);
+
+  final String text;
+}
+
+class ExampleDragTarget extends StatefulComponent {
+  String _text = 'ready';
+
+  void syncFields(ExampleDragTarget source) {
+  }
+
+  void _handleAccept(DragData data) {
+    setState(() {
+      _text = data.text;
+    });
+  }
+
+  Widget build() {
+    return new DragTarget<DragData>(
+      onAccept: _handleAccept,
+      builder: (List<DragData> data, _) {
+        return new Container(
+          width: 100.0,
+          height: 100.0,
+          margin: new EdgeDims.all(10.0),
+          decoration: new BoxDecoration(
+            border: new Border.all(
+              width: 3.0,
+              color: data.isEmpty ? colors.white : colors.Blue[500]
+            ),
+            backgroundColor: data.isEmpty ? colors.Grey[500] : colors.Green[500]
+          ),
+          child: new Center(
+            child: new Text(_text)
+          )
+        );
+      }
+    );
+  }
+}
+
+class Dot extends Component {
+  Widget build() {
+    return new Container(
+      width: 50.0,
+      height: 50.0,
+      decoration: new BoxDecoration(
+        backgroundColor: colors.DeepOrange[500]
+      )
+    );
+  }
+}
+
+class DragAndDropApp extends App {
+  DragController _dragController;
+  Offset _displacement = Offset.zero;
+
+  EventDisposition _startDrag(sky.PointerEvent event) {
+    setState(() {
+      _dragController = new DragController(new DragData("Orange"));
+      _dragController.update(new Point(event.x, event.y));
+      _displacement = Offset.zero;
+    });
+    return EventDisposition.consumed;
+  }
+
+  EventDisposition _updateDrag(sky.PointerEvent event) {
+    setState(() {
+      _dragController.update(new Point(event.x, event.y));
+      _displacement += new Offset(event.dx, event.dy);
+    });
+    return EventDisposition.consumed;
+  }
+
+  EventDisposition _cancelDrag(sky.PointerEvent event) {
+    setState(() {
+      _dragController.cancel();
+      _dragController = null;
+    });
+    return EventDisposition.consumed;
+  }
+
+  EventDisposition _drop(sky.PointerEvent event) {
+    setState(() {
+      _dragController.update(new Point(event.x, event.y));
+      _dragController.drop();
+      _dragController = null;
+      _displacement = Offset.zero;
+    });
+    return EventDisposition.consumed;
+  }
+
+  Widget build() {
+    List<Widget> layers = <Widget>[
+      new Flex([
+        new ExampleDragTarget(),
+        new ExampleDragTarget(),
+        new ExampleDragTarget(),
+        new ExampleDragTarget(),
+      ]),
+      new Positioned(
+        top: kTop,
+        left: kLeft,
+        child: new Listener(
+          onPointerDown: _startDrag,
+          onPointerMove: _updateDrag,
+          onPointerCancel: _cancelDrag,
+          onPointerUp: _drop,
+          child: new Dot()
+        )
+      ),
+    ];
+
+    if (_dragController != null) {
+      layers.add(
+        new Positioned(
+          top: kTop + _displacement.dy,
+          left: kLeft + _displacement.dx,
+          child: new IgnorePointer(
+            child: new Opacity(
+              opacity: 0.5,
+              child: new Dot()
+            )
+          )
+        )
+      );
+    }
+
+    return new Container(
+      decoration: new BoxDecoration(backgroundColor: colors.Pink[500]),
+      child: new Stack(layers)
+    );
+  }
+}
+
+void main() {
+  runApp(new DragAndDropApp());
+}
diff --git a/examples/widgets/overlay_geometry.dart b/examples/widgets/overlay_geometry.dart
index c4f81a1..a3a6d3c 100644
--- a/examples/widgets/overlay_geometry.dart
+++ b/examples/widgets/overlay_geometry.dart
@@ -115,7 +115,7 @@
     setState(() {
       markers[MarkerType.touch] = new Point(event.x, event.y);
       markers[MarkerType.topLeft] = target.localToGlobal(new Point(0.0, 0.0));
-      Size size = (target.root as RenderBox).size;
+      Size size = (target.renderObject as RenderBox).size;
       markers[MarkerType.bottomRight] = target.localToGlobal(new Point(size.width, size.height));
 
       Scrollable scrollable = findScrollableAncestor(target: target);
diff --git a/packages/flutter/lib/rendering/sky_binding.dart b/packages/flutter/lib/rendering/sky_binding.dart
index b81c82c..d77e5a3 100644
--- a/packages/flutter/lib/rendering/sky_binding.dart
+++ b/packages/flutter/lib/rendering/sky_binding.dart
@@ -85,9 +85,7 @@
     if (event is sky.PointerEvent) {
       _handlePointerEvent(event);
     } else if (event is sky.GestureEvent) {
-      HitTestResult result = new HitTestResult();
-      _renderView.hitTest(result, position: new Point(event.x, event.y));
-      dispatchEvent(event, result);
+      dispatchEvent(event, hitTest(new Point(event.x, event.y)));
     } else {
       for (EventListener e in _eventListeners)
         e(event);
@@ -97,8 +95,7 @@
   Map<int, PointerState> _stateForPointer = new Map<int, PointerState>();
 
   PointerState _createStateForPointer(sky.PointerEvent event, Point position) {
-    HitTestResult result = new HitTestResult();
-    _renderView.hitTest(result, position: position);
+    HitTestResult result = hitTest(position);
     PointerState state = new PointerState(result: result, lastPosition: position);
     _stateForPointer[event.pointer] = state;
     return state;
@@ -128,6 +125,12 @@
     return dispatchEvent(event, state.result);
   }
 
+  HitTestResult hitTest(Point position) {
+    HitTestResult result = new HitTestResult();
+    _renderView.hitTest(result, position: position);
+    return result;
+  }
+
   EventDisposition dispatchEvent(sky.Event event, HitTestResult result) {
     assert(result != null);
     EventDisposition disposition = EventDisposition.ignored;
diff --git a/packages/flutter/lib/widgets.dart b/packages/flutter/lib/widgets.dart
index 65fb174..309caea 100644
--- a/packages/flutter/lib/widgets.dart
+++ b/packages/flutter/lib/widgets.dart
@@ -14,6 +14,7 @@
 export 'widgets/default_text_style.dart';
 export 'widgets/dialog.dart';
 export 'widgets/dismissable.dart';
+export 'widgets/drag_target.dart';
 export 'widgets/drawer.dart';
 export 'widgets/drawer_divider.dart';
 export 'widgets/drawer_header.dart';
diff --git a/packages/flutter/lib/widgets/basic.dart b/packages/flutter/lib/widgets/basic.dart
index 88d5264..344dca7 100644
--- a/packages/flutter/lib/widgets/basic.dart
+++ b/packages/flutter/lib/widgets/basic.dart
@@ -37,11 +37,11 @@
   final double opacity;
 
   RenderOpacity createNode() => new RenderOpacity(opacity: opacity);
-  RenderOpacity get root => super.root;
+  RenderOpacity get renderObject => super.renderObject;
 
   void syncRenderObject(Opacity old) {
     super.syncRenderObject(old);
-    root.opacity = opacity;
+    renderObject.opacity = opacity;
   }
 }
 
@@ -53,12 +53,12 @@
   final sky.TransferMode transferMode;
 
   RenderColorFilter createNode() => new RenderColorFilter(color: color, transferMode: transferMode);
-  RenderColorFilter get root => super.root;
+  RenderColorFilter get renderObject => super.renderObject;
 
   void syncRenderObject(ColorFilter old) {
     super.syncRenderObject(old);
-    root.color = color;
-    root.transferMode = transferMode;
+    renderObject.color = color;
+    renderObject.transferMode = transferMode;
   }
 }
 
@@ -69,11 +69,11 @@
   final BoxDecoration decoration;
 
   RenderDecoratedBox createNode() => new RenderDecoratedBox(decoration: decoration);
-  RenderDecoratedBox get root => super.root;
+  RenderDecoratedBox get renderObject => super.renderObject;
 
   void syncRenderObject(DecoratedBox old) {
     super.syncRenderObject(old);
-    root.decoration = decoration;
+    renderObject.decoration = decoration;
   }
 }
 
@@ -85,17 +85,17 @@
   final dynamic token; // set this to be repainted automatically when the token changes
 
   RenderCustomPaint createNode() => new RenderCustomPaint(callback: callback);
-  RenderCustomPaint get root => super.root;
+  RenderCustomPaint get renderObject => super.renderObject;
 
   void syncRenderObject(CustomPaint old) {
     super.syncRenderObject(old);
     if (old != null && old.token != token)
-      root.markNeedsPaint();
-    root.callback = callback;
+      renderObject.markNeedsPaint();
+    renderObject.callback = callback;
   }
 
   void remove() {
-    root.callback = null;
+    renderObject.callback = null;
     super.remove();
   }
 }
@@ -105,7 +105,7 @@
     : super(key: key, child: child);
 
   RenderClipRect createNode() => new RenderClipRect();
-  RenderClipRect get root => super.root;
+  RenderClipRect get renderObject => super.renderObject;
 
   // Nothing to sync, so we don't implement syncRenderObject()
 }
@@ -118,12 +118,12 @@
   final double yRadius;
 
   RenderClipRRect createNode() => new RenderClipRRect(xRadius: xRadius, yRadius: yRadius);
-  RenderClipRRect get root => super.root;
+  RenderClipRRect get renderObject => super.renderObject;
 
   void syncRenderObject(ClipRRect old) {
     super.syncRenderObject(old);
-    root.xRadius = xRadius;
-    root.yRadius = yRadius;
+    renderObject.xRadius = xRadius;
+    renderObject.yRadius = yRadius;
   }
 }
 
@@ -132,7 +132,7 @@
     : super(key: key, child: child);
 
   RenderClipOval createNode() => new RenderClipOval();
-  RenderClipOval get root => super.root;
+  RenderClipOval get renderObject => super.renderObject;
 
   // Nothing to sync, so we don't implement syncRenderObject()
 }
@@ -147,11 +147,11 @@
   final Matrix4 transform;
 
   RenderTransform createNode() => new RenderTransform(transform: transform);
-  RenderTransform get root => super.root;
+  RenderTransform get renderObject => super.renderObject;
 
   void syncRenderObject(Transform old) {
     super.syncRenderObject(old);
-    root.transform = transform;
+    renderObject.transform = transform;
   }
 }
 
@@ -162,11 +162,11 @@
   final EdgeDims padding;
 
   RenderPadding createNode() => new RenderPadding(padding: padding);
-  RenderPadding get root => super.root;
+  RenderPadding get renderObject => super.renderObject;
 
   void syncRenderObject(Padding old) {
     super.syncRenderObject(old);
-    root.padding = padding;
+    renderObject.padding = padding;
   }
 }
 
@@ -175,7 +175,7 @@
     : super(key: key, child: child);
 
   RenderPositionedBox createNode() => new RenderPositionedBox();
-  RenderPositionedBox get root => super.root;
+  RenderPositionedBox get renderObject => super.renderObject;
 
   // Nothing to sync, so we don't implement syncRenderObject()
 }
@@ -188,7 +188,7 @@
   final double height;
 
   RenderConstrainedBox createNode() => new RenderConstrainedBox(additionalConstraints: _additionalConstraints());
-  RenderConstrainedBox get root => super.root;
+  RenderConstrainedBox get renderObject => super.renderObject;
 
   BoxConstraints _additionalConstraints() {
     BoxConstraints result = const BoxConstraints();
@@ -201,7 +201,7 @@
 
   void syncRenderObject(SizedBox old) {
     super.syncRenderObject(old);
-    root.additionalConstraints = _additionalConstraints();
+    renderObject.additionalConstraints = _additionalConstraints();
   }
 }
 
@@ -212,11 +212,11 @@
   final BoxConstraints constraints;
 
   RenderConstrainedBox createNode() => new RenderConstrainedBox(additionalConstraints: constraints);
-  RenderConstrainedBox get root => super.root;
+  RenderConstrainedBox get renderObject => super.renderObject;
 
   void syncRenderObject(ConstrainedBox old) {
     super.syncRenderObject(old);
-    root.additionalConstraints = constraints;
+    renderObject.additionalConstraints = constraints;
   }
 }
 
@@ -227,11 +227,11 @@
   final double aspectRatio;
 
   RenderAspectRatio createNode() => new RenderAspectRatio(aspectRatio: aspectRatio);
-  RenderAspectRatio get root => super.root;
+  RenderAspectRatio get renderObject => super.renderObject;
 
   void syncRenderObject(AspectRatio old) {
     super.syncRenderObject(old);
-    root.aspectRatio = aspectRatio;
+    renderObject.aspectRatio = aspectRatio;
   }
 }
 
@@ -243,12 +243,12 @@
   final double stepHeight;
 
   RenderShrinkWrapWidth createNode() => new RenderShrinkWrapWidth();
-  RenderShrinkWrapWidth get root => super.root;
+  RenderShrinkWrapWidth get renderObject => super.renderObject;
 
   void syncRenderObject(ShrinkWrapWidth old) {
     super.syncRenderObject(old);
-    root.stepWidth = stepWidth;
-    root.stepHeight = stepHeight;
+    renderObject.stepWidth = stepWidth;
+    renderObject.stepHeight = stepHeight;
   }
 }
 
@@ -260,12 +260,12 @@
   final TextBaseline baselineType;
 
   RenderBaseline createNode() => new RenderBaseline(baseline: baseline, baselineType: baselineType);
-  RenderBaseline get root => super.root;
+  RenderBaseline get renderObject => super.renderObject;
 
   void syncRenderObject(Baseline old) {
     super.syncRenderObject(old);
-    root.baseline = baseline;
-    root.baselineType = baselineType;
+    renderObject.baseline = baseline;
+    renderObject.baselineType = baselineType;
   }
 }
 
@@ -281,12 +281,12 @@
   final ScrollDirection scrollDirection;
 
   RenderViewport createNode() => new RenderViewport(scrollOffset: scrollOffset, scrollDirection: scrollDirection);
-  RenderViewport get root => super.root;
+  RenderViewport get renderObject => super.renderObject;
 
   void syncRenderObject(Viewport old) {
     super.syncRenderObject(old);
-    root.scrollOffset = scrollOffset;
-    root.scrollDirection = scrollDirection;
+    renderObject.scrollOffset = scrollOffset;
+    renderObject.scrollDirection = scrollDirection;
   }
 }
 
@@ -297,15 +297,15 @@
   final SizeChangedCallback callback;
 
   RenderSizeObserver createNode() => new RenderSizeObserver(callback: callback);
-  RenderSizeObserver get root => super.root;
+  RenderSizeObserver get renderObject => super.renderObject;
 
   void syncRenderObject(SizeObserver old) {
     super.syncRenderObject(old);
-    root.callback = callback;
+    renderObject.callback = callback;
   }
 
   void remove() {
-    root.callback = null;
+    renderObject.callback = null;
     super.remove();
   }
 }
@@ -381,11 +381,11 @@
   final BlockDirection direction;
 
   RenderBlock createNode() => new RenderBlock(direction: direction);
-  RenderBlock get root => super.root;
+  RenderBlock get renderObject => super.renderObject;
 
   void syncRenderObject(Widget old) {
     super.syncRenderObject(old);
-    root.direction = direction;
+    renderObject.direction = direction;
   }
 }
 
@@ -394,7 +394,7 @@
     : super(key: key, children: children);
 
   RenderStack createNode() => new RenderStack();
-  RenderStack get root => super.root;
+  RenderStack get renderObject => super.renderObject;
 }
 
 class Positioned extends ParentDataNode {
@@ -429,14 +429,14 @@
   final TextBaseline textBaseline;
 
   RenderFlex createNode() => new RenderFlex(direction: direction);
-  RenderFlex get root => super.root;
+  RenderFlex get renderObject => super.renderObject;
 
   void syncRenderObject(Widget old) {
     super.syncRenderObject(old);
-    root.direction = direction;
-    root.justifyContent = justifyContent;
-    root.alignItems = alignItems;
-    root.textBaseline = textBaseline;
+    renderObject.direction = direction;
+    renderObject.justifyContent = justifyContent;
+    renderObject.alignItems = alignItems;
+    renderObject.textBaseline = textBaseline;
   }
 
 }
@@ -452,11 +452,11 @@
   final TextSpan text;
 
   RenderParagraph createNode() => new RenderParagraph(text);
-  RenderParagraph get root => super.root;
+  RenderParagraph get renderObject => super.renderObject;
 
   void syncRenderObject(Widget old) {
     super.syncRenderObject(old);
-    root.text = text;
+    renderObject.text = text;
   }
 }
 
@@ -520,14 +520,14 @@
   final sky.ColorFilter colorFilter;
 
   RenderImage createNode() => new RenderImage(image: image, width: width, height: height, colorFilter: colorFilter);
-  RenderImage get root => super.root;
+  RenderImage get renderObject => super.renderObject;
 
   void syncRenderObject(Widget old) {
     super.syncRenderObject(old);
-    root.image = image;
-    root.width = width;
-    root.height = height;
-    root.colorFilter = colorFilter;
+    renderObject.image = image;
+    renderObject.width = width;
+    renderObject.height = height;
+    renderObject.colorFilter = colorFilter;
   }
 }
 
@@ -626,20 +626,20 @@
   final RenderBox renderBox;
 
   RenderBox createNode() => this.renderBox;
-  RenderBox get root => super.root;
+  RenderBox get renderObject => super.renderObject;
 
   void syncRenderObject(Widget old) {
     super.syncRenderObject(old);
     if (old != null) {
       assert(old is WidgetToRenderBoxAdapter);
-      assert(root == old.root);
+      assert(renderObject == old.renderObject);
     }
   }
 
   void remove() {
     RenderObjectWrapper ancestor = findAncestorRenderObjectWrapper();
     assert(ancestor is RenderObjectWrapper);
-    assert(ancestor.root == root.parent);
+    assert(ancestor.renderObject == renderObject.parent);
     ancestor.detachChildRoot(this);
     super.remove();
   }
@@ -652,5 +652,5 @@
   IgnorePointer({ Key key, Widget child })
     : super(key: key, child: child);
   RenderIgnorePointer createNode() => new RenderIgnorePointer();
-  RenderIgnorePointer get root => super.root;
+  RenderIgnorePointer get renderObject => super.renderObject;
 }
diff --git a/packages/flutter/lib/widgets/block_viewport.dart b/packages/flutter/lib/widgets/block_viewport.dart
index 8bc30c5..04dd891 100644
--- a/packages/flutter/lib/widgets/block_viewport.dart
+++ b/packages/flutter/lib/widgets/block_viewport.dart
@@ -88,7 +88,7 @@
   Object token;
   BlockViewportLayoutState layoutState;
 
-  RenderBlockViewport get root => super.root;
+  RenderBlockViewport get renderObject => super.renderObject;
   RenderBlockViewport createNode() => new RenderBlockViewport();
 
   void walkChildren(WidgetTreeWalker walker) {
@@ -101,20 +101,20 @@
   void insertChildRoot(RenderObjectWrapper child, dynamic slot) {
     if (slot == _omit)
       return;
-    final root = this.root; // TODO(ianh): Remove this once the analyzer is cleverer
+    final renderObject = this.renderObject; // TODO(ianh): Remove this once the analyzer is cleverer
     assert(slot == null || slot is RenderObject);
-    assert(root is ContainerRenderObjectMixin);
-    root.add(child.root, before: slot);
-    assert(root == this.root); // TODO(ianh): Remove this once the analyzer is cleverer
+    assert(renderObject is ContainerRenderObjectMixin);
+    renderObject.add(child.renderObject, before: slot);
+    assert(renderObject == this.renderObject); // TODO(ianh): Remove this once the analyzer is cleverer
   }
 
   void detachChildRoot(RenderObjectWrapper child) {
-    final root = this.root; // TODO(ianh): Remove this once the analyzer is cleverer
-    assert(root is ContainerRenderObjectMixin);
-    if (child.root.parent != root)
+    final renderObject = this.renderObject; // TODO(ianh): Remove this once the analyzer is cleverer
+    assert(renderObject is ContainerRenderObjectMixin);
+    if (child.renderObject.parent != renderObject)
       return; // probably had slot == _omit when inserted
-    root.remove(child.root);
-    assert(root == this.root); // TODO(ianh): Remove this once the analyzer is cleverer
+    renderObject.remove(child.renderObject);
+    assert(renderObject == this.renderObject); // TODO(ianh): Remove this once the analyzer is cleverer
   }
 
   void remove() {
@@ -126,12 +126,12 @@
   }
 
   void didMount() {
-    root.callback = layout;
+    renderObject.callback = layout;
     super.didMount();
   }
 
   void didUnmount() {
-    root.callback = null;
+    renderObject.callback = null;
     super.didUnmount();
   }
 
@@ -173,12 +173,12 @@
   void syncRenderObject(BlockViewport old) {
     super.syncRenderObject(old);
     if (layoutState._dirty || !layoutState.isValid) {
-      root.markNeedsLayout();
+      renderObject.markNeedsLayout();
     } else {
       if (layoutState._visibleChildCount > 0) {
         assert(layoutState.firstVisibleChildIndex >= 0);
         assert(builder != null);
-        assert(root != null);
+        assert(renderObject != null);
         final int startIndex = layoutState._firstVisibleChildIndex;
         int lastIndex = startIndex + layoutState._visibleChildCount - 1;
         for (int index = startIndex; index <= lastIndex; index += 1) {
@@ -188,8 +188,8 @@
           _Key key = new _Key.fromWidget(widget);
           Widget oldWidget = layoutState._childrenByKey[key];
           assert(oldWidget != null);
-          assert(oldWidget.root.parent == root);
-          widget = syncChild(widget, oldWidget, root.childAfter(oldWidget.root));
+          assert(oldWidget.renderObject.parent == renderObject);
+          widget = syncChild(widget, oldWidget, renderObject.childAfter(oldWidget.renderObject));
           assert(widget != null);
           layoutState._childrenByKey[key] = widget;
         }
@@ -214,7 +214,7 @@
     newWidget = syncChild(newWidget, oldWidget, _omit);
     assert(newWidget != null);
     // Update the offsets based on the newWidget's height.
-    RenderBox widgetRoot = newWidget.root;
+    RenderBox widgetRoot = newWidget.renderObject;
     assert(widgetRoot is RenderBox);
     double newHeight = widgetRoot.getMaxIntrinsicHeight(innerConstraints);
     double oldHeight = offsets[index + 1] - offsets[index];
@@ -237,7 +237,7 @@
     if (index >= offsets.length - 1) {
       assert(index == offsets.length - 1);
       final double widgetStartOffset = offsets[index];
-      RenderBox widgetRoot = widget.root;
+      RenderBox widgetRoot = widget.renderObject;
       assert(widgetRoot is RenderBox);
       final double widgetEndOffset = widgetStartOffset + widgetRoot.getMaxIntrinsicHeight(innerConstraints);
       offsets.add(widgetEndOffset);
@@ -266,7 +266,7 @@
 
     final List<double> offsets = layoutState._childOffsets;
     final Map<_Key, Widget> childrenByKey = layoutState._childrenByKey;
-    final double height = root.size.height;
+    final double height = renderObject.size.height;
     final double endOffset = startOffset + height;
     BoxConstraints innerConstraints = new BoxConstraints.tightFor(width: constraints.constrainWidth());
 
@@ -362,7 +362,7 @@
     int index = startIndex;
     if (haveChildren) {
       // Build all the widgets we need.
-      root.startOffset = offsets[index] - startOffset;
+      renderObject.startOffset = offsets[index] - startOffset;
       while (offsets[index] < endOffset) {
         if (!builtChildren.containsKey(index)) {
           Widget widget = _getWidget(index, innerConstraints);
@@ -392,14 +392,14 @@
       while (index > startIndex) {
         index -= 1;
         Widget widget = builtChildren[index];
-        if (widget.root.parent == root) {
-          root.move(widget.root, before: nextSibling);
+        if (widget.renderObject.parent == renderObject) {
+          renderObject.move(widget.renderObject, before: nextSibling);
         } else {
-          assert(widget.root.parent == null);
-          root.add(widget.root, before: nextSibling);
+          assert(widget.renderObject.parent == null);
+          renderObject.add(widget.renderObject, before: nextSibling);
         }
         widget.updateSlot(nextSibling);
-        nextSibling = widget.root;
+        nextSibling = widget.renderObject;
       }
     }
 
diff --git a/packages/flutter/lib/widgets/checkbox.dart b/packages/flutter/lib/widgets/checkbox.dart
index d9a050b..6e615d0 100644
--- a/packages/flutter/lib/widgets/checkbox.dart
+++ b/packages/flutter/lib/widgets/checkbox.dart
@@ -64,16 +64,16 @@
   final Color uncheckedColor;
   final Color accentColor;
 
-  _RenderCheckbox get root => super.root;
+  _RenderCheckbox get renderObject => super.renderObject;
   _RenderCheckbox createNode() => new _RenderCheckbox(
       value: value, uncheckedColor: uncheckedColor, onChanged: onChanged);
 
   void syncRenderObject(_CheckboxWrapper old) {
     super.syncRenderObject(old);
-    root.value = value;
-    root.onChanged = onChanged;
-    root.uncheckedColor = uncheckedColor;
-    root.accentColor = accentColor;
+    renderObject.value = value;
+    renderObject.onChanged = onChanged;
+    renderObject.uncheckedColor = uncheckedColor;
+    renderObject.accentColor = accentColor;
   }
 }
 
diff --git a/packages/flutter/lib/widgets/drag_target.dart b/packages/flutter/lib/widgets/drag_target.dart
new file mode 100644
index 0000000..7f9402b
--- /dev/null
+++ b/packages/flutter/lib/widgets/drag_target.dart
@@ -0,0 +1,119 @@
+// 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:collection';
+
+import 'package:sky/base/hit_test.dart';
+import 'package:sky/rendering/sky_binding.dart';
+import 'package:sky/widgets/basic.dart';
+import 'package:sky/widgets/framework.dart';
+
+typedef bool DragTargetWillAccept<T>(T data);
+typedef void DragTargetAccept<T>(T data);
+typedef Widget DragTargetBuilder<T>(List<T> candidateData, List<dynamic> rejectedData);
+
+class DragTarget<T> extends StatefulComponent {
+  DragTarget({
+    Key key,
+    this.builder,
+    this.onWillAccept,
+    this.onAccept
+  }) : super(key: key);
+
+  DragTargetBuilder<T> builder;
+  DragTargetWillAccept<T> onWillAccept;
+  DragTargetAccept<T> onAccept;
+
+  final List<T> _candidateData = new List<T>();
+  final List<dynamic> _rejectedData = new List<dynamic>();
+
+  void syncFields(DragTarget source) {
+    builder = source.builder;
+    onWillAccept = source.onWillAccept;
+    onAccept = source.onAccept;
+  }
+
+  bool didEnter(dynamic data) {
+    assert(!_candidateData.contains(data));
+    assert(!_rejectedData.contains(data));
+    if (data is T && (onWillAccept == null || onWillAccept(data))) {
+      setState(() {
+        _candidateData.add(data);
+      });
+      return true;
+    }
+    _rejectedData.add(data);
+    return false;
+  }
+
+  void didLeave(dynamic data) {
+    assert(_candidateData.contains(data) || _rejectedData.contains(data));
+    setState(() {
+      _candidateData.remove(data);
+      _rejectedData.remove(data);
+    });
+  }
+
+  void didDrop(dynamic data) {
+    assert(_candidateData.contains(data));
+    setState(() {
+      _candidateData.remove(data);
+    });
+    if (onAccept != null)
+      onAccept(data);
+  }
+
+  Widget build() {
+    return builder(new UnmodifiableListView<T>(_candidateData),
+                   new UnmodifiableListView<dynamic>(_rejectedData));
+  }
+}
+
+class DragController {
+  DragController(this.data);
+
+  final dynamic data;
+
+  DragTarget _activeTarget;
+  bool _activeTargetWillAcceptDrop = false;
+
+  DragTarget _getDragTarget(List<HitTestEntry> path) {
+    for (HitTestEntry entry in path.reversed) {
+      for (Widget widget in RenderObjectWrapper.getWidgetsForRenderObject(entry.target)) {
+        if (widget is DragTarget)
+          return widget;
+      }
+    }
+    return null;
+  }
+
+  void update(Point globalPosition) {
+    HitTestResult result = SkyBinding.instance.hitTest(globalPosition);
+    DragTarget target = _getDragTarget(result.path);
+    if (target == _activeTarget)
+      return;
+    if (_activeTarget != null)
+      _activeTarget.didLeave(data);
+    _activeTarget = target;
+    _activeTargetWillAcceptDrop = _activeTarget != null && _activeTarget.didEnter(data);
+  }
+
+  void cancel() {
+    if (_activeTarget != null)
+      _activeTarget.didLeave(data);
+    _activeTarget = null;
+    _activeTargetWillAcceptDrop = false;
+  }
+
+  void drop() {
+    if (_activeTarget == null)
+      return;
+    if (_activeTargetWillAcceptDrop)
+      _activeTarget.didDrop(data);
+    else
+      _activeTarget.didLeave(data);
+    _activeTarget = null;
+    _activeTargetWillAcceptDrop = false;
+  }
+}
diff --git a/packages/flutter/lib/widgets/framework.dart b/packages/flutter/lib/widgets/framework.dart
index 8453a68..e4a0f98 100644
--- a/packages/flutter/lib/widgets/framework.dart
+++ b/packages/flutter/lib/widgets/framework.dart
@@ -248,10 +248,10 @@
       (key as GlobalKey)._unregister(this); // TODO(ianh): remove cast when analyzer is cleverer
   }
 
-  RenderObject _root;
+  RenderObject _renderObject;
 
   /// The underlying [RenderObject] associated with this [Widget].
-  RenderObject get root => _root;
+  RenderObject get renderObject => _renderObject;
 
   // Subclasses which implements Nodes that become stateful may return true
   // if the node has become stateful and should be retained.
@@ -273,7 +273,7 @@
   }
 
   void remove() {
-    _root = null;
+    _renderObject = null;
     setParent(null);
   }
 
@@ -318,7 +318,7 @@
           assert(!newNode.mounted);
           oldNode.setParent(this);
           oldNode._sync(newNode, slot);
-          assert(oldNode.root is RenderObject);
+          assert(oldNode.renderObject is RenderObject);
           return oldNode;
         } else {
           oldNode.setParent(null);
@@ -335,7 +335,7 @@
     assert(!newNode.mounted);
     newNode.setParent(this);
     newNode._sync(oldNode, slot);
-    assert(newNode.root is RenderObject);
+    assert(newNode.renderObject is RenderObject);
     return newNode;
   }
 
@@ -374,15 +374,15 @@
   // globalToLocal().
   Point globalToLocal(Point point) {
     assert(mounted);
-    assert(root is RenderBox);
-    return (root as RenderBox).globalToLocal(point);
+    assert(renderObject is RenderBox);
+    return (renderObject as RenderBox).globalToLocal(point);
   }
 
   // See globalToLocal().
   Point localToGlobal(Point point) {
     assert(mounted);
-    assert(root is RenderBox);
-    return (root as RenderBox).localToGlobal(point);
+    assert(renderObject is RenderBox);
+    return (renderObject as RenderBox).localToGlobal(point);
   }
 }
 
@@ -410,9 +410,9 @@
     Widget oldChild = old == null ? null : (old as TagNode).child;
     child = syncChild(child, oldChild, slot);
     assert(child.parent == this);
-    assert(child.root != null);
-    _root = child.root;
-    assert(_root == root); // in case a subclass reintroduces it
+    assert(child.renderObject != null);
+    _renderObject = child.renderObject;
+    assert(_renderObject == renderObject); // in case a subclass reintroduces it
   }
 
   void updateSlot(dynamic newSlot) {
@@ -596,7 +596,7 @@
 
   void remove() {
     assert(_built != null);
-    assert(root != null);
+    assert(renderObject != null);
     removeChild(_built);
     _built = null;
     super.remove();
@@ -604,7 +604,7 @@
 
   void detachRoot() {
     assert(_built != null);
-    assert(root != null);
+    assert(renderObject != null);
     _built.detachRoot();
   }
 
@@ -664,15 +664,15 @@
     _isBuilding = false;
 
     _dirty = false;
-    _root = _built.root;
-    assert(_root == root); // in case a subclass reintroduces it
-    assert(root != null);
+    _renderObject = _built.renderObject;
+    assert(_renderObject == renderObject); // in case a subclass reintroduces it
+    assert(renderObject != null);
   }
 
   void _buildIfDirty() {
     if (!_dirty || !_mounted)
       return;
-    assert(root != null);
+    assert(renderObject != null);
     _sync(null, _slot);
   }
 
@@ -866,12 +866,23 @@
       new HashMap<RenderObject, RenderObjectWrapper>();
   static RenderObjectWrapper _getMounted(RenderObject node) => _nodeMap[node];
 
+  static Iterable<Widget> getWidgetsForRenderObject(RenderObject renderObject) sync* {
+    Widget target = RenderObjectWrapper._getMounted(renderObject);
+    if (target == null)
+      return;
+    RenderObject targetRoot = target.renderObject;
+    while (target != null && target.renderObject == targetRoot) {
+      yield target;
+      target = target.parent;
+    }
+  }
+
   RenderObjectWrapper _ancestor;
   void insertChildRoot(RenderObjectWrapper child, dynamic slot);
   void detachChildRoot(RenderObjectWrapper child);
 
   void retainStatefulRenderObjectWrapper(RenderObjectWrapper newNode) {
-    newNode._root = _root;
+    newNode._renderObject = _renderObject;
     newNode._ancestor = _ancestor;
   }
 
@@ -881,21 +892,21 @@
     //               doesn't need.
     assert(parent != null || this is RenderViewWrapper);
     if (old == null) {
-      _root = createNode();
-      assert(_root != null);
+      _renderObject = createNode();
+      assert(_renderObject != null);
       _ancestor = findAncestorRenderObjectWrapper();
       if (_ancestor is RenderObjectWrapper)
         _ancestor.insertChildRoot(this, slot);
     } else {
       assert(old is RenderObjectWrapper);
-      _root = old.root;
+      _renderObject = old.renderObject;
       _ancestor = old._ancestor;
-      assert(_root != null);
+      assert(_renderObject != null);
     }
-    assert(_root == root); // in case a subclass reintroduces it
-    assert(root != null);
+    assert(_renderObject == renderObject); // in case a subclass reintroduces it
+    assert(renderObject != null);
     assert(mounted);
-    _nodeMap[root] = this;
+    _nodeMap[renderObject] = this;
     syncRenderObject(old);
   }
 
@@ -919,22 +930,22 @@
       ancestor = ancestor.parent;
     }
     if (parentData != null) {
-      assert(root.parentData != null);
-      root.parentData.merge(parentData); // this will throw if the types aren't appropriate
-      if (ancestor != null && ancestor.root != null)
-        ancestor.root.markNeedsLayout();
+      assert(renderObject.parentData != null);
+      renderObject.parentData.merge(parentData); // this will throw if the types aren't appropriate
+      if (ancestor != null && ancestor.renderObject != null)
+        ancestor.renderObject.markNeedsLayout();
     }
   }
 
   void remove() {
-    assert(root != null);
-    _nodeMap.remove(root);
+    assert(renderObject != null);
+    _nodeMap.remove(renderObject);
     super.remove();
   }
 
   void detachRoot() {
     assert(_ancestor != null);
-    assert(root != null);
+    assert(renderObject != null);
     _ancestor.detachChildRoot(this);
   }
 
@@ -977,19 +988,19 @@
   }
 
   void insertChildRoot(RenderObjectWrapper child, dynamic slot) {
-    final root = this.root; // TODO(ianh): Remove this once the analyzer is cleverer
-    assert(root is RenderObjectWithChildMixin);
+    final renderObject = this.renderObject; // TODO(ianh): Remove this once the analyzer is cleverer
+    assert(renderObject is RenderObjectWithChildMixin);
     assert(slot == null);
-    root.child = child.root;
-    assert(root == this.root); // TODO(ianh): Remove this once the analyzer is cleverer
+    renderObject.child = child.renderObject;
+    assert(renderObject == this.renderObject); // TODO(ianh): Remove this once the analyzer is cleverer
   }
 
   void detachChildRoot(RenderObjectWrapper child) {
-    final root = this.root; // TODO(ianh): Remove this once the analyzer is cleverer
-    assert(root is RenderObjectWithChildMixin);
-    assert(root.child == child.root);
-    root.child = null;
-    assert(root == this.root); // TODO(ianh): Remove this once the analyzer is cleverer
+    final renderObject = this.renderObject; // TODO(ianh): Remove this once the analyzer is cleverer
+    assert(renderObject is RenderObjectWithChildMixin);
+    assert(renderObject.child == child.renderObject);
+    renderObject.child = null;
+    assert(renderObject == this.renderObject); // TODO(ianh): Remove this once the analyzer is cleverer
   }
 
   void remove() {
@@ -1018,19 +1029,19 @@
   }
 
   void insertChildRoot(RenderObjectWrapper child, dynamic slot) {
-    final root = this.root; // TODO(ianh): Remove this once the analyzer is cleverer
+    final renderObject = this.renderObject; // TODO(ianh): Remove this once the analyzer is cleverer
     assert(slot == null || slot is RenderObject);
-    assert(root is ContainerRenderObjectMixin);
-    root.add(child.root, before: slot);
-    assert(root == this.root); // TODO(ianh): Remove this once the analyzer is cleverer
+    assert(renderObject is ContainerRenderObjectMixin);
+    renderObject.add(child.renderObject, before: slot);
+    assert(renderObject == this.renderObject); // TODO(ianh): Remove this once the analyzer is cleverer
   }
 
   void detachChildRoot(RenderObjectWrapper child) {
-    final root = this.root; // TODO(ianh): Remove this once the analyzer is cleverer
-    assert(root is ContainerRenderObjectMixin);
-    assert(child.root.parent == root);
-    root.remove(child.root);
-    assert(root == this.root); // TODO(ianh): Remove this once the analyzer is cleverer
+    final renderObject = this.renderObject; // TODO(ianh): Remove this once the analyzer is cleverer
+    assert(renderObject is ContainerRenderObjectMixin);
+    assert(child.renderObject.parent == renderObject);
+    renderObject.remove(child.renderObject);
+    assert(renderObject == this.renderObject); // TODO(ianh): Remove this once the analyzer is cleverer
   }
 
   void remove() {
@@ -1059,8 +1070,8 @@
   void syncRenderObject(MultiChildRenderObjectWrapper old) {
     super.syncRenderObject(old);
 
-    final root = this.root; // TODO(ianh): Remove this once the analyzer is cleverer
-    if (root is! ContainerRenderObjectMixin)
+    final renderObject = this.renderObject; // TODO(ianh): Remove this once the analyzer is cleverer
+    if (renderObject is! ContainerRenderObjectMixin)
       return;
 
     var startIndex = 0;
@@ -1079,7 +1090,7 @@
       assert(children[atIndex] != null);
       assert(children[atIndex].parent == this);
       if (atIndex > 0)
-        children[atIndex-1].updateSlot(children[atIndex].root);
+        children[atIndex-1].updateSlot(children[atIndex].renderObject);
     }
 
     // Scan backwards from end of list while nodes can be directly synced
@@ -1095,7 +1106,7 @@
       endIndex--;
       oldEndIndex--;
       sync(endIndex);
-      nextSibling = children[endIndex].root;
+      nextSibling = children[endIndex].renderObject;
     }
 
     HashMap<Key, Widget> oldNodeIdMap = null;
@@ -1136,28 +1147,28 @@
         return false;
 
       oldNodeIdMap[currentNode.key] = null; // mark it reordered
-      assert(root is ContainerRenderObjectMixin);
-      assert(old.root is ContainerRenderObjectMixin);
-      assert(oldNode.root != null);
+      assert(renderObject is ContainerRenderObjectMixin);
+      assert(old.renderObject is ContainerRenderObjectMixin);
+      assert(oldNode.renderObject != null);
 
-      if (old.root == root) {
-        root.move(oldNode.root, before: nextSibling);
+      if (old.renderObject == renderObject) {
+        renderObject.move(oldNode.renderObject, before: nextSibling);
       } else {
-        (old.root as ContainerRenderObjectMixin).remove(oldNode.root); // TODO(ianh): Remove cast once the analyzer is cleverer
-        root.add(oldNode.root, before: nextSibling);
+        (old.renderObject as ContainerRenderObjectMixin).remove(oldNode.renderObject); // TODO(ianh): Remove cast once the analyzer is cleverer
+        renderObject.add(oldNode.renderObject, before: nextSibling);
       }
 
       return true;
     }
 
     // Scan forwards, this time we may re-order;
-    nextSibling = root.firstChild;
+    nextSibling = renderObject.firstChild;
     while (startIndex < endIndex && oldStartIndex < oldEndIndex) {
       currentNode = children[startIndex];
       oldNode = oldChildren[oldStartIndex];
 
       if (currentNode.runtimeType == oldNode.runtimeType && currentNode.key == oldNode.key) {
-        nextSibling = root.childAfter(nextSibling);
+        nextSibling = renderObject.childAfter(nextSibling);
         sync(startIndex);
         startIndex++;
         advanceOldStartIndex();
@@ -1187,7 +1198,7 @@
       advanceOldStartIndex();
     }
 
-    assert(root == this.root); // TODO(ianh): Remove this once the analyzer is cleverer
+    assert(renderObject == this.renderObject); // TODO(ianh): Remove this once the analyzer is cleverer
   }
 
 }
@@ -1209,11 +1220,7 @@
     if (disposition == EventDisposition.consumed)
       return EventDisposition.consumed;
     for (HitTestEntry entry in result.path.reversed) {
-      Widget target = RenderObjectWrapper._getMounted(entry.target);
-      if (target == null)
-        continue;
-      RenderObject targetRoot = target.root;
-      while (target != null && target.root == targetRoot) {
+      for (Widget target in RenderObjectWrapper.getWidgetsForRenderObject(entry.target)) {
         if (target is Listener) {
           EventDisposition targetDisposition = target._handleEvent(event);
           if (targetDisposition == EventDisposition.consumed) {
@@ -1286,7 +1293,7 @@
 
 class RenderViewWrapper extends OneChildRenderObjectWrapper {
   RenderViewWrapper({ Key key, Widget child }) : super(key: key, child: child);
-  RenderView get root => super.root;
+  RenderView get renderObject => super.renderObject;
   RenderView createNode() => SkyBinding.instance.renderView;
 }
 
@@ -1330,14 +1337,14 @@
   void set container(RenderObjectWithChildMixin<RenderBox> value) {
     if (_container != value) {
       assert(value.child == null);
-      if (root != null) {
-        assert(_container.child == root);
+      if (renderObject != null) {
+        assert(_container.child == renderObject);
         _container.child = null;
       }
       _container = value;
-      if (root != null) {
-        _container.child = root;
-        assert(_container.child == root);
+      if (renderObject != null) {
+        _container.child = renderObject;
+        assert(_container.child == renderObject);
       }
     }
   }
@@ -1346,12 +1353,12 @@
 
   void _buildIfDirty() {
     super._buildIfDirty();
-    if (root.parent == null) {
+    if (renderObject.parent == null) {
       // we haven't attached it yet
       assert(_container.child == null);
-      _container.child = root;
+      _container.child = renderObject;
     }
-    assert(root.parent == _container);
+    assert(renderObject.parent == _container);
   }
 
   Widget build() => builder();
diff --git a/packages/flutter/lib/widgets/ink_well.dart b/packages/flutter/lib/widgets/ink_well.dart
index 906f781..6d096ae 100644
--- a/packages/flutter/lib/widgets/ink_well.dart
+++ b/packages/flutter/lib/widgets/ink_well.dart
@@ -131,6 +131,6 @@
   InkWell({ Key key, Widget child })
     : super(key: key, child: child);
 
-  RenderInkWell get root => super.root;
+  RenderInkWell get renderObject => super.renderObject;
   RenderInkWell createNode() => new RenderInkWell();
 }
diff --git a/packages/flutter/lib/widgets/scaffold.dart b/packages/flutter/lib/widgets/scaffold.dart
index 0cc6046..8df48b8 100644
--- a/packages/flutter/lib/widgets/scaffold.dart
+++ b/packages/flutter/lib/widgets/scaffold.dart
@@ -196,7 +196,7 @@
 
   Map<ScaffoldSlots, Widget> _slots = new Map<ScaffoldSlots, Widget>();
 
-  RenderScaffold get root => super.root;
+  RenderScaffold get renderObject => super.renderObject;
   RenderScaffold createNode() => new RenderScaffold();
 
   void walkChildren(WidgetTreeWalker walker) {
@@ -208,15 +208,15 @@
   }
 
   void insertChildRoot(RenderObjectWrapper child, ScaffoldSlots slot) {
-    root[slot] = child != null ? child.root : null;
+    renderObject[slot] = child != null ? child.renderObject : null;
   }
 
   void detachChildRoot(RenderObjectWrapper child) {
-    final root = this.root; // TODO(ianh): Remove this once the analyzer is cleverer
-    assert(root is RenderScaffold);
-    assert(root == child.root.parent);
-    root.remove(child.root);
-    assert(root == this.root); // TODO(ianh): Remove this once the analyzer is cleverer
+    final renderObject = this.renderObject; // TODO(ianh): Remove this once the analyzer is cleverer
+    assert(renderObject is RenderScaffold);
+    assert(renderObject == child.renderObject.parent);
+    renderObject.remove(child.renderObject);
+    assert(renderObject == this.renderObject); // TODO(ianh): Remove this once the analyzer is cleverer
   }
 
   void remove() {
diff --git a/packages/flutter/lib/widgets/scrollable.dart b/packages/flutter/lib/widgets/scrollable.dart
index 25e02e9..596b7bb 100644
--- a/packages/flutter/lib/widgets/scrollable.dart
+++ b/packages/flutter/lib/widgets/scrollable.dart
@@ -233,20 +233,20 @@
 
 bool ensureWidgetIsVisible(Widget target, { ValueAnimation<double> animation }) {
   assert(target.mounted);
-  assert(target.root is RenderBox);
+  assert(target.renderObject is RenderBox);
 
   Scrollable scrollable = findScrollableAncestor(target: target);
   if (scrollable == null)
     return false;
 
-  Size targetSize = (target.root as RenderBox).size;
+  Size targetSize = (target.renderObject as RenderBox).size;
   Point targetCenter = target.localToGlobal(
     scrollable.scrollDirection == ScrollDirection.vertical
       ? new Point(0.0, targetSize.height / 2.0)
       : new Point(targetSize.width / 2.0, 0.0)
   );
 
-  Size scrollableSize = (scrollable.root as RenderBox).size;
+  Size scrollableSize = (scrollable.renderObject as RenderBox).size;
   Point scrollableCenter = scrollable.localToGlobal(
     scrollable.scrollDirection == ScrollDirection.vertical
       ? new Point(0.0, scrollableSize.height / 2.0)
diff --git a/packages/flutter/lib/widgets/switch.dart b/packages/flutter/lib/widgets/switch.dart
index c6f8521..ccdf435 100644
--- a/packages/flutter/lib/widgets/switch.dart
+++ b/packages/flutter/lib/widgets/switch.dart
@@ -55,15 +55,15 @@
   final ValueChanged onChanged;
   final Color thumbColor;
 
-  _RenderSwitch get root => super.root;
+  _RenderSwitch get renderObject => super.renderObject;
   _RenderSwitch createNode() => new _RenderSwitch(
       value: value, thumbColor: thumbColor, onChanged: onChanged);
 
   void syncRenderObject(_SwitchWrapper old) {
     super.syncRenderObject(old);
-    root.value = value;
-    root.onChanged = onChanged;
-    root.thumbColor = thumbColor;
+    renderObject.value = value;
+    renderObject.onChanged = onChanged;
+    renderObject.thumbColor = thumbColor;
   }
 }
 
diff --git a/packages/flutter/lib/widgets/tabs.dart b/packages/flutter/lib/widgets/tabs.dart
index 00007c3..63a469c 100644
--- a/packages/flutter/lib/widgets/tabs.dart
+++ b/packages/flutter/lib/widgets/tabs.dart
@@ -287,18 +287,18 @@
   final bool isScrollable;
   final LayoutChanged onLayoutChanged;
 
-  RenderTabBar get root => super.root;
+  RenderTabBar get renderObject => super.renderObject;
   RenderTabBar createNode() => new RenderTabBar(onLayoutChanged);
 
   void syncRenderObject(Widget old) {
     super.syncRenderObject(old);
-    root.selectedIndex = selectedIndex;
-    root.backgroundColor = backgroundColor;
-    root.indicatorColor = indicatorColor;
-    root.indicatorRect = indicatorRect;
-    root.textAndIcons = textAndIcons;
-    root.isScrollable = isScrollable;
-    root.onLayoutChanged = onLayoutChanged;
+    renderObject.selectedIndex = selectedIndex;
+    renderObject.backgroundColor = backgroundColor;
+    renderObject.indicatorColor = indicatorColor;
+    renderObject.indicatorRect = indicatorRect;
+    renderObject.textAndIcons = textAndIcons;
+    renderObject.isScrollable = isScrollable;
+    renderObject.onLayoutChanged = onLayoutChanged;
   }
 }