| Index: ui/aura/window.cc
|
| diff --git a/ui/aura/window.cc b/ui/aura/window.cc
|
| index e421789684a33322112b4f43b90896f75cd0f56c..846f327d3c8e5561abfd631dec006f115f463098 100644
|
| --- a/ui/aura/window.cc
|
| +++ b/ui/aura/window.cc
|
| @@ -35,6 +35,38 @@
|
|
|
| namespace aura {
|
|
|
| +namespace {
|
| +
|
| +WindowLayerType UILayerTypeToWindowLayerType(ui::LayerType layer_type) {
|
| + switch (layer_type) {
|
| + case ui::LAYER_NOT_DRAWN:
|
| + return WINDOW_LAYER_NOT_DRAWN;
|
| + case ui::LAYER_TEXTURED:
|
| + return WINDOW_LAYER_TEXTURED;
|
| + case ui::LAYER_SOLID_COLOR:
|
| + return WINDOW_LAYER_SOLID_COLOR;
|
| + }
|
| + NOTREACHED();
|
| + return WINDOW_LAYER_NOT_DRAWN;
|
| +}
|
| +
|
| +ui::LayerType WindowLayerTypeToUILayerType(WindowLayerType window_layer_type) {
|
| + switch (window_layer_type) {
|
| + case WINDOW_LAYER_NONE:
|
| + break;
|
| + case WINDOW_LAYER_NOT_DRAWN:
|
| + return ui::LAYER_NOT_DRAWN;
|
| + case WINDOW_LAYER_TEXTURED:
|
| + return ui::LAYER_TEXTURED;
|
| + case WINDOW_LAYER_SOLID_COLOR:
|
| + return ui::LAYER_SOLID_COLOR;
|
| + }
|
| + NOTREACHED();
|
| + return ui::LAYER_NOT_DRAWN;
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| class ScopedCursorHider {
|
| public:
|
| explicit ScopedCursorHider(Window* window)
|
| @@ -154,12 +186,18 @@ Window::~Window() {
|
| }
|
|
|
| void Window::Init(ui::LayerType layer_type) {
|
| - layer_ = new ui::Layer(layer_type);
|
| - layer_owner_.reset(layer_);
|
| - layer_->SetVisible(false);
|
| - layer_->set_delegate(this);
|
| - UpdateLayerName(name_);
|
| - layer_->SetFillsBoundsOpaquely(!transparent_);
|
| + InitWithWindowLayerType(UILayerTypeToWindowLayerType(layer_type));
|
| +}
|
| +
|
| +void Window::InitWithWindowLayerType(WindowLayerType window_layer_type) {
|
| + if (window_layer_type != WINDOW_LAYER_NONE) {
|
| + layer_ = new ui::Layer(WindowLayerTypeToUILayerType(window_layer_type));
|
| + layer_owner_.reset(layer_);
|
| + layer_->SetVisible(false);
|
| + layer_->set_delegate(this);
|
| + UpdateLayerName(name_);
|
| + layer_->SetFillsBoundsOpaquely(!transparent_);
|
| + }
|
|
|
| Env::GetInstance()->NotifyWindowInitialized(this);
|
| }
|
| @@ -203,20 +241,20 @@ ui::Layer* Window::RecreateLayer() {
|
|
|
| void Window::SetType(client::WindowType type) {
|
| // Cannot change type after the window is initialized.
|
| - DCHECK(!layer());
|
| + DCHECK(!layer_);
|
| type_ = type;
|
| }
|
|
|
| void Window::SetName(const std::string& name) {
|
| name_ = name;
|
|
|
| - if (layer())
|
| + if (layer_)
|
| UpdateLayerName(name_);
|
| }
|
|
|
| void Window::SetTransparent(bool transparent) {
|
| transparent_ = transparent;
|
| - if (layer())
|
| + if (layer_)
|
| layer_->SetFillsBoundsOpaquely(!transparent_);
|
| }
|
|
|
| @@ -257,7 +295,13 @@ bool Window::IsVisible() const {
|
| // when a Window is hidden, we want this function to return false immediately
|
| // after, even though the client may decide to animate the hide effect (and
|
| // so the layer will be visible for some time after Hide() is called).
|
| - return visible_ && layer_ && layer_->IsDrawn();
|
| + for (const Window* window = this; window; window = window->parent()) {
|
| + if (!window->visible_)
|
| + return false;
|
| + if (window->layer_)
|
| + return window->layer_->IsDrawn();
|
| + }
|
| + return false;
|
| }
|
|
|
| gfx::Rect Window::GetBoundsInRootWindow() const {
|
| @@ -287,10 +331,15 @@ gfx::Rect Window::GetBoundsInScreen() const {
|
| }
|
|
|
| void Window::SetTransform(const gfx::Transform& transform) {
|
| + if (is_layerless()) {
|
| + // Transforms aren't supported on layerless windows.
|
| + NOTREACHED();
|
| + return;
|
| + }
|
| WindowEventDispatcher* dispatcher = GetDispatcher();
|
| bool contained_mouse = IsVisible() && dispatcher &&
|
| ContainsPointInRoot(dispatcher->GetLastMouseLocationInRoot());
|
| - layer()->SetTransform(transform);
|
| + layer_->SetTransform(transform);
|
| if (dispatcher)
|
| dispatcher->OnWindowTransformed(this, contained_mouse);
|
| }
|
| @@ -330,15 +379,20 @@ void Window::SetBoundsInScreen(const gfx::Rect& new_bounds_in_screen,
|
| }
|
|
|
| gfx::Rect Window::GetTargetBounds() const {
|
| - return layer_->GetTargetBounds();
|
| -}
|
| -
|
| -const gfx::Rect& Window::bounds() const {
|
| - return layer_->bounds();
|
| + // TODO(sky): this needs to be updated when there is a layerless ancestor.
|
| + return is_layerless() ? bounds() : layer_->GetTargetBounds();
|
| }
|
|
|
| void Window::SchedulePaintInRect(const gfx::Rect& rect) {
|
| - if (layer_->SchedulePaint(rect)) {
|
| + if (is_layerless() && parent_) {
|
| + // Notification of paint scheduled happens for the window with a layer.
|
| + gfx::Rect parent_rect(bounds().size());
|
| + parent_rect.Intersect(rect);
|
| + if (!parent_rect.IsEmpty()) {
|
| + parent_rect.Offset(bounds().origin().OffsetFromOrigin());
|
| + parent_->SchedulePaintInRect(parent_rect);
|
| + }
|
| + } else if (layer_ && layer_->SchedulePaint(rect)) {
|
| FOR_EACH_OBSERVER(
|
| WindowObserver, observers_, OnWindowPaintScheduled(this, rect));
|
| }
|
| @@ -378,9 +432,15 @@ void Window::AddChild(Window* child) {
|
| children_.end());
|
| if (child->parent())
|
| child->parent()->RemoveChildImpl(child, this);
|
| - child->parent_ = this;
|
|
|
| - layer_->Add(child->layer_);
|
| + gfx::Vector2d offset;
|
| + aura::Window* ancestor_with_layer = GetAncestorWithLayer(&offset);
|
| + if (ancestor_with_layer) {
|
| + offset += child->bounds().OffsetFromOrigin();
|
| + child->ReparentLayers(ancestor_with_layer->layer(), offset);
|
| + }
|
| +
|
| + child->parent_ = this;
|
|
|
| children_.push_back(child);
|
| if (layout_manager_)
|
| @@ -473,7 +533,7 @@ void Window::ConvertPointToTarget(const Window* source,
|
| client::GetScreenPositionClient(target->GetRootWindow());
|
| target_client->ConvertPointFromScreen(target, point);
|
| } else {
|
| - ui::Layer::ConvertPointToLayer(source->layer(), target->layer(), point);
|
| + ui::Layer::ConvertPointToLayer(source->layer_, target->layer_, point);
|
| }
|
| }
|
|
|
| @@ -743,13 +803,27 @@ void Window::SetBoundsInternal(const gfx::Rect& new_bounds) {
|
|
|
| // Always need to set the layer's bounds -- even if it is to the same thing.
|
| // This may cause important side effects such as stopping animation.
|
| - layer_->SetBounds(actual_new_bounds);
|
| + if (is_layerless()) {
|
| + const gfx::Vector2d origin_delta = new_bounds.OffsetFromOrigin() -
|
| + bounds_.OffsetFromOrigin();
|
| + bounds_ = new_bounds;
|
| + OffsetLayerBounds(origin_delta);
|
| + } else {
|
| + if (parent_ && parent_->is_layerless()) {
|
| + gfx::Vector2d offset;
|
| + const aura::Window* ancestor_with_layer =
|
| + parent_->GetAncestorWithLayer(&offset);
|
| + if (ancestor_with_layer)
|
| + actual_new_bounds.Offset(offset);
|
| + }
|
| + layer_->SetBounds(actual_new_bounds);
|
| + }
|
|
|
| // If we are currently not the layer's delegate, we will not get bounds
|
| // changed notification from the layer (this typically happens after animating
|
| // hidden). We must notify ourselves.
|
| - if (layer_->delegate() != this)
|
| - OnLayerBoundsChanged(old_bounds, ContainsMouse());
|
| + if (is_layerless() || layer_->delegate() != this)
|
| + OnWindowBoundsChanged(old_bounds, ContainsMouse());
|
| }
|
|
|
| void Window::SetVisible(bool visible) {
|
| @@ -854,12 +928,11 @@ void Window::RemoveChildImpl(Window* child, Window* new_parent) {
|
| child, new_root_window);
|
| child->NotifyRemovingFromRootWindow();
|
| }
|
| +
|
| + gfx::Vector2d offset;
|
| + GetAncestorWithLayer(&offset);
|
| + child->UnparentLayers(is_layerless(), offset);
|
| child->parent_ = NULL;
|
| - // We should only remove the child's layer if the child still owns that layer.
|
| - // Someone else may have acquired ownership of it via AcquireLayer() and may
|
| - // expect the hierarchy to go unchanged as the Window is destroyed.
|
| - if (child->layer_owner_)
|
| - layer_->Remove(child->layer_);
|
| Windows::iterator i = std::find(children_.begin(), children_.end(), child);
|
| DCHECK(i != children_.end());
|
| children_.erase(i);
|
| @@ -868,6 +941,60 @@ void Window::RemoveChildImpl(Window* child, Window* new_parent) {
|
| layout_manager_->OnWindowRemovedFromLayout(child);
|
| }
|
|
|
| +void Window::UnparentLayers(bool has_layerless_ancestor,
|
| + const gfx::Vector2d& offset) {
|
| + if (is_layerless()) {
|
| + const gfx::Vector2d new_offset = offset + bounds().OffsetFromOrigin();
|
| + for (size_t i = 0; i < children_.size(); ++i) {
|
| + children_[i]->UnparentLayers(true, new_offset);
|
| + }
|
| + } else {
|
| + // Only remove the layer if we still own it. Someone else may have acquired
|
| + // ownership of it via AcquireLayer() and may expect the hierarchy to go
|
| + // unchanged as the Window is destroyed.
|
| + if (layer_owner_) {
|
| + if (layer_->parent())
|
| + layer_->parent()->Remove(layer_);
|
| + if (has_layerless_ancestor) {
|
| + const gfx::Rect real_bounds(bounds_);
|
| + gfx::Rect layer_bounds(layer_->bounds());
|
| + layer_bounds.Offset(-offset);
|
| + layer_->SetBounds(layer_bounds);
|
| + bounds_ = real_bounds;
|
| + }
|
| + }
|
| + }
|
| +}
|
| +
|
| +void Window::ReparentLayers(ui::Layer* parent_layer,
|
| + const gfx::Vector2d& offset) {
|
| + if (is_layerless()) {
|
| + for (size_t i = 0; i < children_.size(); ++i) {
|
| + children_[i]->ReparentLayers(
|
| + parent_layer,
|
| + offset + children_[i]->bounds().OffsetFromOrigin());
|
| + }
|
| + } else {
|
| + const gfx::Rect real_bounds(bounds());
|
| + parent_layer->Add(layer_);
|
| + gfx::Rect layer_bounds(layer_->bounds().size());
|
| + layer_bounds += offset;
|
| + layer_->SetBounds(layer_bounds);
|
| + bounds_ = real_bounds;
|
| + }
|
| +}
|
| +
|
| +void Window::OffsetLayerBounds(const gfx::Vector2d& offset) {
|
| + if (is_layerless()) {
|
| + for (size_t i = 0; i < children_.size(); ++i)
|
| + children_[i]->OffsetLayerBounds(offset);
|
| + } else {
|
| + gfx::Rect layer_bounds(layer_->bounds());
|
| + layer_bounds += offset;
|
| + layer_->SetBounds(layer_bounds);
|
| + }
|
| +}
|
| +
|
| void Window::OnParentChanged() {
|
| FOR_EACH_OBSERVER(
|
| WindowObserver, observers_, OnWindowParentChanged(this, parent_));
|
| @@ -946,7 +1073,7 @@ void Window::StackChildRelativeTo(Window* child,
|
| // for an explanation of this.
|
| while (final_target_i > 0 &&
|
| children_[direction == STACK_ABOVE ? final_target_i :
|
| - final_target_i - 1]->layer()
|
| + final_target_i - 1]->layer_
|
| ->delegate() == NULL) {
|
| --final_target_i;
|
| }
|
| @@ -954,7 +1081,7 @@ void Window::StackChildRelativeTo(Window* child,
|
| Window* final_target = children_[final_target_i];
|
|
|
| // If we couldn't find a valid target position, don't move anything.
|
| - if (direction == STACK_ABOVE && final_target->layer()->delegate() == NULL)
|
| + if (direction == STACK_ABOVE && final_target->layer_->delegate() == NULL)
|
| return;
|
|
|
| // Don't try to stack a child above itself.
|
| @@ -1006,9 +1133,9 @@ void Window::StackChildRelativeToImpl(Window* child,
|
| children_.insert(children_.begin() + dest_i, child);
|
|
|
| if (direction == STACK_ABOVE)
|
| - layer()->StackAbove(child->layer(), target->layer());
|
| + layer_->StackAbove(child->layer_, target->layer_);
|
| else
|
| - layer()->StackBelow(child->layer(), target->layer());
|
| + layer_->StackBelow(child->layer_, target->layer_);
|
|
|
| child->OnStackingChanged();
|
| }
|
| @@ -1139,8 +1266,19 @@ void Window::NotifyWindowVisibilityChangedUp(aura::Window* target,
|
| }
|
| }
|
|
|
| -void Window::OnLayerBoundsChanged(const gfx::Rect& old_bounds,
|
| - bool contained_mouse) {
|
| +void Window::OnWindowBoundsChanged(const gfx::Rect& old_bounds,
|
| + bool contained_mouse) {
|
| + if (layer_) {
|
| + bounds_ = layer_->bounds();
|
| + if (parent_ && parent_->is_layerless()) {
|
| + gfx::Vector2d offset;
|
| + aura::Window* ancestor_with_layer =
|
| + parent_->GetAncestorWithLayer(&offset);
|
| + if (ancestor_with_layer)
|
| + bounds_.Offset(-offset);
|
| + }
|
| + }
|
| +
|
| if (layout_manager_)
|
| layout_manager_->OnWindowResized();
|
| if (delegate_)
|
| @@ -1159,7 +1297,7 @@ void Window::OnPaintLayer(gfx::Canvas* canvas) {
|
| }
|
|
|
| base::Closure Window::PrepareForLayerBoundsChange() {
|
| - return base::Bind(&Window::OnLayerBoundsChanged, base::Unretained(this),
|
| + return base::Bind(&Window::OnWindowBoundsChanged, base::Unretained(this),
|
| bounds(), ContainsMouse());
|
| }
|
|
|
| @@ -1194,7 +1332,7 @@ ui::EventTarget* Window::GetParentTarget() {
|
|
|
| void Window::UpdateLayerName(const std::string& name) {
|
| #if !defined(NDEBUG)
|
| - DCHECK(layer());
|
| + DCHECK(layer_);
|
|
|
| std::string layer_name(name_);
|
| if (layer_name.empty())
|
| @@ -1205,7 +1343,7 @@ void Window::UpdateLayerName(const std::string& name) {
|
| base::snprintf(id_buf, sizeof(id_buf), " %d", id_);
|
| layer_name.append(id_buf);
|
| }
|
| - layer()->set_name(layer_name);
|
| + layer_->set_name(layer_name);
|
| #endif
|
| }
|
|
|
| @@ -1219,4 +1357,14 @@ bool Window::ContainsMouse() {
|
| return contains_mouse;
|
| }
|
|
|
| +const Window* Window::GetAncestorWithLayer(gfx::Vector2d* offset) const {
|
| + for (const aura::Window* window = this; window; window = window->parent()) {
|
| + if (!window->is_layerless())
|
| + return window;
|
| + *offset += window->bounds().OffsetFromOrigin();
|
| + }
|
| + *offset = gfx::Vector2d();
|
| + return NULL;
|
| +}
|
| +
|
| } // namespace aura
|
|
|