Reland the layer creation change since the touchui issues will be resolved in a follow up CL.

This reverts 103580 - Revert the layer creation change r103338 due to some issues with the keyboard on touch. I'll re-land later once I can get a working linux build.TBR=skyBUG=noneTEST=none
Review URL: http://codereview.chromium.org/8100015

[email protected]
Review URL: http://codereview.chromium.org/8115010

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@103777 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/views/view.cc b/views/view.cc
index 9b5e26bb..3bc87aa 100644
--- a/views/view.cc
+++ b/views/view.cc
@@ -113,6 +113,7 @@
       clip_y_(0.0),
       needs_layout_(true),
       flip_canvas_on_paint_for_rtl_ui_(false),
+      paint_to_layer_(false),
       accelerator_registration_delayed_(false),
       accelerator_focus_manager_(NULL),
       registered_accelerator_count_(0),
@@ -170,21 +171,13 @@
   view->parent_ = this;
   children_.insert(children_.begin() + index, view);
 
-  if (GetWidget()) {
-    // Sending out notification of insert may result in adding other views.
-    // Invoke this first to make sure we know the layer is created (if needed).
-    view->CreateLayerIfNecessary();
-  }
-
   for (View* v = this; v; v = v->parent_)
     v->ViewHierarchyChangedImpl(false, true, this, view);
 
   view->PropagateAddNotifications(this, view);
   UpdateTooltip();
-  if (GetWidget()) {
+  if (GetWidget())
     RegisterChildrenForVisibleBoundsNotification(view);
-    view->CreateLayerIfNecessary();
-  }
 
   if (layout_manager_.get())
     layout_manager_->ViewAdded(this, view);
