summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsadrul@chromium.org <sadrul@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-01-20 01:10:22 +0000
committersadrul@chromium.org <sadrul@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-01-20 01:10:22 +0000
commit00353d188a87c6a2f953e22a73d7c18fa2c37b2a (patch)
treeb173998f99fbb347a8906f411628f01d370ef3b3
parentf57cb24377708369400972fd89f5d94f2379b3ea (diff)
downloadchromium_src-00353d188a87c6a2f953e22a73d7c18fa2c37b2a.zip
chromium_src-00353d188a87c6a2f953e22a73d7c18fa2c37b2a.tar.gz
chromium_src-00353d188a87c6a2f953e22a73d7c18fa2c37b2a.tar.bz2
overscroll: Avoid flickering during history navigation.
Keep the window showing the history screenshot on top of the content window until the content window has something to paint for the newly navigated window. BUG=170700 Review URL: https://codereview.chromium.org/11956043 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@177863 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--content/browser/renderer_host/render_widget_host_view_aura.cc15
-rw-r--r--content/browser/renderer_host/render_widget_host_view_aura.h32
-rw-r--r--content/browser/web_contents/web_contents_view_aura.cc129
-rw-r--r--content/browser/web_contents/web_contents_view_aura.h9
4 files changed, 179 insertions, 6 deletions
diff --git a/content/browser/renderer_host/render_widget_host_view_aura.cc b/content/browser/renderer_host/render_widget_host_view_aura.cc
index 5c2bc7b..81d3a4e 100644
--- a/content/browser/renderer_host/render_widget_host_view_aura.cc
+++ b/content/browser/renderer_host/render_widget_host_view_aura.cc
@@ -299,7 +299,8 @@ RenderWidgetHostViewAura::RenderWidgetHostViewAura(RenderWidgetHost* host)
paint_canvas_(NULL),
synthetic_move_sent_(false),
accelerated_compositing_state_changed_(false),
- can_lock_compositor_(YES) {
+ can_lock_compositor_(YES),
+ paint_observer_(NULL) {
host_->SetView(this);
window_observer_.reset(new WindowObserver(this));
window_->AddObserver(window_observer_.get());
@@ -568,6 +569,8 @@ void RenderWidgetHostViewAura::UpdateCursor(const WebCursor& cursor) {
}
void RenderWidgetHostViewAura::SetIsLoading(bool is_loading) {
+ if (is_loading_ && !is_loading && paint_observer_)
+ paint_observer_->OnPageLoadComplete();
is_loading_ = is_loading;
UpdateCursorIfOverSelf();
}
@@ -893,6 +896,8 @@ void RenderWidgetHostViewAura::AcceleratedSurfaceBuffersSwapped(
window_->SchedulePaintInRect(gfx::Rect(surface_size));
}
+ if (paint_observer_)
+ paint_observer_->OnUpdateCompositorContent();
SwapBuffersCompleted(ack_params);
}
@@ -952,6 +957,8 @@ void RenderWidgetHostViewAura::AcceleratedSurfacePostSubBuffer(
rect_to_paint.Inset(-1, -1);
rect_to_paint.Intersect(window_->bounds());
+ if (paint_observer_)
+ paint_observer_->OnUpdateCompositorContent();
window_->SchedulePaintInRect(rect_to_paint);
}
@@ -1357,6 +1364,8 @@ void RenderWidgetHostViewAura::OnPaint(gfx::Canvas* canvas) {
if (backing_store) {
static_cast<BackingStoreAura*>(backing_store)->SkiaShowRect(gfx::Point(),
canvas);
+ if (paint_observer_)
+ paint_observer_->OnPaintComplete();
} else if (aura::Env::GetInstance()->render_white_bg()) {
canvas->DrawColor(SK_ColorWHITE);
}
@@ -1756,6 +1765,8 @@ void RenderWidgetHostViewAura::OnCompositingStarted(
void RenderWidgetHostViewAura::OnCompositingEnded(
ui::Compositor* compositor) {
+ if (paint_observer_)
+ paint_observer_->OnCompositingComplete();
}
void RenderWidgetHostViewAura::OnCompositingAborted(
@@ -1796,6 +1807,8 @@ void RenderWidgetHostViewAura::OnLostResources() {
// RenderWidgetHostViewAura, private:
RenderWidgetHostViewAura::~RenderWidgetHostViewAura() {
+ if (paint_observer_)
+ paint_observer_->OnViewDestroyed();
if (!shared_surface_handle_.is_null()) {
ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
factory->DestroySharedSurfaceHandle(shared_surface_handle_);
diff --git a/content/browser/renderer_host/render_widget_host_view_aura.h b/content/browser/renderer_host/render_widget_host_view_aura.h
index 2e8797e..6c6efaa 100644
--- a/content/browser/renderer_host/render_widget_host_view_aura.h
+++ b/content/browser/renderer_host/render_widget_host_view_aura.h
@@ -61,6 +61,33 @@ class RenderWidgetHostViewAura
public ImageTransportFactoryObserver,
public base::SupportsWeakPtr<RenderWidgetHostViewAura> {
public:
+ // Used to notify whenever the paint-content of the view changes.
+ class PaintObserver {
+ public:
+ PaintObserver() {}
+ virtual ~PaintObserver() {}
+
+ // This is called when painting of the page is completed.
+ virtual void OnPaintComplete() = 0;
+
+ // This is called when compositor painting of the page is completed.
+ virtual void OnCompositingComplete() = 0;
+
+ // This is called when the contents for compositor painting changes.
+ virtual void OnUpdateCompositorContent() = 0;
+
+ // This is called loading the page has completed.
+ virtual void OnPageLoadComplete() = 0;
+
+ // This is called when the view is destroyed, so that the observer can
+ // perform any necessary clean-up.
+ virtual void OnViewDestroyed() = 0;
+ };
+
+ void set_paint_observer(PaintObserver* observer) {
+ paint_observer_ = observer;
+ }
+
// RenderWidgetHostView implementation.
virtual void InitAsChild(gfx::NativeView parent_view) OVERRIDE;
virtual RenderWidgetHost* GetRenderWidgetHost() const OVERRIDE;
@@ -433,6 +460,11 @@ class RenderWidgetHostViewAura
};
CanLockCompositorState can_lock_compositor_;
+ // An observer to notify that the paint content of the view has changed. The
+ // observer is not owned by the view, and must remove itself as an oberver
+ // when it is being destroyed.
+ PaintObserver* paint_observer_;
+
DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostViewAura);
};
diff --git a/content/browser/web_contents/web_contents_view_aura.cc b/content/browser/web_contents/web_contents_view_aura.cc
index a6c8cf4..b7c98b1 100644
--- a/content/browser/web_contents/web_contents_view_aura.cc
+++ b/content/browser/web_contents/web_contents_view_aura.cc
@@ -72,7 +72,7 @@ class OverscrollWindowDelegate : public aura::WindowDelegate {
public:
OverscrollWindowDelegate(WebContentsImpl* web_contents,
OverscrollMode overscroll_mode)
- : web_contents_window_(web_contents->GetView()->GetContentNativeView()) {
+ : web_contents_(web_contents) {
const NavigationControllerImpl& controller = web_contents->GetController();
const NavigationEntryImpl* entry = NULL;
if (overscroll_mode == OVERSCROLL_WEST && controller.CanGoForward()) {
@@ -87,13 +87,17 @@ class OverscrollWindowDelegate : public aura::WindowDelegate {
std::vector<gfx::ImagePNGRep> image_reps;
image_reps.push_back(gfx::ImagePNGRep(entry->screenshot(),
- ui::GetScaleFactorForNativeView(web_contents_window_)));
+ ui::GetScaleFactorForNativeView(web_contents_window())));
image_ = gfx::Image(image_reps);
}
private:
virtual ~OverscrollWindowDelegate() {}
+ aura::Window* web_contents_window() {
+ return web_contents_->GetView()->GetContentNativeView();
+ }
+
// aura::WindowDelegate implementation:
virtual gfx::Size GetMinimumSize() const OVERRIDE {
return gfx::Size();
@@ -161,10 +165,16 @@ class OverscrollWindowDelegate : public aura::WindowDelegate {
// Overridden from ui::EventHandler.
virtual void OnScrollEvent(ui::ScrollEvent* event) OVERRIDE {
- web_contents_window_->delegate()->OnScrollEvent(event);
+ if (web_contents_window())
+ web_contents_window()->delegate()->OnScrollEvent(event);
}
- aura::Window* web_contents_window_;
+ virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE {
+ if (web_contents_window())
+ web_contents_window()->delegate()->OnGestureEvent(event);
+ }
+
+ WebContents* web_contents_;
gfx::Image image_;
DISALLOW_COPY_AND_ASSIGN(OverscrollWindowDelegate);
@@ -378,6 +388,97 @@ int GetResistedScrollAmount(int scroll, int threshold) {
} // 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 RenderWidgetHostViewAura::PaintObserver {
+ public:
+ OverscrollNavigationOverlay()
+ : view_(NULL),
+ loading_complete_(false),
+ received_paint_update_(false),
+ compositor_updated_(false) {
+ }
+
+ virtual ~OverscrollNavigationOverlay() {
+ if (view_)
+ view_->set_paint_observer(NULL);
+ }
+
+ bool has_window() const { return !!window_.get(); }
+
+ void StartObservingView(RenderWidgetHostViewAura* view) {
+ if (view_)
+ view_->set_paint_observer(NULL);
+
+ loading_complete_ = false;
+ received_paint_update_ = false;
+ compositor_updated_ = false;
+ view_ = view;
+ view_->set_paint_observer(this);
+
+ // 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) {
+ window_ = window.Pass();
+ if (window_.get() && window_->parent())
+ window_->parent()->StackChildAtTop(window_.get());
+ }
+
+ private:
+ // Stop observing the page if the page-load has completed and the page has
+ // been painted.
+ void StopObservingIfDone() {
+ if (!received_paint_update_ || !loading_complete_)
+ return;
+ window_.reset();
+ if (view_) {
+ view_->set_paint_observer(NULL);
+ view_ = NULL;
+ }
+ }
+
+ // Overridden from RenderWidgetHostViewAura::PaintObserver:
+ virtual void OnPaintComplete() OVERRIDE {
+ received_paint_update_ = true;
+ StopObservingIfDone();
+ }
+
+ virtual void OnCompositingComplete() OVERRIDE {
+ received_paint_update_ = compositor_updated_;
+ StopObservingIfDone();
+ }
+
+ virtual void OnUpdateCompositorContent() OVERRIDE {
+ compositor_updated_ = true;
+ }
+
+ virtual void OnPageLoadComplete() OVERRIDE {
+ loading_complete_ = true;
+ StopObservingIfDone();
+ }
+
+ virtual void OnViewDestroyed() OVERRIDE {
+ DCHECK(view_);
+ view_->set_paint_observer(NULL);
+ view_ = NULL;
+ }
+
+ scoped_ptr<aura::Window> window_;
+ RenderWidgetHostViewAura* view_;
+ bool loading_complete_;
+ bool received_paint_update_;
+ bool compositor_updated_;
+
+ DISALLOW_COPY_AND_ASSIGN(OverscrollNavigationOverlay);
+};
+
class WebContentsViewAura::WindowObserver
: public aura::WindowObserver, public aura::RootWindowObserver {
public:
@@ -620,6 +721,12 @@ gfx::Vector2d WebContentsViewAura::GetTranslationForOverscroll(int delta_x,
return gfx::Vector2d(delta_x < 0 ? -scroll : scroll, 0);
}
+void WebContentsViewAura::PrepareOverscrollNavigationOverlay() {
+ navigation_overlay_->SetOverlayWindow(overscroll_window_.Pass());
+ navigation_overlay_->StartObservingView(static_cast<
+ RenderWidgetHostViewAura*>(web_contents_->GetRenderWidgetHostView()));
+}
+
////////////////////////////////////////////////////////////////////////////////
// WebContentsViewAura, WebContentsView implementation:
@@ -666,6 +773,12 @@ RenderWidgetHostView* WebContentsViewAura::CreateViewForWidget(
RenderWidgetHostView::CreateViewForWidget(render_widget_host);
view->InitAsChild(NULL);
GetNativeView()->AddChild(view->GetNativeView());
+
+ if (navigation_overlay_.get() && navigation_overlay_->has_window()) {
+ navigation_overlay_->StartObservingView(static_cast<
+ RenderWidgetHostViewAura*>(view));
+ }
+
view->Show();
// We listen to drag drop events in the newly created view's window.
@@ -674,8 +787,11 @@ RenderWidgetHostView* WebContentsViewAura::CreateViewForWidget(
RenderWidgetHostImpl* host_impl =
RenderWidgetHostImpl::From(render_widget_host);
if (host_impl->overscroll_controller() && web_contents_->GetDelegate() &&
- web_contents_->GetDelegate()->CanOverscrollContent())
+ web_contents_->GetDelegate()->CanOverscrollContent()) {
host_impl->overscroll_controller()->set_delegate(this);
+ if (!navigation_overlay_.get())
+ navigation_overlay_.reset(new OverscrollNavigationOverlay());
+ }
return view;
}
@@ -916,8 +1032,10 @@ void WebContentsViewAura::OnOverscrollModeChange(OverscrollMode old_mode,
void WebContentsViewAura::OnImplicitAnimationsCompleted() {
if (completed_overscroll_gesture_ == OVERSCROLL_WEST) {
+ PrepareOverscrollNavigationOverlay();
web_contents_->GetController().GoForward();
} else if (completed_overscroll_gesture_ == OVERSCROLL_EAST) {
+ PrepareOverscrollNavigationOverlay();
web_contents_->GetController().GoBack();
}
@@ -994,6 +1112,7 @@ void WebContentsViewAura::OnWindowDestroying() {
// then destroying it in the WebContentsViewAura destructor can trigger other
// virtual functions to be called (e.g. OnImplicitAnimationsCompleted()). So
// destroy the overscroll window here.
+ navigation_overlay_.reset();
overscroll_window_.reset();
}
diff --git a/content/browser/web_contents/web_contents_view_aura.h b/content/browser/web_contents/web_contents_view_aura.h
index 206783e..fe8d136 100644
--- a/content/browser/web_contents/web_contents_view_aura.h
+++ b/content/browser/web_contents/web_contents_view_aura.h
@@ -26,6 +26,7 @@ class DropTargetEvent;
}
namespace content {
+class OverscrollNavigationOverlay;
class WebContentsViewDelegate;
class WebContentsImpl;
class WebDragDestDelegate;
@@ -77,6 +78,10 @@ class CONTENT_EXPORT WebContentsViewAura
// the overscroll gesture.
gfx::Vector2d GetTranslationForOverscroll(int delta_x, int delta_y);
+ // A window showing the screenshot is overlayed during a navigation triggered
+ // by overscroll. This function sets this up.
+ void PrepareOverscrollNavigationOverlay();
+
// Overridden from WebContentsView:
virtual void CreateView(
const gfx::Size& initial_size, gfx::NativeView context) OVERRIDE;
@@ -191,6 +196,10 @@ class CONTENT_EXPORT WebContentsViewAura
// callback that happens in response to a completed overscroll gesture.
OverscrollMode completed_overscroll_gesture_;
+ // This manages the overlay window that shows the screenshot during a history
+ // navigation triggered by the overscroll gesture.
+ scoped_ptr<OverscrollNavigationOverlay> navigation_overlay_;
+
DISALLOW_COPY_AND_ASSIGN(WebContentsViewAura);
};