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