@@ -313,8 +306,7 @@
   ui::Transform transform;
 
   while (view != NULL && !vis_bounds.IsEmpty()) {
-    if (view->transform())
-      transform.ConcatTransform(*view->transform());
+    transform.ConcatTransform(view->GetTransform());
     transform.ConcatTranslate(static_cast<float>(view->GetMirroredX()),
                               static_cast<float>(view->y()));
 
@@ -371,16 +363,13 @@
 void View::SetVisible(bool visible) {
   if (visible != visible_) {
     // If the View is currently visible, schedule paint to refresh parent.
+    // TODO(beng): not sure we should be doing this if we have a layer.
     if (visible_)
       SchedulePaint();
 
     visible_ = visible;
-
-    if (visible_)
-      CreateLayerIfNecessary();
-    else
-      // Destroy layer if the View is invisible as invisible Views never paint.
-      DestroyLayerRecurse();
+    if (layer())
+      layer()->SetVisible(visible_);
 
     // This notifies all sub-views recursively.
     PropagateVisibilityNotifications(this, visible_);
@@ -418,70 +407,47 @@
 
 const ui::Transform& View::GetTransform() const {
   static const ui::Transform* no_op = new ui::Transform;
-  return transform() ? *transform() : *no_op;
+  return layer() ? layer()->transform() : *no_op;
 }
 
 void View::SetTransform(const ui::Transform& transform) {
   if (!transform.HasChange()) {
-    if (!layer_helper_.get() || !this->transform())
-      return;
-    layer_helper_->SetTransform(transform);
-
-    if (!ShouldPaintToLayer())
-      DestroyLayerAndReparent();
-    else if (layer())
-      layer_helper_->property_setter()->SetTransform(layer(), transform);
-
-    SchedulePaint();
-  } else {
-    if (!layer_helper_.get())
-      layer_helper_.reset(new internal::LayerHelper());
-    layer_helper_->SetTransform(transform);
-    if (!layer()) {
-      CreateLayer();
-      SchedulePaint();
+    if (layer()) {
+      layer_property_setter_->SetTransform(layer(), transform);
+      if (!paint_to_layer_)
+        DestroyLayer();
     } else {
-      layer_helper_->property_setter()->SetTransform(layer(), transform);
-      // We have a layer. When the transform changes and the layer is up to
-      // date we don't want to SchedulePaint as it'll trigger painting to the
-      // layer. Instead we tell the Widget to paint, which makes the
-      // compositor draw using the existing layer.
-      // We schedule paint the complete bounds as compositor generally don't
-      // support partial painting.
-      Widget* widget = GetWidget();
-      if (widget)
-        widget->SchedulePaintInRect(widget->GetRootView()->bounds());
+      // Nothing.
     }
+  } else {
+    if (!layer())
+      CreateLayer();
+    layer_property_setter_->SetTransform(layer(), transform);
+    layer()->ScheduleDraw();
   }
 }
 
-void View::SetPaintToLayer(bool value) {
-  bool paint_to_layer = layer_helper_.get() && layer_helper_->paint_to_layer();
-  if (value == paint_to_layer)
-    return;
-
-  if (value) {
-    if (!layer_helper_.get())
-      layer_helper_.reset(new internal::LayerHelper());
-    layer_helper_->set_paint_to_layer(true);
+void View::SetPaintToLayer(bool paint_to_layer) {
+  paint_to_layer_ = paint_to_layer;
+  if (paint_to_layer_ && !layer()) {
     CreateLayer();
-  } else if (layer_helper_.get()) {
-    layer_helper_->set_paint_to_layer(false);
-    if (!ShouldPaintToLayer())
-      DestroyLayerAndReparent();
+  } else if (!paint_to_layer_ && layer()) {
+    DestroyLayer();
   }
 }
 
 void View::SetLayerPropertySetter(LayerPropertySetter* setter) {
-  if ((layer_helper_.get() && layer_helper_->property_setter() == setter) ||
-      (!layer_helper_.get() && setter == NULL)) {
+  DCHECK(layer());
+  LayerPropertySetter* old_setter = layer_property_setter_.get();
+  if (!layer() || (old_setter && old_setter == setter))
     return;
-  }
+  if (!setter)
+    setter = LayerPropertySetter::CreateDefaultSetter();
 
-  if (!layer_helper_.get())
-    layer_helper_.reset(new internal::LayerHelper());
-  layer_helper_->set_property_setter_explicitly_set(setter != NULL);
-  layer_helper_->SetPropertySetter(setter);
+  if (old_setter)
+    old_setter->Uninstalled(layer());
+  layer_property_setter_.reset(setter);
+  layer_property_setter_->Installed(layer());
 }
 
 // RTL positioning -------------------------------------------------------------
@@ -657,8 +623,7 @@
 
 gfx::Rect View::ConvertRectToParent(const gfx::Rect& rect) const {
   gfx::Rect x_rect = rect;
-  if (transform())
-    transform()->TransformRect(&x_rect);
+  GetTransform().TransformRect(&x_rect);
   x_rect.Offset(GetMirroredPosition());
   return x_rect;
 }
@@ -710,8 +675,7 @@
   // where this view is located (related to its parent).
   canvas->TranslateInt(GetMirroredX(), y());
 
-  if (transform())
-    canvas->Transform(*transform());
+  canvas->Transform(GetTransform());
 
   PaintCommon(canvas);
 }
@@ -1106,23 +1070,16 @@
 // Accelerated Painting --------------------------------------------------------
 
 void View::SetFillsBoundsOpaquely(bool fills_bounds_opaquely) {
-  if (!layer_helper_.get())
-    layer_helper_.reset(new internal::LayerHelper());
-
-  layer_helper_->set_fills_bounds_opaquely(fills_bounds_opaquely);
-
+  // This method should not have the side-effect of creating the layer.
   if (layer())
     layer()->SetFillsBoundsOpaquely(fills_bounds_opaquely);
 }
 
 bool View::SetExternalTexture(ui::Texture* texture) {
   DCHECK(texture);
-  if (!layer_helper_.get())
-    return true;
+  SetPaintToLayer(true);
 
-  if (!layer_helper_.get())
-    layer_helper_.reset(new internal::LayerHelper());
-  layer_helper_->SetExternalTexture(texture);
+  layer()->SetExternalTexture(texture);
 
   // Child views must not paint into the external texture. So make sure each
   // child view has its own layer to paint into.
@@ -1130,18 +1087,9 @@
     (*i)->SetPaintToLayer(true);
 
   SchedulePaintInRect(GetLocalBounds());
-
   return true;
 }
 
-const ui::Compositor* View::GetCompositor() const {
-  return parent_ ? parent_->GetCompositor() : NULL;
-}
-
-ui::Compositor* View::GetCompositor() {
-  return parent_ ? parent_->GetCompositor() : NULL;
-}
-
 void View::CalculateOffsetToAncestorWithLayer(gfx::Point* offset,
                                               ui::Layer** layer_parent) {
   if (layer()) {
@@ -1156,13 +1104,6 @@
   parent_->CalculateOffsetToAncestorWithLayer(offset, layer_parent);
 }
 
-void View::CreateLayerIfNecessary() {
-  if (ShouldPaintToLayer())
-    CreateLayer();
-
-  for (int i = 0, count = child_count(); i < count; ++i)
-    child_at(i)->CreateLayerIfNecessary();
-}
 
 void View::MoveLayerToParent(ui::Layer* parent_layer,
                              const gfx::Point& point) {
@@ -1171,29 +1112,24 @@
     local_point.Offset(x(), y());
   if (layer() && parent_layer != layer()) {
     parent_layer->Add(layer());
-    layer()->SetBounds(
-        gfx::Rect(local_point.x(), local_point.y(), width(), height()));
+    layer()->SetBounds(gfx::Rect(local_point.x(), local_point.y(),
+                                 width(), height()));
   } else {
     for (int i = 0, count = child_count(); i < count; ++i)
       child_at(i)->MoveLayerToParent(parent_layer, local_point);
   }
 }
 
-void View::DestroyLayerRecurse() {
-  for (int i = child_count() - 1; i >= 0; --i)
-    child_at(i)->DestroyLayerRecurse();
-  DestroyLayer();
-}
-
-void View::UpdateLayerBounds(const gfx::Point& offset) {
+void View::UpdateChildLayerBounds(const gfx::Point& offset) {
   if (layer()) {
-    layer_helper_->property_setter()->SetBounds(
-        layer(),
-        gfx::Rect(offset.x() + x(), offset.y() + y(), width(), height()));
+    layer_property_setter_->SetBounds(layer(), gfx::Rect(offset.x(), offset.y(),
+                                                         width(), height()));
   } else {
-    gfx::Point new_offset(offset.x() + x(), offset.y() + y());
-    for (int i = 0, count = child_count(); i < count; ++i)
-      child_at(i)->UpdateLayerBounds(new_offset);
+    for (int i = 0, count = child_count(); i < count; ++i) {
+      gfx::Point new_offset(offset.x() + child_at(i)->x(),
+                            offset.y() + child_at(i)->y());
+      child_at(i)->UpdateChildLayerBounds(new_offset);
+    }
   }
 }
 
@@ -1487,7 +1423,6 @@
 
     if (GetWidget())
       UnregisterChildrenForVisibleBoundsNotification(view);
-    view->DestroyLayerRecurse();
     view->PropagateRemoveNotifications(this);
     view->parent_ = NULL;
 
@@ -1549,6 +1484,9 @@
     }
   }
 
+  if (is_add && layer() && !layer()->parent())
+    UpdateParentLayer();
+
   ViewHierarchyChanged(is_add, parent, child);
   parent->needs_layout_ = true;
 }
@@ -1582,26 +1520,24 @@
           gfx::Point offset;
           parent_->CalculateOffsetToAncestorWithLayer(&offset, NULL);
           offset.Offset(x(), y());
-          layer_helper_->property_setter()->SetBounds(
-              layer(), gfx::Rect(offset, size()));
+          layer_property_setter_->SetBounds(layer(), gfx::Rect(offset, size()));
         } else {
-          layer_helper_->property_setter()->SetBounds(layer(), bounds_);
+          layer_property_setter_->SetBounds(layer(), bounds_);
         }
+        // TODO(beng): this seems redundant with the SchedulePaint at the top of
+        //             this function. explore collapsing.
         if (previous_bounds.size() != bounds_.size() &&
             !layer()->layer_updated_externally()) {
           // If our bounds have changed then we need to update the complete
           // texture.
           layer()->SchedulePaint(GetLocalBounds());
         }
-      } else if (GetCompositor()) {
+      } else {
         // If our bounds have changed, then any descendant layer bounds may
         // have changed. Update them accordingly.
         gfx::Point offset;
         CalculateOffsetToAncestorWithLayer(&offset, NULL);
-        // CalculateOffsetToAncestorWithLayer includes our location as does
-        // UpdateLayerBounds.
-        offset.Offset(-x(), -y());
-        UpdateLayerBounds(offset);
+        UpdateChildLayerBounds(offset);
       }
     }
   }
