| Index: content/browser/web_contents/web_contents_view_aura.cc
|
| diff --git a/content/browser/web_contents/web_contents_view_aura.cc b/content/browser/web_contents/web_contents_view_aura.cc
|
| index 83362893595a346a6ebd0406de641e10d746c366..bee2a646967ade63fa9efc2bbacdeae3d4a21783 100644
|
| --- a/content/browser/web_contents/web_contents_view_aura.cc
|
| +++ b/content/browser/web_contents/web_contents_view_aura.cc
|
| @@ -27,6 +27,7 @@
|
| #include "content/public/browser/web_contents_view_delegate.h"
|
| #include "content/public/browser/web_drag_dest_delegate.h"
|
| #include "third_party/WebKit/Source/WebKit/chromium/public/WebInputEvent.h"
|
| +#include "third_party/skia/include/effects/SkGradientShader.h"
|
| #include "ui/aura/client/aura_constants.h"
|
| #include "ui/aura/client/drag_drop_client.h"
|
| #include "ui/aura/client/drag_drop_delegate.h"
|
| @@ -48,6 +49,7 @@
|
| #include "ui/gfx/image/image_png_rep.h"
|
| #include "ui/gfx/image/image_skia.h"
|
| #include "ui/gfx/screen.h"
|
| +#include "ui/gfx/skia_util.h"
|
| #include "webkit/glue/webdropdata.h"
|
|
|
| #if defined(OS_WIN)
|
| @@ -66,6 +68,18 @@ WebContentsView* CreateWebContentsView(
|
|
|
| namespace {
|
|
|
| +const SkColor kShadowLightColor = SkColorSetARGB(0x0, 0, 0, 0);
|
| +const SkColor kShadowDarkColor = SkColorSetARGB(0x70, 0, 0, 0);
|
| +const int kShadowThick = 7;
|
| +
|
| +enum ShadowEdge {
|
| + SHADOW_NONE,
|
| + SHADOW_LEFT,
|
| + SHADOW_RIGHT,
|
| + SHADOW_TOP,
|
| + SHADOW_BOTTOM
|
| +};
|
| +
|
| bool ShouldNavigateForward(const NavigationController& controller,
|
| OverscrollMode mode) {
|
| return mode == (base::i18n::IsRTL() ? OVERSCROLL_EAST : OVERSCROLL_WEST) &&
|
| @@ -85,7 +99,8 @@ class OverscrollWindowDelegate : public aura::WindowDelegate {
|
| public:
|
| OverscrollWindowDelegate(WebContentsImpl* web_contents,
|
| OverscrollMode overscroll_mode)
|
| - : web_contents_(web_contents) {
|
| + : web_contents_(web_contents),
|
| + show_shadow_(false) {
|
| const NavigationControllerImpl& controller = web_contents->GetController();
|
| const NavigationEntryImpl* entry = NULL;
|
| if (ShouldNavigateForward(controller, overscroll_mode)) {
|
| @@ -106,6 +121,10 @@ class OverscrollWindowDelegate : public aura::WindowDelegate {
|
|
|
| bool has_screenshot() const { return !image_.IsEmpty(); }
|
|
|
| + void set_show_shadow(bool show) {
|
| + show_shadow_ = show;
|
| + }
|
| +
|
| private:
|
| virtual ~OverscrollWindowDelegate() {}
|
|
|
| @@ -148,10 +167,33 @@ class OverscrollWindowDelegate : public aura::WindowDelegate {
|
| }
|
|
|
| virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE {
|
| + if (show_shadow_) {
|
| + canvas->Save();
|
| + canvas->Translate(gfx::Vector2d(kShadowThick, 0));
|
| + }
|
| if (image_.IsEmpty())
|
| canvas->DrawColor(SK_ColorGRAY);
|
| else
|
| canvas->DrawImageInt(image_.AsImageSkia(), 0, 0);
|
| +
|
| + if (show_shadow_) {
|
| + canvas->Restore();
|
| + SkPoint points[2];
|
| + points[0].iset(0, 0);
|
| + points[1].iset(kShadowThick, 0);
|
| + SkColor colors[2] = { kShadowLightColor, kShadowDarkColor };
|
| + skia::RefPtr<SkShader> shader = skia::AdoptRef(
|
| + SkGradientShader::CreateLinear(points, colors, NULL,
|
| + arraysize(points), SkShader::kRepeat_TileMode, NULL));
|
| +
|
| + SkRect rect = { SkIntToScalar(0),
|
| + SkIntToScalar(0),
|
| + SkIntToScalar(kShadowThick),
|
| + SkIntToScalar(web_contents_window()->bounds().height()) };
|
| + SkPaint paint;
|
| + paint.setShader(shader.get());
|
| + canvas->sk_canvas()->drawRect(rect, paint);
|
| + }
|
| }
|
|
|
| virtual void OnDeviceScaleFactorChanged(float device_scale_factor) OVERRIDE {
|
| @@ -191,6 +233,7 @@ class OverscrollWindowDelegate : public aura::WindowDelegate {
|
|
|
| WebContents* web_contents_;
|
| gfx::Image image_;
|
| + bool show_shadow_;
|
|
|
| DISALLOW_COPY_AND_ASSIGN(OverscrollWindowDelegate);
|
| };
|
| @@ -403,6 +446,142 @@ int GetResistedScrollAmount(int scroll, int threshold) {
|
|
|
| } // namespace
|
|
|
| +// ShadowWindow is used to paint shadows around a content window.
|
| +// A ShadowWindow destroys itself when the content window is destroyed, and
|
| +// updates its bounds to make sure the shadows are painted in the correct size.
|
| +class ShadowWindow : public aura::Window,
|
| + public aura::WindowObserver {
|
| + public:
|
| + explicit ShadowWindow(aura::Window* window)
|
| + : aura::Window(NULL),
|
| + window_(window),
|
| + edge_(SHADOW_NONE) {
|
| + SetType(aura::client::WINDOW_TYPE_CONTROL);
|
| + SetTransparent(true);
|
| + set_owned_by_parent(false);
|
| + Init(ui::LAYER_NOT_DRAWN);
|
| + layer()->SetMasksToBounds(false);
|
| +
|
| + AddChild(window);
|
| + window_->AddObserver(this);
|
| +
|
| + SetBounds(gfx::Rect(window->bounds().size()));
|
| + Show();
|
| + }
|
| +
|
| + void SetShadowEdge(ShadowEdge edge) {
|
| + edge_ = edge;
|
| + if (edge_ == SHADOW_NONE) {
|
| + shadow_.reset();
|
| + return;
|
| + }
|
| +
|
| + shadow_.reset(new ui::Layer(ui::LAYER_TEXTURED));
|
| + shadow_->set_delegate(this);
|
| + shadow_->SetFillsBoundsOpaquely(false);
|
| + layer()->Add(shadow_.get());
|
| + layer()->StackBelow(shadow_.get(), window_->layer());
|
| + UpdateShadowBounds();
|
| + }
|
| +
|
| + private:
|
| + friend class base::DeleteHelper<content::ShadowWindow>;
|
| +
|
| + virtual ~ShadowWindow() {
|
| + }
|
| +
|
| + void UpdateShadowBounds() {
|
| + if (!shadow_.get())
|
| + return;
|
| + gfx::Rect bound;
|
| + switch (edge_) {
|
| + case SHADOW_LEFT:
|
| + bound.SetRect(-kShadowThick, 0, kShadowThick, bounds().height());
|
| + break;
|
| + case SHADOW_RIGHT:
|
| + bound.SetRect(bounds().right(), 0, kShadowThick, bounds().height());
|
| + break;
|
| + case SHADOW_TOP:
|
| + bound.SetRect(0, -kShadowThick, bounds().width(), kShadowThick);
|
| + break;
|
| + case SHADOW_BOTTOM:
|
| + bound.SetRect(0, bounds().bottom(), bounds().width(), kShadowThick);
|
| + break;
|
| + case SHADOW_NONE:
|
| + NOTREACHED();
|
| + }
|
| + shadow_->SetBounds(bound);
|
| + }
|
| +
|
| + // Overridden from aura::WindowObserver:
|
| + virtual void OnWindowBoundsChanged(Window* window,
|
| + const gfx::Rect& old_bounds,
|
| + const gfx::Rect& new_bounds) OVERRIDE {
|
| + SetBounds(gfx::Rect(new_bounds.size()));
|
| + UpdateShadowBounds();
|
| + }
|
| +
|
| + virtual void OnWindowDestroying(aura::Window* window) OVERRIDE {
|
| + DCHECK_EQ(window, window_);
|
| + window_->RemoveObserver(this);
|
| + window_ = NULL;
|
| + MessageLoop::current()->DeleteSoon(FROM_HERE, this);
|
| + }
|
| +
|
| + // Overridden from ui::LayerDelegate:
|
| + virtual void OnPaintLayer(gfx::Canvas* canvas) OVERRIDE {
|
| + SkPoint points[2];
|
| + SkColor colors[2];
|
| +
|
| + points[0].iset(0, 0);
|
| + switch (edge_) {
|
| + case SHADOW_LEFT:
|
| + case SHADOW_RIGHT:
|
| + points[1].iset(shadow_->bounds().width(), 0);
|
| + break;
|
| +
|
| + case SHADOW_TOP:
|
| + case SHADOW_BOTTOM:
|
| + points[1].iset(0, shadow_->bounds().height());
|
| + break;
|
| +
|
| + default:
|
| + NOTREACHED();
|
| + }
|
| +
|
| + switch (edge_) {
|
| + case SHADOW_LEFT:
|
| + case SHADOW_TOP:
|
| + colors[0] = kShadowLightColor;
|
| + colors[1] = kShadowDarkColor;
|
| + break;
|
| +
|
| + case SHADOW_RIGHT:
|
| + case SHADOW_BOTTOM:
|
| + colors[0] = kShadowDarkColor;
|
| + colors[1] = kShadowLightColor;
|
| + break;
|
| +
|
| + default:
|
| + NOTREACHED();
|
| + }
|
| +
|
| + skia::RefPtr<SkShader> shader = skia::AdoptRef(
|
| + SkGradientShader::CreateLinear(points, colors, NULL,
|
| + arraysize(points), SkShader::kRepeat_TileMode, NULL));
|
| +
|
| + SkPaint paint;
|
| + paint.setShader(shader.get());
|
| + canvas->sk_canvas()->drawRect(gfx::RectToSkRect(bounds()), paint);
|
| + }
|
| +
|
| + aura::Window* window_;
|
| + scoped_ptr<ui::Layer> shadow_;
|
| + ShadowEdge edge_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(ShadowWindow);
|
| +};
|
| +
|
| // When a history navigation is triggered at the end of an overscroll
|
| // navigation, it is necessary to show the history-screenshot until the page is
|
| // done navigating and painting. This class accomplishes this by showing the
|
| @@ -573,6 +752,7 @@ WebContentsViewAura::WebContentsViewAura(
|
| current_drag_op_(WebKit::WebDragOperationNone),
|
| drag_dest_delegate_(NULL),
|
| current_rvh_for_drag_(NULL),
|
| + content_container_(NULL),
|
| overscroll_change_brightness_(false),
|
| current_overscroll_gesture_(OVERSCROLL_NONE),
|
| completed_overscroll_gesture_(OVERSCROLL_NONE) {
|
| @@ -629,7 +809,7 @@ void WebContentsViewAura::PrepareOverscrollWindow() {
|
| current_overscroll_gesture_);
|
| overscroll_window_.reset(new aura::Window(overscroll_delegate));
|
| overscroll_window_->SetType(aura::client::WINDOW_TYPE_CONTROL);
|
| - overscroll_window_->SetTransparent(false);
|
| + overscroll_window_->SetTransparent(true);
|
| overscroll_window_->Init(ui::LAYER_TEXTURED);
|
| overscroll_window_->layer()->SetMasksToBounds(true);
|
| overscroll_window_->SetName("OverscrollOverlay");
|
| @@ -646,10 +826,34 @@ void WebContentsViewAura::PrepareOverscrollWindow() {
|
| bounds.Offset(base::i18n::IsRTL() ? -bounds.width() : bounds.width(), 0);
|
| }
|
|
|
| - if (GetWindowToAnimateForOverscroll() == overscroll_window_.get())
|
| - window_->StackChildAbove(overscroll_window_.get(), GetContentNativeView());
|
| - else
|
| - window_->StackChildBelow(overscroll_window_.get(), GetContentNativeView());
|
| + if (GetWindowToAnimateForOverscroll() == overscroll_window_.get()) {
|
| + overscroll_delegate->set_show_shadow(true);
|
| + window_->StackChildAbove(overscroll_window_.get(), content_container_);
|
| + } else {
|
| + window_->StackChildBelow(overscroll_window_.get(), content_container_);
|
| +
|
| + switch (current_overscroll_gesture_) {
|
| + case OVERSCROLL_EAST:
|
| + content_container_->SetShadowEdge(SHADOW_LEFT);
|
| + break;
|
| +
|
| + case OVERSCROLL_WEST:
|
| + content_container_->SetShadowEdge(SHADOW_RIGHT);
|
| + break;
|
| +
|
| + case OVERSCROLL_NORTH:
|
| + content_container_->SetShadowEdge(SHADOW_BOTTOM);
|
| + break;
|
| +
|
| + case OVERSCROLL_SOUTH:
|
| + content_container_->SetShadowEdge(SHADOW_TOP);
|
| + break;
|
| +
|
| + case OVERSCROLL_NONE:
|
| + case OVERSCROLL_COUNT:
|
| + NOTREACHED();
|
| + }
|
| + }
|
|
|
| UpdateOverscrollWindowBrightness(0.f);
|
|
|
| @@ -658,7 +862,7 @@ void WebContentsViewAura::PrepareOverscrollWindow() {
|
| }
|
|
|
| void WebContentsViewAura::PrepareContentWindowForOverscroll() {
|
| - aura::Window* content = GetContentNativeView();
|
| + aura::Window* content = content_container_;
|
| if (!content)
|
| return;
|
|
|
| @@ -725,7 +929,7 @@ aura::Window* WebContentsViewAura::GetWindowToAnimateForOverscroll() {
|
|
|
| return ShouldNavigateForward(web_contents_->GetController(),
|
| current_overscroll_gesture_) ?
|
| - overscroll_window_.get() : GetContentNativeView();
|
| + overscroll_window_.get() : content_container_;
|
| }
|
|
|
| gfx::Vector2d WebContentsViewAura::GetTranslationForOverscroll(int delta_x,
|
| @@ -757,6 +961,11 @@ gfx::Vector2d WebContentsViewAura::GetTranslationForOverscroll(int delta_x,
|
| }
|
|
|
| void WebContentsViewAura::PrepareOverscrollNavigationOverlay() {
|
| + OverscrollWindowDelegate* delegate = static_cast<OverscrollWindowDelegate*>(
|
| + overscroll_window_->delegate());
|
| + delegate->set_show_shadow(false);
|
| + overscroll_window_->SchedulePaintInRect(
|
| + gfx::Rect(overscroll_window_->bounds().size()));
|
| navigation_overlay_->SetOverlayWindow(overscroll_window_.Pass());
|
| navigation_overlay_->StartObservingView(static_cast<
|
| RenderWidgetHostViewAura*>(web_contents_->GetRenderWidgetHostView()));
|
| @@ -835,7 +1044,8 @@ RenderWidgetHostView* WebContentsViewAura::CreateViewForWidget(
|
| RenderWidgetHostView* view =
|
| RenderWidgetHostView::CreateViewForWidget(render_widget_host);
|
| view->InitAsChild(NULL);
|
| - GetNativeView()->AddChild(view->GetNativeView());
|
| + content_container_ = new ShadowWindow(view->GetNativeView());
|
| + GetNativeView()->AddChild(content_container_);
|
|
|
| if (navigation_overlay_.get() && navigation_overlay_->has_window()) {
|
| navigation_overlay_->StartObservingView(static_cast<
|
| @@ -1105,8 +1315,9 @@ void WebContentsViewAura::OnImplicitAnimationsCompleted() {
|
| }
|
|
|
| if (GetContentNativeView()) {
|
| - GetContentNativeView()->SetTransform(gfx::Transform());
|
| - GetContentNativeView()->layer()->SetLayerBrightness(0.f);
|
| + content_container_->SetTransform(gfx::Transform());
|
| + content_container_->layer()->SetLayerBrightness(0.f);
|
| + content_container_->SetShadowEdge(SHADOW_NONE);
|
| }
|
| current_overscroll_gesture_ = OVERSCROLL_NONE;
|
| completed_overscroll_gesture_ = OVERSCROLL_NONE;
|
|
|