diff options
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); |