@@ -1613,9 +1549,8 @@
     Layout();
   }
 
-  if (NeedsNotificationWhenVisibleBoundsChange()) {
+  if (NeedsNotificationWhenVisibleBoundsChange())
     OnVisibleBoundsChanged();
-  }
 
   // Notify interested Views that visible bounds within the root view may have
   // changed.
@@ -1685,8 +1620,7 @@
   const View* p = this;
 
   while (p && p != ancestor) {
-    if (p->transform())
-      transform->ConcatTransform(*p->transform());
+    transform->ConcatTransform(p->GetTransform());
     transform->ConcatTranslate(static_cast<float>(p->GetMirroredX()),
                                static_cast<float>(p->y()));
 
@@ -1765,69 +1699,67 @@
 
 // Accelerated painting --------------------------------------------------------
 
-bool View::ShouldPaintToLayer() const {
-  return use_acceleration_when_possible &&
-      ((layer_helper_.get() && layer_helper_->ShouldPaintToLayer()) ||
-       (parent_ && parent_->layer() &&
-        parent_->layer()->layer_updated_externally()));
-}
-
 void View::CreateLayer() {
-  if (!ShouldPaintToLayer() || layer())
-    return;
+  layer_.reset(new ui::Layer(NULL));
+  layer_->set_delegate(this);
+  if (layer_property_setter_.get())
+    layer_property_setter_->Installed(layer());
+  else
+    SetLayerPropertySetter(NULL);
 
-  ui::Compositor* compositor = GetCompositor();
-  if (!compositor)
-    return;
-
-  DCHECK(layer_helper_.get());
-
-  ui::Layer* layer_parent = NULL;
-  gfx::Point offset;
-  CalculateOffsetToAncestorWithLayer(&offset, &layer_parent);
-
-  DCHECK(layer_parent || parent_ == NULL);
-
-  layer_helper_->SetLayer(new ui::Layer(compositor));
-  layer()->set_delegate(this);
-  layer()->SetFillsBoundsOpaquely(layer_helper_->fills_bounds_opaquely());
-  layer()->SetBounds(gfx::Rect(offset.x(), offset.y(), width(), height()));
-  layer()->SetTransform(GetTransform());
-  if (layer_parent)
-    layer_parent->Add(layer());
-  layer()->SchedulePaint(GetLocalBounds());
-
-  MoveLayerToParent(layer(), gfx::Point());
+  UpdateParentLayers();
 }
 
-void View::DestroyLayerAndReparent() {
+void View::UpdateParentLayers() {
+  // Attach all top-level un-parented layers.
+  if (layer() && !layer()->parent()) {
+    UpdateParentLayer();
+  } else {
+    for (int i = 0, count = child_count(); i < count; ++i)
+      child_at(i)->UpdateParentLayers();
+  }
+}
+
+void View::UpdateParentLayer() {
   if (!layer())
     return;
 
-  ui::Layer* new_parent = layer()->parent();
-  std::vector<ui::Layer*> children = layer()->children();
-  for (size_t i = 0; i < children.size(); ++i)
-    new_parent->Add(children[i]);
+  ui::Layer* parent_layer = NULL;
+  gfx::Point offset(x(), y());
+  if (parent_)
+    parent_->CalculateOffsetToAncestorWithLayer(&offset, &parent_layer);
 
-  DestroyLayer();
+  ReparentLayer(offset, parent_layer);
+}
 
-  gfx::Point offset;
-  CalculateOffsetToAncestorWithLayer(&offset, NULL);
-  offset.Offset(-x(), -y());
-  UpdateLayerBounds(offset);
+void View::ReparentLayer(const gfx::Point& offset, ui::Layer* parent_layer) {
+  layer_->SetBounds(gfx::Rect(offset.x(), offset.y(), width(), height()));
+  DCHECK_NE(layer(), parent_layer);
+  if (parent_layer)
+    parent_layer->Add(layer());
+  layer_->SchedulePaint(GetLocalBounds());
+  MoveLayerToParent(layer(), gfx::Point());
 }
 
 void View::DestroyLayer() {
-  if (!layer_helper_.get())
-    return;
+  ui::Layer* new_parent = layer()->parent();
+  std::vector<ui::Layer*> children = layer()->children();
+  for (size_t i = 0; i < children.size(); ++i) {
+    layer()->Remove(children[i]);
+    if (new_parent)
+      new_parent->Add(children[i]);
+  }
 
-  if (!layer_helper_->property_setter_explicitly_set() &&
-      !ShouldPaintToLayer() &&
-      !layer_helper_->fills_bounds_opaquely() &&
-      !layer_helper_->layer_updated_externally())
-    layer_helper_.reset();
-  else
-    layer_helper_->SetLayer(NULL);
+  if (layer_property_setter_.get())
+    layer_property_setter_->Uninstalled(layer());
+
+  layer_.reset();
+
+  gfx::Point offset;
+  CalculateOffsetToAncestorWithLayer(&offset, NULL);
+  UpdateChildLayerBounds(offset);
+
+  SchedulePaint();
 }
 
 // Input -----------------------------------------------------------------------
@@ -1891,8 +1823,8 @@
 }
 
 ui::TouchStatus View::ProcessTouchEvent(const TouchEvent& event) {
-  // TODO(rjkroege): Implement a grab scheme similar to as
-  // as is found in MousePressed.
+  // TODO(rjkroege): Implement a grab scheme similar to as as is found in
+  //                 MousePressed.
   return OnTouchEvent(event);
 }