summaryrefslogtreecommitdiffstats
path: root/content
diff options
context:
space:
mode:
authorsadrul@chromium.org <sadrul@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-02-14 04:59:20 +0000
committersadrul@chromium.org <sadrul@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-02-14 04:59:20 +0000
commit0aef1fc3afa4eb9e3d5d90652decd5f3595462d1 (patch)
tree502bfdab92061068531eb106402c9606a67c5574 /content
parent043de5ebf0afeefb83345d310d5271ad40d4f8e1 (diff)
downloadchromium_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.cc233
-rw-r--r--content/browser/web_contents/web_contents_view_aura.h8
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.