diff options
author | sadrul@chromium.org <sadrul@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-02-14 04:59:20 +0000 |
---|---|---|
committer | sadrul@chromium.org <sadrul@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-02-14 04:59:20 +0000 |
commit | 0aef1fc3afa4eb9e3d5d90652decd5f3595462d1 (patch) | |
tree | 502bfdab92061068531eb106402c9606a67c5574 /content | |
parent | 043de5ebf0afeefb83345d310d5271ad40d4f8e1 (diff) | |
download | chromium_src-0aef1fc3afa4eb9e3d5d90652decd5f3595462d1.zip chromium_src-0aef1fc3afa4eb9e3d5d90652decd5f3595462d1.tar.gz chromium_src-0aef1fc3afa4eb9e3d5d90652decd5f3595462d1.tar.bz2 |
overscroll: Show a shadow for the sliding window during nav gesture.
BUG=174219
Review URL: https://codereview.chromium.org/12225163
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@182388 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content')
-rw-r--r-- | content/browser/web_contents/web_contents_view_aura.cc | 233 | ||||
-rw-r--r-- | content/browser/web_contents/web_contents_view_aura.h | 8 |
2 files changed, 230 insertions, 11 deletions
diff --git a/content/browser/web_contents/web_contents_view_aura.cc b/content/browser/web_contents/web_contents_view_aura.cc index 8336289..bee2a64 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; diff --git a/content/browser/web_contents/web_contents_view_aura.h b/content/browser/web_contents/web_contents_view_aura.h index 46c76c6..83dd4ef 100644 --- a/content/browser/web_contents/web_contents_view_aura.h +++ b/content/browser/web_contents/web_contents_view_aura.h @@ -27,6 +27,7 @@ class DropTargetEvent; namespace content { class OverscrollNavigationOverlay; +class ShadowWindow; class WebContentsViewDelegate; class WebContentsImpl; class WebDragDestDelegate; @@ -172,6 +173,9 @@ class CONTENT_EXPORT WebContentsViewAura virtual int OnPerformDrop(const ui::DropTargetEvent& event) OVERRIDE; scoped_ptr<aura::Window> window_; + + // The window that shows the screenshot of the history page during an + // overscroll navigation gesture. scoped_ptr<aura::Window> overscroll_window_; scoped_ptr<WindowObserver> window_observer_; @@ -193,6 +197,10 @@ class CONTENT_EXPORT WebContentsViewAura // pointers. void* current_rvh_for_drag_; + // The container for the content-window. The doc for ShadowWindow explains its + // lifetime and ownership. + ShadowWindow* content_container_; + bool overscroll_change_brightness_; // The overscroll gesture currently in progress. |