diff options
author | ananta@chromium.org <ananta@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-11-21 18:29:14 +0000 |
---|---|---|
committer | ananta@chromium.org <ananta@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-11-21 18:29:14 +0000 |
commit | f1a0eae704dcc8848847201d48922aa1984e522a (patch) | |
tree | 044105541a11d8db2468416711d2e9397e441038 /chrome | |
parent | db5de6e6dc5b1692f2aa557ab1931246f43b775d (diff) | |
download | chromium_src-f1a0eae704dcc8848847201d48922aa1984e522a.zip chromium_src-f1a0eae704dcc8848847201d48922aa1984e522a.tar.gz chromium_src-f1a0eae704dcc8848847201d48922aa1984e522a.tar.bz2 |
Relanding this fix. The earlier attempt broke test_shell_tests. The fix
has been added to this CB.
Fix Silverlight windowless plugin painting issues. This fixes the
following
issues:-
1. http://code.google.com/p/chromium/issues/detail?id=4272
2. http://code.google.com/p/chromium/issues/detail?id=301 (Partially)
The fixes are as below:-
1. Silverlight in the NPP_HandleEvent call for WM_PAINT,
calls NPN_GetProperty for a bunch of properties like
pageXOffset, pageYOffset, etc. It expects these
properties to have integer types on return. We always
return double. Firefox returns integer for these
properties. Added a check in the conversion
to NPVariant function in v8 to check for whether the
value is an integer and return the intger type.
2. When the windowless plugin calls NPN_InvalidateRect we
ask the plugin to paint in the same call, which the
Silverlight plugin does not like. It relies
on the fact that browsers would initiate invalidation
asynchronously and eventually paint. This is a perfectly
legal assumption. The Flash plugin does work if we
synchronously ask it to paint. However other plugins
could have similar issues. I verified with
worldofwarcraft.com to see if the async paint
has any sideeffects and there were none.
3.If the Silverlight plugin is not visible initially as on
msdn.microsoft.com, it does not paint. This occurs
because the plugin expects proper paints to
come from the browser. It does not invalidate itself in
UpdateGeometry as Flash. The plugin widget on msdn is not
dynamic. It does call NPN_InvalidateRect
initially when it is not visible. We don't send the call
to the renderer as the plugin is not visible. To workaround
this we now track the damaged rect even if the rect does not
intersect the clipping rect of the plugin. In a geometry update
if the plugin is visible, we send over the accumulated damaged rect
to the renderer.
The Silverlight plugin instance on msdn.microsoft.com does not work correctly
even with these fixes. However it paints correctly.
R=jam
Bug=4272,301
Review URL: http://codereview.chromium.org/11569
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@5829 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r-- | chrome/plugin/webplugin_proxy.cc | 28 | ||||
-rw-r--r-- | chrome/plugin/webplugin_proxy.h | 5 |
2 files changed, 27 insertions, 6 deletions
diff --git a/chrome/plugin/webplugin_proxy.cc b/chrome/plugin/webplugin_proxy.cc index 2cbb3ee..255c843 100644 --- a/chrome/plugin/webplugin_proxy.cc +++ b/chrome/plugin/webplugin_proxy.cc @@ -34,7 +34,9 @@ WebPluginProxy::WebPluginProxy( window_npobject_(NULL), plugin_element_(NULL), delegate_(delegate), - waiting_for_paint_(false) { + waiting_for_paint_(false), +#pragma warning(suppress: 4355) // can use this + runnable_method_factory_(this) { HANDLE event; BOOL result = DuplicateHandle(channel->renderer_handle(), @@ -84,21 +86,22 @@ void WebPluginProxy::Invalidate() { } void WebPluginProxy::InvalidateRect(const gfx::Rect& rect) { + damaged_rect_ = damaged_rect_.Union(rect); // Ignore NPN_InvalidateRect calls with empty rects. Also don't send an // invalidate if it's outside the clipping region, since if we did it won't // lead to a paint and we'll be stuck waiting forever for a DidPaint response. if (rect.IsEmpty() || !delegate_->clip_rect().Intersects(rect)) return; - damaged_rect_ = damaged_rect_.Union(rect); // Only send a single InvalidateRect message at a time. From DidPaint we // will dispatch an additional InvalidateRect message if necessary. if (!waiting_for_paint_) { waiting_for_paint_ = true; - // Paint to the plugin bitmap and let the renderer know so it can update - // its backing store. - Paint(damaged_rect_); - Send(new PluginHostMsg_InvalidateRect(route_id_, damaged_rect_)); + // Invalidates caused by calls to NPN_InvalidateRect/NPN_InvalidateRgn + // need to be painted asynchronously as per the NPAPI spec. + MessageLoop::current()->PostTask(FROM_HERE, + runnable_method_factory_.NewRunnableMethod( + &WebPluginProxy::OnPaint, damaged_rect_)); damaged_rect_ = gfx::Rect(); } } @@ -282,6 +285,8 @@ void WebPluginProxy::UpdateGeometry( const base::SharedMemoryHandle& windowless_buffer, const base::SharedMemoryHandle& background_buffer) { gfx::Rect old = delegate_->rect(); + gfx::Rect old_clip_rect = delegate_->clip_rect(); + bool moved = delegate_->rect().x() != window_rect.x() || delegate_->rect().y() != window_rect.y(); delegate_->UpdateGeometry(window_rect, clip_rect, cutout_rects, visible); @@ -292,6 +297,12 @@ void WebPluginProxy::UpdateGeometry( // The plugin moved, so update our world transform. UpdateTransform(); } + // Send over any pending invalidates which occured when the plugin was + // off screen. + if (visible && delegate_->windowless() && !clip_rect.IsEmpty() && + old_clip_rect.IsEmpty() && !damaged_rect_.IsEmpty()) { + InvalidateRect(damaged_rect_); + } } void WebPluginProxy::SetWindowlessBuffer( @@ -376,3 +387,8 @@ void WebPluginProxy::InitiateHTTPRangeRequest(const char* url, range_info, existing_stream, notify_needed, notify_data)); } + +void WebPluginProxy::OnPaint(const gfx::Rect& damaged_rect) { + Paint(damaged_rect); + Send(new PluginHostMsg_InvalidateRect(route_id_, damaged_rect)); +} diff --git a/chrome/plugin/webplugin_proxy.h b/chrome/plugin/webplugin_proxy.h index e6a231d..c2cefc7 100644 --- a/chrome/plugin/webplugin_proxy.h +++ b/chrome/plugin/webplugin_proxy.h @@ -108,6 +108,9 @@ class WebPluginProxy : public WebPlugin { ScopedBitmap* bitmap, ScopedHDC* hdc); + // Handler for sending over the paint event to the plugin. + void OnPaint(const gfx::Rect& damaged_rect); + // Called when a plugin's origin moves, so that we can update the world // transform of the local HDC. void UpdateTransform(); @@ -137,6 +140,8 @@ class WebPluginProxy : public WebPlugin { ScopedHandle background_shared_section_; ScopedBitmap background_bitmap_; ScopedHDC background_hdc_; + + ScopedRunnableMethodFactory<WebPluginProxy> runnable_method_factory_; }; #endif // CHROME_PLUGIN_PLUGIN_WEBPLUGIN_PROXY_H__ |