diff options
author | sadrul@chromium.org <sadrul@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-02-06 01:33:44 +0000 |
---|---|---|
committer | sadrul@chromium.org <sadrul@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-02-06 01:33:44 +0000 |
commit | 5def89eb4f851f06ed7d322ec5308aae6d50fd6b (patch) | |
tree | 0f444fb952f841f8405e15a2f78a16fc28de752d | |
parent | 398fb9a7e86ba438559268e645d9b992fecc9f6c (diff) | |
download | chromium_src-5def89eb4f851f06ed7d322ec5308aae6d50fd6b.zip chromium_src-5def89eb4f851f06ed7d322ec5308aae6d50fd6b.tar.gz chromium_src-5def89eb4f851f06ed7d322ec5308aae6d50fd6b.tar.bz2 |
gesture-nav: Move OverscrollNavigationOverlay into its own file.
BUG=340751
R=mfomitchev@chromium.org, piman@chromium.org, sky@chromium.org
Review URL: https://codereview.chromium.org/132203013
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@249200 0039d316-1c4b-4281-b951-d872f2087c98
4 files changed, 320 insertions, 243 deletions
diff --git a/content/browser/web_contents/aura/overscroll_navigation_overlay.cc b/content/browser/web_contents/aura/overscroll_navigation_overlay.cc new file mode 100644 index 0000000..b82c248 --- /dev/null +++ b/content/browser/web_contents/aura/overscroll_navigation_overlay.cc @@ -0,0 +1,212 @@ +// Copyright 2014 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 "content/browser/web_contents/aura/overscroll_navigation_overlay.h" + +#include "content/browser/frame_host/navigation_entry_impl.h" +#include "content/browser/web_contents/aura/image_window_delegate.h" +#include "content/browser/web_contents/web_contents_impl.h" +#include "ui/aura/window.h" +#include "ui/compositor/layer.h" +#include "ui/gfx/canvas.h" +#include "ui/gfx/image/image_png_rep.h" +#include "ui/gfx/image/image_skia.h" + +namespace content { + +// A LayerDelegate that paints an image for the layer. +class ImageLayerDelegate : public ui::LayerDelegate { + public: + ImageLayerDelegate() {} + + virtual ~ImageLayerDelegate() {} + + void SetImage(const gfx::Image& image) { + image_ = image; + image_size_ = image.AsImageSkia().size(); + } + const gfx::Image& image() const { return image_; } + + private: + // Overridden from ui::LayerDelegate: + virtual void OnPaintLayer(gfx::Canvas* canvas) OVERRIDE { + if (image_.IsEmpty()) { + canvas->DrawColor(SK_ColorGRAY); + } else { + SkISize size = canvas->sk_canvas()->getDeviceSize(); + if (size.width() != image_size_.width() || + size.height() != image_size_.height()) { + canvas->DrawColor(SK_ColorWHITE); + } + canvas->DrawImageInt(image_.AsImageSkia(), 0, 0); + } + } + + // Called when the layer's device scale factor has changed. + virtual void OnDeviceScaleFactorChanged(float device_scale_factor) OVERRIDE { + } + + // Invoked prior to the bounds changing. The returned closured is run after + // the bounds change. + virtual base::Closure PrepareForLayerBoundsChange() OVERRIDE { + return base::Closure(); + } + + gfx::Image image_; + gfx::Size image_size_; + + DISALLOW_COPY_AND_ASSIGN(ImageLayerDelegate); +}; + +OverscrollNavigationOverlay::OverscrollNavigationOverlay( + WebContentsImpl* web_contents) + : web_contents_(web_contents), + image_delegate_(NULL), + loading_complete_(false), + received_paint_update_(false), + slide_direction_(SLIDE_UNKNOWN), + need_paint_update_(true) { +} + +OverscrollNavigationOverlay::~OverscrollNavigationOverlay() { +} + +void OverscrollNavigationOverlay::StartObserving() { + loading_complete_ = false; + received_paint_update_ = false; + Observe(web_contents_); + + // Make sure the overlay window is on top. + if (window_.get() && window_->parent()) + window_->parent()->StackChildAtTop(window_.get()); +} + +void OverscrollNavigationOverlay::SetOverlayWindow( + scoped_ptr<aura::Window> window, + ImageWindowDelegate* delegate) { + window_ = window.Pass(); + if (window_.get() && window_->parent()) + window_->parent()->StackChildAtTop(window_.get()); + image_delegate_ = delegate; + + if (window_.get() && delegate->has_image()) { + window_slider_.reset(new WindowSlider(this, + window_->parent(), + window_.get())); + slide_direction_ = SLIDE_UNKNOWN; + } else { + window_slider_.reset(); + } +} + +void OverscrollNavigationOverlay::SetupForTesting() { + need_paint_update_ = false; +} + +void OverscrollNavigationOverlay::StopObservingIfDone() { + // If there is a screenshot displayed in the overlay window, then wait for + // the navigated page to complete loading and some paint update before + // hiding the overlay. + // If there is no screenshot in the overlay window, then hide this view + // as soon as there is any new painting notification. + if ((need_paint_update_ && !received_paint_update_) || + (image_delegate_->has_image() && !loading_complete_)) { + return; + } + + // If a slide is in progress, then do not destroy the window or the slide. + if (window_slider_.get() && window_slider_->IsSlideInProgress()) + return; + + Observe(NULL); + window_slider_.reset(); + window_.reset(); + image_delegate_ = NULL; +} + +ui::Layer* OverscrollNavigationOverlay::CreateSlideLayer(int offset) { + const NavigationControllerImpl& controller = web_contents_->GetController(); + const NavigationEntryImpl* entry = NavigationEntryImpl::FromNavigationEntry( + controller.GetEntryAtOffset(offset)); + + gfx::Image image; + if (entry && entry->screenshot().get()) { + std::vector<gfx::ImagePNGRep> image_reps; + image_reps.push_back(gfx::ImagePNGRep(entry->screenshot(), + ui::GetImageScale( + ui::GetScaleFactorForNativeView(window_.get())))); + image = gfx::Image(image_reps); + } + if (!layer_delegate_) + layer_delegate_.reset(new ImageLayerDelegate()); + layer_delegate_->SetImage(image); + + ui::Layer* layer = new ui::Layer(ui::LAYER_TEXTURED); + layer->set_delegate(layer_delegate_.get()); + return layer; +} + +ui::Layer* OverscrollNavigationOverlay::CreateBackLayer() { + if (!web_contents_->GetController().CanGoBack()) + return NULL; + slide_direction_ = SLIDE_BACK; + return CreateSlideLayer(-1); +} + +ui::Layer* OverscrollNavigationOverlay::CreateFrontLayer() { + if (!web_contents_->GetController().CanGoForward()) + return NULL; + slide_direction_ = SLIDE_FRONT; + return CreateSlideLayer(1); +} + +void OverscrollNavigationOverlay::OnWindowSlideComplete() { + if (slide_direction_ == SLIDE_UNKNOWN) { + window_slider_.reset(); + StopObservingIfDone(); + return; + } + + // Change the image used for the overlay window. + image_delegate_->SetImage(layer_delegate_->image()); + window_->layer()->SetTransform(gfx::Transform()); + window_->SchedulePaintInRect(gfx::Rect(window_->bounds().size())); + + SlideDirection direction = slide_direction_; + slide_direction_ = SLIDE_UNKNOWN; + + // Reset state and wait for the new navigation page to complete + // loading/painting. + StartObserving(); + + // Perform the navigation. + if (direction == SLIDE_BACK) + web_contents_->GetController().GoBack(); + else if (direction == SLIDE_FRONT) + web_contents_->GetController().GoForward(); + else + NOTREACHED(); +} + +void OverscrollNavigationOverlay::OnWindowSlideAborted() { + StopObservingIfDone(); +} + +void OverscrollNavigationOverlay::OnWindowSliderDestroyed() { + // The slider has just been destroyed. Release the ownership. + WindowSlider* slider ALLOW_UNUSED = window_slider_.release(); + StopObservingIfDone(); +} + +void OverscrollNavigationOverlay::DidFirstVisuallyNonEmptyPaint(int32 page_id) { + received_paint_update_ = true; + StopObservingIfDone(); +} + +void OverscrollNavigationOverlay::DidStopLoading(RenderViewHost* host) { + loading_complete_ = true; + StopObservingIfDone(); +} + +} // namespace content diff --git a/content/browser/web_contents/aura/overscroll_navigation_overlay.h b/content/browser/web_contents/aura/overscroll_navigation_overlay.h new file mode 100644 index 0000000..29f2622 --- /dev/null +++ b/content/browser/web_contents/aura/overscroll_navigation_overlay.h @@ -0,0 +1,105 @@ +// Copyright 2014 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 CONTENT_BROWSER_WEB_CONTENTS_AURA_OVERSCROLL_NAVIGATION_OVERLAY_H_ +#define CONTENT_BROWSER_WEB_CONTENTS_AURA_OVERSCROLL_NAVIGATION_OVERLAY_H_ + +#include "base/macros.h" +#include "content/browser/web_contents/aura/window_slider.h" +#include "content/public/browser/web_contents_observer.h" + +namespace content { + +class ImageLayerDelegate; +class ImageWindowDelegate; + +// 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 +// screenshot window on top of the page until the page has completed loading and +// painting. +class OverscrollNavigationOverlay : public WebContentsObserver, + public WindowSlider::Delegate { + public: + explicit OverscrollNavigationOverlay(WebContentsImpl* web_contents); + virtual ~OverscrollNavigationOverlay(); + + bool has_window() const { return !!window_.get(); } + + // Starts observing |web_contents_| for page load/paint updates. This function + // makes sure that the screenshot window is stacked on top, so that it hides + // the content window behind it, and destroys the screenshot window when the + // page is done loading/painting. + void StartObserving(); + + // Sets the screenshot window and the delegate. This takes ownership of + // |window|. + // Note that ImageWindowDelegate manages its own lifetime, so this function + // does not take ownership of |delegate|. + void SetOverlayWindow(scoped_ptr<aura::Window> window, + ImageWindowDelegate* delegate); + + // Sets up the overlay for tests. + void SetupForTesting(); + + private: + enum SlideDirection { + SLIDE_UNKNOWN, + SLIDE_BACK, + SLIDE_FRONT + }; + + // Stop observing the page if the page-load has completed and the page has + // been painted, and a window-slide isn't in progress. + void StopObservingIfDone(); + + // Creates a layer to be used for window-slide. |offset| is the offset of the + // NavigationEntry for the screenshot image to display. + ui::Layer* CreateSlideLayer(int offset); + + // Overridden from WindowSlider::Delegate: + virtual ui::Layer* CreateBackLayer() OVERRIDE; + virtual ui::Layer* CreateFrontLayer() OVERRIDE; + virtual void OnWindowSlideComplete() OVERRIDE; + virtual void OnWindowSlideAborted() OVERRIDE; + virtual void OnWindowSliderDestroyed() OVERRIDE; + + // Overridden from WebContentsObserver: + virtual void DidFirstVisuallyNonEmptyPaint(int32 page_id) OVERRIDE; + virtual void DidStopLoading(RenderViewHost* host) OVERRIDE; + + // The WebContents which is being navigated. + WebContentsImpl* web_contents_; + + // The screenshot overlay window. + scoped_ptr<aura::Window> window_; + + // This is the WindowDelegate of |window_|. The delegate manages its own + // lifetime (destroys itself when |window_| is destroyed). + ImageWindowDelegate* image_delegate_; + + bool loading_complete_; + bool received_paint_update_; + + // The |WindowSlider| that allows sliding history layers while the page is + // being reloaded. + scoped_ptr<WindowSlider> window_slider_; + + // The direction of the in-progress slide (if any). + SlideDirection slide_direction_; + + // The LayerDelegate used for the back/front layers during a slide. + scoped_ptr<ImageLayerDelegate> layer_delegate_; + + // During tests, the aura windows don't get any paint updates. So the overlay + // container keeps waiting for a paint update it never receives, causing a + // timeout. So during tests, disable the wait for paint updates. + bool need_paint_update_; + + DISALLOW_COPY_AND_ASSIGN(OverscrollNavigationOverlay); +}; + +} // namespace content + +#endif // CONTENT_BROWSER_WEB_CONTENTS_AURA_OVERSCROLL_NAVIGATION_OVERLAY_H_ diff --git a/content/browser/web_contents/web_contents_view_aura.cc b/content/browser/web_contents/web_contents_view_aura.cc index ad5623c..aa3be21 100644 --- a/content/browser/web_contents/web_contents_view_aura.cc +++ b/content/browser/web_contents/web_contents_view_aura.cc @@ -19,6 +19,7 @@ #include "content/browser/renderer_host/render_widget_host_impl.h" #include "content/browser/renderer_host/render_widget_host_view_aura.h" #include "content/browser/web_contents/aura/image_window_delegate.h" +#include "content/browser/web_contents/aura/overscroll_navigation_overlay.h" #include "content/browser/web_contents/aura/shadow_layer_delegate.h" #include "content/browser/web_contents/aura/window_slider.h" #include "content/browser/web_contents/touch_editable_impl_aura.h" @@ -441,251 +442,8 @@ int ConvertAuraEventFlagsToWebInputEventModifiers(int aura_event_flags) { return web_input_event_modifiers; } -// A LayerDelegate that paints an image for the layer. -class ImageLayerDelegate : public ui::LayerDelegate { - public: - ImageLayerDelegate() {} - - virtual ~ImageLayerDelegate() {} - - void SetImage(const gfx::Image& image) { - image_ = image; - image_size_ = image.AsImageSkia().size(); - } - const gfx::Image& image() const { return image_; } - - private: - // Overridden from ui::LayerDelegate: - virtual void OnPaintLayer(gfx::Canvas* canvas) OVERRIDE { - if (image_.IsEmpty()) { - canvas->DrawColor(SK_ColorGRAY); - } else { - SkISize size = canvas->sk_canvas()->getDeviceSize(); - if (size.width() != image_size_.width() || - size.height() != image_size_.height()) { - canvas->DrawColor(SK_ColorWHITE); - } - canvas->DrawImageInt(image_.AsImageSkia(), 0, 0); - } - } - - // Called when the layer's device scale factor has changed. - virtual void OnDeviceScaleFactorChanged(float device_scale_factor) OVERRIDE { - } - - // Invoked prior to the bounds changing. The returned closured is run after - // the bounds change. - virtual base::Closure PrepareForLayerBoundsChange() OVERRIDE { - return base::Closure(); - } - - gfx::Image image_; - gfx::Size image_size_; - - DISALLOW_COPY_AND_ASSIGN(ImageLayerDelegate); -}; - } // namespace -// 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 -// screenshot window on top of the page until the page has completed loading and -// painting. -class OverscrollNavigationOverlay : public WebContentsObserver, - public WindowSlider::Delegate { - public: - explicit OverscrollNavigationOverlay(WebContentsImpl* web_contents) - : web_contents_(web_contents), - image_delegate_(NULL), - loading_complete_(false), - received_paint_update_(false), - slide_direction_(SLIDE_UNKNOWN), - need_paint_update_(true) { - } - - virtual ~OverscrollNavigationOverlay() { - } - - bool has_window() const { return !!window_.get(); } - - void StartObserving() { - loading_complete_ = false; - received_paint_update_ = false; - Observe(web_contents_); - - // Make sure the overlay window is on top. - if (window_.get() && window_->parent()) - window_->parent()->StackChildAtTop(window_.get()); - } - - void SetOverlayWindow(scoped_ptr<aura::Window> window, - ImageWindowDelegate* delegate) { - window_ = window.Pass(); - if (window_.get() && window_->parent()) - window_->parent()->StackChildAtTop(window_.get()); - image_delegate_ = delegate; - - if (window_.get() && delegate->has_image()) { - window_slider_.reset(new WindowSlider(this, - window_->parent(), - window_.get())); - slide_direction_ = SLIDE_UNKNOWN; - } else { - window_slider_.reset(); - } - } - - void SetupForTesting() { - need_paint_update_ = false; - } - - private: - // Stop observing the page if the page-load has completed and the page has - // been painted, and a window-slide isn't in progress. - void StopObservingIfDone() { - // If there is a screenshot displayed in the overlay window, then wait for - // the navigated page to complete loading and some paint update before - // hiding the overlay. - // If there is no screenshot in the overlay window, then hide this view - // as soon as there is any new painting notification. - if ((need_paint_update_ && !received_paint_update_) || - (image_delegate_->has_image() && !loading_complete_)) { - return; - } - - // If a slide is in progress, then do not destroy the window or the slide. - if (window_slider_.get() && window_slider_->IsSlideInProgress()) - return; - - Observe(NULL); - window_slider_.reset(); - window_.reset(); - image_delegate_ = NULL; - } - - // Creates a layer to be used for window-slide. |offset| is the offset of the - // NavigationEntry for the screenshot image to display. - ui::Layer* CreateSlideLayer(int offset) { - const NavigationControllerImpl& controller = web_contents_->GetController(); - const NavigationEntryImpl* entry = NavigationEntryImpl::FromNavigationEntry( - controller.GetEntryAtOffset(offset)); - - gfx::Image image; - if (entry && entry->screenshot().get()) { - std::vector<gfx::ImagePNGRep> image_reps; - image_reps.push_back(gfx::ImagePNGRep(entry->screenshot(), - ui::GetImageScale( - ui::GetScaleFactorForNativeView(window_.get())))); - image = gfx::Image(image_reps); - } - layer_delegate_.SetImage(image); - - ui::Layer* layer = new ui::Layer(ui::LAYER_TEXTURED); - layer->set_delegate(&layer_delegate_); - return layer; - } - - // Overridden from WindowSlider::Delegate: - virtual ui::Layer* CreateBackLayer() OVERRIDE { - if (!web_contents_->GetController().CanGoBack()) - return NULL; - slide_direction_ = SLIDE_BACK; - return CreateSlideLayer(-1); - } - - virtual ui::Layer* CreateFrontLayer() OVERRIDE { - if (!web_contents_->GetController().CanGoForward()) - return NULL; - slide_direction_ = SLIDE_FRONT; - return CreateSlideLayer(1); - } - - virtual void OnWindowSlideComplete() OVERRIDE { - if (slide_direction_ == SLIDE_UNKNOWN) { - window_slider_.reset(); - StopObservingIfDone(); - return; - } - - // Change the image used for the overlay window. - image_delegate_->SetImage(layer_delegate_.image()); - window_->layer()->SetTransform(gfx::Transform()); - window_->SchedulePaintInRect(gfx::Rect(window_->bounds().size())); - - SlideDirection direction = slide_direction_; - slide_direction_ = SLIDE_UNKNOWN; - - // Reset state and wait for the new navigation page to complete - // loading/painting. - StartObserving(); - - // Perform the navigation. - if (direction == SLIDE_BACK) - web_contents_->GetController().GoBack(); - else if (direction == SLIDE_FRONT) - web_contents_->GetController().GoForward(); - else - NOTREACHED(); - } - - virtual void OnWindowSlideAborted() OVERRIDE { - StopObservingIfDone(); - } - - virtual void OnWindowSliderDestroyed() OVERRIDE { - // The slider has just been destroyed. Release the ownership. - WindowSlider* slider ALLOW_UNUSED = window_slider_.release(); - StopObservingIfDone(); - } - - // Overridden from WebContentsObserver: - virtual void DidFirstVisuallyNonEmptyPaint(int32 page_id) OVERRIDE { - received_paint_update_ = true; - StopObservingIfDone(); - } - - virtual void DidStopLoading(RenderViewHost* host) OVERRIDE { - loading_complete_ = true; - StopObservingIfDone(); - } - - // The WebContents which is being navigated. - WebContentsImpl* web_contents_; - - scoped_ptr<aura::Window> window_; - - // This is the WindowDelegate of |window_|. The delegate manages its own - // lifetime (destroys itself when |window_| is destroyed). - ImageWindowDelegate* image_delegate_; - - bool loading_complete_; - bool received_paint_update_; - - enum SlideDirection { - SLIDE_UNKNOWN, - SLIDE_BACK, - SLIDE_FRONT - }; - - // The |WindowSlider| that allows sliding history layers while the page is - // being reloaded. - scoped_ptr<WindowSlider> window_slider_; - - // The direction of the in-progress slide (if any). - SlideDirection slide_direction_; - - // The LayerDelegate used for the back/front layers during a slide. - ImageLayerDelegate layer_delegate_; - - // During tests, the aura windows don't get any paint updates. So the overlay - // container keeps waiting for a paint update it never receives, causing a - // timeout. So during tests, disable the wait for paint updates. - bool need_paint_update_; - - DISALLOW_COPY_AND_ASSIGN(OverscrollNavigationOverlay); -}; - class WebContentsViewAura::WindowObserver : public aura::WindowObserver, public aura::RootWindowObserver { public: diff --git a/content/content_browser.gypi b/content/content_browser.gypi index 76cc65d..d265433 100644 --- a/content/content_browser.gypi +++ b/content/content_browser.gypi @@ -1215,6 +1215,8 @@ 'browser/vibration/vibration_provider_android.h', 'browser/web_contents/aura/image_window_delegate.cc', 'browser/web_contents/aura/image_window_delegate.h', + 'browser/web_contents/aura/overscroll_navigation_overlay.cc', + 'browser/web_contents/aura/overscroll_navigation_overlay.h', 'browser/web_contents/aura/shadow_layer_delegate.cc', 'browser/web_contents/aura/shadow_layer_delegate.h', 'browser/web_contents/aura/window_slider.cc', |