Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(66)

Unified Diff: ui/aura/window.cc

Issue 82283002: Initial cut at layerless windows. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: tweaks Created 7 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: ui/aura/window.cc
diff --git a/ui/aura/window.cc b/ui/aura/window.cc
index e421789684a33322112b4f43b90896f75cd0f56c..d39a54329cbb7e9c7420997bb0ba320c96945bbe 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)
@@ -77,7 +109,8 @@ class ScopedCursorHider {
};
Window::Window(WindowDelegate* delegate)
- : dispatcher_(NULL),
+ : window_layer_type_(WINDOW_LAYER_NOT_DRAWN),
+ dispatcher_(NULL),
type_(client::WINDOW_TYPE_UNKNOWN),
owned_by_parent_(true),
delegate_(delegate),
@@ -154,12 +187,20 @@ 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) {
+ window_layer_type_ = 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 +244,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 +298,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 +334,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 +382,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 +435,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 +536,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 +806,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 +931,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 +944,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 {
+ // We should only remove the child's layer if the child still owns that
Ben Goodger (Google) 2013/11/22 05:49:24 use of the term "child" here is confusing. // We
sky 2013/11/22 20:20:12 Ya, sorry, I copied this comment from 858 old wher
+ // 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 (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 +1076,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 +1084,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 +1136,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 +1269,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 +1300,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 +1335,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 +1346,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 +1360,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
« ui/aura/window.h ('K') | « ui/aura/window.h ('k') | ui/aura/window_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698