Index: chrome/browser/renderer_host/render_widget_host_view_mac.mm |
diff --git a/chrome/browser/renderer_host/render_widget_host_view_mac.mm b/chrome/browser/renderer_host/render_widget_host_view_mac.mm |
index 74b7647e6fb9ddb6fae771c8b241ce3eb979f661..92b8ea164011cd9cefdba50e7a015256bc44a950 100644 |
--- a/chrome/browser/renderer_host/render_widget_host_view_mac.mm |
+++ b/chrome/browser/renderer_host/render_widget_host_view_mac.mm |
@@ -450,7 +450,8 @@ RenderWidgetHostViewMac::RenderWidgetHostViewMac(RenderWidgetHost* widget) |
text_input_type_(WebKit::WebTextInputTypeNone), |
is_loading_(false), |
is_hidden_(false), |
- shutdown_factory_(this) { |
+ shutdown_factory_(this), |
+ needs_gpu_visibility_update_after_repaint_(false) { |
// |cocoa_view_| owns us and we will be deleted when |cocoa_view_| goes away. |
// Since we autorelease it, our caller must put |native_view()| into the view |
// hierarchy right after calling us. |
@@ -686,45 +687,53 @@ void RenderWidgetHostViewMac::ImeCancelComposition() { |
void RenderWidgetHostViewMac::DidUpdateBackingStore( |
const gfx::Rect& scroll_rect, int scroll_dx, int scroll_dy, |
const std::vector<gfx::Rect>& copy_rects) { |
- if (is_hidden_) |
- return; |
- |
- std::vector<gfx::Rect> rects(copy_rects); |
- |
- // Because the findbar might be open, we cannot use scrollRect:by: here. For |
- // now, simply mark all of scroll rect as dirty. |
- if (!scroll_rect.IsEmpty()) |
- rects.push_back(scroll_rect); |
- |
- for (size_t i = 0; i < rects.size(); ++i) { |
- NSRect ns_rect = [cocoa_view_ flipRectToNSRect:rects[i]]; |
- |
- if (about_to_validate_and_paint_) { |
- // As much as we'd like to use -setNeedsDisplayInRect: here, we can't. |
- // We're in the middle of executing a -drawRect:, and as soon as it |
- // returns Cocoa will clear its record of what needs display. We instead |
- // use |performSelector:| to call |setNeedsDisplayInRect:| after returning |
- // to the main loop, at which point |drawRect:| is no longer on the stack. |
- DCHECK([NSThread isMainThread]); |
- if (!call_set_needs_display_in_rect_pending_) { |
- [cocoa_view_ performSelector:@selector(callSetNeedsDisplayInRect) |
- withObject:nil |
- afterDelay:0]; |
- call_set_needs_display_in_rect_pending_ = true; |
- invalid_rect_ = ns_rect; |
+ if (!is_hidden_) { |
+ std::vector<gfx::Rect> rects(copy_rects); |
+ |
+ // Because the findbar might be open, we cannot use scrollRect:by: here. For |
+ // now, simply mark all of scroll rect as dirty. |
+ if (!scroll_rect.IsEmpty()) |
+ rects.push_back(scroll_rect); |
+ |
+ for (size_t i = 0; i < rects.size(); ++i) { |
+ NSRect ns_rect = [cocoa_view_ flipRectToNSRect:rects[i]]; |
+ |
+ if (about_to_validate_and_paint_) { |
+ // As much as we'd like to use -setNeedsDisplayInRect: here, we can't. |
+ // We're in the middle of executing a -drawRect:, and as soon as it |
+ // returns Cocoa will clear its record of what needs display. We |
+ // instead use |performSelector:| to call |setNeedsDisplayInRect:| |
+ // after returning to the main loop, at which point |drawRect:| is no |
+ // longer on the stack. |
+ DCHECK([NSThread isMainThread]); |
+ if (!call_set_needs_display_in_rect_pending_) { |
+ [cocoa_view_ performSelector:@selector(callSetNeedsDisplayInRect) |
+ withObject:nil |
+ afterDelay:0]; |
+ call_set_needs_display_in_rect_pending_ = true; |
+ invalid_rect_ = ns_rect; |
+ } else { |
+ // The old invalid rect is probably invalid now, since the view has |
+ // most likely been resized, but there's no harm in dirtying the |
+ // union. In the limit, this becomes equivalent to dirtying the |
+ // whole view. |
+ invalid_rect_ = NSUnionRect(invalid_rect_, ns_rect); |
+ } |
} else { |
- // The old invalid rect is probably invalid now, since the view has most |
- // likely been resized, but there's no harm in dirtying the union. In |
- // the limit, this becomes equivalent to dirtying the whole view. |
- invalid_rect_ = NSUnionRect(invalid_rect_, ns_rect); |
+ [cocoa_view_ setNeedsDisplayInRect:ns_rect]; |
} |
- } else { |
- [cocoa_view_ setNeedsDisplayInRect:ns_rect]; |
} |
+ |
+ if (!about_to_validate_and_paint_) |
+ [cocoa_view_ displayIfNeeded]; |
} |
+ // If |about_to_validate_and_paint_| is set, then -drawRect: is on the stack |
+ // and it's not allowed to call -setHidden on the accelerated view. In that |
+ // case, -callSetNeedsDisplayInRect: will hide it later. |
+ // If |about_to_validate_and_paint_| is not set, do it now. |
if (!about_to_validate_and_paint_) |
- [cocoa_view_ displayIfNeeded]; |
+ HandleDelayedGpuViewHiding(); |
} |
void RenderWidgetHostViewMac::RenderViewGone() { |
@@ -942,16 +951,15 @@ void RenderWidgetHostViewMac::AcceleratedSurfaceBuffersSwapped( |
[view setSurfaceWasSwapped:YES]; |
} |
-void RenderWidgetHostViewMac::GpuRenderingStateDidChange() { |
- CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
+void RenderWidgetHostViewMac::UpdateRootGpuViewVisibility( |
+ bool show_gpu_widget) { |
// Plugins are destroyed on page navigate. The compositor layer on the other |
// hand is created on demand and then stays alive until its renderer process |
// dies (usually on cross-domain navigation). Instead, only a flag |
// |is_gpu_rendering_active()| is flipped when the compositor output should be |
// shown/hidden. |
// Show/hide the view belonging to the compositor here. |
- plugin_container_manager_.set_gpu_rendering_active( |
- GetRenderWidgetHost()->is_gpu_rendering_active()); |
+ plugin_container_manager_.set_gpu_rendering_active(show_gpu_widget); |
gfx::PluginWindowHandle root_handle = |
plugin_container_manager_.root_container_handle(); |
@@ -963,10 +971,28 @@ void RenderWidgetHostViewMac::GpuRenderingStateDidChange() { |
} |
bool visible = |
plugin_container_manager_.SurfaceShouldBeVisible(root_handle); |
+ [[it->second window] disableScreenUpdatesUntilFlush]; |
[it->second setHidden:!visible]; |
} |
} |
+void RenderWidgetHostViewMac::HandleDelayedGpuViewHiding() { |
+ if (needs_gpu_visibility_update_after_repaint_) { |
+ UpdateRootGpuViewVisibility(false); |
+ needs_gpu_visibility_update_after_repaint_ = false; |
+ } |
+} |
+ |
+void RenderWidgetHostViewMac::GpuRenderingStateDidChange() { |
+ CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
+ if (GetRenderWidgetHost()->is_gpu_rendering_active()) { |
+ UpdateRootGpuViewVisibility( |
+ GetRenderWidgetHost()->is_gpu_rendering_active()); |
+ } else { |
+ needs_gpu_visibility_update_after_repaint_ = true; |
+ } |
+} |
+ |
void RenderWidgetHostViewMac::DrawAcceleratedSurfaceInstance( |
CGLContextObj context, |
gfx::PluginWindowHandle plugin_handle, |
@@ -1497,6 +1523,8 @@ void RenderWidgetHostViewMac::SetTextInputActive(bool active) { |
[self setNeedsDisplayInRect:renderWidgetHostView_->invalid_rect_]; |
renderWidgetHostView_->call_set_needs_display_in_rect_pending_ = false; |
renderWidgetHostView_->invalid_rect_ = NSZeroRect; |
+ |
+ renderWidgetHostView_->HandleDelayedGpuViewHiding(); |
} |
// Fills with white the parts of the area to the right and bottom for |rect| |