summaryrefslogtreecommitdiffstats
path: root/WebCore
diff options
context:
space:
mode:
authorPatrick Scott <phanna@android.com>2010-11-04 10:11:34 -0400
committerPatrick Scott <phanna@android.com>2010-12-03 09:15:36 -0500
commit82f247bdbb98dd80c44209d87692c650c3704617 (patch)
treed8e9cb36f483b1e50d099563759d868aa6fef175 /WebCore
parent50114931eb31b3ee57480bf3d0068891aa62571f (diff)
downloadexternal_webkit-82f247bdbb98dd80c44209d87692c650c3704617.zip
external_webkit-82f247bdbb98dd80c44209d87692c650c3704617.tar.gz
external_webkit-82f247bdbb98dd80c44209d87692c650c3704617.tar.bz2
Rewrite scrollable layers using multiple layers.
Remove PlatformBridge::updateLayers and instead call layersDraw from ChromeClientAndroid during a requested sync. Instead of LayerAndroid having knowledge of scrolling pictures, use multiple layers (background, mask, foreground). Update navigation to use the new structure. Always record nodes in absolute, unscrolled coordinates. Do not track layers unless the node has a composited layer and a last child. Check for composited parents when adding to tracked layers as well. TODO: * developer.android.com doesn't completely work with navigation due to some nodes being clipped out. * BaseLayerAndroid needs to be able to operate with a matrix other than identity. * nested fixed position elements do not draw correctly. * nested overflow layers haven't been tested. Change-Id: I0e2bd37612341e8884d68153ab36194cb2dc1eeb
Diffstat (limited to 'WebCore')
-rw-r--r--WebCore/platform/android/PlatformBridge.h2
-rw-r--r--WebCore/platform/graphics/GraphicsLayer.h6
-rw-r--r--WebCore/platform/graphics/android/BaseLayerAndroid.cpp5
-rw-r--r--WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp121
-rw-r--r--WebCore/platform/graphics/android/GraphicsLayerAndroid.h3
-rw-r--r--WebCore/platform/graphics/android/LayerAndroid.cpp129
-rw-r--r--WebCore/platform/graphics/android/LayerAndroid.h44
-rw-r--r--WebCore/rendering/RenderLayer.cpp33
-rw-r--r--WebCore/rendering/RenderLayer.h9
-rw-r--r--WebCore/rendering/RenderLayerBacking.cpp26
-rw-r--r--WebCore/rendering/RenderLayerCompositor.cpp7
11 files changed, 193 insertions, 192 deletions
diff --git a/WebCore/platform/android/PlatformBridge.h b/WebCore/platform/android/PlatformBridge.h
index 2019d1a..2d6451a 100644
--- a/WebCore/platform/android/PlatformBridge.h
+++ b/WebCore/platform/android/PlatformBridge.h
@@ -137,8 +137,6 @@ public:
static void updateTextfield(FrameView*, Node*, bool changeToPassword, const WTF::String& text);
- // Updates the layers on the UI
- static void updateLayers(FrameView* view);
// Language
static String computeDefaultLanguage();
// Memory details for V8 GC
diff --git a/WebCore/platform/graphics/GraphicsLayer.h b/WebCore/platform/graphics/GraphicsLayer.h
index 991ca32..81aa6d0 100644
--- a/WebCore/platform/graphics/GraphicsLayer.h
+++ b/WebCore/platform/graphics/GraphicsLayer.h
@@ -82,6 +82,12 @@ class LayerChromium;
typedef LayerChromium PlatformLayer;
typedef void* NativeLayer;
}
+#elif PLATFORM(ANDROID)
+namespace WebCore {
+class LayerAndroid;
+typedef LayerAndroid PlatformLayer;
+typedef void* NativeLayer;
+}
#else
typedef void* PlatformLayer;
typedef void* NativeLayer;
diff --git a/WebCore/platform/graphics/android/BaseLayerAndroid.cpp b/WebCore/platform/graphics/android/BaseLayerAndroid.cpp
index f139eeb..996b272 100644
--- a/WebCore/platform/graphics/android/BaseLayerAndroid.cpp
+++ b/WebCore/platform/graphics/android/BaseLayerAndroid.cpp
@@ -92,7 +92,10 @@ void BaseLayerAndroid::setContent(const PictureSet& src)
android::Mutex::Autolock lock(m_drawLock);
#endif
m_content.set(src);
- setSize(src.width(), src.height());
+ // FIXME: We cannot set the size of the base layer because it will screw up
+ // the matrix used. We need to fix matrix computation for the base layer
+ // and then we can set the size.
+ // setSize(src.width(), src.height());
}
void BaseLayerAndroid::setExtra(SkPicture& src)
diff --git a/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp b/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp
index 593c896..fe7b132 100644
--- a/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp
+++ b/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp
@@ -120,7 +120,9 @@ GraphicsLayerAndroid::GraphicsLayerAndroid(GraphicsLayerClient* client) :
m_translateY(0),
m_currentTranslateX(0),
m_currentTranslateY(0),
- m_currentPosition(0, 0)
+ m_currentPosition(0, 0),
+ m_foregroundLayer(0),
+ m_foregroundClipLayer(0)
{
m_contentLayer = new LayerAndroid(true);
RenderLayer* renderLayer = renderLayerFromClient(m_client);
@@ -134,6 +136,8 @@ GraphicsLayerAndroid::GraphicsLayerAndroid(GraphicsLayerClient* client) :
GraphicsLayerAndroid::~GraphicsLayerAndroid()
{
m_contentLayer->unref();
+ SkSafeUnref(m_foregroundLayer);
+ SkSafeUnref(m_foregroundClipLayer);
gDebugGraphicsLayerAndroidInstances--;
}
@@ -162,8 +166,8 @@ bool GraphicsLayerAndroid::setChildren(const Vector<GraphicsLayer*>& children)
void GraphicsLayerAndroid::addChild(GraphicsLayer* childLayer)
{
#ifndef NDEBUG
- const char* n = (static_cast<GraphicsLayerAndroid*>(childLayer))->m_name.latin1().data();
- LOG("(%x) addChild: %x (%s)", this, childLayer, n);
+ const String& name = childLayer->name();
+ LOG("(%x) addChild: %x (%s)", this, childLayer, name.latin1().data());
#endif
GraphicsLayer::addChild(childLayer);
m_needsSyncChildren = true;
@@ -206,19 +210,11 @@ bool GraphicsLayerAndroid::replaceChild(GraphicsLayer* oldChild, GraphicsLayer*
void GraphicsLayerAndroid::removeFromParent()
{
LOG("(%x) removeFromParent()", this);
- if (m_parent)
- static_cast<GraphicsLayerAndroid*>(m_parent)->needsSyncChildren();
GraphicsLayer::removeFromParent();
m_needsSyncChildren = true;
askForSync();
}
-void GraphicsLayerAndroid::needsSyncChildren()
-{
- m_needsSyncChildren = true;
- askForSync();
-}
-
void GraphicsLayerAndroid::updateFixedPosition()
{
if (!m_client)
@@ -353,6 +349,19 @@ void GraphicsLayerAndroid::setDrawsContent(bool drawsContent)
if (m_contentLayer->isRootLayer())
return;
if (m_drawsContent) {
+#if ENABLE(ANDROID_OVERFLOW_SCROLL)
+ RenderLayer* layer = renderLayerFromClient(m_client);
+ if (layer && layer->hasOverflowScroll() && !m_foregroundLayer) {
+ m_foregroundLayer = new LayerAndroid(false);
+ m_foregroundLayer->setContentScrollable(true);
+ m_foregroundClipLayer = new LayerAndroid(false);
+ m_foregroundClipLayer->setMasksToBounds(true);
+
+ m_foregroundClipLayer->addChild(m_foregroundLayer);
+ m_contentLayer->addChild(m_foregroundClipLayer);
+ }
+#endif
+
m_haveContents = true;
setNeedsDisplay();
}
@@ -440,18 +449,42 @@ bool GraphicsLayerAndroid::repaint()
// with SkPicture, we request the entire layer's content.
IntRect layerBounds(0, 0, m_size.width(), m_size.height());
- if (m_contentsRect.width() > m_size.width() ||
- m_contentsRect.height() > m_size.height()) {
+ if (m_foregroundLayer) {
PaintingPhase phase(this);
// Paint the background into a separate context.
phase.set(GraphicsLayerPaintBackground);
if (!paintContext(m_contentLayer->recordContext(), layerBounds))
return false;
+
+ RenderLayer* layer = renderLayerFromClient(m_client);
+ // Construct the foreground layer and draw.
+ RenderBox* box = layer->renderBox();
+ int outline = box->view()->maximalOutlineSize();
+ IntRect contentsRect(0, 0,
+ box->borderLeft() + box->borderRight() + layer->scrollWidth(),
+ box->borderTop() + box->borderBottom() + layer->scrollHeight());
+ contentsRect.inflate(outline);
+ // Update the foreground layer size.
+ m_foregroundLayer->setSize(contentsRect.width(), contentsRect.height());
// Paint everything else into the main recording canvas.
phase.clear(GraphicsLayerPaintBackground);
- if (!paintContext(m_contentLayer->foregroundContext(),
- m_contentsRect))
+ if (!paintContext(m_foregroundLayer->recordContext(), contentsRect))
return false;
+
+ // Construct the clip layer for masking the contents.
+ IntRect clip = layer->renderer()->absoluteBoundingBoxRect();
+ // absoluteBoundingBoxRect does not include the outline so we need
+ // to offset the position.
+ int x = box->borderLeft() + outline;
+ int y = box->borderTop() + outline;
+ int width = clip.width() - box->borderLeft() - box->borderRight();
+ int height = clip.height() - box->borderTop() - box->borderBottom();
+ m_foregroundClipLayer->setPosition(x, y);
+ m_foregroundClipLayer->setSize(width, height);
+
+ // Need to offset the foreground layer by the clip layer in order
+ // for the contents to be in the correct position.
+ m_foregroundLayer->setPosition(-x, -y);
} else {
// If there is no contents clip, we can draw everything into one
// picture.
@@ -469,24 +502,6 @@ bool GraphicsLayerAndroid::repaint()
m_needsRepaint = false;
m_invalidatedRects.clear();
- RenderLayer* layer = renderLayerFromClient(m_client);
- // Use the absolute bounds of the renderer instead of the layer's
- // bounds because the layer will add in the outline. What we want
- // is the content bounds inside the outline.
- FloatRect clip = layer->renderer()->absoluteBoundingBoxRect();
- // Move the clip local to the layer position.
- clip.setLocation(FloatPoint(0, 0));
-#if ENABLE(ANDROID_OVERFLOW_SCROLL)
- if (layer->hasOverflowScroll()) {
- // If this is a scrollable layer, inset the clip by the border.
- RenderBox* box = layer->renderBox();
- clip.move(box->borderLeft(), box->borderTop());
- clip.setWidth(clip.width() - box->borderLeft() - box->borderRight());
- clip.setHeight(clip.height() - box->borderTop() - box->borderBottom());
- }
-#endif
- m_contentLayer->setForegroundClip(clip);
-
return true;
}
return false;
@@ -511,7 +526,7 @@ bool GraphicsLayerAndroid::paintContext(SkPicture* context,
void GraphicsLayerAndroid::setNeedsDisplayInRect(const FloatRect& rect)
{
for (unsigned int i = 0; i < m_children.size(); i++) {
- GraphicsLayerAndroid* layer = static_cast<GraphicsLayerAndroid*>(m_children[i]);
+ GraphicsLayer* layer = m_children[i];
if (layer) {
FloatRect childrenRect(m_position.x() + m_translateX + rect.x(),
m_position.y() + m_translateY + rect.y(),
@@ -548,16 +563,6 @@ void GraphicsLayerAndroid::setNeedsDisplayInRect(const FloatRect& rect)
m_needsRepaint = true;
askForSync();
-
- if (!m_client)
- return;
-
- // Update the layers on the UI
- RenderLayer* renderLayer = renderLayerFromClient(m_client);
- if (renderLayer) {
- FrameView* frameView = renderLayer->root()->renderer()->view()->frameView();
- PlatformBridge::updateLayers(frameView);
- }
}
void GraphicsLayerAndroid::pauseDisplay(bool state)
@@ -862,7 +867,7 @@ void GraphicsLayerAndroid::setContentsToImage(Image* image)
PlatformLayer* GraphicsLayerAndroid::platformLayer() const
{
LOG("platformLayer");
- return (PlatformLayer*) m_contentLayer;
+ return m_contentLayer;
}
#ifndef NDEBUG
@@ -884,6 +889,9 @@ void GraphicsLayerAndroid::setZPosition(float position)
void GraphicsLayerAndroid::askForSync()
{
+ if (!m_client)
+ return;
+
if (m_client)
m_client->notifySyncRequired(this);
}
@@ -892,10 +900,10 @@ void GraphicsLayerAndroid::syncChildren()
{
if (m_needsSyncChildren) {
m_contentLayer->removeChildren();
- for (unsigned int i = 0; i < m_children.size(); i++) {
- m_contentLayer->addChild(
- (static_cast<GraphicsLayerAndroid*>(m_children[i]))->contentLayer());
- }
+ if (m_foregroundClipLayer)
+ m_contentLayer->addChild(m_foregroundClipLayer);
+ for (unsigned int i = 0; i < m_children.size(); i++)
+ m_contentLayer->addChild(m_children[i]->platformLayer());
m_needsSyncChildren = false;
}
}
@@ -904,8 +912,7 @@ void GraphicsLayerAndroid::syncMask()
{
if (m_needsSyncMask) {
if (m_maskLayer) {
- GraphicsLayerAndroid* layer = static_cast<GraphicsLayerAndroid*>(m_maskLayer);
- LayerAndroid* mask = reinterpret_cast<LayerAndroid*>(layer->platformLayer());
+ LayerAndroid* mask = m_maskLayer->platformLayer();
m_contentLayer->setMaskLayer(mask);
} else
m_contentLayer->setMaskLayer(0);
@@ -929,10 +936,8 @@ void GraphicsLayerAndroid::syncPositionState()
void GraphicsLayerAndroid::syncCompositingState()
{
- for (unsigned int i = 0; i < m_children.size(); i++) {
- GraphicsLayerAndroid* layer = static_cast<GraphicsLayerAndroid*>(m_children[i]);
- layer->syncCompositingState();
- }
+ for (unsigned int i = 0; i < m_children.size(); i++)
+ m_children[i]->syncCompositingState();
syncChildren();
syncMask();
@@ -944,10 +949,8 @@ void GraphicsLayerAndroid::syncCompositingState()
void GraphicsLayerAndroid::notifyClientAnimationStarted()
{
- for (unsigned int i = 0; i < m_children.size(); i++) {
- GraphicsLayerAndroid* layer = static_cast<GraphicsLayerAndroid*>(m_children[i]);
- layer->notifyClientAnimationStarted();
- }
+ for (unsigned int i = 0; i < m_children.size(); i++)
+ static_cast<GraphicsLayerAndroid*>(m_children[i])->notifyClientAnimationStarted();
if (m_needsNotifyClient) {
if (client())
diff --git a/WebCore/platform/graphics/android/GraphicsLayerAndroid.h b/WebCore/platform/graphics/android/GraphicsLayerAndroid.h
index 80c92f3..098ad37 100644
--- a/WebCore/platform/graphics/android/GraphicsLayerAndroid.h
+++ b/WebCore/platform/graphics/android/GraphicsLayerAndroid.h
@@ -119,7 +119,6 @@ private:
void askForSync();
void syncPositionState();
- void needsSyncChildren();
void syncChildren();
void syncMask();
@@ -150,6 +149,8 @@ private:
Vector<FloatRect> m_invalidatedRects;
LayerAndroid* m_contentLayer;
+ LayerAndroid* m_foregroundLayer;
+ LayerAndroid* m_foregroundClipLayer;
};
} // namespace WebCore
diff --git a/WebCore/platform/graphics/android/LayerAndroid.cpp b/WebCore/platform/graphics/android/LayerAndroid.cpp
index 0a6d3e2..68bdec0 100644
--- a/WebCore/platform/graphics/android/LayerAndroid.cpp
+++ b/WebCore/platform/graphics/android/LayerAndroid.cpp
@@ -13,7 +13,6 @@
#include "SkPicture.h"
#include <wtf/CurrentTime.h>
-
#define LAYER_DEBUG // Add diagonals for debugging
#undef LAYER_DEBUG
@@ -52,8 +51,8 @@ LayerAndroid::LayerAndroid(bool isRootLayer) : SkLayer(),
m_haveClip(false),
m_doRotation(false),
m_isFixed(false),
+ m_contentScrollable(false),
m_recordingPicture(0),
- m_foregroundPicture(0),
m_contentsImage(0),
m_extra(0),
m_uniqueId(++gUniqueId)
@@ -62,8 +61,6 @@ LayerAndroid::LayerAndroid(bool isRootLayer) : SkLayer(),
m_translation.set(0, 0);
m_scale.set(1, 1);
m_backgroundColor = 0;
- m_foregroundClip.setEmpty();
- m_foregroundLocation.set(0, 0);
gDebugLayerAndroidInstances++;
}
@@ -71,6 +68,7 @@ LayerAndroid::LayerAndroid(bool isRootLayer) : SkLayer(),
LayerAndroid::LayerAndroid(const LayerAndroid& layer) : SkLayer(layer),
m_isRootLayer(layer.m_isRootLayer),
m_haveClip(layer.m_haveClip),
+ m_contentScrollable(layer.m_contentScrollable),
m_extra(0), // deliberately not copied
m_uniqueId(layer.m_uniqueId)
{
@@ -95,12 +93,7 @@ LayerAndroid::LayerAndroid(const LayerAndroid& layer) : SkLayer(layer),
m_fixedRect = layer.m_fixedRect;
m_recordingPicture = layer.m_recordingPicture;
- m_foregroundPicture = layer.m_foregroundPicture;
SkSafeRef(m_recordingPicture);
- SkSafeRef(m_foregroundPicture);
-
- m_foregroundClip = layer.m_foregroundClip;
- m_foregroundLocation = layer.m_foregroundLocation;
for (int i = 0; i < layer.countChildren(); i++)
addChild(new LayerAndroid(*layer.getChild(i)))->unref();
@@ -117,8 +110,8 @@ LayerAndroid::LayerAndroid(SkPicture* picture) : SkLayer(),
m_haveClip(false),
m_doRotation(false),
m_isFixed(false),
+ m_contentScrollable(false),
m_recordingPicture(picture),
- m_foregroundPicture(0),
m_contentsImage(0),
m_extra(0),
m_uniqueId(-1)
@@ -127,8 +120,6 @@ LayerAndroid::LayerAndroid(SkPicture* picture) : SkLayer(),
m_translation.set(0, 0);
m_scale.set(1, 1);
m_backgroundColor = 0;
- m_foregroundClip.setEmpty();
- m_foregroundLocation.set(0, 0);
SkSafeRef(m_recordingPicture);
gDebugLayerAndroidInstances++;
}
@@ -138,7 +129,6 @@ LayerAndroid::~LayerAndroid()
removeChildren();
m_contentsImage->safeUnref();
m_recordingPicture->safeUnref();
- m_foregroundPicture->safeUnref();
m_animations.clear();
gDebugLayerAndroidInstances--;
}
@@ -198,11 +188,6 @@ void LayerAndroid::setMaskLayer(LayerAndroid* layer)
m_haveClip = true;
}
-void LayerAndroid::setMasksToBounds(bool masksToBounds)
-{
- m_haveClip = masksToBounds;
-}
-
void LayerAndroid::setBackgroundColor(SkColor color)
{
m_backgroundColor = color;
@@ -323,6 +308,11 @@ public:
int x() const { return m_x; }
int y() const { return m_y; }
+ void setLocation(int x, int y) {
+ m_x = x;
+ m_y = y;
+ }
+
protected:
int m_x;
int m_y;
@@ -336,18 +326,20 @@ void LayerAndroid::findInner(LayerAndroid::FindState& state) const
{
int x = state.x();
int y = state.y();
- for (int i = 0; i < countChildren(); i++)
- getChild(i)->findInner(state);
SkRect localBounds;
bounds(&localBounds);
if (!localBounds.contains(x, y))
return;
- if (!m_foregroundPicture) {
- if (!m_recordingPicture)
- return;
- if (!state.drew(m_recordingPicture, localBounds))
- return;
- }
+ // Move into local coordinates.
+ state.setLocation(x - localBounds.fLeft, y - localBounds.fTop);
+ for (int i = 0; i < countChildren(); i++)
+ getChild(i)->findInner(state);
+ // Move back into the parent coordinates.
+ state.setLocation(x + localBounds.fLeft, y + localBounds.fTop);
+ if (!m_recordingPicture)
+ return;
+ if (!state.drew(m_recordingPicture, localBounds))
+ return;
state.setBest(this); // set last match (presumably on top)
}
@@ -450,14 +442,6 @@ void LayerAndroid::onDraw(SkCanvas* canvas, SkScalar opacity) {
canvas->drawBitmapRect(m_contentsImage->bitmap(), 0, dest);
} else {
canvas->drawPicture(*m_recordingPicture);
- if (m_foregroundPicture) {
- canvas->save();
- canvas->clipRect(m_foregroundClip);
- canvas->translate(-m_foregroundLocation.fX,
- -m_foregroundLocation.fY);
- canvas->drawPicture(*m_foregroundPicture);
- canvas->restore();
- }
}
if (m_extra) {
IntRect dummy; // inval area, unused for now
@@ -492,38 +476,48 @@ SkPicture* LayerAndroid::recordContext()
return 0;
}
-SkPicture* LayerAndroid::foregroundContext()
-{
- // Always create a new picture since this method is called only when
- // recording the foreground picture.
- m_foregroundPicture = new SkPicture();
- return m_foregroundPicture;
-}
-
-bool LayerAndroid::contentIsScrollable() const {
- return m_foregroundPicture != 0 &&
- (getWidth() < SkIntToScalar(m_foregroundPicture->width()) ||
- getHeight() < SkIntToScalar(m_foregroundPicture->height()));
-}
-
bool LayerAndroid::scrollBy(int dx, int dy) {
- if (m_foregroundPicture == 0)
+ if (!contentIsScrollable())
return false;
- SkScalar maxScrollX = SkIntToScalar(m_foregroundPicture->width()) - getWidth();
- SkScalar maxScrollY = SkIntToScalar(m_foregroundPicture->height()) - getHeight();
- SkScalar x = m_foregroundLocation.fX + dx;
- SkScalar y = m_foregroundLocation.fY + dy;
- x = SkScalarClampMax(x, maxScrollX);
- y = SkScalarClampMax(y, maxScrollY);
- if (x != m_foregroundLocation.fX || y != m_foregroundLocation.fY) {
- m_foregroundLocation.set(x, y);
- return true;
- }
- return false;
+
+ // Scrollable layers have a mask layer and then the actual main layer.
+ if (getParent() == 0 || getParent()->getParent() == 0)
+ return false;
+ LayerAndroid* realLayer = static_cast<LayerAndroid*>(getParent()->getParent());
+
+ SkRect scrollBounds;
+ realLayer->bounds(&scrollBounds);
+
+ const SkPoint& maskLayerPosition = getParent()->getPosition();
+ // Our original position is the offset of the mask layer's position.
+ SkScalar maxX = -maskLayerPosition.fX;
+ SkScalar maxY = -maskLayerPosition.fY;
+ SkScalar minX = maxX - (getSize().width() - scrollBounds.width());
+ SkScalar minY = maxY - (getSize().height() - scrollBounds.height());
+
+ // Move the layer's position by the difference and pin the result to within
+ // the scrollable range.
+ SkPoint diff;
+ diff.iset(dx, dy);
+ SkPoint pos = getPosition() - diff;
+ pos.fX = SkScalarPin(pos.fX, minX, maxX);
+ pos.fY = SkScalarPin(pos.fY, minY, maxY);
+
+ // Update the difference to reflect the changes.
+ diff = getPosition() - pos;
+ if (diff.equals(0, 0))
+ // no change
+ return false;
+
+ setPosition(pos.fX, pos.fY);
+ return true;
}
bool LayerAndroid::prepareContext(bool force)
{
+ if (masksToBounds())
+ return false;
+
if (!m_isRootLayer) {
if (force || !m_recordingPicture
|| (m_recordingPicture
@@ -696,17 +690,6 @@ void LayerAndroid::dumpLayers(FILE* file, int indentLevel) const
writeIntVal(file, indentLevel + 1, "m_recordingPicture.height", m_recordingPicture->height());
}
- if (m_foregroundPicture) {
- writeIntVal(file, indentLevel + 1, "m_foregroundPicture.width", m_foregroundPicture->width());
- writeIntVal(file, indentLevel + 1, "m_foregroundPicture.height", m_foregroundPicture->height());
- writeFloatVal(file, indentLevel + 1, "m_foregroundClip.fLeft", m_foregroundClip.fLeft);
- writeFloatVal(file, indentLevel + 1, "m_foregroundClip.fTop", m_foregroundClip.fTop);
- writeFloatVal(file, indentLevel + 1, "m_foregroundClip.fRight", m_foregroundClip.fRight);
- writeFloatVal(file, indentLevel + 1, "m_foregroundClip.fBottom", m_foregroundClip.fBottom);
- writeFloatVal(file, indentLevel + 1, "m_foregroundLocation.fX", m_foregroundLocation.fX);
- writeFloatVal(file, indentLevel + 1, "m_foregroundLocation.fY", m_foregroundLocation.fY);
- }
-
if (countChildren()) {
writeln(file, indentLevel + 1, "children = [");
for (int i = 0; i < countChildren(); i++) {
@@ -732,12 +715,12 @@ void LayerAndroid::dumpToLog() const
fclose(file);
}
-const LayerAndroid* LayerAndroid::findById(int match) const
+LayerAndroid* LayerAndroid::findById(int match)
{
if (m_uniqueId == match)
return this;
for (int i = 0; i < countChildren(); i++) {
- const LayerAndroid* result = getChild(i)->findById(match);
+ LayerAndroid* result = getChild(i)->findById(match);
if (result)
return result;
}
diff --git a/WebCore/platform/graphics/android/LayerAndroid.h b/WebCore/platform/graphics/android/LayerAndroid.h
index 939c95c..a9a9c69 100644
--- a/WebCore/platform/graphics/android/LayerAndroid.h
+++ b/WebCore/platform/graphics/android/LayerAndroid.h
@@ -121,31 +121,18 @@ public:
void setBackgroundColor(SkColor color);
void setMaskLayer(LayerAndroid*);
- void setMasksToBounds(bool);
+ void setMasksToBounds(bool masksToBounds) {
+ m_haveClip = masksToBounds;
+ }
+ bool masksToBounds() const { return m_haveClip; }
void setIsRootLayer(bool isRootLayer) { m_isRootLayer = isRootLayer; }
bool isRootLayer() const { return m_isRootLayer; }
SkPicture* recordContext();
- // The foreground context is used to draw overflow scroll content.
- SkPicture* foregroundContext();
-
- // The foreground clip is set when there is content within the node that
- // can be scrolled (i.e. a div with overflow:scroll).
- void setForegroundClip(const SkRect& clip) {
- m_foregroundClip = clip;
- }
-
- // Return the foreground clip offset by the position of the layer.
- SkRect foregroundClip() const { return m_foregroundClip; }
-
- bool contentIsScrollable() const;
-
// Returns true if the content position has changed.
bool scrollBy(int dx, int dy);
- const SkPoint& scrollPosition() const { return m_foregroundLocation; }
- void setScrollPosition(const SkPoint& pos) { m_foregroundLocation = pos; }
void addAnimation(PassRefPtr<AndroidAnimation> anim);
void removeAnimation(const String& name);
@@ -180,7 +167,10 @@ public:
void clipArea(SkTDArray<SkRect>* region) const;
const LayerAndroid* find(int x, int y, SkPicture* root) const;
- const LayerAndroid* findById(int uniqueID) const;
+ const LayerAndroid* findById(int uniqueID) const {
+ return const_cast<LayerAndroid*>(this)->findById(uniqueID);
+ }
+ LayerAndroid* findById(int uniqueID);
LayerAndroid* getChild(int index) const {
return static_cast<LayerAndroid*>(this->INHERITED::getChild(index));
}
@@ -196,6 +186,14 @@ public:
void setContentsImage(SkBitmapRef* img);
void bounds(SkRect* ) const;
+
+ bool contentIsScrollable() const { return m_contentScrollable; }
+
+ // Set when building the layer hierarchy for scrollable elements.
+ void setContentScrollable(bool scrollable) {
+ m_contentScrollable = scrollable;
+ }
+
protected:
virtual void onDraw(SkCanvas*, SkScalar opacity);
@@ -215,6 +213,7 @@ private:
bool m_doRotation;
bool m_isFixed;
bool m_backgroundColorSet;
+ bool m_contentScrollable;
SkLength m_fixedLeft;
SkLength m_fixedTop;
@@ -239,15 +238,6 @@ private:
// it is a much faster method than using m_recordingPicture.
SkPicture* m_recordingPicture;
- // m_foregroundPicture is set only when compositing a scrollable div. It
- // contains the contents minus the background and border which is drawn
- // first by the rendering tree. When we draw the layer, we draw
- // m_recordingPicture (containing the background + border) first and then
- // clip to m_foregroundClip and draw m_foregroundPicture.
- SkPicture* m_foregroundPicture;
- SkRect m_foregroundClip;
- SkPoint m_foregroundLocation;
-
SkBitmapRef* m_contentsImage;
typedef HashMap<String, RefPtr<AndroidAnimation> > KeyframesMap;
diff --git a/WebCore/rendering/RenderLayer.cpp b/WebCore/rendering/RenderLayer.cpp
index 12360c8..4221816 100644
--- a/WebCore/rendering/RenderLayer.cpp
+++ b/WebCore/rendering/RenderLayer.cpp
@@ -1938,6 +1938,14 @@ bool RenderLayer::hasOverflowScroll() const
return true;
return false;
}
+
+bool RenderLayer::hasOverflowParent() const
+{
+ const RenderLayer* layer = this;
+ while (layer && !layer->hasOverflowScroll())
+ layer = layer->parent();
+ return layer;
+}
#endif
void RenderLayer::positionOverflowControls(int tx, int ty)
@@ -2012,13 +2020,6 @@ void RenderLayer::computeScrollDimensions(bool* needHBar, bool* needVBar)
*needHBar = rightPos > clientWidth;
if (needVBar)
*needVBar = bottomPos > clientHeight;
-#if ENABLE(ANDROID_OVERFLOW_SCROLL)
- if (hasOverflowScroll()) {
- compositor()->setCompositingLayersNeedRebuild(true);
- compositor()->enableCompositingMode(true);
- compositor()->updateCompositingLayers(CompositingUpdateAfterLayoutOrStyleChange, this);
- }
-#endif
}
void RenderLayer::updateOverflowStatus(bool horizontalOverflow, bool verticalOverflow)
@@ -2154,6 +2155,14 @@ RenderLayer::updateScrollInfoAfterLayout()
if (renderer()->node() && renderer()->document()->hasListenerType(Document::OVERFLOWCHANGED_LISTENER))
updateOverflowStatus(horizontalOverflow, verticalOverflow);
+
+#if ENABLE(ANDROID_OVERFLOW_SCROLL)
+ if (hasOverflowScroll()) {
+ rendererContentChanged();
+ dirtyStackingContextZOrderLists();
+ dirtyZOrderLists();
+ }
+#endif
}
void RenderLayer::paintOverflowControls(GraphicsContext* context, int tx, int ty, const IntRect& damageRect)
@@ -3213,6 +3222,15 @@ void RenderLayer::calculateClipRects(const RenderLayer* rootLayer, ClipRects& cl
if (renderer()->hasOverflowClip()) {
IntRect newOverflowClip = toRenderBox(renderer())->overflowClipRect(x, y);
+#if ENABLE(ANDROID_OVERFLOW_SCROLL)
+ if (hasOverflowScroll()) {
+ RenderBox* box = toRenderBox(renderer());
+ newOverflowClip =
+ IntRect(x, y,
+ box->borderLeft() + box->borderRight() + m_scrollWidth,
+ box->borderTop() + box->borderBottom() + m_scrollHeight);
+ }
+#endif
clipRects.setOverflowClipRect(intersection(newOverflowClip, clipRects.overflowClipRect()));
if (renderer()->isPositioned() || renderer()->isRelPositioned())
clipRects.setPosClipRect(intersection(newOverflowClip, clipRects.posClipRect()));
@@ -3277,6 +3295,7 @@ void RenderLayer::calculateRects(const RenderLayer* rootLayer, const IntRect& pa
// This layer establishes a clip of some kind.
#if ENABLE(ANDROID_OVERFLOW_SCROLL)
if (hasOverflowScroll()) {
+ // Use the entire foreground rectangle to record the contents.
RenderBox* box = toRenderBox(renderer());
foregroundRect =
IntRect(x, y,
diff --git a/WebCore/rendering/RenderLayer.h b/WebCore/rendering/RenderLayer.h
index 27d2b31..6b60fe1 100644
--- a/WebCore/rendering/RenderLayer.h
+++ b/WebCore/rendering/RenderLayer.h
@@ -260,6 +260,7 @@ public:
bool hasOverflowControls() const;
#if ENABLE(ANDROID_OVERFLOW_SCROLL)
bool hasOverflowScroll() const;
+ bool hasOverflowParent() const;
#endif
void positionOverflowControls(int tx, int ty);
bool isPointInResizeControl(const IntPoint& absolutePoint) const;
@@ -323,11 +324,19 @@ public:
bool isFixed() const { return renderer()->isPositioned() && renderer()->style()->position() == FixedPosition; }
// If fixed elements are composited, they will be containing children
bool isStackingContext() const {
+#if ENABLE(ANDROID_OVERFLOW_SCROLL)
+ if (hasOverflowScroll())
+ return true;
+#endif
return !hasAutoZIndex() || renderer()->isRenderView() || (isComposited() && isFixed());
}
#else
+#if ENABLE(ANDROID_OVERFLOW_SCROLL)
+ bool isStackingContext() const { return !hasAutoZIndex() || renderer()->isRenderView() || hasOverflowScroll(); }
+#else
bool isStackingContext() const { return !hasAutoZIndex() || renderer()->isRenderView() ; }
#endif
+#endif
void dirtyZOrderLists();
void dirtyStackingContextZOrderLists();
diff --git a/WebCore/rendering/RenderLayerBacking.cpp b/WebCore/rendering/RenderLayerBacking.cpp
index 517a6d2..215b41f 100644
--- a/WebCore/rendering/RenderLayerBacking.cpp
+++ b/WebCore/rendering/RenderLayerBacking.cpp
@@ -57,10 +57,6 @@
#include "Settings.h"
#include "WebGLRenderingContext.h"
-#if ENABLE(ANDROID_OVERFLOW_SCROLL)
-#include "GraphicsLayerAndroid.h"
-#endif
-
using namespace std;
namespace WebCore {
@@ -883,20 +879,6 @@ IntRect RenderLayerBacking::contentsBox() const
} else
#endif
contentsRect = toRenderBox(renderer())->contentBoxRect();
-#if ENABLE(ANDROID_OVERFLOW_SCROLL)
- if (m_owningLayer->hasOverflowScroll()) {
- // Update the contents rect to have the width and height of the entire
- // contents. This rect is only used by the platform GraphicsLayer and
- // the position of the rectangle is ignored. Use the layer's scroll
- // width/height (which contain the padding).
- RenderBox* box = toRenderBox(renderer());
- int outline = box->view()->maximalOutlineSize() << 1;
- contentsRect.setWidth(box->borderLeft() + box->borderRight() +
- m_owningLayer->scrollWidth() + outline);
- contentsRect.setHeight(box->borderTop() + box->borderBottom() +
- m_owningLayer->scrollHeight() + outline);
- }
-#endif
IntSize contentOffset = contentOffsetInCompostingLayer();
contentsRect.move(contentOffset);
@@ -1116,10 +1098,10 @@ void RenderLayerBacking::paintContents(const GraphicsLayer*, GraphicsContext& co
// can compute and cache clipRects.
IntRect enclosingBBox = compositedBounds();
#if ENABLE(ANDROID_OVERFLOW_SCROLL)
- if (m_owningLayer->hasOverflowScroll()) {
- enclosingBBox.setSize(contentsBox().size());
- enclosingBBox.setLocation(m_compositedBounds.location());
- }
+ // If we encounter a scrollable layer, layers inside the scrollable layer
+ // will need their entire content recorded.
+ if (m_owningLayer->hasOverflowParent())
+ enclosingBBox.setSize(clip.size());
#endif
IntRect clipRect(clip);
diff --git a/WebCore/rendering/RenderLayerCompositor.cpp b/WebCore/rendering/RenderLayerCompositor.cpp
index da804dd..cf75a2a 100644
--- a/WebCore/rendering/RenderLayerCompositor.cpp
+++ b/WebCore/rendering/RenderLayerCompositor.cpp
@@ -286,6 +286,13 @@ bool RenderLayerCompositor::updateBacking(RenderLayer* layer, CompositingChangeR
// 3D transforms turn off the testing of overlap.
if (requiresCompositingForTransform(layer->renderer()))
setCompositingConsultsOverlap(false);
+#if ENABLE(ANDROID_OVERFLOW_SCROLL)
+ // If we are a child of a scrollable layer, ignore the overlap from the
+ // scrollable layer as it can cause child layers to become composited
+ // siblings and will not scroll with the main content layer.
+ if (layer->hasOverflowParent())
+ setCompositingConsultsOverlap(false);
+#endif
if (!layer->backing()) {