Commit 88fa18e8 authored by sky@chromium.org's avatar sky@chromium.org

Initial cut at layerless windows.

This has the minimal support working. You can create layerless
windows add/remove them from a hierarchy, add children with layers and
everything is kept in sync (including bounds).

Painting has not been wired up yet.

The interesting bit of this change is that Layer and Window bounds are
no longer in sync. This is necessitated by Layer's having to be
parented to Layers. To avoid changing bounds() to dynamically figure
out the real bounds I made Window cache the bounds.

BUG=none
TEST=none
R=ben@chromium.org

Review URL: https://codereview.chromium.org/82283002

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@238408 0039d316-1c4b-4281-b951-d872f2087c98
parent 917cd320
...@@ -100,6 +100,7 @@ ...@@ -100,6 +100,7 @@
'window.cc', 'window.cc',
'window.h', 'window.h',
'window_delegate.h', 'window_delegate.h',
'window_layer_type.h',
'window_observer.h', 'window_observer.h',
'window_tracker.cc', 'window_tracker.cc',
'window_tracker.h', 'window_tracker.h',
......
This diff is collapsed.
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include "base/strings/string16.h" #include "base/strings/string16.h"
#include "ui/aura/aura_export.h" #include "ui/aura/aura_export.h"
#include "ui/aura/client/window_types.h" #include "ui/aura/client/window_types.h"
#include "ui/aura/window_layer_type.h"
#include "ui/aura/window_observer.h" #include "ui/aura/window_observer.h"
#include "ui/compositor/layer_animator.h" #include "ui/compositor/layer_animator.h"
#include "ui/compositor/layer_delegate.h" #include "ui/compositor/layer_delegate.h"
...@@ -32,6 +33,7 @@ ...@@ -32,6 +33,7 @@
namespace gfx { namespace gfx {
class Display; class Display;
class Transform; class Transform;
class Vector2d;
} }
namespace ui { namespace ui {
...@@ -74,6 +76,9 @@ class AURA_EXPORT Window : public ui::LayerDelegate, ...@@ -74,6 +76,9 @@ class AURA_EXPORT Window : public ui::LayerDelegate,
// Initializes the window. This creates the window's layer. // Initializes the window. This creates the window's layer.
void Init(ui::LayerType layer_type); void Init(ui::LayerType layer_type);
// TODO(sky): replace other Init() with this once m32 is more baked.
void InitWithWindowLayerType(WindowLayerType layer_type);
// Creates a new layer for the window. Erases the layer-owned bounds, so the // Creates a new layer for the window. Erases the layer-owned bounds, so the
// caller may wish to set new bounds and other state on the window/layer. // caller may wish to set new bounds and other state on the window/layer.
// Returns the old layer, which can be used for animations. Caller owns the // Returns the old layer, which can be used for animations. Caller owns the
...@@ -107,7 +112,7 @@ class AURA_EXPORT Window : public ui::LayerDelegate, ...@@ -107,7 +112,7 @@ class AURA_EXPORT Window : public ui::LayerDelegate,
WindowDelegate* delegate() { return delegate_; } WindowDelegate* delegate() { return delegate_; }
const WindowDelegate* delegate() const { return delegate_; } const WindowDelegate* delegate() const { return delegate_; }
const gfx::Rect& bounds() const; const gfx::Rect& bounds() const { return bounds_; }
Window* parent() { return parent_; } Window* parent() { return parent_; }
const Window* parent() const { return parent_; } const Window* parent() const { return parent_; }
...@@ -411,6 +416,22 @@ class AURA_EXPORT Window : public ui::LayerDelegate, ...@@ -411,6 +416,22 @@ class AURA_EXPORT Window : public ui::LayerDelegate,
// to. // to.
void RemoveChildImpl(Window* child, Window* new_parent); void RemoveChildImpl(Window* child, Window* new_parent);
// If this Window has a layer the layer's parent is set to NULL, otherwise
// UnparentLayers() is invoked on all the children. |offset| is the offset
// relative to the nearest ancestor with a layer.
void UnparentLayers(bool has_layerless_ancestor,
const gfx::Vector2d& offset);
// If this Window has a layer it is added to |parent| and the origin set to
// |offset|. Otherwise this recurses through the children invoking
// ReparentLayers(). The net effect is both setting the parent of layers to
// |parent| as well as updating bounds of windows with a layerless ancestor.
void ReparentLayers(ui::Layer* parent, const gfx::Vector2d& offset);
// Offsets the first encountered Windows with layers by |offset|. This
// recurses through all layerless Windows, stopping at windows with layers.
void OffsetLayerBounds(const gfx::Vector2d& offset);
// Called when this window's parent has changed. // Called when this window's parent has changed.
void OnParentChanged(); void OnParentChanged();
...@@ -473,11 +494,12 @@ class AURA_EXPORT Window : public ui::LayerDelegate, ...@@ -473,11 +494,12 @@ class AURA_EXPORT Window : public ui::LayerDelegate,
// Notifies this window and its parent hierarchy. // Notifies this window and its parent hierarchy.
void NotifyWindowVisibilityChangedUp(aura::Window* target, bool visible); void NotifyWindowVisibilityChangedUp(aura::Window* target, bool visible);
// Invoked from the closure returned by PrepareForLayerBoundsChange() after // Invoked when the bounds of the window changes. This may be invoked directly
// the bounds of the layer has changed. |old_bounds| is the previous bounds of // by us, or from the closure returned by PrepareForLayerBoundsChange() after
// the layer, and |contained_mouse| is true if the mouse was previously within // the bounds of the layer has changed. |old_bounds| is the previous bounds,
// the window's bounds. // and |contained_mouse| is true if the mouse was previously within the
void OnLayerBoundsChanged(const gfx::Rect& old_bounds, bool contained_mouse); // window's bounds.
void OnWindowBoundsChanged(const gfx::Rect& old_bounds, bool contained_mouse);
// Overridden from ui::LayerDelegate: // Overridden from ui::LayerDelegate:
virtual void OnPaintLayer(gfx::Canvas* canvas) OVERRIDE; virtual void OnPaintLayer(gfx::Canvas* canvas) OVERRIDE;
...@@ -497,6 +519,20 @@ class AURA_EXPORT Window : public ui::LayerDelegate, ...@@ -497,6 +519,20 @@ class AURA_EXPORT Window : public ui::LayerDelegate,
// Returns true if the mouse is currently within our bounds. // Returns true if the mouse is currently within our bounds.
bool ContainsMouse(); bool ContainsMouse();
// Returns the first ancestor (starting at |this|) with a layer. |offset| is
// set to the offset from |this| to the first ancestor with a layer.
Window* GetAncestorWithLayer(gfx::Vector2d* offset) {
return const_cast<Window*>(
const_cast<const Window*>(this)->GetAncestorWithLayer(offset));
}
const Window* GetAncestorWithLayer(gfx::Vector2d* offset) const;
// Bounds of this window relative to the parent. This is cached as the bounds
// of the Layer and Window are not necessarily the same. In particular bounds
// of the Layer are relative to the first ancestor with a Layer, where as this
// is relative to the parent Window.
gfx::Rect bounds_;
WindowEventDispatcher* dispatcher_; WindowEventDispatcher* dispatcher_;
client::WindowType type_; client::WindowType type_;
......
// Copyright (c) 2012 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.
#ifndef UI_AURA_WINDOW_LAYER_TYPE_H_
#define UI_AURA_WINDOW_LAYER_TYPE_H_
namespace aura {
// These constants mirror that of ui::LayerType with the addition of
// WINDOW_LAYER_NONE. See ui::LayerType for description of ones in common.
enum WindowLayerType {
// Note that Windows with WINDOW_LAYER_NONE impose limitations on the
// Window: transforms and animations aren't supported.
WINDOW_LAYER_NONE,
WINDOW_LAYER_NOT_DRAWN,
WINDOW_LAYER_TEXTURED,
WINDOW_LAYER_SOLID_COLOR,
};
} // namespace aura
#endif // UI_AURA_WINDOW_LAYER_TYPE_H_
...@@ -40,6 +40,7 @@ ...@@ -40,6 +40,7 @@
#include "ui/events/keycodes/keyboard_codes.h" #include "ui/events/keycodes/keyboard_codes.h"
#include "ui/gfx/canvas.h" #include "ui/gfx/canvas.h"
#include "ui/gfx/screen.h" #include "ui/gfx/screen.h"
#include "ui/gfx/skia_util.h"
DECLARE_WINDOW_PROPERTY_TYPE(const char*) DECLARE_WINDOW_PROPERTY_TYPE(const char*)
DECLARE_WINDOW_PROPERTY_TYPE(int) DECLARE_WINDOW_PROPERTY_TYPE(int)
...@@ -2879,7 +2880,7 @@ TEST_F(WindowTest, DelegateNotifiedAsBoundsChangeInHiddenLayer) { ...@@ -2879,7 +2880,7 @@ TEST_F(WindowTest, DelegateNotifiedAsBoundsChangeInHiddenLayer) {
// No bounds changed notification at the end of animation since layer // No bounds changed notification at the end of animation since layer
// delegate is NULL. // delegate is NULL.
EXPECT_FALSE(delegate.bounds_changed()); EXPECT_FALSE(delegate.bounds_changed());
EXPECT_NE("0,0 100x100", window->bounds().ToString()); EXPECT_NE("0,0 100x100", window->layer()->bounds().ToString());
} }
namespace { namespace {
...@@ -3185,5 +3186,185 @@ TEST_F(WindowTest, NotifyDelegateAfterDeletingTransients) { ...@@ -3185,5 +3186,185 @@ TEST_F(WindowTest, NotifyDelegateAfterDeletingTransients) {
EXPECT_EQ("parent", destruction_order[1]); EXPECT_EQ("parent", destruction_order[1]);
} }
// Verifies SchedulePaint() on a layerless window results in damaging the right
// thing.
TEST_F(WindowTest, LayerlessWindowSchedulePaint) {
Window root(NULL);
root.Init(ui::LAYER_NOT_DRAWN);
root.SetBounds(gfx::Rect(0, 0, 100, 100));
Window* layerless_window = new Window(NULL); // Owned by |root|.
layerless_window->InitWithWindowLayerType(WINDOW_LAYER_NONE);
layerless_window->SetBounds(gfx::Rect(10, 11, 12, 13));
root.AddChild(layerless_window);
root.layer()->SendDamagedRects();
layerless_window->SchedulePaintInRect(gfx::Rect(1, 2, 100, 4));
// Note the the region is clipped by the parent hence 100 going to 11.
EXPECT_EQ("11,13 11x4",
gfx::SkIRectToRect(root.layer()->damaged_region().getBounds()).
ToString());
Window* layerless_window2 = new Window(NULL); // Owned by |layerless_window|.
layerless_window2->InitWithWindowLayerType(WINDOW_LAYER_NONE);
layerless_window2->SetBounds(gfx::Rect(1, 2, 3, 4));
layerless_window->AddChild(layerless_window2);
root.layer()->SendDamagedRects();
layerless_window2->SchedulePaintInRect(gfx::Rect(1, 2, 100, 4));
// Note the the region is clipped by the |layerless_window| hence 100 going to
// 2.
EXPECT_EQ("12,15 2x2",
gfx::SkIRectToRect(root.layer()->damaged_region().getBounds()).
ToString());
}
// Verifies bounds of layerless windows are correctly updated when adding
// removing.
TEST_F(WindowTest, NestedLayerlessWindowsBoundsOnAddRemove) {
// Creates the following structure (all children owned by root):
// root
// w1ll 1,2
// w11ll 3,4
// w111 5,6
// w12 7,8
// w121 9,10
//
// ll: layer less, eg no layer
Window root(NULL);
root.InitWithWindowLayerType(WINDOW_LAYER_NOT_DRAWN);
root.SetBounds(gfx::Rect(0, 0, 100, 100));
Window* w1ll = new Window(NULL);
w1ll->InitWithWindowLayerType(WINDOW_LAYER_NONE);
w1ll->SetBounds(gfx::Rect(1, 2, 100, 100));
Window* w11ll = new Window(NULL);
w11ll->InitWithWindowLayerType(WINDOW_LAYER_NONE);
w11ll->SetBounds(gfx::Rect(3, 4, 100, 100));
w1ll->AddChild(w11ll);
Window* w111 = new Window(NULL);
w111->InitWithWindowLayerType(WINDOW_LAYER_NOT_DRAWN);
w111->SetBounds(gfx::Rect(5, 6, 100, 100));
w11ll->AddChild(w111);
Window* w12 = new Window(NULL);
w12->InitWithWindowLayerType(WINDOW_LAYER_NOT_DRAWN);
w12->SetBounds(gfx::Rect(7, 8, 100, 100));
w1ll->AddChild(w12);
Window* w121 = new Window(NULL);
w121->InitWithWindowLayerType(WINDOW_LAYER_NOT_DRAWN);
w121->SetBounds(gfx::Rect(9, 10, 100, 100));
w12->AddChild(w121);
root.AddChild(w1ll);
// All layers should be parented to the root.
EXPECT_EQ(root.layer(), w111->layer()->parent());
EXPECT_EQ(root.layer(), w12->layer()->parent());
EXPECT_EQ(w12->layer(), w121->layer()->parent());
// Ensure bounds are what we expect.
EXPECT_EQ("1,2 100x100", w1ll->bounds().ToString());
EXPECT_EQ("3,4 100x100", w11ll->bounds().ToString());
EXPECT_EQ("5,6 100x100", w111->bounds().ToString());
EXPECT_EQ("7,8 100x100", w12->bounds().ToString());
EXPECT_EQ("9,10 100x100", w121->bounds().ToString());
// Bounds of layers are relative to the nearest ancestor with a layer.
EXPECT_EQ("8,10 100x100", w12->layer()->bounds().ToString());
EXPECT_EQ("9,12 100x100", w111->layer()->bounds().ToString());
EXPECT_EQ("9,10 100x100", w121->layer()->bounds().ToString());
// Remove and repeat.
root.RemoveChild(w1ll);
EXPECT_TRUE(w111->layer()->parent() == NULL);
EXPECT_TRUE(w12->layer()->parent() == NULL);
// Verify bounds haven't changed again.
EXPECT_EQ("1,2 100x100", w1ll->bounds().ToString());
EXPECT_EQ("3,4 100x100", w11ll->bounds().ToString());
EXPECT_EQ("5,6 100x100", w111->bounds().ToString());
EXPECT_EQ("7,8 100x100", w12->bounds().ToString());
EXPECT_EQ("9,10 100x100", w121->bounds().ToString());
// Bounds of layers should now match that of windows.
EXPECT_EQ("7,8 100x100", w12->layer()->bounds().ToString());
EXPECT_EQ("5,6 100x100", w111->layer()->bounds().ToString());
EXPECT_EQ("9,10 100x100", w121->layer()->bounds().ToString());
delete w1ll;
}
// Verifies bounds of layerless windows are correctly updated when bounds
// of ancestor changes.
TEST_F(WindowTest, NestedLayerlessWindowsBoundsOnSetBounds) {
// Creates the following structure (all children owned by root):
// root
// w1ll 1,2
// w11ll 3,4
// w111 5,6
// w12 7,8
// w121 9,10
//
// ll: layer less, eg no layer
Window root(NULL);
root.InitWithWindowLayerType(WINDOW_LAYER_NOT_DRAWN);
root.SetBounds(gfx::Rect(0, 0, 100, 100));
Window* w1ll = new Window(NULL);
w1ll->InitWithWindowLayerType(WINDOW_LAYER_NONE);
w1ll->SetBounds(gfx::Rect(1, 2, 100, 100));
Window* w11ll = new Window(NULL);
w11ll->InitWithWindowLayerType(WINDOW_LAYER_NONE);
w11ll->SetBounds(gfx::Rect(3, 4, 100, 100));
w1ll->AddChild(w11ll);
Window* w111 = new Window(NULL);
w111->InitWithWindowLayerType(WINDOW_LAYER_NOT_DRAWN);
w111->SetBounds(gfx::Rect(5, 6, 100, 100));
w11ll->AddChild(w111);
Window* w12 = new Window(NULL);
w12->InitWithWindowLayerType(WINDOW_LAYER_NOT_DRAWN);
w12->SetBounds(gfx::Rect(7, 8, 100, 100));
w1ll->AddChild(w12);
Window* w121 = new Window(NULL);
w121->InitWithWindowLayerType(WINDOW_LAYER_NOT_DRAWN);
w121->SetBounds(gfx::Rect(9, 10, 100, 100));
w12->AddChild(w121);
root.AddChild(w1ll);
w111->SetBounds(gfx::Rect(7, 8, 11, 12));
EXPECT_EQ("7,8 11x12", w111->bounds().ToString());
EXPECT_EQ("11,14 11x12", w111->layer()->bounds().ToString());
// Set back.
w111->SetBounds(gfx::Rect(5, 6, 100, 100));
EXPECT_EQ("5,6 100x100", w111->bounds().ToString());
EXPECT_EQ("9,12 100x100", w111->layer()->bounds().ToString());
// Setting the bounds of a layerless window needs to adjust the bounds of
// layered children.
w11ll->SetBounds(gfx::Rect(5, 6, 100, 100));
EXPECT_EQ("5,6 100x100", w11ll->bounds().ToString());
EXPECT_EQ("5,6 100x100", w111->bounds().ToString());
EXPECT_EQ("11,14 100x100", w111->layer()->bounds().ToString());
root.RemoveChild(w1ll);
w111->SetBounds(gfx::Rect(7, 8, 11, 12));
EXPECT_EQ("7,8 11x12", w111->bounds().ToString());
EXPECT_EQ("7,8 11x12", w111->layer()->bounds().ToString());
delete w1ll;
}
} // namespace test } // namespace test
} // namespace aura } // namespace aura
...@@ -287,6 +287,8 @@ class COMPOSITOR_EXPORT Layer ...@@ -287,6 +287,8 @@ class COMPOSITOR_EXPORT Layer
// |compostior_| to repaint the content. // |compostior_| to repaint the content.
void SendDamagedRects(); void SendDamagedRects();
const SkRegion& damaged_region() const { return damaged_region_; }
// Suppresses painting the content by disgarding damaged region and ignoring // Suppresses painting the content by disgarding damaged region and ignoring
// new paint requests. // new paint requests.
void SuppressPaint(); void SuppressPaint();
......
...@@ -5,10 +5,10 @@ ...@@ -5,10 +5,10 @@
#ifndef UI_VIEWS_FOCUS_BORDER_H_ #ifndef UI_VIEWS_FOCUS_BORDER_H_
#define UI_VIEWS_FOCUS_BORDER_H_ #define UI_VIEWS_FOCUS_BORDER_H_
#include "base/basictypes.h"
#include "third_party/skia/include/core/SkColor.h" #include "third_party/skia/include/core/SkColor.h"
#include "ui/gfx/insets.h" #include "ui/gfx/insets.h"
#include "ui/views/views_export.h" #include "ui/views/views_export.h"
#include "base/basictypes.h"
namespace gfx { namespace gfx {
class Canvas; class Canvas;
......
...@@ -1110,12 +1110,11 @@ class VIEWS_EXPORT View : public ui::LayerDelegate, ...@@ -1110,12 +1110,11 @@ class VIEWS_EXPORT View : public ui::LayerDelegate,
// recurses through all children. This is used when adding a layer to an // recurses through all children. This is used when adding a layer to an
// existing view to make sure all descendants that have layers are parented to // existing view to make sure all descendants that have layers are parented to
// the right layer. // the right layer.
virtual void MoveLayerToParent(ui::Layer* parent_layer, void MoveLayerToParent(ui::Layer* parent_layer, const gfx::Point& point);
const gfx::Point& point);
// Called to update the bounds of any child layers within this View's // Called to update the bounds of any child layers within this View's
// hierarchy when something happens to the hierarchy. // hierarchy when something happens to the hierarchy.
virtual void UpdateChildLayerBounds(const gfx::Vector2d& offset); void UpdateChildLayerBounds(const gfx::Vector2d& offset);
// Overridden from ui::LayerDelegate: // Overridden from ui::LayerDelegate:
virtual void OnPaintLayer(gfx::Canvas* canvas) OVERRIDE; virtual void OnPaintLayer(gfx::Canvas* canvas) OVERRIDE;
......
...@@ -343,11 +343,11 @@ ...@@ -343,11 +343,11 @@
'touchui/touch_selection_controller_impl.h', 'touchui/touch_selection_controller_impl.h',
'view.cc', 'view.cc',
'view.h', 'view.h',
'view_aura.cc',
'view_constants.cc', 'view_constants.cc',
'view_constants.h', 'view_constants.h',
'view_constants_aura.cc', 'view_constants_aura.cc',
'view_constants_aura.h', 'view_constants_aura.h',
'view_aura.cc',
'view_model.cc', 'view_model.cc',
'view_model.h', 'view_model.h',
'view_model_utils.cc', 'view_model_utils.cc',
......
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