summaryrefslogtreecommitdiffstats
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
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
-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
-rw-r--r--WebKit/android/WebCoreSupport/ChromeClientAndroid.cpp7
-rw-r--r--WebKit/android/WebCoreSupport/PlatformBridge.cpp6
-rw-r--r--WebKit/android/jni/WebViewCore.cpp69
-rw-r--r--WebKit/android/nav/CacheBuilder.cpp77
-rw-r--r--WebKit/android/nav/CacheBuilder.h2
-rw-r--r--WebKit/android/nav/CachedFrame.cpp16
-rw-r--r--WebKit/android/nav/CachedLayer.cpp85
-rw-r--r--WebKit/android/nav/CachedLayer.h12
-rw-r--r--WebKit/android/nav/WebView.cpp47
20 files changed, 345 insertions, 361 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()) {
diff --git a/WebKit/android/WebCoreSupport/ChromeClientAndroid.cpp b/WebKit/android/WebCoreSupport/ChromeClientAndroid.cpp
index f1e6279..80a90fe 100644
--- a/WebKit/android/WebCoreSupport/ChromeClientAndroid.cpp
+++ b/WebKit/android/WebCoreSupport/ChromeClientAndroid.cpp
@@ -71,7 +71,12 @@ WebCore::GraphicsLayer* ChromeClientAndroid::layersSync()
void ChromeClientAndroid::scheduleCompositingLayerSync()
{
- m_needsLayerSync = true;
+ if (m_needsLayerSync)
+ return;
+ m_needsLayerSync = true;
+ WebViewCore* webViewCore = WebViewCore::getWebViewCore(m_webFrame->page()->mainFrame()->view());
+ if (webViewCore)
+ webViewCore->layersDraw();
}
void ChromeClientAndroid::setNeedsOneShotDrawingSynchronization()
diff --git a/WebKit/android/WebCoreSupport/PlatformBridge.cpp b/WebKit/android/WebCoreSupport/PlatformBridge.cpp
index 89af00a..2c238b2 100644
--- a/WebKit/android/WebCoreSupport/PlatformBridge.cpp
+++ b/WebKit/android/WebCoreSupport/PlatformBridge.cpp
@@ -184,12 +184,6 @@ void PlatformBridge::updateTextfield(FrameView* frameView, Node* nodePtr, bool c
webViewCore->updateTextfield(nodePtr, changeToPassword, text);
}
-void PlatformBridge::updateLayers(FrameView* frameView)
-{
- android::WebViewCore* webViewCore = android::WebViewCore::getWebViewCore(frameView);
- webViewCore->layersDraw();
-}
-
int PlatformBridge::lowMemoryUsageMB()
{
return MemoryUsage::lowMemoryUsageMb();
diff --git a/WebKit/android/jni/WebViewCore.cpp b/WebKit/android/jni/WebViewCore.cpp
index 1fdc3d5..5f5bb53 100644
--- a/WebKit/android/jni/WebViewCore.cpp
+++ b/WebKit/android/jni/WebViewCore.cpp
@@ -1176,14 +1176,6 @@ void WebViewCore::setSizeScreenWidthAndScale(int width, int height,
WebCoreViewBridge* window = m_mainFrame->view()->platformWidget();
int ow = window->width();
int oh = window->height();
- window->setSize(width, height);
- window->setVisibleSize(screenWidth, screenHeight);
- if (width != screenWidth) {
- m_mainFrame->view()->setUseFixedLayout(true);
- m_mainFrame->view()->setFixedLayoutSize(IntSize(width, height));
- } else {
- m_mainFrame->view()->setUseFixedLayout(false);
- }
int osw = m_screenWidth;
int osh = m_screenHeight;
int otw = m_textWrapWidth;
@@ -1210,7 +1202,7 @@ void WebViewCore::setSizeScreenWidthAndScale(int width, int height,
// orientation change. Try to keep the anchor at the same place.
if (otw && textWrapWidth && otw != textWrapWidth) {
WebCore::HitTestResult hitTestResult =
- m_mainFrame->eventHandler()-> hitTestResultAtPoint(
+ m_mainFrame->eventHandler()->hitTestResultAtPoint(
anchorPoint, false);
node = hitTestResult.innerNode();
}
@@ -1230,8 +1222,20 @@ void WebViewCore::setSizeScreenWidthAndScale(int width, int height,
}
}
}
+
+ // Set the size after finding the old anchor point as
+ // hitTestResultAtPoint causes a layout.
+ window->setSize(width, height);
+ window->setVisibleSize(screenWidth, screenHeight);
+ if (width != screenWidth) {
+ m_mainFrame->view()->setUseFixedLayout(true);
+ m_mainFrame->view()->setFixedLayoutSize(IntSize(width, height));
+ } else {
+ m_mainFrame->view()->setUseFixedLayout(false);
+ }
r->setNeedsLayoutAndPrefWidthsRecalc();
m_mainFrame->view()->forceLayout();
+
// scroll to restore current screen center
if (node) {
const WebCore::IntRect& newBounds = node->getRect();
@@ -1261,6 +1265,16 @@ void WebViewCore::setSizeScreenWidthAndScale(int width, int height,
}
}
}
+ } else {
+ window->setSize(width, height);
+ window->setVisibleSize(screenWidth, screenHeight);
+ m_mainFrame->view()->resize(width, height);
+ if (width != screenWidth) {
+ m_mainFrame->view()->setUseFixedLayout(true);
+ m_mainFrame->view()->setFixedLayoutSize(IntSize(width, height));
+ } else {
+ m_mainFrame->view()->setUseFixedLayout(false);
+ }
}
// update the currently visible screen as perceived by the plugin
@@ -2792,33 +2806,35 @@ void WebViewCore::touchUp(int touchGeneration,
// Return the RenderLayer for the given RenderObject only if the layer is
// composited and it contains a scrollable content layer.
-static WebCore::RenderLayer* getLayerFromRenderer(
- WebCore::RenderObject* renderer, LayerAndroid** aLayer)
+static WebCore::RenderLayer* getScrollingLayerFromRenderer(
+ WebCore::RenderObject* renderer)
{
+#if ENABLE(ANDROID_OVERFLOW_SCROLL)
if (!renderer)
return 0;
WebCore::RenderLayer* layer = renderer->enclosingSelfPaintingLayer();
- if (!layer || !layer->backing())
- return 0;
- GraphicsLayerAndroid* graphicsLayer =
- static_cast<GraphicsLayerAndroid*>(layer->backing()->graphicsLayer());
- if (!graphicsLayer)
- return 0;
- LayerAndroid* layerAndroid = graphicsLayer->contentLayer();
- if (!layerAndroid || !layerAndroid->contentIsScrollable())
+ if (!layer)
return 0;
- *aLayer = layerAndroid;
+ // Find the layer that actually has overflow scroll in case this renderer is
+ // inside a child layer.
+ while (layer && !layer->hasOverflowScroll())
+ layer = layer->parent();
return layer;
+#endif
+ return 0;
}
// Scroll the RenderLayer associated with a scrollable div element. This is
// done so that the node is visible when it is clicked.
static void scrollLayer(WebCore::RenderObject* renderer, WebCore::IntPoint* pos)
{
- LayerAndroid* aLayer;
- WebCore::RenderLayer* layer = getLayerFromRenderer(renderer, &aLayer);
+ WebCore::RenderLayer* layer = getScrollingLayerFromRenderer(renderer);
if (!layer)
return;
+ // The cache uses absolute coordinates when clicking on nodes and it assumes
+ // the layer is not scrolled.
+ layer->scrollToOffset(0, 0, false, false);
+
WebCore::IntRect absBounds = renderer->absoluteBoundingBoxRect();
// Do not include the outline when moving the node's bounds.
WebCore::IntRect layerBounds = layer->renderer()->absoluteBoundingBoxRect();
@@ -2826,16 +2842,11 @@ static void scrollLayer(WebCore::RenderObject* renderer, WebCore::IntPoint* pos)
// Move the node's bounds into the layer's coordinates.
absBounds.move(-layerBounds.x(), -layerBounds.y());
- int diffX = layer->scrollXOffset();
- int diffY = layer->scrollYOffset();
- // Scroll the layer to the node's position. The false parameters tell the
- // layer not to invalidate.
+ // Scroll the layer to the node's position.
layer->scrollToOffset(absBounds.x(), absBounds.y(), false, true);
- diffX = layer->scrollXOffset() - diffX;
- diffY = layer->scrollYOffset() - diffY;
// Update the mouse position to the layer offset.
- pos->move(-diffX, -diffY);
+ pos->move(-layer->scrollXOffset(), -layer->scrollYOffset());
}
// Common code for both clicking with the trackball and touchUp
diff --git a/WebKit/android/nav/CacheBuilder.cpp b/WebKit/android/nav/CacheBuilder.cpp
index 449b9e2..f0333f2 100644
--- a/WebKit/android/nav/CacheBuilder.cpp
+++ b/WebKit/android/nav/CacheBuilder.cpp
@@ -93,6 +93,12 @@ Frame* CacheBuilder::FrameAnd(const CacheBuilder* cacheBuilder) {
return loader->getFrame();
}
+CacheBuilder::LayerTracker::~LayerTracker() {
+ if (mRenderLayer)
+ // Restore the scroll position of the layer. Does not affect layers
+ // without overflow scroll as the layer will not be scrolled.
+ mRenderLayer->scrollToOffset(mScroll.x(), mScroll.y(), false, false);
+}
#if DUMP_NAV_CACHE
@@ -919,8 +925,7 @@ static bool checkForPluginViewThatWantsFocus(RenderObject* renderer) {
}
#if USE(ACCELERATED_COMPOSITING)
-static void AddLayer(CachedFrame* frame, size_t index, const IntPoint& location,
- const IntPoint& scroll, int id)
+static void AddLayer(CachedFrame* frame, size_t index, const IntPoint& location, int id)
{
DBG_NAV_LOGD("frame=%p index=%d loc=(%d,%d) id=%d", frame, index,
location.x(), location.y(), id);
@@ -928,7 +933,6 @@ static void AddLayer(CachedFrame* frame, size_t index, const IntPoint& location,
cachedLayer.reset();
cachedLayer.setCachedNodeIndex(index);
cachedLayer.setOffset(location);
- cachedLayer.setScrollOffset(scroll);
cachedLayer.setUniqueId(id);
frame->add(cachedLayer);
}
@@ -1099,7 +1103,9 @@ void CacheBuilder::BuildFrame(Frame* root, Frame* frame,
hasCursorRing = style->tapHighlightColor().alpha() > 0;
#endif
#if USE(ACCELERATED_COMPOSITING)
- if (nodeRenderer->hasLayer()) {
+ // If this renderer has its own layer and the layer is composited,
+ // start tracking it.
+ if (lastChild && nodeRenderer->hasLayer() && toRenderBox(nodeRenderer)->layer()->backing()) {
TrackLayer(layerTracker, nodeRenderer, lastChild,
globalOffsetX, globalOffsetY);
size_t size = tracker.size();
@@ -1108,11 +1114,9 @@ void CacheBuilder::BuildFrame(Frame* root, Frame* frame,
int id = layer->uniqueId();
const RenderLayer* renderLayer =
layerTracker.last().mRenderLayer;
- IntPoint loc(SkScalarRound(layer->getPosition().fX),
- SkScalarRound(layer->getPosition().fY));
+ // Global location
+ IntPoint loc = renderLayer->absoluteBoundingBox().location();
loc.move(globalOffsetX, globalOffsetY);
- IntPoint scroll(renderLayer->scrollXOffset(),
- renderLayer->scrollYOffset());
// if this is a child of a CachedNode, add a layer
size_t limit = cachedFrame->layerCount() == 0 ? 0 :
cachedFrame->lastLayer()->cachedNodeIndex();
@@ -1128,7 +1132,7 @@ void CacheBuilder::BuildFrame(Frame* root, Frame* frame,
CachedNode* trackedNode = cachedFrame->getIndex(index);
trackedNode->setIsInLayer(true);
trackedNode->setIsUnclipped(true);
- AddLayer(cachedFrame, index, loc, scroll, id);
+ AddLayer(cachedFrame, index, loc, id);
}
}
}
@@ -1174,11 +1178,8 @@ void CacheBuilder::BuildFrame(Frame* root, Frame* frame,
absBounds.move(globalOffsetX, globalOffsetY);
hasClip = nodeRenderer->hasOverflowClip();
#if ENABLE(ANDROID_OVERFLOW_SCROLL)
- if (nodeRenderer->hasLayer()) {
- const LayerAndroid* layer = layerTracker.last().mLayer;
- if (layer && layer->contentIsScrollable())
- hasClip = false;
- }
+ if (nodeRenderer->enclosingLayer() && nodeRenderer->enclosingLayer()->hasOverflowParent())
+ hasClip = false;
#endif
if (node->hasTagName(HTMLNames::canvasTag))
@@ -1399,22 +1400,23 @@ void CacheBuilder::BuildFrame(Frame* root, Frame* frame,
}
bool isInLayer = false;
#if USE(ACCELERATED_COMPOSITING)
+ // If this renderer has a composited parent layer (including itself),
+ // add the node to the cached layer.
// FIXME: does not work for area rects
- LayerAndroid* layer = layerTracker.last().mLayer;
- if (layer) {
- const IntRect& layerClip = layerTracker.last().mBounds;
- const RenderLayer* renderLayer = layerTracker.last().mRenderLayer;
- if (!layer->contentIsScrollable() && !layerClip.isEmpty() &&
- !cachedNode.clip(layerClip)) {
- DBG_NAV_LOGD("skipped on layer clip %d", cacheIndex);
- continue; // skip this node if outside of the clip
+ RenderLayer* enclosingLayer = nodeRenderer->enclosingLayer();
+ if (enclosingLayer && enclosingLayer->enclosingCompositingLayer()) {
+ LayerAndroid* layer = layerTracker.last().mLayer;
+ if (layer) {
+ const IntRect& layerClip = layerTracker.last().mBounds;
+ if (!layerClip.isEmpty() && !cachedNode.clip(layerClip)) {
+ DBG_NAV_LOGD("skipped on layer clip %d", cacheIndex);
+ continue; // skip this node if outside of the clip
+ }
+ isInLayer = true;
+ isUnclipped = true; // assume that layers do not have occluded nodes
+ AddLayer(cachedFrame, cachedFrame->size(), layerClip.location(),
+ layer->uniqueId());
}
- isInLayer = true;
- isUnclipped = true; // assume that layers do not have occluded nodes
- IntPoint scroll(renderLayer->scrollXOffset(),
- renderLayer->scrollYOffset());
- AddLayer(cachedFrame, cachedFrame->size(), layerClip.location(),
- scroll, layer->uniqueId());
}
#endif
cachedNode.setNavableRects();
@@ -2919,7 +2921,7 @@ bool CacheBuilder::setData(CachedFrame* cachedFrame)
void CacheBuilder::TrackLayer(WTF::Vector<LayerTracker>& layerTracker,
RenderObject* nodeRenderer, Node* lastChild, int offsetX, int offsetY)
{
- RenderLayer* layer = toRenderBoxModelObject(nodeRenderer)->layer();
+ RenderLayer* layer = nodeRenderer->enclosingLayer();
RenderLayerBacking* back = layer->backing();
if (!back)
return;
@@ -2930,13 +2932,28 @@ void CacheBuilder::TrackLayer(WTF::Vector<LayerTracker>& layerTracker,
LayerAndroid* aLayer = grLayer->contentLayer();
if (!aLayer)
return;
+ IntPoint scroll(layer->scrollXOffset(), layer->scrollYOffset());
+#if ENABLE(ANDROID_OVERFLOW_SCROLL)
+ // If this is an overflow element, track the content layer.
+ if (layer->hasOverflowParent() && aLayer->getChild(0))
+ aLayer = aLayer->getChild(0)->getChild(0);
+ if (!aLayer)
+ return;
+ layer->scrollToOffset(0, 0, false, false);
+#endif
layerTracker.grow(layerTracker.size() + 1);
LayerTracker& indexTracker = layerTracker.last();
indexTracker.mLayer = aLayer;
indexTracker.mRenderLayer = layer;
indexTracker.mBounds = IntRect(FloatRect(aLayer->bounds()));
+ // Use the absolute location of the layer as the bounds location. This
+ // provides the original offset of nodes in the layer so that we can
+ // translate nodes between their original location and the layer's new
+ // location.
+ indexTracker.mBounds.setLocation(layer->absoluteBoundingBox().location());
indexTracker.mBounds.move(offsetX, offsetY);
- indexTracker.mLastChild = lastChild ? OneAfter(lastChild) : 0;
+ indexTracker.mScroll = scroll;
+ indexTracker.mLastChild = OneAfter(lastChild);
DBG_NAV_LOGD("layer=%p [%d] bounds=(%d,%d,w=%d,h=%d)", aLayer,
aLayer->uniqueId(), indexTracker.mBounds.x(), indexTracker.mBounds.y(),
indexTracker.mBounds.width(), indexTracker.mBounds.height());
diff --git a/WebKit/android/nav/CacheBuilder.h b/WebKit/android/nav/CacheBuilder.h
index 9832865..d229df0 100644
--- a/WebKit/android/nav/CacheBuilder.h
+++ b/WebKit/android/nav/CacheBuilder.h
@@ -202,6 +202,8 @@ private:
LayerAndroid* mLayer;
RenderLayer* mRenderLayer;
IntRect mBounds;
+ IntPoint mScroll;
+ ~LayerTracker();
};
struct TabIndexTracker : Tracker {
int mTabIndex;
diff --git a/WebKit/android/nav/CachedFrame.cpp b/WebKit/android/nav/CachedFrame.cpp
index 4f9ec06..55a7c0e 100644
--- a/WebKit/android/nav/CachedFrame.cpp
+++ b/WebKit/android/nav/CachedFrame.cpp
@@ -53,12 +53,8 @@ WebCore::IntRect CachedFrame::adjustBounds(const CachedNode* node,
const CachedLayer* cachedLayer = layer(node);
const WebCore::LayerAndroid* rootLayer = mRoot->rootLayer();
const LayerAndroid* aLayer = cachedLayer->layer(rootLayer);
- if (aLayer) {
- IntRect rrect = cachedLayer->adjustBounds(rootLayer, rect);
- if (!aLayer->contentIsScrollable())
- rrect.move(-mViewBounds.x(), -mViewBounds.y());
- return rrect;
- }
+ if (aLayer)
+ return cachedLayer->adjustBounds(rootLayer, rect);
#endif
return rect;
}
@@ -74,12 +70,8 @@ WebCore::IntRect CachedFrame::unadjustBounds(const CachedNode* node,
const CachedLayer* cachedLayer = layer(node);
const WebCore::LayerAndroid* rootLayer = mRoot->rootLayer();
const LayerAndroid* aLayer = cachedLayer->layer(rootLayer);
- if (aLayer) {
- IntRect rrect = cachedLayer->unadjustBounds(rootLayer, rect);
- if (!aLayer->contentIsScrollable())
- rrect.move(mViewBounds.x(), mViewBounds.y());
- return rrect;
- }
+ if (aLayer)
+ return cachedLayer->unadjustBounds(rootLayer, rect);
}
#endif
return rect;
diff --git a/WebKit/android/nav/CachedLayer.cpp b/WebKit/android/nav/CachedLayer.cpp
index 5ad5c8b..0c53da2 100644
--- a/WebKit/android/nav/CachedLayer.cpp
+++ b/WebKit/android/nav/CachedLayer.cpp
@@ -49,10 +49,6 @@ IntRect CachedLayer::adjustBounds(const LayerAndroid* root,
// First, remove the original offset from the bounds.
temp.move(-mOffset.x(), -mOffset.y());
- // Now, add in the original scroll position. This moves the node to the
- // original location within the layer.
- temp.move(mScrollOffset.x(), mScrollOffset.y());
-
// Next, add in the new position of the layer (could be different due to a
// fixed position layer).
FloatPoint position = getGlobalPosition(aLayer);
@@ -62,32 +58,16 @@ IntRect CachedLayer::adjustBounds(const LayerAndroid* root,
const FloatPoint& translation = aLayer->translation();
temp.move(translation.x(), translation.y());
- // Move the bounds by the layer's internal scroll position.
- const SkPoint& scroll = aLayer->scrollPosition();
- temp.move(SkScalarToFloat(-scroll.fX), SkScalarToFloat(-scroll.fY));
-
IntRect result = enclosingIntRect(temp);
- // Finally, clip the result to the foreground (this includes the object's
- // border which does not scroll).
- IntRect clip(aLayer->foregroundClip());
- if (!clip.isEmpty()) {
- clip.move(position.x(), position.y());
- result.intersect(clip);
- }
-
DBG_NAV_LOGV("root=%p aLayer=%p [%d]"
" bounds=(%d,%d,w=%d,h=%d) trans=(%g,%g) pos=(%f,%f)"
- " offset=(%d,%d) clip=(%d,%d,w=%d,h=%d)"
- " scroll=(%d,%d) origScroll=(%d,%d)"
+ " offset=(%d,%d)"
" result=(%d,%d,w=%d,h=%d)",
root, aLayer, aLayer->uniqueId(),
bounds.x(), bounds.y(), bounds.width(), bounds.height(),
translation.x(), translation.y(), position.x(), position.y(),
mOffset.x(), mOffset.y(),
- clip.x(), clip.y(), clip.width(), clip.height(),
- SkScalarRound(scroll.fX), SkScalarRound(scroll.fY),
- mScrollOffset.x(), mScrollOffset.y(),
result.x(), result.y(), result.width(), result.height());
return result;
}
@@ -109,26 +89,17 @@ IntRect CachedLayer::unadjustBounds(const LayerAndroid* root,
const FloatPoint& translation = aLayer->translation();
temp.move(-translation.x(), -translation.y());
- // Move the bounds by the internal scroll position.
- const SkPoint& scroll = aLayer->scrollPosition();
- temp.move(SkScalarRound(scroll.fX), SkScalarRound(scroll.fY));
-
// Move it back to the original offset.
temp.move(mOffset.x(), mOffset.y());
- // Move the bounds by the original scroll.
- temp.move(-mScrollOffset.x(), -mScrollOffset.y());
DBG_NAV_LOGD("root=%p aLayer=%p [%d]"
" bounds=(%d,%d,w=%d,h=%d) trans=(%g,%g) pos=(%f,%f)"
" offset=(%d,%d)"
- " scroll=(%d,%d) origScroll=(%d,%d)"
" result=(%d,%d,w=%d,h=%d)",
root, aLayer, aLayer->uniqueId(),
bounds.x(), bounds.y(), bounds.width(), bounds.height(),
translation.x(), translation.y(), position.x(), position.y(),
mOffset.x(), mOffset.y(),
- SkScalarRound(scroll.fX), SkScalarRound(scroll.fY),
- mScrollOffset.x(), mScrollOffset.y(),
temp.x(), temp.y(), temp.width(), temp.height());
return temp;
}
@@ -153,7 +124,7 @@ const LayerAndroid* CachedLayer::layer(const LayerAndroid* root) const
return mLayer = root->findById(mUniqueId);
}
-// return bounds relative to enclosing layer as recorded when walking the dom
+// return bounds relative to the layer as recorded when walking the dom
IntRect CachedLayer::localBounds(const LayerAndroid* root,
const IntRect& bounds) const
{
@@ -161,45 +132,14 @@ IntRect CachedLayer::localBounds(const LayerAndroid* root,
// Remove the original offset from the bounds.
temp.move(-mOffset.x(), -mOffset.y());
- // We add in the original scroll position in order to position the node
- // relative to the current internal scroll position.
- temp.move(mScrollOffset.x(), mScrollOffset.y());
-
- const LayerAndroid* aLayer = layer(root);
- FloatPoint position;
- if (aLayer) {
- const LayerAndroid* parent = static_cast<const LayerAndroid*>
- (aLayer->getParent());
- if (parent) {
- position = getGlobalPosition(parent);
- temp.move(-position.x(), -position.y());
- }
- // Move the bounds by the scroll position of the layer.
- const SkPoint& scroll = aLayer->scrollPosition();
- temp.move(SkScalarToFloat(-scroll.fX), SkScalarToFloat(-scroll.fY));
-
- // Clip by the layer's foreground bounds. Since the bounds have
- // already be moved local to the layer, no need to move the foreground
- // clip.
- IntRect foregroundClip(aLayer->foregroundClip());
- if (!foregroundClip.isEmpty())
- temp.intersect(foregroundClip);
- }
-
#if DEBUG_NAV_UI
- const FloatPoint& translation = aLayer->translation();
- SkPoint scroll = SkPoint::Make(0,0);
- if (aLayer) scroll = aLayer->scrollPosition();
+ const LayerAndroid* aLayer = layer(root);
DBG_NAV_LOGD("aLayer=%p [%d] bounds=(%d,%d,w=%d,h=%d) offset=(%d,%d)"
- " scrollOffset=(%d,%d) position=(%g,%g) result=(%d,%d,w=%d,h=%d)"
- " scroll=(%d,%d) trans=(%g,%g)",
+ " result=(%d,%d,w=%d,h=%d)",
aLayer, aLayer ? aLayer->uniqueId() : 0,
bounds.x(), bounds.y(), bounds.width(), bounds.height(),
mOffset.x(), mOffset.y(),
- mScrollOffset.x(), mScrollOffset.y(), position.x(), position.y(),
- temp.x(), temp.y(), temp.width(), temp.height(),
- scroll.fX, scroll.fY,
- translation.x(), translation.y());
+ temp.x(), temp.y(), temp.width(), temp.height());
#endif
return temp;
@@ -240,8 +180,6 @@ void CachedLayer::Debug::print() const
DUMP_NAV_LOGD(" // LayerAndroid* mLayer=%p;\n", b->mLayer);
DUMP_NAV_LOGD(" // int mOffset=(%d, %d);\n",
b->mOffset.x(), b->mOffset.y());
- DUMP_NAV_LOGD(" // int mScrollOffset=(%d, %d);\n",
- b->mScrollOffset.x(), b->mScrollOffset.y());
DUMP_NAV_LOGD(" // int mUniqueId=%p;\n", b->mUniqueId);
DUMP_NAV_LOGD("%s\n", "");
}
@@ -257,11 +195,10 @@ void CachedLayer::Debug::printLayerAndroid(const LayerAndroid* layer)
++spaces;
SkRect bounds;
layer->bounds(&bounds);
- DUMP_NAV_LOGD("%.*s layer=%p [%d] (%g,%g,%g,%g)"
- " position=(%g,%g) translation=(%g,%g) anchor=(%g,%g)"
- " matrix=(%g,%g) childMatrix=(%g,%g)"
- " foregroundLocation=(%g,%g)"
- " picture=%p clipped=%s\n",
+ DBG_NAV_LOGD("%.*s layer=%p [%d] (%g,%g,%g,%g)"
+ " position=(%g,%g) translation=(%g,%g) anchor=(%g,%g)"
+ " matrix=(%g,%g) childMatrix=(%g,%g) picture=%p clipped=%s"
+ " scrollable=%s\n",
spaces, " ", layer, layer->uniqueId(),
bounds.fLeft, bounds.fTop, bounds.width(), bounds.height(),
layer->getPosition().fX, layer->getPosition().fY,
@@ -270,8 +207,8 @@ void CachedLayer::Debug::printLayerAndroid(const LayerAndroid* layer)
layer->getMatrix().getTranslateX(), layer->getMatrix().getTranslateY(),
layer->getChildrenMatrix().getTranslateX(),
layer->getChildrenMatrix().getTranslateY(),
- layer->scrollPosition().fX, layer->scrollPosition().fY,
- layer->picture(), layer->m_haveClip ? "true" : "false");
+ layer->picture(), layer->m_haveClip ? "true" : "false",
+ layer->contentIsScrollable() ? "true" : "false");
for (int i = 0; i < layer->countChildren(); i++)
printLayerAndroid(layer->getChild(i));
--spaces;
diff --git a/WebKit/android/nav/CachedLayer.h b/WebKit/android/nav/CachedLayer.h
index fd5f4a0..db7bfb1 100644
--- a/WebKit/android/nav/CachedLayer.h
+++ b/WebKit/android/nav/CachedLayer.h
@@ -48,7 +48,7 @@ public:
}
// FIXME: adjustBounds should be renamed globalBounds or toGlobal
IntRect adjustBounds(const LayerAndroid* root, const IntRect& bounds) const;
- // Moves the bounds by the layer's scroll position. Assumes the incoming
+ // Moves the bounds by the layer's position. Assumes the incoming
// bounds have been adjusted by adjustBounds.
IntRect unadjustBounds(const LayerAndroid* root,
const IntRect& bounds) const;
@@ -60,19 +60,17 @@ public:
void toLocal(const LayerAndroid* root, int* xPtr, int* yPtr) const;
void reset() { mLayer = 0; }
void setCachedNodeIndex(int index) { mCachedNodeIndex = index; }
+ // Set the global position of the layer. This is recorded by the nav cache
+ // and corresponds to RenderLayer::absoluteBoundingBox() which is in
+ // document coordinates. This can be different from the global position of
+ // the layer if the layer is fixed positioned or scrollable.
void setOffset(const IntPoint& offset) { mOffset = offset; }
- void setScrollOffset(const IntPoint& scrollOffset) {
- mScrollOffset = scrollOffset;
- }
void setUniqueId(int uniqueId) { mUniqueId = uniqueId; }
int uniqueId() const { return mUniqueId; }
private:
int mCachedNodeIndex;
mutable const LayerAndroid* mLayer;
- // mOffset and mScrollOffset are the position and scroll offset of the
- // layer when recorded by the nav cache.
IntPoint mOffset;
- IntPoint mScrollOffset;
int mUniqueId;
#if DUMP_NAV_CACHE
diff --git a/WebKit/android/nav/WebView.cpp b/WebKit/android/nav/WebView.cpp
index 6370021..4d92ce8 100644
--- a/WebKit/android/nav/WebView.cpp
+++ b/WebKit/android/nav/WebView.cpp
@@ -971,15 +971,38 @@ bool motionUp(int x, int y, int slop)
return pageScrolled;
}
+#if USE(ACCELERATED_COMPOSITING)
+static const LayerAndroid* findScrollableLayer(const LayerAndroid* parent, int x, int y) {
+ SkRect bounds;
+ parent->bounds(&bounds);
+ // Check the parent bounds first; this will clip to within a masking layer's
+ // bounds.
+ if (!bounds.contains(x, y))
+ return 0;
+ // Move the hit test local to parent.
+ x -= bounds.fLeft;
+ y -= bounds.fTop;
+ int count = parent->countChildren();
+ for (int i = 0; i < count; i++) {
+ const LayerAndroid* child = parent->getChild(i);
+ const LayerAndroid* result = findScrollableLayer(child, x, y);
+ if (result)
+ return result;
+ }
+ if (parent->contentIsScrollable())
+ return parent;
+ return 0;
+}
+#endif
+
const LayerAndroid* scrollableLayer(int x, int y)
{
-#if ENABLE(ANDROID_OVERFLOW_SCROLL) && USE(ACCELERATED_COMPOSITING)
+#if USE(ACCELERATED_COMPOSITING)
const LayerAndroid* layerRoot = compositeRoot();
if (!layerRoot)
return 0;
- const LayerAndroid* result = layerRoot->find(x, y, 0);
- if (result != 0 && result->contentIsScrollable())
- return result;
+ const LayerAndroid* result = findScrollableLayer(layerRoot, x, y);
+ return result;
#endif
return 0;
}
@@ -1269,6 +1292,7 @@ LayerAndroid* compositeRoot() const
return 0;
}
+#if ENABLE(ANDROID_OVERFLOW_SCROLL)
static void copyScrollPositionRecursive(const LayerAndroid* from,
LayerAndroid* root)
{
@@ -1277,14 +1301,15 @@ static void copyScrollPositionRecursive(const LayerAndroid* from,
for (int i = 0; i < from->countChildren(); i++) {
const LayerAndroid* l = from->getChild(i);
if (l->contentIsScrollable()) {
- LayerAndroid* match =
- const_cast<LayerAndroid*>(root->findById(l->uniqueId()));
- if (match != 0)
- match->setScrollPosition(l->scrollPosition());
+ const SkPoint& pos = l->getPosition();
+ LayerAndroid* match = root->findById(l->uniqueId());
+ if (match && match->contentIsScrollable())
+ match->setPosition(pos.fX, pos.fY);
}
copyScrollPositionRecursive(l, root);
}
}
+#endif
void setBaseLayer(BaseLayerAndroid* layer, WebCore::IntRect& rect)
{
@@ -1293,10 +1318,12 @@ void setBaseLayer(BaseLayerAndroid* layer, WebCore::IntRect& rect)
m_glWebViewState->setBaseLayer(layer, rect);
#endif
+#if ENABLE(ANDROID_OVERFLOW_SCROLL)
if (layer) {
- copyScrollPositionRecursive(compositeRoot(),
- static_cast<LayerAndroid*>(layer->getChild(0)));
+ LayerAndroid* newCompositeRoot = static_cast<LayerAndroid*>(layer->getChild(0));
+ copyScrollPositionRecursive(compositeRoot(), newCompositeRoot);
}
+#endif
delete m_baseLayer;
m_baseLayer = layer;
CachedRoot* root = getFrameCache(DontAllowNewer);