Draw intermediate snapshots if possible
https://bugs.webkit.org/show_bug.cgi?id=110811
Reviewed by Simon Fraser.
After http://webkit.org/b/110495 we delayed snapshotting until we've
received a nice image, but this made the page look like it is broken.
We should draw any intermediate snapshots that we find, which might
include content such as progress bars/spinners.
Source/WebCore:
* html/HTMLPlugInElement.h:
(WebCore::HTMLPlugInElement::isPlugInImageElement): Expose virtual method
to indicate if this is a HTMLPlugInImageElement or not.
* html/HTMLPlugInImageElement.cpp:
(WebCore::HTMLPlugInImageElement::updateSnapshot): If we have
a RenderEmbeddedObject renderer, then tell it to repaint.
* html/HTMLPlugInImageElement.h:
(WebCore::HTMLPlugInImageElement::snapshotImage): Expose an
accessor for snapshot images.
* rendering/RenderEmbeddedObject.cpp:
(WebCore::RenderEmbeddedObject::paintSnapshotImage): New helper
method to render an image directly. This code is similar to
that in RenderSnapshottedPlugIn.
(WebCore::RenderEmbeddedObject::paintContents): The virtual implementation
of this method for use when we have a snapshot to paint. If we are a plugin that is
in the process of being snapshotted, ask our HTMLPlugInImageElement for a
snapshot and paint that instead. In the case where we are not snapshotting,
or we do not yet have a snapshot, this will call back into the RenderWidget code.
* rendering/RenderEmbeddedObject.h:
(RenderEmbeddedObject): New methods paintSnapshotImage and paintContents
* rendering/RenderWidget.cpp:
(WebCore::RenderWidget::paintContents): New method called in the middle
of paint() that can be overridden by RenderEmbeddedObject. The code here was
simply moved out of the previous paint().
(WebCore::RenderWidget::paint): Call paintContents at the appropriate time.
* rendering/RenderWidget.h:
(RenderWidget): New virtual method paintContents.
Source/WebKit2:
* WebProcess/Plugins/PluginView.cpp:
(WebKit): Reinstate 60 attempts at snapshots before giving up.
(WebKit::PluginView::isAcceleratedCompositingEnabled): We do not
want accelerated compositing enabled when we are trying to capture
snapshots.
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@144067 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog
index dd83bcb..020706d 100644
--- a/Source/WebCore/ChangeLog
+++ b/Source/WebCore/ChangeLog
@@ -1,3 +1,43 @@
+2013-02-26 Dean Jackson <dino@apple.com>
+
+ Draw intermediate snapshots if possible
+ https://bugs.webkit.org/show_bug.cgi?id=110811
+
+ Reviewed by Simon Fraser.
+
+ After http://webkit.org/b/110495 we delayed snapshotting until we've
+ received a nice image, but this made the page look like it is broken.
+ We should draw any intermediate snapshots that we find, which might
+ include content such as progress bars/spinners.
+
+ * html/HTMLPlugInElement.h:
+ (WebCore::HTMLPlugInElement::isPlugInImageElement): Expose virtual method
+ to indicate if this is a HTMLPlugInImageElement or not.
+ * html/HTMLPlugInImageElement.cpp:
+ (WebCore::HTMLPlugInImageElement::updateSnapshot): If we have
+ a RenderEmbeddedObject renderer, then tell it to repaint.
+ * html/HTMLPlugInImageElement.h:
+ (WebCore::HTMLPlugInImageElement::snapshotImage): Expose an
+ accessor for snapshot images.
+ * rendering/RenderEmbeddedObject.cpp:
+ (WebCore::RenderEmbeddedObject::paintSnapshotImage): New helper
+ method to render an image directly. This code is similar to
+ that in RenderSnapshottedPlugIn.
+ (WebCore::RenderEmbeddedObject::paintContents): The virtual implementation
+ of this method for use when we have a snapshot to paint. If we are a plugin that is
+ in the process of being snapshotted, ask our HTMLPlugInImageElement for a
+ snapshot and paint that instead. In the case where we are not snapshotting,
+ or we do not yet have a snapshot, this will call back into the RenderWidget code.
+ * rendering/RenderEmbeddedObject.h:
+ (RenderEmbeddedObject): New methods paintSnapshotImage and paintContents
+ * rendering/RenderWidget.cpp:
+ (WebCore::RenderWidget::paintContents): New method called in the middle
+ of paint() that can be overridden by RenderEmbeddedObject. The code here was
+ simply moved out of the previous paint().
+ (WebCore::RenderWidget::paint): Call paintContents at the appropriate time.
+ * rendering/RenderWidget.h:
+ (RenderWidget): New virtual method paintContents.
+
2013-02-26 Levi Weintraub <leviw@chromium.org>
Add support for 8 bit TextRuns for Chromium/HarfBuzz
diff --git a/Source/WebCore/html/HTMLPlugInElement.h b/Source/WebCore/html/HTMLPlugInElement.h
index ce6fd02..a7559a8 100644
--- a/Source/WebCore/html/HTMLPlugInElement.h
+++ b/Source/WebCore/html/HTMLPlugInElement.h
@@ -74,6 +74,8 @@
virtual bool willRespondToMouseClickEvents() OVERRIDE;
+ virtual bool isPlugInImageElement() const { return false; }
+
protected:
HTMLPlugInElement(const QualifiedName& tagName, Document*);
diff --git a/Source/WebCore/html/HTMLPlugInImageElement.cpp b/Source/WebCore/html/HTMLPlugInImageElement.cpp
index b165b2d..84e0edd 100644
--- a/Source/WebCore/html/HTMLPlugInImageElement.cpp
+++ b/Source/WebCore/html/HTMLPlugInImageElement.cpp
@@ -284,10 +284,14 @@
return;
m_snapshotImage = image;
+
if (renderer()->isSnapshottedPlugIn()) {
toRenderSnapshottedPlugIn(renderer())->updateSnapshot(image);
return;
}
+
+ if (renderer()->isEmbeddedObject())
+ renderer()->repaint();
}
static AtomicString classNameForShadowRoot(const Node* node)
diff --git a/Source/WebCore/html/HTMLPlugInImageElement.h b/Source/WebCore/html/HTMLPlugInImageElement.h
index e6a3fe9..f85b3f2 100644
--- a/Source/WebCore/html/HTMLPlugInImageElement.h
+++ b/Source/WebCore/html/HTMLPlugInImageElement.h
@@ -66,6 +66,7 @@
void userDidClickSnapshot(PassRefPtr<MouseEvent>);
void updateSnapshotInfo();
+ Image* snapshotImage() const { return m_snapshotImage.get(); }
// Plug-in URL might not be the same as url() with overriding parameters.
void subframeLoaderWillCreatePlugIn(const KURL& plugInURL);
@@ -111,6 +112,8 @@
void swapRendererTimerFired(Timer<HTMLPlugInImageElement>*);
+ virtual bool isPlugInImageElement() const OVERRIDE { return true; }
+
bool m_needsWidgetUpdate;
bool m_shouldPreferPlugInsForImages;
bool m_needsDocumentActivationCallbacks;
diff --git a/Source/WebCore/rendering/RenderEmbeddedObject.cpp b/Source/WebCore/rendering/RenderEmbeddedObject.cpp
index 5d16d28..aabe76c 100644
--- a/Source/WebCore/rendering/RenderEmbeddedObject.cpp
+++ b/Source/WebCore/rendering/RenderEmbeddedObject.cpp
@@ -148,6 +148,47 @@
repaint();
}
+void RenderEmbeddedObject::paintSnapshotImage(PaintInfo& paintInfo, const LayoutPoint& paintOffset, Image* image)
+{
+ LayoutUnit cWidth = contentWidth();
+ LayoutUnit cHeight = contentHeight();
+ if (!cWidth || !cHeight)
+ return;
+
+ GraphicsContext* context = paintInfo.context;
+ LayoutSize contentSize(cWidth, cHeight);
+ LayoutPoint contentLocation = location() + paintOffset;
+ contentLocation.move(borderLeft() + paddingLeft(), borderTop() + paddingTop());
+
+ LayoutRect rect(contentLocation, contentSize);
+ IntRect alignedRect = pixelSnappedIntRect(rect);
+ if (alignedRect.width() <= 0 || alignedRect.height() <= 0)
+ return;
+
+ bool useLowQualityScaling = shouldPaintAtLowQuality(context, image, image, alignedRect.size());
+ context->drawImage(image, style()->colorSpace(), alignedRect, CompositeSourceOver, shouldRespectImageOrientation(), useLowQualityScaling);
+}
+
+void RenderEmbeddedObject::paintContents(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
+{
+ Element* element = static_cast<Element*>(node());
+ if (!element || !element->isPluginElement())
+ return;
+
+ HTMLPlugInElement* plugInElement = static_cast<HTMLPlugInElement*>(element);
+ if (plugInElement->displayState() > HTMLPlugInElement::DisplayingSnapshot) {
+ RenderPart::paintContents(paintInfo, paintOffset);
+ return;
+ }
+
+ if (!plugInElement->isPlugInImageElement())
+ return;
+
+ Image* snapshot = static_cast<HTMLPlugInImageElement*>(plugInElement)->snapshotImage();
+ if (snapshot)
+ paintSnapshotImage(paintInfo, paintOffset, snapshot);
+}
+
void RenderEmbeddedObject::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
{
Page* page = 0;
diff --git a/Source/WebCore/rendering/RenderEmbeddedObject.h b/Source/WebCore/rendering/RenderEmbeddedObject.h
index 277d2ec..6964707 100644
--- a/Source/WebCore/rendering/RenderEmbeddedObject.h
+++ b/Source/WebCore/rendering/RenderEmbeddedObject.h
@@ -75,6 +75,9 @@
virtual const char* renderName() const { return "RenderEmbeddedObject"; }
virtual bool isEmbeddedObject() const { return true; }
+ void paintSnapshotImage(PaintInfo&, const LayoutPoint&, Image*);
+ virtual void paintContents(PaintInfo&, const LayoutPoint&) OVERRIDE;
+
#if USE(ACCELERATED_COMPOSITING)
virtual bool requiresLayer() const;
#endif
diff --git a/Source/WebCore/rendering/RenderWidget.cpp b/Source/WebCore/rendering/RenderWidget.cpp
index fb396f0..c07681f 100644
--- a/Source/WebCore/rendering/RenderWidget.cpp
+++ b/Source/WebCore/rendering/RenderWidget.cpp
@@ -235,6 +235,39 @@
m_widget->notifyWidget(notification);
}
+void RenderWidget::paintContents(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
+{
+ LayoutPoint adjustedPaintOffset = paintOffset + location();
+
+ // Tell the widget to paint now. This is the only time the widget is allowed
+ // to paint itself. That way it will composite properly with z-indexed layers.
+ IntPoint widgetLocation = m_widget->frameRect().location();
+ IntPoint paintLocation(roundToInt(adjustedPaintOffset.x() + borderLeft() + paddingLeft()),
+ roundToInt(adjustedPaintOffset.y() + borderTop() + paddingTop()));
+ IntRect paintRect = paintInfo.rect;
+
+ IntSize widgetPaintOffset = paintLocation - widgetLocation;
+ // When painting widgets into compositing layers, tx and ty are relative to the enclosing compositing layer,
+ // not the root. In this case, shift the CTM and adjust the paintRect to be root-relative to fix plug-in drawing.
+ if (!widgetPaintOffset.isZero()) {
+ paintInfo.context->translate(widgetPaintOffset);
+ paintRect.move(-widgetPaintOffset);
+ }
+ m_widget->paint(paintInfo.context, paintRect);
+
+ if (!widgetPaintOffset.isZero())
+ paintInfo.context->translate(-widgetPaintOffset);
+
+ if (m_widget->isFrameView()) {
+ FrameView* frameView = static_cast<FrameView*>(m_widget.get());
+ bool runOverlapTests = !frameView->useSlowRepaintsIfNotOverlapped() || frameView->hasCompositedContentIncludingDescendants();
+ if (paintInfo.overlapTestRequests && runOverlapTests) {
+ ASSERT(!paintInfo.overlapTestRequests->contains(this));
+ paintInfo.overlapTestRequests->set(this, m_widget->frameRect());
+ }
+ }
+}
+
void RenderWidget::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
{
if (!shouldPaint(paintInfo, paintOffset))
@@ -274,35 +307,8 @@
clipRoundedInnerRect(paintInfo.context, borderRect, roundedInnerRect);
}
- if (m_widget) {
- // Tell the widget to paint now. This is the only time the widget is allowed
- // to paint itself. That way it will composite properly with z-indexed layers.
- IntPoint widgetLocation = m_widget->frameRect().location();
- IntPoint paintLocation(roundToInt(adjustedPaintOffset.x() + borderLeft() + paddingLeft()),
- roundToInt(adjustedPaintOffset.y() + borderTop() + paddingTop()));
- IntRect paintRect = paintInfo.rect;
-
- IntSize widgetPaintOffset = paintLocation - widgetLocation;
- // When painting widgets into compositing layers, tx and ty are relative to the enclosing compositing layer,
- // not the root. In this case, shift the CTM and adjust the paintRect to be root-relative to fix plug-in drawing.
- if (!widgetPaintOffset.isZero()) {
- paintInfo.context->translate(widgetPaintOffset);
- paintRect.move(-widgetPaintOffset);
- }
- m_widget->paint(paintInfo.context, paintRect);
-
- if (!widgetPaintOffset.isZero())
- paintInfo.context->translate(-widgetPaintOffset);
-
- if (m_widget->isFrameView()) {
- FrameView* frameView = static_cast<FrameView*>(m_widget.get());
- bool runOverlapTests = !frameView->useSlowRepaintsIfNotOverlapped() || frameView->hasCompositedContentIncludingDescendants();
- if (paintInfo.overlapTestRequests && runOverlapTests) {
- ASSERT(!paintInfo.overlapTestRequests->contains(this));
- paintInfo.overlapTestRequests->set(this, m_widget->frameRect());
- }
- }
- }
+ if (m_widget)
+ paintContents(paintInfo, paintOffset);
if (style()->hasBorderRadius())
paintInfo.context->restore();
diff --git a/Source/WebCore/rendering/RenderWidget.h b/Source/WebCore/rendering/RenderWidget.h
index 9d2ad7f..ef8f3b7 100644
--- a/Source/WebCore/rendering/RenderWidget.h
+++ b/Source/WebCore/rendering/RenderWidget.h
@@ -85,6 +85,8 @@
virtual CursorDirective getCursor(const LayoutPoint&, Cursor&) const;
virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) OVERRIDE;
+ virtual void paintContents(PaintInfo&, const LayoutPoint&);
+
private:
virtual bool isWidget() const { return true; }
diff --git a/Source/WebKit2/ChangeLog b/Source/WebKit2/ChangeLog
index 713e86f..e96ee36 100644
--- a/Source/WebKit2/ChangeLog
+++ b/Source/WebKit2/ChangeLog
@@ -1,3 +1,21 @@
+2013-02-26 Dean Jackson <dino@apple.com>
+
+ Draw intermediate snapshots if possible
+ https://bugs.webkit.org/show_bug.cgi?id=110811
+
+ Reviewed by Simon Fraser.
+
+ After http://webkit.org/b/110495 we delayed snapshotting until we've
+ received a nice image, but this made the page look like it is broken.
+ We should draw any intermediate snapshots that we find, which might
+ include content such as progress bars/spinners.
+
+ * WebProcess/Plugins/PluginView.cpp:
+ (WebKit): Reinstate 60 attempts at snapshots before giving up.
+ (WebKit::PluginView::isAcceleratedCompositingEnabled): We do not
+ want accelerated compositing enabled when we are trying to capture
+ snapshots.
+
2013-02-26 Andras Becsi <andras.becsi@digia.com>
Remove nonexistent StringPairVector.h from Target.pri after r142839
diff --git a/Source/WebKit2/WebProcess/Plugins/PluginView.cpp b/Source/WebKit2/WebProcess/Plugins/PluginView.cpp
index 96611ee..8df14cb 100644
--- a/Source/WebKit2/WebProcess/Plugins/PluginView.cpp
+++ b/Source/WebKit2/WebProcess/Plugins/PluginView.cpp
@@ -71,7 +71,7 @@
// This simulated mouse click delay in HTMLPlugInImageElement.cpp should generally be the same or shorter than this delay.
static const double pluginSnapshotTimerDelay = 1.1;
-static const unsigned maximumSnapshotRetries = 4;
+static const unsigned maximumSnapshotRetries = 60;
class PluginView::URLRequest : public RefCounted<URLRequest> {
public:
@@ -1349,6 +1349,8 @@
if (!settings)
return false;
+ if (m_pluginElement->displayState() < HTMLPlugInElement::PlayingWithPendingMouseClick)
+ return false;
return settings->acceleratedCompositingEnabled();
}