summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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);