Commit a54e65be authored by derat@chromium.org's avatar derat@chromium.org

aura: Draw drop shadows under browsers and menus.

This is largely a port of the existing X window manager's
code for drawing shadows around windows.  It adds an
ImageGrid class for drawing a scaled 3x3 grid of gfx::Images
and a Shadow class (managed by aura_shell::ShadowController)
that uses ImageGrid to draw a shadow.  Shadows can be
disabled via --aura-no-shadows.

BUG=101977
TEST=added unit tests; also manually checked that shadows get drawn

Review URL: http://codereview.chromium.org/8555025

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@111009 0039d316-1c4b-4281-b951-d872f2087c98
parent 844b1008
......@@ -13,6 +13,9 @@
#include "third_party/skia/include/core/SkCanvas.h"
#include "third_party/skia/include/core/SkColor.h"
#include "ui/aura/aura_switches.h"
#include "ui/aura/client/aura_constants.h"
#include "ui/aura/client/shadow_types.h"
#include "ui/aura/window.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/base/theme_provider.h"
#include "ui/gfx/canvas.h"
......@@ -169,6 +172,9 @@ BrowserFrameAura::BrowserFrameAura(BrowserFrame* browser_frame,
browser_view_->layer()->SetFillsBoundsOpaquely(false);
// Background only needed for Aura-style windows.
browser_view_->set_background(new ToolbarBackground(browser_view));
} else {
GetNativeWindow()->SetIntProperty(aura::kShadowTypeKey,
aura::SHADOW_TYPE_RECTANGULAR);
}
}
......
......@@ -8,6 +8,10 @@ namespace switches {
// Initial dimensions for the host window in the form "1024x768".
const char kAuraHostWindowSize[] = "aura-host-window-size";
// Avoid drawing drop shadows under windows.
const char kAuraNoShadows[] = "aura-no-shadows";
// Use Aura-style window frames and drag behavior.
const char kAuraWindows[] = "aura-windows";
......
......@@ -11,6 +11,7 @@
namespace switches {
AURA_EXPORT extern const char kAuraHostWindowSize[];
AURA_EXPORT extern const char kAuraNoShadows[];
AURA_EXPORT extern const char kAuraWindows[];
} // namespace switches
......
......@@ -7,11 +7,12 @@
namespace aura {
const char kAlwaysOnTopKey[] = "AlwaysOnTop";
const char kRestoreBoundsKey[] = "RestoreBoundsKey";
const char kShowStateKey[] = "ShowStateKey";
const char kTooltipTextKey[] = "TooltipTextKey";
const char kModalKey[] = "ModalKey";
const char kDesktopDragDropClientKey[] = "DesktopDragDropClientKey";
const char kDragDropDelegateKey[] = "DragDropDelegateKey";
const char kRestoreBoundsKey[] = "RestoreBounds";
const char kShowStateKey[] = "ShowState";
const char kTooltipTextKey[] = "TooltipText";
const char kModalKey[] = "Modal";
const char kShadowTypeKey[] = "ShadowType";
const char kDesktopDragDropClientKey[] = "DesktopDragDropClient";
const char kDragDropDelegateKey[] = "DragDropDelegate";
} // namespace aura
......@@ -29,6 +29,10 @@ AURA_EXPORT extern const char kTooltipTextKey[];
// A property key to store the boolean property of window modality.
AURA_EXPORT extern const char kModalKey[];
// A property key for a value from aura::ShadowType describing the drop shadow
// that should be displayed under the window. If unset, no shadow is displayed.
AURA_EXPORT extern const char kShadowTypeKey[];
// A property key to store the drag and drop client for the desktop. The type of
// the value is |aura::DragDropClient*|.
AURA_EXPORT extern const char kDesktopDragDropClientKey[];
......
// Copyright (c) 2011 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_CLIENT_SHADOW_TYPES_H_
#define UI_AURA_CLIENT_SHADOW_TYPES_H_
#pragma once
namespace aura {
// Different types of drop shadows that can be drawn under a window by the
// shell. Used as a value for the kShadowTypeKey property.
enum AURA_EXPORT ShadowType {
SHADOW_TYPE_NONE = 0,
SHADOW_TYPE_RECTANGULAR,
};
} // namespace aura
#endif // UI_AURA_CLIENT_SHADOW_TYPES_H_
......@@ -382,6 +382,10 @@ void Desktop::Deactivate(Window* window) {
SetActiveWindow(to_activate, NULL);
}
void Desktop::WindowInitialized(Window* window) {
FOR_EACH_OBSERVER(DesktopObserver, observers_, OnWindowInitialized(window));
}
void Desktop::WindowDestroying(Window* window) {
// Update the focused window state if the window was focused.
if (focused_window_ == window)
......
......@@ -109,6 +109,9 @@ class AURA_EXPORT Desktop : public ui::CompositorDelegate,
// activate.
void Deactivate(Window* window);
// Invoked when |window| is initialized.
void WindowInitialized(Window* window);
// Invoked when |window| is being destroyed.
void WindowDestroying(Window* window);
......
......@@ -21,6 +21,9 @@ class AURA_EXPORT DesktopObserver {
// Invoked after the desktop is resized.
virtual void OnDesktopResized(const gfx::Size& new_size) {}
// Invoked when a new window is initialized.
virtual void OnWindowInitialized(Window* window) {}
// Invoked when the active window is changed. |active| may be NULL if there is
// not active window.
virtual void OnActiveWindowChanged(Window* active) {}
......
......@@ -78,6 +78,7 @@ void Window::Init(ui::Layer::LayerType layer_type) {
layer_.reset(new ui::Layer(layer_type));
layer_->SetVisible(false);
layer_->set_delegate(this);
#if !defined(NDEBUG)
std::string layer_name(name_);
if (layer_name.empty())
......@@ -90,6 +91,8 @@ void Window::Init(ui::Layer::LayerType layer_type) {
}
layer_->set_name(layer_name);
#endif
Desktop::GetInstance()->WindowInitialized(this);
}
void Window::SetType(WindowType type) {
......@@ -218,6 +221,8 @@ void Window::MoveChildAbove(Window* child, Window* other) {
last_transient = transient_child;
}
}
child->OnStackingChanged();
}
bool Window::CanActivate() const {
......@@ -230,11 +235,14 @@ void Window::AddChild(Window* child) {
if (child->parent())
child->parent()->RemoveChild(child);
child->parent_ = this;
layer_->Add(child->layer_.get());
children_.push_back(child);
if (layout_manager_.get())
layout_manager_->OnWindowAddedToLayout(child);
FOR_EACH_OBSERVER(WindowObserver, observers_, OnWindowAdded(child));
child->OnParentChanged();
}
void Window::AddTransientChild(Window* child) {
......@@ -267,6 +275,7 @@ void Window::RemoveChild(Window* child) {
desktop->WindowDetachedFromDesktop(child);
layer_->Remove(child->layer_.get());
children_.erase(i);
child->OnParentChanged();
}
Window* Window::GetChildById(int id) {
......@@ -450,6 +459,9 @@ void Window::SetBoundsInternal(const gfx::Rect& new_bounds) {
layout_manager_->OnWindowResized();
if (delegate_)
delegate_->OnBoundsChanged(old_bounds, actual_new_bounds);
FOR_EACH_OBSERVER(WindowObserver,
observers_,
OnWindowBoundsChanged(this, actual_new_bounds));
}
void Window::SetVisible(bool visible) {
......@@ -464,6 +476,7 @@ void Window::SetVisible(bool visible) {
if (delegate_)
delegate_->OnWindowVisibilityChanged(is_visible);
}
if (parent_ && parent_->layout_manager_.get())
parent_->layout_manager_->OnChildWindowVisibilityChanged(this, visible);
FOR_EACH_OBSERVER(WindowObserver, observers_,
......@@ -512,6 +525,15 @@ Window* Window::GetWindowForPoint(const gfx::Point& local_point,
return delegate_ ? this : NULL;
}
void Window::OnParentChanged() {
FOR_EACH_OBSERVER(
WindowObserver, observers_, OnWindowParentChanged(this, parent_));
}
void Window::OnStackingChanged() {
FOR_EACH_OBSERVER(WindowObserver, observers_, OnWindowStackingChanged(this));
}
void Window::OnPaintLayer(gfx::Canvas* canvas) {
if (delegate_)
delegate_->OnPaint(canvas);
......
......@@ -288,6 +288,12 @@ class AURA_EXPORT Window : public ui::LayerDelegate {
bool return_tightest,
bool for_event_handling);
// Called when this window's parent has changed.
void OnParentChanged();
// Called when this window's stacking order among its siblings is changed.
void OnStackingChanged();
// Overridden from ui::LayerDelegate:
virtual void OnPaintLayer(gfx::Canvas* canvas) OVERRIDE;
......
......@@ -8,27 +8,42 @@
#include "ui/aura/aura_export.h"
namespace gfx {
class Rect;
} // namespace gfx
namespace aura {
class Window;
class AURA_EXPORT WindowObserver {
public:
// Invoked when the Window |new_window| has been added.
// Invoked when |new_window| has been added as a child of this window.
virtual void OnWindowAdded(Window* new_window) {}
// Invoked prior to removing |window|.
// Invoked prior to removing |window| as a child of this window.
virtual void OnWillRemoveWindow(Window* window) {}
// Invoked when |SetProperty| or |SetIntProperty| is called on |window|.
// Invoked when this window's parent window changes. |parent| may be NULL.
virtual void OnWindowParentChanged(Window* window, Window* parent) {}
// Invoked when SetProperty() or SetIntProperty() is called on |window|.
// |old| is the old property value.
virtual void OnPropertyChanged(Window* window, const char* key, void* old) {}
// Invoked when the SetVisible() is invoked on a window. |visible| is the
// Invoked when SetVisible() is invoked on a window. |visible| is the
// value supplied to SetVisible(). If |visible| is true, window->IsVisible()
// may still return false. See description in Window::IsVisible() for details.
virtual void OnWindowVisibilityChanged(Window* window, bool visible) {}
// Invoked when SetBounds() is invoked on |window|. |bounds| contains the
// window's new bounds.
virtual void OnWindowBoundsChanged(Window* window, const gfx::Rect& bounds) {}
// Invoked when |window|'s position among its siblings in the stacking order
// has changed.
virtual void OnWindowStackingChanged(Window* window) {}
// Invoked when the Window has been destroyed (i.e. from its destructor).
virtual void OnWindowDestroyed(Window* window) {}
......
......@@ -49,6 +49,8 @@
'drag_drop_controller.h',
'drag_image_view.cc',
'drag_image_view.h',
'image_grid.cc',
'image_grid.h',
'launcher/app_launcher_button.cc',
'launcher/app_launcher_button.h',
'launcher/launcher.cc',
......@@ -72,6 +74,10 @@
'modality_event_filter_delegate.h',
'property_util.cc',
'property_util.h',
'shadow.cc',
'shadow.h',
'shadow_controller.cc',
'shadow_controller.h',
'shelf_layout_controller.cc',
'shelf_layout_controller.h',
'shell.cc',
......@@ -129,11 +135,13 @@
'default_container_layout_manager_unittest.cc',
'desktop_event_filter_unittest.cc',
'drag_drop_controller_unittest.cc',
'image_grid_unittest.cc',
'launcher/launcher_model_unittest.cc',
'launcher/view_model_unittest.cc',
'launcher/view_model_utils_unittest.cc',
'modal_container_layout_manager_unittest.cc',
'run_all_unittests.cc',
'shadow_controller_unittest.cc',
'shell_unittest.cc',
'stacking_controller_unittest.cc',
'test_suite.cc',
......
......@@ -47,7 +47,7 @@ void DesktopLayoutManager::OnWillRemoveWindowFromLayout(aura::Window* child) {
}
void DesktopLayoutManager::OnChildWindowVisibilityChanged(aura::Window* child,
bool visibile) {
bool visible) {
}
void DesktopLayoutManager::SetChildBounds(aura::Window* child,
......
......@@ -43,7 +43,7 @@ class DesktopLayoutManager : public aura::LayoutManager {
virtual void OnWindowAddedToLayout(aura::Window* child) OVERRIDE;
virtual void OnWillRemoveWindowFromLayout(aura::Window* child) OVERRIDE;
virtual void OnChildWindowVisibilityChanged(aura::Window* child,
bool visibile) OVERRIDE;
bool visible) OVERRIDE;
virtual void SetChildBounds(aura::Window* child,
const gfx::Rect& requested_bounds) OVERRIDE;
......
// Copyright (c) 2011 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.
#include "ui/aura_shell/image_grid.h"
#include <algorithm>
#include "ui/gfx/canvas.h"
#include "ui/gfx/image/image.h"
#include "ui/gfx/transform.h"
#include "third_party/skia/include/core/SkColor.h"
#include "third_party/skia/include/core/SkXfermode.h"
using std::max;
namespace aura_shell {
namespace internal {
gfx::Rect ImageGrid::TestAPI::GetTransformedLayerBounds(
const ui::Layer& layer) {
gfx::Rect bounds = layer.bounds();
layer.transform().TransformRect(&bounds);
return bounds;
}
ImageGrid::ImageGrid()
: top_image_height_(0),
bottom_image_height_(0),
left_image_width_(0),
right_image_width_(0),
top_row_height_(0),
bottom_row_height_(0),
left_column_width_(0),
right_column_width_(0) {
}
ImageGrid::~ImageGrid() {
}
void ImageGrid::Init(const gfx::Image* top_left_image,
const gfx::Image* top_image,
const gfx::Image* top_right_image,
const gfx::Image* left_image,
const gfx::Image* center_image,
const gfx::Image* right_image,
const gfx::Image* bottom_left_image,
const gfx::Image* bottom_image,
const gfx::Image* bottom_right_image) {
layer_.reset(new ui::Layer(ui::Layer::LAYER_HAS_NO_TEXTURE));
InitImage(top_left_image, &top_left_layer_, &top_left_painter_);
InitImage(top_image, &top_layer_, &top_painter_);
InitImage(top_right_image, &top_right_layer_, &top_right_painter_);
InitImage(left_image, &left_layer_, &left_painter_);
InitImage(center_image, &center_layer_, &center_painter_);
InitImage(right_image, &right_layer_, &right_painter_);
InitImage(bottom_left_image, &bottom_left_layer_, &bottom_left_painter_);
InitImage(bottom_image, &bottom_layer_, &bottom_painter_);
InitImage(bottom_right_image, &bottom_right_layer_, &bottom_right_painter_);
top_image_height_ = GetImageSize(top_image).height();
bottom_image_height_ = GetImageSize(bottom_image).height();
left_image_width_ = GetImageSize(left_image).width();
right_image_width_ = GetImageSize(right_image).width();
top_row_height_ = max(GetImageSize(top_left_image).height(),
max(GetImageSize(top_image).height(),
GetImageSize(top_right_image).height()));
bottom_row_height_ = max(GetImageSize(bottom_left_image).height(),
max(GetImageSize(bottom_image).height(),
GetImageSize(bottom_right_image).height()));
left_column_width_ = max(GetImageSize(top_left_image).width(),
max(GetImageSize(left_image).width(),
GetImageSize(bottom_left_image).width()));
right_column_width_ = max(GetImageSize(top_right_image).width(),
max(GetImageSize(right_image).width(),
GetImageSize(bottom_right_image).width()));
}
void ImageGrid::SetSize(const gfx::Size& size) {
if (size_ == size)
return;
size_ = size;
gfx::Rect updated_bounds = layer_->bounds();
updated_bounds.set_size(size);
layer_->SetBounds(updated_bounds);
float center_width = size.width() - left_column_width_ - right_column_width_;
float center_height = size.height() - top_row_height_ - bottom_row_height_;
if (top_layer_.get()) {
ui::Transform transform;
transform.SetScaleX(center_width / top_layer_->bounds().width());
transform.ConcatTranslate(left_column_width_, 0);
top_layer_->SetTransform(transform);
}
if (bottom_layer_.get()) {
ui::Transform transform;
transform.SetScaleX(center_width / bottom_layer_->bounds().width());
transform.ConcatTranslate(
left_column_width_, size.height() - bottom_layer_->bounds().height());
bottom_layer_->SetTransform(transform);
}
if (left_layer_.get()) {
ui::Transform transform;
transform.SetScaleY(center_height / left_layer_->bounds().height());
transform.ConcatTranslate(0, top_row_height_);
left_layer_->SetTransform(transform);
}
if (right_layer_.get()) {
ui::Transform transform;
transform.SetScaleY(center_height / right_layer_->bounds().height());
transform.ConcatTranslate(
size.width() - right_layer_->bounds().width(), top_row_height_);
right_layer_->SetTransform(transform);
}
if (top_left_layer_.get()) {
// No transformation needed; it should be at (0, 0) and unscaled.
}
if (top_right_layer_.get()) {
ui::Transform transform;
transform.SetTranslateX(size.width() - top_right_layer_->bounds().width());
top_right_layer_->SetTransform(transform);
}
if (bottom_left_layer_.get()) {
ui::Transform transform;
transform.SetTranslateY(
size.height() - bottom_left_layer_->bounds().height());
bottom_left_layer_->SetTransform(transform);
}
if (bottom_right_layer_.get()) {
ui::Transform transform;
transform.SetTranslate(
size.width() - bottom_right_layer_->bounds().width(),
size.height() - bottom_right_layer_->bounds().height());
bottom_right_layer_->SetTransform(transform);
}
if (center_layer_.get()) {
ui::Transform transform;
transform.SetScale(center_width / center_layer_->bounds().width(),
center_height / center_layer_->bounds().height());
transform.ConcatTranslate(left_column_width_, top_row_height_);
center_layer_->SetTransform(transform);
}
}
void ImageGrid::ImagePainter::OnPaintLayer(gfx::Canvas* canvas) {
canvas->DrawBitmapInt(*(image_->ToSkBitmap()), 0, 0);
}
// static
gfx::Size ImageGrid::GetImageSize(const gfx::Image* image) {
return image ?
gfx::Size(image->ToSkBitmap()->width(), image->ToSkBitmap()->height()) :
gfx::Size();
}
void ImageGrid::InitImage(const gfx::Image* image,
scoped_ptr<ui::Layer>* layer_ptr,
scoped_ptr<ImagePainter>* painter_ptr) {
if (!image)
return;
layer_ptr->reset(new ui::Layer(ui::Layer::LAYER_HAS_TEXTURE));
const gfx::Size size = GetImageSize(image);
layer_ptr->get()->SetBounds(gfx::Rect(0, 0, size.width(), size.height()));
painter_ptr->reset(new ImagePainter(image));
layer_ptr->get()->set_delegate(painter_ptr->get());
layer_ptr->get()->SetFillsBoundsOpaquely(false);
layer_ptr->get()->SetVisible(true);
layer_->Add(layer_ptr->get());
}
} // namespace internal
} // namespace aura_shell
// Copyright (c) 2011 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_SHELL_IMAGE_GRID_H_
#define UI_AURA_SHELL_IMAGE_GRID_H_
#pragma once
#include "base/basictypes.h"
#include "base/gtest_prod_util.h"
#include "base/memory/scoped_ptr.h"
#include "ui/gfx/compositor/layer.h"
#include "ui/gfx/compositor/layer_delegate.h"
#include "ui/gfx/rect.h"
#include "ui/gfx/size.h"
namespace gfx {
class Image;
} // namespace gfx
namespace aura_shell {
namespace internal {
// An ImageGrid is a 3x3 array of ui::Layers, each containing an image.
//
// As the grid is resized, its images fill the requested space:
// - corner images are not scaled
// - top and bottom images are scaled horizontally
// - left and right images are scaled vertically
// - the center image is scaled in both directions
//
// If one of the non-center images is smaller than the largest images in its
// row or column, it will be aligned with the outside of the grid. For
// example, given 4x4 top-left and top-right images and a 1x2 top images:
//
// +--------+---------------------+--------+
// | | top | |
// | top- +---------------------+ top- +
// | left | | right |
// +----+---+ +---+----+
// | | | |
// ...
//
// This may seem odd at first, but it lets ImageGrid be used to draw shadows
// with curved corners that extend inwards beyond a window's borders. In the
// below example, the top-left corner image is overlaid on top of the window's
// top-left corner:
//
// +---------+-----------------------
// | ..xxx|XXXXXXXXXXXXXXXXXX
// | .xXXXXX|XXXXXXXXXXXXXXXXXX_____
// | .xXX | ^ window's top edge
// | .xXX |
// +---------+
// | xXX|
// | xXX|< window's left edge
// | xXX|
// ...
//
class ImageGrid {
public:
// Helper class for use by tests.
class TestAPI {
public:
TestAPI(ImageGrid* grid) : grid_(grid) {}
ui::Layer* top_left_layer() const { return grid_->top_left_layer_.get(); }
ui::Layer* top_layer() const { return grid_->top_layer_.get(); }
ui::Layer* top_right_layer() const { return grid_->top_right_layer_.get(); }
ui::Layer* left_layer() const { return grid_->left_layer_.get(); }
ui::Layer* center_layer() const { return grid_->center_layer_.get(); }
ui::Layer* right_layer() const { return grid_->right_layer_.get(); }
ui::Layer* bottom_left_layer() const {
return grid_->bottom_left_layer_.get();
}
ui::Layer* bottom_layer() const { return grid_->bottom_layer_.get(); }
ui::Layer* bottom_right_layer() const {
return grid_->bottom_right_layer_.get();
}
// Returns |layer|'s bounds after applying the layer's current transform.
gfx::Rect GetTransformedLayerBounds(const ui::Layer& layer);
private:
ImageGrid* grid_; // not owned
DISALLOW_COPY_AND_ASSIGN(TestAPI);
};
ImageGrid();
~ImageGrid();
ui::Layer* layer() { return layer_.get(); }
int top_image_height() const { return top_image_height_; }
int bottom_image_height() const { return bottom_image_height_; }
int left_image_width() const { return left_image_width_; }
int right_image_width() const { return right_image_width_; }
// Initializes the grid to display the passed-in images (any of which can be
// NULL). Ownership of the images remains with the caller.
void Init(const gfx::Image* top_left_image,
const gfx::Image* top_image,
const gfx::Image* top_right_image,
const gfx::Image* left_image,
const gfx::Image* center_image,
const gfx::Image* right_image,
const gfx::Image* bottom_left_image,
const gfx::Image* bottom_image,
const gfx::Image* bottom_right_image);
void SetSize(const gfx::Size& size);
private:
// Delegate responsible for painting a specific image on a layer.
class ImagePainter : public ui::LayerDelegate {
public:
ImagePainter(const gfx::Image* image) : image_(image) {}
virtual ~ImagePainter() {}
// ui::LayerDelegate implementation:
virtual void OnPaintLayer(gfx::Canvas* canvas) OVERRIDE;
private:
const gfx::Image* image_; // not owned
DISALLOW_COPY_AND_ASSIGN(ImagePainter);
};
// Returns the dimensions of |image| if non-NULL or gfx::Size(0, 0) otherwise.
static gfx::Size GetImageSize(const gfx::Image* image);
// Initializes |layer_ptr| and |painter_ptr| to display |image|.
// Also adds the passed-in layer to |layer_|.
void InitImage(const gfx::Image* image,
scoped_ptr<ui::Layer>* layer_ptr,
scoped_ptr<ImagePainter>* painter_ptr);
// Layer that contains all of the image layers.
scoped_ptr<ui::Layer> layer_;
// The grid's dimensions.
gfx::Size size_;
// Heights and widths of the images displayed by |top_layer_|,
// |bottom_layer_|, |left_layer_|, and |right_layer_|.
int top_image_height_;
int bottom_image_height_;
int left_image_width_;
int right_image_width_;
// Heights of the tallest images in the top and bottom rows and the widest
// images in the left and right columns.
int top_row_height_;
int bottom_row_height_;
int left_column_width_;
int right_column_width_;
// Layers used to display the various images. Children of |layer_|.
// Positions for which no images were supplied are NULL.
scoped_ptr<ui::Layer> top_left_layer_;
scoped_ptr<ui::Layer> top_layer_;
scoped_ptr<ui::Layer> top_right_layer_;
scoped_ptr<ui::Layer> left_layer_;
scoped_ptr<ui::Layer> center_layer_;
scoped_ptr<ui::Layer> right_layer_;
scoped_ptr<ui::Layer> bottom_left_layer_;
scoped_ptr<ui::Layer> bottom_layer_;
scoped_ptr<ui::Layer> bottom_right_layer_;
// Delegates responsible for painting the above layers.
// Positions for which no images were supplied are NULL.
scoped_ptr<ImagePainter> top_left_painter_;
scoped_ptr<ImagePainter> top_painter_;
scoped_ptr<ImagePainter> top_right_painter_;
scoped_ptr<ImagePainter> left_painter_;
scoped_ptr<ImagePainter> center_painter_;
scoped_ptr<ImagePainter> right_painter_;
scoped_ptr<ImagePainter> bottom_left_painter_;
scoped_ptr<ImagePainter> bottom_painter_;
scoped_ptr<ImagePainter> bottom_right_painter_;
DISALLOW_COPY_AND_ASSIGN(ImageGrid);
};
} // namespace internal
} // namespace aura_shell
#endif // UI_AURA_SHELL_IMAGE_GRID_H_
// Copyright (c) 2011 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.
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/aura_shell/image_grid.h"
#include "ui/aura_shell/test/aura_shell_test_base.h"
#include "ui/gfx/image/image.h"
using aura_shell::internal::ImageGrid;
namespace aura_shell {
namespace test {
namespace {
// Creates a gfx::Image with the requested dimensions.
gfx::Image* CreateImage(const gfx::Size& size) {
SkBitmap* bitmap = new SkBitmap();
bitmap->setConfig(SkBitmap::kARGB_8888_Config, size.width(), size.height());
return new gfx::Image(bitmap);
}
} // namespace
typedef aura_shell::test::AuraShellTestBase ImageGridTest;
// Test that an ImageGrid's layers are transformed correctly when SetSize() is
// called.
TEST_F(ImageGridTest, Basic) {
// Size of the images around the grid's border.
const int kBorder = 2;
scoped_ptr<gfx::Image> image_1x1(CreateImage(gfx::Size(1, 1)));
scoped_ptr<gfx::Image> image_1xB(CreateImage(gfx::Size(1, kBorder)));
scoped_ptr<gfx::Image> image_Bx1(CreateImage(gfx::Size(kBorder, 1)));
scoped_ptr<gfx::Image> image_BxB(CreateImage(gfx::Size(kBorder, kBorder)));
ImageGrid grid;
grid.Init(image_BxB.get(), image_1xB.get(), image_BxB.get(),
image_Bx1.get(), image_1x1.get(), image_Bx1.get(),
image_BxB.get(), image_1xB.get(), image_BxB.get());
ImageGrid::TestAPI test_api(&grid);
ASSERT_TRUE(test_api.top_left_layer() != NULL);
ASSERT_TRUE(test_api.top_layer() != NULL);
ASSERT_TRUE(test_api.top_right_layer() != NULL);
ASSERT_TRUE(test_api.left_layer() != NULL);
ASSERT_TRUE(test_api.center_layer() != NULL);
ASSERT_TRUE(test_api.right_layer() != NULL);
ASSERT_TRUE(test_api.bottom_left_layer() != NULL);
ASSERT_TRUE(test_api.bottom_layer() != NULL);
ASSERT_TRUE(test_api.bottom_right_layer() != NULL);
const gfx::Size size(20, 30);
grid.SetSize(size);
// The top-left layer should be flush with the top-left corner and unscaled.
EXPECT_EQ(gfx::Rect(0, 0, kBorder, kBorder).ToString(),
test_api.GetTransformedLayerBounds(
*test_api.top_left_layer()).ToString());
// The top layer should be flush with the top edge and stretched horizontally
// between the two top corners.
EXPECT_EQ(gfx::Rect(
kBorder, 0, size.width() - 2 * kBorder, kBorder).ToString(),
test_api.GetTransformedLayerBounds(
*test_api.top_layer()).ToString());
// The top-right layer should be flush with the top-right corner and unscaled.
EXPECT_EQ(gfx::Rect(size.width() - kBorder, 0, kBorder, kBorder).ToString(),
test_api.GetTransformedLayerBounds(
*test_api.top_right_layer()).ToString());
// The left layer should be flush with the left edge and stretched vertically
// between the two left corners.
EXPECT_EQ(gfx::Rect(
0, kBorder, kBorder, size.height() - 2 * kBorder).ToString(),
test_api.GetTransformedLayerBounds(
*test_api.left_layer()).ToString());
// The center layer should fill the space in the middle of the grid.
EXPECT_EQ(gfx::Rect(
kBorder, kBorder, size.width() - 2 * kBorder,
size.height() - 2 * kBorder).ToString(),
test_api.GetTransformedLayerBounds(
*test_api.center_layer()).ToString());
// The right layer should be flush with the right edge and stretched
// vertically between the two right corners.
EXPECT_EQ(gfx::Rect(
size.width() - kBorder, kBorder,
kBorder, size.height() - 2 * kBorder).ToString(),
test_api.GetTransformedLayerBounds(
*test_api.right_layer()).ToString());
// The bottom-left layer should be flush with the bottom-left corner and
// unscaled.
EXPECT_EQ(gfx::Rect(0, size.height() - kBorder, kBorder, kBorder).ToString(),
test_api.GetTransformedLayerBounds(
*test_api.bottom_left_layer()).ToString());
// The bottom layer should be flush with the bottom edge and stretched
// horizontally between the two bottom corners.
EXPECT_EQ(gfx::Rect(
kBorder, size.height() - kBorder,
size.width() - 2 * kBorder, kBorder).ToString(),
test_api.GetTransformedLayerBounds(
*test_api.bottom_layer()).ToString());
// The bottom-right layer should be flush with the bottom-right corner and
// unscaled.
EXPECT_EQ(gfx::Rect(
size.width() - kBorder, size.height() - kBorder,
kBorder, kBorder).ToString(),
test_api.GetTransformedLayerBounds(
*test_api.bottom_right_layer()).ToString());
}
// Check that we don't crash if only a single image is supplied.
TEST_F(ImageGridTest, SingleImage) {
const int kBorder = 1;
scoped_ptr<gfx::Image> image(CreateImage(gfx::Size(kBorder, kBorder)));
ImageGrid grid;
grid.Init(NULL, image.get(), NULL,
NULL, NULL, NULL,
NULL, NULL, NULL);
ImageGrid::TestAPI test_api(&grid);
EXPECT_TRUE(test_api.top_left_layer() == NULL);
ASSERT_TRUE(test_api.top_layer() != NULL);
EXPECT_TRUE(test_api.top_right_layer() == NULL);
EXPECT_TRUE(test_api.left_layer() == NULL);
EXPECT_TRUE(test_api.center_layer() == NULL);
EXPECT_TRUE(test_api.right_layer() == NULL);
EXPECT_TRUE(test_api.bottom_left_layer() == NULL);
EXPECT_TRUE(test_api.bottom_layer() == NULL);
EXPECT_TRUE(test_api.bottom_right_layer() == NULL);
const gfx::Size kSize(10, 10);
grid.SetSize(kSize);
// The top layer should be scaled horizontally across the entire width, but it
// shouldn't be scaled vertically.
EXPECT_EQ(gfx::Rect(0, 0, kSize.width(), kBorder).ToString(),
test_api.GetTransformedLayerBounds(
*test_api.top_layer()).ToString());
}
// Test that side (top, left, right, bottom) layers that are narrower than their
// adjacent corner layers stay pinned to the outside edges instead of getting
// moved inwards or scaled. This exercises the scenario used for shadows.
TEST_F(ImageGridTest, SmallerSides) {
const int kCorner = 2;
const int kEdge = 1;
scoped_ptr<gfx::Image> top_left_image(
CreateImage(gfx::Size(kCorner, kCorner)));
scoped_ptr<gfx::Image> top_image(CreateImage(gfx::Size(kEdge, kEdge)));
scoped_ptr<gfx::Image> top_right_image(
CreateImage(gfx::Size(kCorner, kCorner)));
scoped_ptr<gfx::Image> left_image(CreateImage(gfx::Size(kEdge, kEdge)));
scoped_ptr<gfx::Image> right_image(CreateImage(gfx::Size(kEdge, kEdge)));
ImageGrid grid;
grid.Init(top_left_image.get(), top_image.get(), top_right_image.get(),
left_image.get(), NULL, right_image.get(),
NULL, NULL, NULL);
ImageGrid::TestAPI test_api(&grid);
const gfx::Size kSize(20, 30);
grid.SetSize(kSize);
// The top layer should be flush with the top edge and stretched horizontally
// between the two top corners.
EXPECT_EQ(gfx::Rect(
kCorner, 0, kSize.width() - 2 * kCorner, kEdge).ToString(),
test_api.GetTransformedLayerBounds(
*test_api.top_layer()).ToString());
// The left layer should be flush with the left edge and stretched vertically
// between the top left corner and the bottom.
EXPECT_EQ(gfx::Rect(
0, kCorner, kEdge, kSize.height() - kCorner).ToString(),
test_api.GetTransformedLayerBounds(
*test_api.left_layer()).ToString());
// The right layer should be flush with the right edge and stretched
// vertically between the top right corner and the bottom.
EXPECT_EQ(gfx::Rect(
kSize.width() - kEdge, kCorner,
kEdge, kSize.height() - kCorner).ToString(),
test_api.GetTransformedLayerBounds(
*test_api.right_layer()).ToString());
}
} // namespace test
} // namespace aura_shell
// Copyright (c) 2011 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.
#include "ui/aura_shell/shadow.h"
#include "grit/ui_resources.h"
#include "ui/aura_shell/image_grid.h"
#include "ui/base/resource/resource_bundle.h"
namespace aura_shell {
namespace internal {
Shadow::Shadow() {
}
Shadow::~Shadow() {
}
ui::Layer* Shadow::layer() const { return image_grid_->layer(); }
void Shadow::Init() {
image_grid_.reset(new ImageGrid);
ResourceBundle& res = ResourceBundle::GetSharedInstance();
image_grid_->Init(&res.GetImageNamed(IDR_AURA_SHADOW_RECT_TOP_LEFT),
&res.GetImageNamed(IDR_AURA_SHADOW_RECT_TOP),
&res.GetImageNamed(IDR_AURA_SHADOW_RECT_TOP_RIGHT),
&res.GetImageNamed(IDR_AURA_SHADOW_RECT_LEFT),
NULL,
&res.GetImageNamed(IDR_AURA_SHADOW_RECT_RIGHT),
&res.GetImageNamed(IDR_AURA_SHADOW_RECT_BOTTOM_LEFT),
&res.GetImageNamed(IDR_AURA_SHADOW_RECT_BOTTOM),
&res.GetImageNamed(IDR_AURA_SHADOW_RECT_BOTTOM_RIGHT));
}
void Shadow::SetContentBounds(const gfx::Rect& content_bounds) {
content_bounds_ = content_bounds;
image_grid_->SetSize(
gfx::Size(content_bounds.width() +
image_grid_->left_image_width() +
image_grid_->right_image_width(),
content_bounds.height() +
image_grid_->top_image_height() +
image_grid_->bottom_image_height()));
image_grid_->layer()->SetBounds(
gfx::Rect(content_bounds.x() - image_grid_->left_image_width(),
content_bounds.y() - image_grid_->top_image_height(),
image_grid_->layer()->bounds().width(),
image_grid_->layer()->bounds().height()));
}
} // namespace internal
} // namespace aura_shell
// Copyright (c) 2011 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_SHELL_SHADOW_H_
#define UI_AURA_SHELL_SHADOW_H_
#pragma once
#include "base/basictypes.h"
#include "base/memory/scoped_ptr.h"
#include "ui/gfx/rect.h"
namespace ui {
class Layer;
} // namespace ui
namespace aura_shell {
namespace internal {
class ImageGrid;
// Simple class that draws a drop shadow around content at given bounds.
class Shadow {
public:
Shadow();
~Shadow();
// Returns |image_grid_|'s ui::Layer. This is exposed so it can be added to
// the same layer as the content and stacked below it. SetContentBounds()
// should be used to adjust the shadow's size and position (rather than
// applying transformations to this layer).
ui::Layer* layer() const;
const gfx::Rect& content_bounds() const { return content_bounds_; }
void Init();
// Moves and resizes |image_grid_| to frame |content_bounds|.
void SetContentBounds(const gfx::Rect& content_bounds);
private:
scoped_ptr<ImageGrid> image_grid_;
// Bounds of the content that the shadow encloses.
gfx::Rect content_bounds_;
DISALLOW_COPY_AND_ASSIGN(Shadow);
};
} // namespace internal
} // namespace aura_shell
#endif // UI_AURA_SHELL_SHADOW_H_
// Copyright (c) 2011 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.
#include "ui/aura_shell/shadow_controller.h"
#include <utility>
#include "base/logging.h"
#include "ui/aura/client/aura_constants.h"
#include "ui/aura/client/shadow_types.h"
#include "ui/aura/desktop.h"
#include "ui/aura/window.h"
#include "ui/aura_shell/shadow.h"
using std::make_pair;
namespace aura_shell {
namespace internal {
ShadowController::ShadowController() {
aura::Desktop::GetInstance()->AddObserver(this);
}
ShadowController::~ShadowController() {
for (WindowShadowMap::const_iterator it = window_shadows_.begin();
it != window_shadows_.end(); ++it) {
it->first->RemoveObserver(this);
}
aura::Desktop::GetInstance()->RemoveObserver(this);
}
void ShadowController::OnWindowInitialized(aura::Window* window) {
window->AddObserver(this);
}
void ShadowController::OnWindowParentChanged(aura::Window* window,
aura::Window* parent) {
Shadow* shadow = GetShadowForWindow(window);
if (parent) {
if (shadow) {
parent->layer()->Add(shadow->layer());
StackShadowBelowWindow(shadow, window);
} else {
if (ShouldShowShadowForWindow(window))
CreateShadowForWindow(window);
}
} else {
if (shadow && shadow->layer()->parent())
shadow->layer()->parent()->Remove(shadow->layer());
}
}
void ShadowController::OnPropertyChanged(aura::Window* window,
const char* name,
void* old) {
if (name == aura::kShadowTypeKey)
HandlePossibleShadowVisibilityChange(window);
}
void ShadowController::OnWindowVisibilityChanged(aura::Window* window,
bool visible) {
HandlePossibleShadowVisibilityChange(window);
}
void ShadowController::OnWindowBoundsChanged(aura::Window* window,
const gfx::Rect& bounds) {
Shadow* shadow = GetShadowForWindow(window);
if (shadow)
shadow->SetContentBounds(bounds);
}
void ShadowController::OnWindowStackingChanged(aura::Window* window) {
Shadow* shadow = GetShadowForWindow(window);
if (shadow)
StackShadowBelowWindow(shadow, window);
}
void ShadowController::OnWindowDestroyed(aura::Window* window) {
window_shadows_.erase(window);
}
bool ShadowController::ShouldShowShadowForWindow(aura::Window* window) const {
const aura::ShadowType type = static_cast<aura::ShadowType>(
window->GetIntProperty(aura::kShadowTypeKey));
bool requested = false;
switch (type) {
case aura::SHADOW_TYPE_NONE:
break;
case aura::SHADOW_TYPE_RECTANGULAR:
requested = true;
break;
default:
NOTREACHED() << "Unknown shadow type " << type;
}
return requested && window->layer()->visible();
}
Shadow* ShadowController::GetShadowForWindow(aura::Window* window) {
WindowShadowMap::const_iterator it = window_shadows_.find(window);
return it != window_shadows_.end() ? it->second.get() : NULL;
}
void ShadowController::HandlePossibleShadowVisibilityChange(
aura::Window* window) {
const bool should_show = ShouldShowShadowForWindow(window);
Shadow* shadow = GetShadowForWindow(window);
if (shadow)
shadow->layer()->SetVisible(should_show);
else if (should_show && !shadow)
CreateShadowForWindow(window);
}
void ShadowController::CreateShadowForWindow(aura::Window* window) {
linked_ptr<Shadow> shadow(new Shadow());
window_shadows_.insert(make_pair(window, shadow));
shadow->Init();
shadow->SetContentBounds(window->bounds());
shadow->layer()->SetVisible(ShouldShowShadowForWindow(window));
if (window->parent()) {
window->parent()->layer()->Add(shadow->layer());
StackShadowBelowWindow(shadow.get(), window);
}
}
void ShadowController::StackShadowBelowWindow(Shadow* shadow,
aura::Window* window) {
ui::Layer* parent_layer = window->parent()->layer();
DCHECK_EQ(shadow->layer()->parent(), parent_layer);
// TODO(derat): Add a MoveBelow() method and use that instead (although we
// then run the risk of other layers getting stacked between a window and its
// shadow).
parent_layer->MoveAbove(shadow->layer(), window->layer());
parent_layer->MoveAbove(window->layer(), shadow->layer());
}
} // namespace internal
} // namespace aura_shell
// Copyright (c) 2011 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_SHELL_SHADOW_CONTROLLER_H_
#define UI_AURA_SHELL_SHADOW_CONTROLLER_H_
#pragma once
#include <map>
#include "base/basictypes.h"
#include "base/compiler_specific.h"
#include "base/memory/linked_ptr.h"
#include "ui/aura/desktop_observer.h"
#include "ui/aura/window_observer.h"
namespace aura {
class Window;
}
namespace gfx {
class Rect;
}
namespace aura_shell {
namespace internal {
class Shadow;
// ShadowController observes changes to windows and creates and updates drop
// shadows as needed.
class ShadowController : public aura::DesktopObserver,
public aura::WindowObserver {
public:
class TestApi {
public:
explicit TestApi(ShadowController* controller) : controller_(controller) {}
~TestApi() {}
Shadow* GetShadowForWindow(aura::Window* window) {
return controller_->GetShadowForWindow(window);
}
private:
ShadowController* controller_; // not owned
DISALLOW_COPY_AND_ASSIGN(TestApi);
};
explicit ShadowController();
virtual ~ShadowController();
// aura::DesktopObserver override:
virtual void OnWindowInitialized(aura::Window* window) OVERRIDE;
// aura::WindowObserver overrides:
virtual void OnWindowParentChanged(
aura::Window* window, aura::Window* parent) OVERRIDE;
virtual void OnPropertyChanged(
aura::Window* window, const char* name, void* old) OVERRIDE;
virtual void OnWindowVisibilityChanged(
aura::Window* window, bool visible) OVERRIDE;
virtual void OnWindowBoundsChanged(
aura::Window* window, const gfx::Rect& bounds) OVERRIDE;
virtual void OnWindowStackingChanged(aura::Window* window) OVERRIDE;
virtual void OnWindowDestroyed(aura::Window* window) OVERRIDE;
private:
typedef std::map<aura::Window*, linked_ptr<Shadow> > WindowShadowMap;
// Checks if |window| is visible and contains a property requesting a shadow.
bool ShouldShowShadowForWindow(aura::Window* window) const;
// Returns |window|'s shadow from |window_shadows_|, or NULL if no shadow
// exists.
Shadow* GetShadowForWindow(aura::Window* window);
// Shows or hides |window|'s shadow as needed (creating the shadow if
// necessary).
void HandlePossibleShadowVisibilityChange(aura::Window* window);
// Creates a new shadow for |window| and stores it in |window_shadows_|. The
// shadow's visibility, bounds, and stacking are initialized appropriately.
void CreateShadowForWindow(aura::Window* window);
// Stacks |shadow|'s layer directly beneath |window|'s layer.
void StackShadowBelowWindow(Shadow* shadow, aura::Window* window);
WindowShadowMap window_shadows_;
DISALLOW_COPY_AND_ASSIGN(ShadowController);
};
} // namepsace aura_shell
} // namepsace internal
#endif // UI_AURA_SHELL_SHADOW_CONTROLLER_H_
// Copyright (c) 2011 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.
#include "base/memory/scoped_ptr.h"
#include "ui/aura/client/aura_constants.h"
#include "ui/aura/client/shadow_types.h"
#include "ui/aura/desktop.h"
#include "ui/aura/window.h"
#include "ui/aura_shell/shadow.h"
#include "ui/aura_shell/shadow_controller.h"
#include "ui/aura_shell/shell.h"
#include "ui/aura_shell/test/aura_shell_test_base.h"
namespace aura_shell {
namespace test {
typedef aura_shell::test::AuraShellTestBase ShadowControllerTest;
// Tests that various methods in Window update the Shadow object as expected.
TEST_F(ShadowControllerTest, Shadow) {
scoped_ptr<aura::Window> window(new aura::Window(NULL));
window->SetType(aura::WINDOW_TYPE_NORMAL);
window->SetIntProperty(aura::kShadowTypeKey, aura::SHADOW_TYPE_RECTANGULAR);
window->Init(ui::Layer::LAYER_HAS_TEXTURE);
window->SetParent(NULL);
// We shouldn't create the shadow before the window is visible.
internal::ShadowController::TestApi api(
aura_shell::Shell::GetInstance()->shadow_controller());
EXPECT_TRUE(api.GetShadowForWindow(window.get()) == NULL);
// The shadow's visibility should be updated along with the window's.
window->Show();
const internal::Shadow* shadow = api.GetShadowForWindow(window.get());
ASSERT_TRUE(shadow != NULL);
EXPECT_TRUE(shadow->layer()->visible());
window->Hide();
EXPECT_FALSE(shadow->layer()->visible());
// If the shadow is disabled, it shouldn't be shown even when the window is.
window->SetIntProperty(aura::kShadowTypeKey, aura::SHADOW_TYPE_NONE);
window->Show();
EXPECT_FALSE(shadow->layer()->visible());
window->SetIntProperty(aura::kShadowTypeKey, aura::SHADOW_TYPE_RECTANGULAR);
EXPECT_TRUE(shadow->layer()->visible());
// The shadow's layer should have the same parent as the window's.
EXPECT_EQ(window->parent()->layer(), shadow->layer()->parent());
// TODO(derat): Test stacking (after adding additional methods to ui::Layer so
// that stacking order can be queried).
// When we remove the window from the hierarchy, its shadow should be removed
// too.
window->parent()->RemoveChild(window.get());
EXPECT_TRUE(shadow->layer()->parent() == NULL);
aura::Window* window_ptr = window.get();
window.reset();
EXPECT_TRUE(api.GetShadowForWindow(window_ptr) == NULL);
}
// Tests that the window's shadow's bounds are updated correctly.
TEST_F(ShadowControllerTest, ShadowBounds) {
scoped_ptr<aura::Window> window(new aura::Window(NULL));
window->SetType(aura::WINDOW_TYPE_NORMAL);
window->Init(ui::Layer::LAYER_HAS_TEXTURE);
window->SetParent(NULL);
window->Show();
const gfx::Rect kOldBounds(20, 30, 400, 300);
window->SetBounds(kOldBounds);
// When the shadow is first created, it should use the window's bounds.
window->SetIntProperty(aura::kShadowTypeKey, aura::SHADOW_TYPE_RECTANGULAR);
internal::ShadowController::TestApi api(
aura_shell::Shell::GetInstance()->shadow_controller());
const internal::Shadow* shadow = api.GetShadowForWindow(window.get());
ASSERT_TRUE(shadow != NULL);
EXPECT_EQ(kOldBounds, shadow->content_bounds());
// When we change the window's bounds, the shadow's should be updated too.
gfx::Rect kNewBounds(50, 60, 500, 400);
window->SetBounds(kNewBounds);
EXPECT_EQ(kNewBounds, shadow->content_bounds());
}
} // namespace test
} // namespace aura_shell
......@@ -19,6 +19,7 @@
#include "ui/aura_shell/drag_drop_controller.h"
#include "ui/aura_shell/launcher/launcher.h"
#include "ui/aura_shell/modal_container_layout_manager.h"
#include "ui/aura_shell/shadow_controller.h"
#include "ui/aura_shell/shelf_layout_controller.h"
#include "ui/aura_shell/shell_delegate.h"
#include "ui/aura_shell/shell_factory.h"
......@@ -172,9 +173,11 @@ void Shell::Init() {
shelf_layout_controller_.reset(new internal::ShelfLayoutController(
launcher_->widget(), status_widget));
desktop_layout->set_shelf(shelf_layout_controller_.get());
if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kAuraNoShadows))
shadow_controller_.reset(new internal::ShadowController());
if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kAuraWindows)) {
EnableWorkspaceManager();
} else {
......@@ -187,7 +190,6 @@ void Shell::Init() {
// Force a layout.
desktop_layout->OnWindowResized();
// Initialize drag drop controller.
drag_drop_controller_.reset(new internal::DragDropController);
aura::Desktop::GetInstance()->SetProperty(aura::kDesktopDragDropClientKey,
static_cast<aura::DragDropClient*>(drag_drop_controller_.get()));
......
......@@ -31,6 +31,7 @@ class ShellDelegate;
namespace internal {
class DragDropController;
class ShadowController;
class ShelfLayoutController;
class WorkspaceController;
}
......@@ -64,6 +65,11 @@ class AURA_SHELL_EXPORT Shell {
ShellDelegate* delegate() { return delegate_.get(); }
Launcher* launcher() { return launcher_.get(); }
// Made available for tests.
internal::ShadowController* shadow_controller() {
return shadow_controller_.get();
}
private:
typedef std::pair<aura::Window*, gfx::Rect> WindowAndBoundsPair;
......@@ -88,6 +94,7 @@ class AURA_SHELL_EXPORT Shell {
scoped_ptr<internal::DragDropController> drag_drop_controller_;
scoped_ptr<internal::WorkspaceController> workspace_controller_;
scoped_ptr<internal::ShelfLayoutController> shelf_layout_controller_;
scoped_ptr<internal::ShadowController> shadow_controller_;
DISALLOW_COPY_AND_ASSIGN(Shell);
};
......
......@@ -26,7 +26,7 @@ public:
explicit ShowStateController(WorkspaceManager* layout_manager);
virtual ~ShowStateController();
// Invoked when window proparty has changed.
// aura::WindowObserver overrides:
virtual void OnPropertyChanged(aura::Window* window,
const char* name,
void* old) OVERRIDE;
......
......@@ -8,6 +8,7 @@
#include "base/string_util.h"
#include "ui/aura/client/aura_constants.h"
#include "ui/aura/client/drag_drop_client.h"
#include "ui/aura/client/shadow_types.h"
#include "ui/aura/desktop.h"
#include "ui/aura/desktop_observer.h"
#include "ui/aura/event.h"
......@@ -160,12 +161,17 @@ void NativeWidgetAura::InitNativeWidget(const Widget::InitParams& params) {
GetWidget()->GetRootView());
tooltip_manager_.reset(manager);
}
drop_helper_.reset(new DropHelper(GetWidget()->GetRootView()));
if (params.type != Widget::InitParams::TYPE_TOOLTIP &&
params.type != Widget::InitParams::TYPE_POPUP) {
window_->SetProperty(aura::kDragDropDelegateKey,
static_cast<aura::WindowDragDropDelegate*>(this));
}
if (window_type == Widget::InitParams::TYPE_MENU)
window_->SetIntProperty(aura::kShadowTypeKey,
aura::SHADOW_TYPE_RECTANGULAR);
}
NonClientFrameView* NativeWidgetAura::CreateNonClientFrameView() {
......
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