summaryrefslogtreecommitdiffstats
path: root/webkit
diff options
context:
space:
mode:
authorjam@chromium.org <jam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-01-16 23:04:23 +0000
committerjam@chromium.org <jam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-01-16 23:04:23 +0000
commitd7f4595986302dcf131b943152a843d067e53c1e (patch)
tree7165e6c839aaae33587dab4dbc28df862d1c8428 /webkit
parentefb07436b9ba4737247cdf0e8ba0529e27942468 (diff)
downloadchromium_src-d7f4595986302dcf131b943152a843d067e53c1e.zip
chromium_src-d7f4595986302dcf131b943152a843d067e53c1e.tar.gz
chromium_src-d7f4595986302dcf131b943152a843d067e53c1e.tar.bz2
Improve scrolling performance when there are many windowed plugins in a page.
This works by parenting windowed plugins with an HWND that's hosted in the browser process, so that no synchronous cross process messages are used when scrolling. BUG=5428 Review URL: http://codereview.chromium.org/18082 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@8239 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'webkit')
-rw-r--r--webkit/glue/plugins/test/plugin_npobject_lifetime_test.cc3
-rw-r--r--webkit/glue/plugins/webplugin_delegate_impl.cc89
-rw-r--r--webkit/glue/plugins/webplugin_delegate_impl.h23
-rw-r--r--webkit/glue/webplugin_delegate.h8
-rw-r--r--webkit/glue/webplugin_impl.cc87
-rw-r--r--webkit/glue/webplugin_impl.h6
-rw-r--r--webkit/tools/test_shell/test_webview_delegate.cc30
7 files changed, 87 insertions, 159 deletions
diff --git a/webkit/glue/plugins/test/plugin_npobject_lifetime_test.cc b/webkit/glue/plugins/test/plugin_npobject_lifetime_test.cc
index 8f3a89f..2907a5e 100644
--- a/webkit/glue/plugins/test/plugin_npobject_lifetime_test.cc
+++ b/webkit/glue/plugins/test/plugin_npobject_lifetime_test.cc
@@ -113,9 +113,6 @@ NPObjectDeletePluginInNPN_Evaluate::~NPObjectDeletePluginInNPN_Evaluate() {
}
NPError NPObjectDeletePluginInNPN_Evaluate::SetWindow(NPWindow* np_window) {
- if (!::IsWindowVisible(reinterpret_cast<HWND>(np_window->window)))
- return NPERR_NO_ERROR;
-
HWND window_handle = reinterpret_cast<HWND>(np_window->window);
// We setup a timerproc to invoke NPN_Evaluate to destroy this plugin
// instance. This is to ensure that we don't destroy the plugin instance
diff --git a/webkit/glue/plugins/webplugin_delegate_impl.cc b/webkit/glue/plugins/webplugin_delegate_impl.cc
index 0f713d7..a0de8da 100644
--- a/webkit/glue/plugins/webplugin_delegate_impl.cc
+++ b/webkit/glue/plugins/webplugin_delegate_impl.cc
@@ -9,8 +9,6 @@
#include "base/file_util.h"
#include "base/message_loop.h"
-#include "base/gfx/gdi_util.h"
-#include "base/gfx/point.h"
#include "base/stats_counters.h"
#include "base/string_util.h"
#include "webkit/default_plugin/plugin_impl.h"
@@ -133,7 +131,6 @@ WebPluginDelegateImpl::WebPluginDelegateImpl(
plugin_wnd_proc_(NULL),
last_message_(0),
is_calling_wndproc(false),
- initial_plugin_resize_done_(false),
dummy_window_for_activation_(NULL),
handle_event_message_filter_hook_(NULL),
handle_event_pump_messages_event_(NULL),
@@ -322,13 +319,11 @@ void WebPluginDelegateImpl::DestroyInstance() {
void WebPluginDelegateImpl::UpdateGeometry(
const gfx::Rect& window_rect,
- const gfx::Rect& clip_rect,
- const std::vector<gfx::Rect>& cutout_rects,
- bool visible) {
+ const gfx::Rect& clip_rect) {
if (windowless_) {
WindowlessUpdateGeometry(window_rect, clip_rect);
} else {
- WindowedUpdateGeometry(window_rect, clip_rect, cutout_rects, visible);
+ WindowedUpdateGeometry(window_rect, clip_rect);
}
}
@@ -377,6 +372,12 @@ void WebPluginDelegateImpl::SendJavaScriptStream(const std::string& url,
void WebPluginDelegateImpl::DidReceiveManualResponse(
const std::string& url, const std::string& mime_type,
const std::string& headers, uint32 expected_length, uint32 last_modified) {
+ if (!windowless_) {
+ // Calling NPP_WriteReady before NPP_SetWindow causes movies to not load in
+ // Flash. See http://b/issue?id=892174.
+ DCHECK(windowed_did_set_window_);
+ }
+
instance()->DidReceiveManualResponse(url, mime_type, headers,
expected_length, last_modified);
}
@@ -408,10 +409,8 @@ void WebPluginDelegateImpl::InstallMissingPlugin() {
void WebPluginDelegateImpl::WindowedUpdateGeometry(
const gfx::Rect& window_rect,
- const gfx::Rect& clip_rect,
- const std::vector<gfx::Rect>& cutout_rects,
- bool visible) {
- if (WindowedReposition(window_rect, clip_rect, cutout_rects, visible) ||
+ const gfx::Rect& clip_rect) {
+ if (WindowedReposition(window_rect, clip_rect) ||
!windowed_did_set_window_) {
// Let the plugin know that it has been moved
WindowedSetWindow();
@@ -663,69 +662,33 @@ bool WebPluginDelegateImpl::CreateDummyWindowForActivation() {
return true;
}
-void WebPluginDelegateImpl::MoveWindow(
- HWND window,
- const gfx::Rect& window_rect,
- const gfx::Rect& clip_rect,
- const std::vector<gfx::Rect>& cutout_rects,
- bool visible) {
- HRGN hrgn = ::CreateRectRgn(clip_rect.x(),
- clip_rect.y(),
- clip_rect.right(),
- clip_rect.bottom());
- gfx::SubtractRectanglesFromRegion(hrgn, cutout_rects);
-
- // Note: System will own the hrgn after we call SetWindowRgn,
- // so we don't need to call DeleteObject(hrgn)
- ::SetWindowRgn(window, hrgn, FALSE);
-
- unsigned long flags = 0;
- if (visible)
- flags |= SWP_SHOWWINDOW;
- else
- flags |= SWP_HIDEWINDOW;
-
- ::SetWindowPos(window,
- NULL,
- window_rect.x(),
- window_rect.y(),
- window_rect.width(),
- window_rect.height(),
- flags);
-}
-
bool WebPluginDelegateImpl::WindowedReposition(
const gfx::Rect& window_rect,
- const gfx::Rect& clip_rect,
- const std::vector<gfx::Rect>& cutout_rects,
- bool visible) {
+ const gfx::Rect& clip_rect) {
if (!windowed_handle_) {
NOTREACHED();
return false;
}
- if (window_rect_ == window_rect && clip_rect_ == clip_rect &&
- cutout_rects == cutout_rects_ &&
- initial_plugin_resize_done_)
+ if (window_rect_ == window_rect && clip_rect_ == clip_rect)
return false;
+ // Clipping is handled by WebPlugin.
+ if (window_rect.size() != window_rect_.size()) {
+ ::SetWindowPos(windowed_handle_,
+ NULL,
+ 0,
+ 0,
+ window_rect.width(),
+ window_rect.height(),
+ SWP_SHOWWINDOW);
+ }
+
window_rect_ = window_rect;
clip_rect_ = clip_rect;
- cutout_rects_ = cutout_rects;
-
- if (!initial_plugin_resize_done_) {
- // We need to ensure that the plugin process continues to reposition
- // the plugin window until we receive an indication that it is now visible.
- // Subsequent repositions will be done by the browser.
- if (visible)
- initial_plugin_resize_done_ = true;
- // We created the window with 0 width and height since we didn't know it
- // at the time. Now that we know the geometry, we we can update its size
- // since the browser only calls SetWindowPos when scrolling occurs.
- MoveWindow(windowed_handle_, window_rect, clip_rect, cutout_rects, visible);
- // Ensure that the entire window gets repainted.
- ::InvalidateRect(windowed_handle_, NULL, FALSE);
- }
+
+ // Ensure that the entire window gets repainted.
+ ::InvalidateRect(windowed_handle_, NULL, FALSE);
return true;
}
diff --git a/webkit/glue/plugins/webplugin_delegate_impl.h b/webkit/glue/plugins/webplugin_delegate_impl.h
index 468d3c7..d01046c 100644
--- a/webkit/glue/plugins/webplugin_delegate_impl.h
+++ b/webkit/glue/plugins/webplugin_delegate_impl.h
@@ -44,9 +44,7 @@ class WebPluginDelegateImpl : public WebPluginDelegate {
WebPlugin* plugin,
bool load_manually);
virtual void UpdateGeometry(const gfx::Rect& window_rect,
- const gfx::Rect& clip_rect,
- const std::vector<gfx::Rect>& cutout_rects,
- bool visible);
+ const gfx::Rect& clip_rect);
virtual void Paint(HDC hdc, const gfx::Rect& rect);
virtual void Print(HDC hdc);
virtual void SetFocus(); // only called when windowless
@@ -99,12 +97,6 @@ class WebPluginDelegateImpl : public WebPluginDelegate {
int quirks() { return quirks_; }
- static void MoveWindow(HWND window,
- const gfx::Rect& window_rect,
- const gfx::Rect& clip_rect,
- const std::vector<gfx::Rect>& cutout_rects,
- bool visible);
-
private:
WebPluginDelegateImpl(gfx::NativeView containing_view,
NPAPI::PluginInstance *instance);
@@ -113,9 +105,7 @@ class WebPluginDelegateImpl : public WebPluginDelegate {
//--------------------------
// used for windowed plugins
void WindowedUpdateGeometry(const gfx::Rect& window_rect,
- const gfx::Rect& clip_rect,
- const std::vector<gfx::Rect>& cutout_rects,
- bool visible);
+ const gfx::Rect& clip_rect);
// Create the native window.
// Returns true if the window is created (or already exists).
// Returns false if unable to create the window.
@@ -127,9 +117,7 @@ class WebPluginDelegateImpl : public WebPluginDelegate {
// Reposition the native window to be in sync with the given geometry.
// Returns true if the native window has moved or been clipped differently.
bool WindowedReposition(const gfx::Rect& window_rect,
- const gfx::Rect& clip_rect,
- const std::vector<gfx::Rect>& cutout_rects,
- bool visible);
+ const gfx::Rect& clip_rect);
// Tells the plugin about the current state of the window.
// See NPAPI NPP_SetWindow for more information.
@@ -202,11 +190,6 @@ class WebPluginDelegateImpl : public WebPluginDelegate {
std::vector<gfx::Rect> cutout_rects_;
int quirks_;
- // We only move/size the plugin window once after its creation. The
- // rest of the moves are controlled by the browser. This flag controls
- // this behaviour.
- bool initial_plugin_resize_done_;
-
// Windowless plugins don't have keyboard focus causing issues with the
// plugin not receiving keyboard events if the plugin enters a modal
// loop like TrackPopupMenuEx or MessageBox, etc.
diff --git a/webkit/glue/webplugin_delegate.h b/webkit/glue/webplugin_delegate.h
index bfa462a..7ffd952 100644
--- a/webkit/glue/webplugin_delegate.h
+++ b/webkit/glue/webplugin_delegate.h
@@ -48,13 +48,9 @@ class WebPluginDelegate {
// plugin, relative to its containing window, to the coords given by
// window_rect. Its contents should be clipped to the coords given
// by clip_rect, which are relative to the origin of the plugin
- // window. It's contents should also not overlap the given cutout
- // rects. The clip_rect and cutout_rects are in plugin-relative
- // coordinates.
+ // window. The clip_rect is in plugin-relative coordinates.
virtual void UpdateGeometry(const gfx::Rect& window_rect,
- const gfx::Rect& clip_rect,
- const std::vector<gfx::Rect>& cutout_rects,
- bool visible) = 0;
+ const gfx::Rect& clip_rect) = 0;
// Tells the plugin to paint the damaged rect. The HDC is only used for
// windowless plugins.
diff --git a/webkit/glue/webplugin_impl.cc b/webkit/glue/webplugin_impl.cc
index 003ece7..72234ad 100644
--- a/webkit/glue/webplugin_impl.cc
+++ b/webkit/glue/webplugin_impl.cc
@@ -134,6 +134,11 @@ bool WebPluginContainer::isPluginView() const {
void WebPluginContainer::setFrameRect(const WebCore::IntRect& rect) {
+ // WebKit calls move every time it paints (see RenderWidget::paint). No need
+ // to do expensive operations if we didn't actually move.
+ if (rect == frameRect())
+ return;
+
WebCore::Widget::setFrameRect(rect);
impl_->setFrameRect(rect);
}
@@ -166,12 +171,8 @@ void WebPluginContainer::setFocus() {
void WebPluginContainer::show() {
// We don't want to force a geometry update when the plugin widget is
// already visible as this involves a geometry update which may lead
- // to unnecessary window moves in the plugin process. The only case
- // where this does not apply is if the force_geometry_update_ flag
- // is set, which occurs when a plugin is created and does not have
- // a parent. We can send out geometry updates only when the plugin
- // widget has a parent.
- if (!impl_->visible_ || impl_->force_geometry_update_) {
+ // to unnecessary window moves in the plugin process.
+ if (!impl_->visible_) {
impl_->show();
WebCore::Widget::show();
// This is to force an updategeometry call to the plugin process
@@ -181,9 +182,7 @@ void WebPluginContainer::show() {
}
void WebPluginContainer::hide() {
- // Please refer to WebPluginContainer::show for the reasoning behind
- // the if check below.
- if (impl_->visible_ || impl_->force_geometry_update_) {
+ if (impl_->visible_) {
impl_->hide();
WebCore::Widget::hide();
// This is to force an updategeometry call to the plugin process
@@ -216,6 +215,18 @@ void WebPluginContainer::setParentVisible(bool visible) {
hide();
}
+// We override this function so that if the plugin is windowed, we can call
+// NPP_SetWindow at the first possible moment. This ensures that NPP_SetWindow
+// is called before the manual load data is sent to a plugin. If this order is
+// reversed, Flash won't load videos.
+void WebPluginContainer::setParent(WebCore::ScrollView* view) {
+ WebCore::Widget::setParent(view);
+ if (view) {
+ impl_->setFrameRect(frameRect());
+ impl_->delegate_->FlushGeometryUpdates();
+ }
+}
+
void WebPluginContainer::windowCutoutRects(const WebCore::IntRect& bounds,
WTF::Vector<WebCore::IntRect>*
cutouts) const {
@@ -224,7 +235,6 @@ void WebPluginContainer::windowCutoutRects(const WebCore::IntRect& bounds,
void WebPluginContainer::didReceiveResponse(
const WebCore::ResourceResponse& response) {
-
set_ignore_response_error(false);
HttpResponseInfo http_response_info;
@@ -315,9 +325,7 @@ WebPluginImpl::WebPluginImpl(WebCore::Element* element,
element_(element),
webframe_(webframe),
delegate_(delegate),
- force_geometry_update_(false),
visible_(false),
- received_first_paint_notification_(false),
widget_(NULL),
plugin_url_(plugin_url),
load_manually_(load_manually),
@@ -634,18 +642,11 @@ void WebPluginImpl::windowCutoutRects(
}
void WebPluginImpl::setFrameRect(const WebCore::IntRect& rect) {
- // Compute a new position and clip rect for ourselves relative to the
- // containing window. We ask our delegate to reposition us accordingly.
-
- // When the plugin is loaded we don't have a parent frame yet. We need
- // to force the plugin window to get created in the plugin process,
- // when the plugin widget position is updated. This occurs just after
- // the plugin is loaded (See http://b/issue?id=892174).
- if (!parent()) {
- force_geometry_update_ = true;
+ if (!parent())
return;
- }
+ // Compute a new position and clip rect for ourselves relative to the
+ // containing window. We ask our delegate to reposition us accordingly.
WebCore::Frame* frame = element_->document()->frame();
WebFrameImpl* webframe = WebFrameImpl::FromFrame(frame);
WebViewImpl* webview = webframe->webview_impl();
@@ -660,7 +661,11 @@ void WebPluginImpl::setFrameRect(const WebCore::IntRect& rect) {
std::vector<gfx::Rect> cutout_rects;
CalculateBounds(rect, &window_rect, &clip_rect, &cutout_rects);
- if (window_ && received_first_paint_notification_) {
+ delegate_->UpdateGeometry(
+ webkit_glue::FromIntRect(window_rect),
+ webkit_glue::FromIntRect(clip_rect));
+
+ if (window_) {
// Let the WebViewDelegate know that the plugin window needs to be moved,
// so that all the HWNDs are moved together.
WebPluginGeometry move;
@@ -673,17 +678,6 @@ void WebPluginImpl::setFrameRect(const WebCore::IntRect& rect) {
webview->delegate()->DidMove(webview, move);
}
- delegate_->UpdateGeometry(
- webkit_glue::FromIntRect(window_rect),
- webkit_glue::FromIntRect(clip_rect), cutout_rects,
- windowless_ || received_first_paint_notification_ ? visible_ : false);
-
- // delegate_ can go away as a result of above call, so check it first.
- if (force_geometry_update_ && delegate_) {
- force_geometry_update_ = false;
- delegate_->FlushGeometryUpdates();
- }
-
// Initiate a download on the plugin url. This should be done for the
// first update geometry sequence.
if (first_geometry_update_) {
@@ -709,31 +703,6 @@ void WebPluginImpl::paint(WebCore::GraphicsContext* gc,
if (!widget_->frameRect().intersects(damage_rect))
return;
- // A windowed plugin starts out by being invisible regardless of the style
- // which webkit tells us. The paint notification from webkit indicates that
- // the plugin widget is being shown and we need to make sure that
- // it becomes visible.
- // Please refer to https://bugs.webkit.org/show_bug.cgi?id=18901 for more
- // details on this issue.
- // TODO(iyengar): Remove this hack when this issue is fixed in webkit.
- if (!received_first_paint_notification_) {
- received_first_paint_notification_ = true;
-
- if (!windowless_) {
- WebCore::IntRect window_rect;
- WebCore::IntRect clip_rect;
- std::vector<gfx::Rect> cutout_rects;
-
- CalculateBounds(widget_->frameRect(), &window_rect, &clip_rect,
- &cutout_rects);
-
- delegate_->UpdateGeometry(webkit_glue::FromIntRect(window_rect),
- webkit_glue::FromIntRect(clip_rect),
- cutout_rects, visible_);
- delegate_->FlushGeometryUpdates();
- }
- }
-
gc->save();
DCHECK(parent()->isFrameView());
diff --git a/webkit/glue/webplugin_impl.h b/webkit/glue/webplugin_impl.h
index 1d11d71..3654d3a 100644
--- a/webkit/glue/webplugin_impl.h
+++ b/webkit/glue/webplugin_impl.h
@@ -41,6 +41,7 @@ namespace WebCore {
class ResourceHandle;
class ResourceError;
class ResourceResponse;
+ class ScrollView;
class String;
class Widget;
}
@@ -66,6 +67,7 @@ class WebPluginContainer : public WebCore::Widget {
virtual void handleEvent(WebCore::Event* event);
virtual void frameRectsChanged();
virtual void setParentVisible(bool visible);
+ virtual void setParent(WebCore::ScrollView* view);
#if USE(JSC)
virtual bool isPluginView() const;
@@ -325,11 +327,7 @@ class WebPluginImpl : public WebPlugin,
WebFrameImpl* webframe_;
WebPluginDelegate* delegate_;
- bool force_geometry_update_;
bool visible_;
- // Set when we receive the first paint notification for a windowed
- // plugin widget.
- bool received_first_paint_notification_;
WebPluginContainer* widget_;
diff --git a/webkit/tools/test_shell/test_webview_delegate.cc b/webkit/tools/test_shell/test_webview_delegate.cc
index fc28aa1..631d48e 100644
--- a/webkit/tools/test_shell/test_webview_delegate.cc
+++ b/webkit/tools/test_shell/test_webview_delegate.cc
@@ -29,6 +29,7 @@
#if defined(OS_WIN)
// TODO(port): make these files work everywhere.
+#include "base/gfx/gdi_util.h"
#include "webkit/glue/plugins/webplugin_delegate_impl.h"
#include "webkit/tools/test_shell/drag_delegate.h"
#include "webkit/tools/test_shell/drop_delegate.h"
@@ -696,11 +697,32 @@ void TestWebViewDelegate::Blur(WebWidget* webwidget) {
void TestWebViewDelegate::DidMove(WebWidget* webwidget,
const WebPluginGeometry& move) {
#if defined(OS_WIN)
- // TODO(port): add me once plugins work.
- WebPluginDelegateImpl::MoveWindow(
- move.window, move.window_rect, move.clip_rect, move.cutout_rects,
- move.visible);
+ HRGN hrgn = ::CreateRectRgn(move.clip_rect.x(),
+ move.clip_rect.y(),
+ move.clip_rect.right(),
+ move.clip_rect.bottom());
+ gfx::SubtractRectanglesFromRegion(hrgn, move.cutout_rects);
+
+ // Note: System will own the hrgn after we call SetWindowRgn,
+ // so we don't need to call DeleteObject(hrgn)
+ ::SetWindowRgn(move.window, hrgn, FALSE);
+
+ unsigned long flags = 0;
+ if (move.visible)
+ flags |= SWP_SHOWWINDOW;
+ else
+ flags |= SWP_HIDEWINDOW;
+
+ ::SetWindowPos(move.window,
+ NULL,
+ move.window_rect.x(),
+ move.window_rect.y(),
+ move.window_rect.width(),
+ move.window_rect.height(),
+ flags);
+
#endif
+ // TODO(port): add me once plugins work.
}
bool TestWebViewDelegate::IsHidden() {