diff options
10 files changed, 132 insertions, 79 deletions
diff --git a/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp b/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp index 0acdc3b..2f9b379 100644 --- a/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp +++ b/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp @@ -215,7 +215,7 @@ void GraphicsLayerAndroid::removeFromParent() } } -void GraphicsLayerAndroid::updateFixedPosition() +void GraphicsLayerAndroid::updatePositionedLayers() { RenderLayer* renderLayer = renderLayerFromClient(m_client); if (!renderLayer) @@ -234,6 +234,7 @@ void GraphicsLayerAndroid::updateFixedPosition() // If we are a fixed position layer, just set it if (view->isPositioned() && view->style()->position() == FixedPosition) { + m_contentLayer->setAbsolutePosition(false); // We need to get the passed CSS properties for the element SkLength left, top, right, bottom; left = convertLength(view->style()->left()); @@ -274,8 +275,12 @@ void GraphicsLayerAndroid::updateFixedPosition() marginRight, marginBottom, renderLayerPos, viewRect); - } else if (m_contentLayer->isFixed()) + } else if (view->isPositioned() && view->style()->position() == AbsolutePosition) { + m_contentLayer->setAbsolutePosition(true); + } else { m_contentLayer->setFixedPosition(0); + m_contentLayer->setAbsolutePosition(false); + } } void GraphicsLayerAndroid::setPosition(const FloatPoint& point) @@ -1036,7 +1041,7 @@ void GraphicsLayerAndroid::syncCompositingStateForThisLayerOnly() } updateScrollingLayers(); - updateFixedPosition(); + updatePositionedLayers(); syncChildren(); syncMask(); diff --git a/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.h b/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.h index 1eb77d6..27dfde2 100644 --- a/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.h +++ b/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.h @@ -137,7 +137,7 @@ private: void syncChildren(); void syncMask(); - void updateFixedPosition(); + void updatePositionedLayers(); void updateScrollingLayers(); // with SkPicture, we always repaint the entire layer's content. diff --git a/Source/WebCore/platform/graphics/android/LayerAndroid.cpp b/Source/WebCore/platform/graphics/android/LayerAndroid.cpp index 349df3a..946d2a3 100644 --- a/Source/WebCore/platform/graphics/android/LayerAndroid.cpp +++ b/Source/WebCore/platform/graphics/android/LayerAndroid.cpp @@ -59,6 +59,7 @@ LayerAndroid::LayerAndroid(RenderLayer* owner) : Layer(), m_visible(true), m_preserves3D(false), m_anchorPointZ(0), + m_isPositionAbsolute(false), m_fixedPosition(0), m_zValue(0), m_uniqueId(++gUniqueId), @@ -83,6 +84,7 @@ LayerAndroid::LayerAndroid(RenderLayer* owner) : Layer(), LayerAndroid::LayerAndroid(const LayerAndroid& layer) : Layer(layer), m_haveClip(layer.m_haveClip), + m_isPositionAbsolute(layer.m_isPositionAbsolute), m_fixedPosition(0), m_zValue(layer.m_zValue), m_uniqueId(layer.m_uniqueId), @@ -119,8 +121,42 @@ LayerAndroid::LayerAndroid(const LayerAndroid& layer) : Layer(layer), m_scale = layer.m_scale; m_lastComputeTextureSize = 0; - for (int i = 0; i < layer.countChildren(); i++) - addChild(layer.getChild(i)->copy())->unref(); + // If we have absolute elements, we may need to reorder them if they + // are followed by another layer that is not also absolutely positioned. + // (as absolutely positioned elements are out of the normal flow) + bool hasAbsoluteChildren = false; + bool hasOnlyAbsoluteFollowers = true; + for (int i = 0; i < layer.countChildren(); i++) { + if (layer.getChild(i)->isPositionAbsolute()) { + hasAbsoluteChildren = true; + continue; + } + if (hasAbsoluteChildren + && !layer.getChild(i)->isPositionAbsolute()) { + hasOnlyAbsoluteFollowers = false; + break; + } + } + + if (hasAbsoluteChildren && !hasOnlyAbsoluteFollowers) { + Vector<LayerAndroid*> normalLayers; + Vector<LayerAndroid*> absoluteLayers; + for (int i = 0; i < layer.countChildren(); i++) { + LayerAndroid* child = layer.getChild(i); + if (child->isPositionAbsolute() + || child->isPositionFixed()) + absoluteLayers.append(child); + else + normalLayers.append(child); + } + for (unsigned int i = 0; i < normalLayers.size(); i++) + addChild(normalLayers[i]->copy())->unref(); + for (unsigned int i = 0; i < absoluteLayers.size(); i++) + addChild(absoluteLayers[i]->copy())->unref(); + } else { + for (int i = 0; i < layer.countChildren(); i++) + addChild(layer.getChild(i)->copy())->unref(); + } KeyframesMap::const_iterator end = layer.m_animations.end(); for (KeyframesMap::const_iterator it = layer.m_animations.begin(); it != end; ++it) { @@ -379,7 +415,7 @@ void LayerAndroid::updateLayerPositions(SkRect viewport, IFrameLayerAndroid* par void LayerAndroid::updatePositions() { // apply the viewport to us - if (!isFixed()) { + if (!isPositionFixed()) { // turn our fields into a matrix. // // FIXME: this should happen in the caller, and we should remove these @@ -405,7 +441,7 @@ void LayerAndroid::updateGLPositionsAndScale(const TransformationMatrix& parentM float originX = anchorPoint.x() * layerSize.width(); float originY = anchorPoint.y() * layerSize.height(); TransformationMatrix localMatrix; - if (!isFixed()) + if (!isPositionFixed()) localMatrix = parentMatrix; localMatrix.translate3d(originX + position.x(), originY + position.y(), @@ -573,7 +609,7 @@ void LayerAndroid::showLayer(int indent) visible.x(), visible.y(), visible.width(), visible.height(), clip.x(), clip.y(), clip.width(), clip.height(), contentIsScrollable() ? "SCROLLABLE" : "", - isFixed() ? "FIXED" : "", + isPositionFixed() ? "FIXED" : "", m_content, m_content ? m_content->width() : -1, m_content ? m_content->height() : -1); @@ -701,7 +737,7 @@ void LayerAndroid::assignGroups(LayerMergeState* mergeState) ALOGD("%*slayer %p(%d) rl %p %s group %p, fixed %d, anim %d, intCom %d, haveClip %d scroll %d", 4*mergeState->depth, "", this, m_uniqueId, m_owningLayer, needNewGroup ? "NEW" : "joins", mergeState->currentLayerGroup, - m_isFixed, m_animations.size() != 0, + isPositionFixed(), m_animations.size() != 0, m_intrinsicallyComposited, m_haveClip, contentIsScrollable()); @@ -710,7 +746,7 @@ void LayerAndroid::assignGroups(LayerMergeState* mergeState) mergeState->currentLayerGroup->addLayer(this, m_drawTransform); m_layerGroup = mergeState->currentLayerGroup; - if (m_haveClip || contentIsScrollable() || isFixed()) { + if (m_haveClip || contentIsScrollable() || isPositionFixed()) { // disable layer merging within the children of these layer types mergeState->nonMergeNestedLevel++; } @@ -733,7 +769,7 @@ void LayerAndroid::assignGroups(LayerMergeState* mergeState) mergeState->depth--; } - if (m_haveClip || contentIsScrollable() || isFixed()) { + if (m_haveClip || contentIsScrollable() || isPositionFixed()) { // re-enable joining mergeState->nonMergeNestedLevel--; @@ -940,7 +976,7 @@ void LayerAndroid::dumpLayer(FILE* file, int indentLevel) const writeHexVal(file, indentLevel + 1, "layer", (int)this); writeIntVal(file, indentLevel + 1, "layerId", m_uniqueId); writeIntVal(file, indentLevel + 1, "haveClip", m_haveClip); - writeIntVal(file, indentLevel + 1, "isFixed", isFixed()); + writeIntVal(file, indentLevel + 1, "isFixed", isPositionFixed()); writeFloatVal(file, indentLevel + 1, "opacity", getOpacity()); writeSize(file, indentLevel + 1, "size", getSize()); diff --git a/Source/WebCore/platform/graphics/android/LayerAndroid.h b/Source/WebCore/platform/graphics/android/LayerAndroid.h index 459c159..7436676 100644 --- a/Source/WebCore/platform/graphics/android/LayerAndroid.h +++ b/Source/WebCore/platform/graphics/android/LayerAndroid.h @@ -236,10 +236,12 @@ public: virtual bool isMedia() const { return false; } virtual bool isVideo() const { return false; } - bool isFixed() const { return m_fixedPosition; } virtual bool isIFrame() const { return false; } virtual bool isIFrameContent() const { return false; } + bool isPositionFixed() const { return m_fixedPosition; } + void setAbsolutePosition(bool isAbsolute) { m_isPositionAbsolute = isAbsolute; } + bool isPositionAbsolute() { return m_isPositionAbsolute; } void setFixedPosition(FixedPositioning* position); FixedPositioning* fixedPosition() { return m_fixedPosition; } @@ -305,6 +307,7 @@ private: float m_anchorPointZ; float m_drawOpacity; + bool m_isPositionAbsolute; FixedPositioning* m_fixedPosition; typedef HashMap<pair<String, int>, RefPtr<AndroidAnimation> > KeyframesMap; diff --git a/Source/WebCore/platform/graphics/android/TiledTexture.cpp b/Source/WebCore/platform/graphics/android/TiledTexture.cpp index 3d36a1b..9ce6f6d 100644 --- a/Source/WebCore/platform/graphics/android/TiledTexture.cpp +++ b/Source/WebCore/platform/graphics/android/TiledTexture.cpp @@ -386,12 +386,12 @@ void DualTiledTexture::computeTexturesAmount(TexturesResult* result, LayerAndroi int nbTexturesClipped = tiledTexture->nbTextures(clippedVisibleArea, m_scale); // Set kFixedLayers level - if (layer->isFixed()) + if (layer->isPositionFixed()) result->fixed += nbTexturesClipped; // Set kScrollableAndFixedLayers level if (layer->contentIsScrollable() - || layer->isFixed()) + || layer->isPositionFixed()) result->scrollable += nbTexturesClipped; // Set kClippedTextures level diff --git a/Source/WebCore/platform/graphics/android/TransferQueue.cpp b/Source/WebCore/platform/graphics/android/TransferQueue.cpp index d5ffc1a..ac45112 100644 --- a/Source/WebCore/platform/graphics/android/TransferQueue.cpp +++ b/Source/WebCore/platform/graphics/android/TransferQueue.cpp @@ -135,8 +135,9 @@ bool TransferQueue::checkObsolete(const TileTransferData* data) } BaseTileTexture* baseTileTexture = baseTilePtr->backTexture(); - if (!baseTileTexture) { - ALOGV("Invalid baseTileTexture , such that the tile is obsolete"); + if (!baseTileTexture || baseTileTexture != data->savedBaseTileTexturePtr) { + ALOGV("Invalid baseTileTexture %p (vs expected %p), such that the tile is obsolete", + baseTileTexture, data->savedBaseTileTexturePtr); return true; } diff --git a/Source/WebCore/rendering/RenderLayerCompositor.cpp b/Source/WebCore/rendering/RenderLayerCompositor.cpp index d7f5c6b..733a418 100644 --- a/Source/WebCore/rendering/RenderLayerCompositor.cpp +++ b/Source/WebCore/rendering/RenderLayerCompositor.cpp @@ -78,7 +78,7 @@ struct CompositingState { : m_compositingAncestor(compAncestor) , m_subtreeIsCompositing(false) #if ENABLE(COMPOSITED_FIXED_ELEMENTS) - , m_fixedSibling(false) + , m_positionedSibling(false) , m_hasFixedElement(false) #endif #if ENABLE(ANDROID_OVERFLOW_SCROLL) @@ -97,7 +97,7 @@ struct CompositingState { // It is used to reject creating unnecesary layers. IntRect m_compositingBounds; #if ENABLE(COMPOSITED_FIXED_ELEMENTS) - bool m_fixedSibling; + bool m_positionedSibling; bool m_hasFixedElement; #endif #if ENABLE(ANDROID_OVERFLOW_SCROLL) @@ -351,7 +351,11 @@ bool RenderLayerCompositor::updateBacking(RenderLayer* layer, CompositingChangeR { bool layerChanged = false; +#if ENABLE(ANDROID_OVERFLOW_SCROLL) + if (needsToBeComposited(layer) || layer->shouldComposite()) { +#else if (needsToBeComposited(layer)) { +#endif enableCompositingMode(); // 3D transforms turn off the testing of overlap. @@ -617,23 +621,49 @@ bool RenderLayerCompositor::overlapsCompositedLayers(OverlapMap& overlapMap, con #if ENABLE(COMPOSITED_FIXED_ELEMENTS) -// to properly support z-index with composited fixed elements, we need to turn -// layers following a fixed layer into compositing mode; but if a layer is fully -// contained into a previous layer already composited (that is not the fixed -// layer), we don't need to composite it. This saves up quite a bit on the -// number of layers we have to composite. -// -bool RenderLayerCompositor::checkForFixedLayers(Vector<RenderLayer*>* list, bool stopAtFixedLayer) +bool RenderLayerCompositor::checkForPositionedElements(Vector<RenderLayer*>* list) { int listSize = list->size(); int haveFixedLayer = -1; bool fixedSibling = false; + bool positionedSibling = false; + + // For absolute positioned elements, we need to check if they are followed + // by a composited element; if so, they also need to be composited, as the + // layer display rendering might be incorrect (absolute elements being + // removed from the flow). + for (int i = 0; i < listSize; ++i) { + RenderLayer* currentLayer = list->at(i); + if (!needsToBeComposited(currentLayer) + && !currentLayer->shouldComposite() + && currentLayer->renderer()->isPositioned()) { + positionedSibling = true; + // check if there is a composited layer later, if so we should be + // composited. + for (int j = i + 1; j < listSize; ++j) { + RenderLayer* layer = list->at(j); + if (needsToBeComposited(layer)) { + currentLayer->setShouldComposite(true); + break; + } + } + break; + } + } + + // If we find a fixed layer, let's mark all the following layers as being + // composited. The layers' surfaces will be merged if needed UI-side. for (int j = 0; j < listSize; ++j) { RenderLayer* currentLayer = list->at(j); + if (currentLayer->shouldComposite()) + continue; + if (currentLayer->isFixed() && needsToBeComposited(currentLayer)) { haveFixedLayer = j; fixedSibling = true; } + + // Bypass fixed layers with a width or height or 1 or less... IntRect currentLayerBounds = currentLayer->renderer()->localToAbsoluteQuad( FloatRect(currentLayer->localBoundingBox())).enclosingBoundingBox(); if ((currentLayerBounds.width() <= 1 @@ -642,28 +672,11 @@ bool RenderLayerCompositor::checkForFixedLayers(Vector<RenderLayer*>* list, bool haveFixedLayer = -1; fixedSibling = false; } - if (haveFixedLayer != -1 && haveFixedLayer != j) { - bool needComposite = true; - int stop = 0; - if (stopAtFixedLayer) - stop = haveFixedLayer + 1; - - for (int k = j - 1; k >= stop; --k) { - RenderLayer* aLayer = list->at(k); - if (aLayer && aLayer->renderer()) { - IntRect bounds = aLayer->renderer()->localToAbsoluteQuad( - FloatRect(aLayer->localBoundingBox())).enclosingBoundingBox(); - if (bounds.contains(currentLayerBounds) - && needsToBeComposited(aLayer) && aLayer->isStackingContext()) { - needComposite = false; - break; - } - } - } - currentLayer->setShouldComposite(needComposite); - } + + if (haveFixedLayer != -1 && haveFixedLayer != j) + currentLayer->setShouldComposite(true); } - return fixedSibling; + return positionedSibling || fixedSibling; } #endif @@ -707,16 +720,9 @@ void RenderLayerCompositor::computeCompositingRequirements(RenderLayer* layer, O if (compositingState.m_subtreeIsCompositing || !compositingState.m_compositingBounds.contains(absBounds)) mustOverlapCompositedLayers = overlapsCompositedLayers(*overlapMap, absBounds); } - -#if ENABLE(COMPOSITED_FIXED_ELEMENTS) - if (compositingState.m_fixedSibling) - layer->setMustOverlapCompositedLayers(layer->shouldComposite()); - else - layer->setMustOverlapCompositedLayers(mustOverlapCompositedLayers); -#else + layer->setMustOverlapCompositedLayers(mustOverlapCompositedLayers); -#endif - + // The children of this layer don't need to composite, unless there is // a compositing layer among them, so start by inheriting the compositing // ancestor with m_subtreeIsCompositing set to false. @@ -731,6 +737,11 @@ void RenderLayerCompositor::computeCompositingRequirements(RenderLayer* layer, O bool willBeComposited = needsToBeComposited(layer); +#if ENABLE(COMPOSITED_FIXED_ELEMENTS) + willBeComposited |= layer->shouldComposite(); + layer->setMustOverlapCompositedLayers(layer->shouldComposite()); +#endif + #if ENABLE(ANDROID_OVERFLOW_SCROLL) // tell the parent it has scrollable descendants. if (layer->hasOverflowScroll()) @@ -763,9 +774,9 @@ void RenderLayerCompositor::computeCompositingRequirements(RenderLayer* layer, O if (Vector<RenderLayer*>* negZOrderList = layer->negZOrderList()) { size_t listSize = negZOrderList->size(); #if ENABLE(COMPOSITED_FIXED_ELEMENTS) - childState.m_fixedSibling = compositingState.m_fixedSibling; - if (checkForFixedLayers(negZOrderList, false)) - childState.m_fixedSibling = true; + childState.m_positionedSibling = compositingState.m_positionedSibling; + if (checkForPositionedElements(negZOrderList)) + childState.m_positionedSibling = true; #endif for (size_t i = 0; i < listSize; ++i) { RenderLayer* curLayer = negZOrderList->at(i); @@ -800,9 +811,9 @@ void RenderLayerCompositor::computeCompositingRequirements(RenderLayer* layer, O if (Vector<RenderLayer*>* normalFlowList = layer->normalFlowList()) { size_t listSize = normalFlowList->size(); #if ENABLE(COMPOSITED_FIXED_ELEMENTS) - childState.m_fixedSibling = compositingState.m_fixedSibling; - if (checkForFixedLayers(normalFlowList, true)) - childState.m_fixedSibling = true; + childState.m_positionedSibling = compositingState.m_positionedSibling; + if (checkForPositionedElements(normalFlowList)) + childState.m_positionedSibling = true; #endif for (size_t i = 0; i < listSize; ++i) { RenderLayer* curLayer = normalFlowList->at(i); @@ -814,9 +825,9 @@ void RenderLayerCompositor::computeCompositingRequirements(RenderLayer* layer, O if (Vector<RenderLayer*>* posZOrderList = layer->posZOrderList()) { size_t listSize = posZOrderList->size(); #if ENABLE(COMPOSITED_FIXED_ELEMENTS) - childState.m_fixedSibling = compositingState.m_fixedSibling; - if (checkForFixedLayers(posZOrderList, true)) - childState.m_fixedSibling = true; + childState.m_positionedSibling = compositingState.m_positionedSibling; + if (checkForPositionedElements(posZOrderList)) + childState.m_positionedSibling = true; #endif for (size_t i = 0; i < listSize; ++i) { RenderLayer* curLayer = posZOrderList->at(i); diff --git a/Source/WebCore/rendering/RenderLayerCompositor.h b/Source/WebCore/rendering/RenderLayerCompositor.h index 813e265..2de1037 100644 --- a/Source/WebCore/rendering/RenderLayerCompositor.h +++ b/Source/WebCore/rendering/RenderLayerCompositor.h @@ -219,7 +219,7 @@ private: void updateCompositingLayersTimerFired(Timer<RenderLayerCompositor>*); #if ENABLE(COMPOSITED_FIXED_ELEMENTS) - bool checkForFixedLayers(Vector<RenderLayer*>* list, bool stopAtFixedLayer); + bool checkForPositionedElements(Vector<RenderLayer*>* list); #endif // Returns true if any layer's compositing changed diff --git a/Source/WebKit/android/jni/ViewStateSerializer.cpp b/Source/WebKit/android/jni/ViewStateSerializer.cpp index 23f6fd7..2be3ecb 100644 --- a/Source/WebKit/android/jni/ViewStateSerializer.cpp +++ b/Source/WebKit/android/jni/ViewStateSerializer.cpp @@ -269,7 +269,7 @@ void serializeLayer(LayerAndroid* layer, SkWStream* stream) // Next up, LayerAndroid fields stream->writeBool(layer->m_haveClip); - stream->writeBool(layer->isFixed()); + stream->writeBool(layer->isPositionFixed()); stream->writeBool(layer->m_backgroundColorSet); stream->writeBool(layer->isIFrame()); diff --git a/Source/WebKit/android/jni/WebViewCore.cpp b/Source/WebKit/android/jni/WebViewCore.cpp index 1bba9b8..33a6382 100644 --- a/Source/WebKit/android/jni/WebViewCore.cpp +++ b/Source/WebKit/android/jni/WebViewCore.cpp @@ -484,7 +484,7 @@ WebViewCore::WebViewCore(JNIEnv* env, jobject javaWebViewCore, WebCore::Frame* m #endif m_javaGlue->m_setWebTextViewAutoFillable = GetJMethod(env, clazz, "setWebTextViewAutoFillable", "(ILjava/lang/String;)V"); m_javaGlue->m_selectAt = GetJMethod(env, clazz, "selectAt", "(II)V"); - m_javaGlue->m_initEditField = GetJMethod(env, clazz, "initEditField", "(ILjava/lang/String;IZZZLjava/lang/String;Ljava/lang/String;IIIILandroid/graphics/Rect;I)V"); + m_javaGlue->m_initEditField = GetJMethod(env, clazz, "initEditField", "(ILjava/lang/String;IZZZZLjava/lang/String;Ljava/lang/String;IIIILandroid/graphics/Rect;I)V"); m_javaGlue->m_updateMatchCount = GetJMethod(env, clazz, "updateMatchCount", "(IILjava/lang/String;)V"); m_javaGlue->m_chromeCanTakeFocus = GetJMethod(env, clazz, "chromeCanTakeFocus", "(I)Z"); m_javaGlue->m_chromeTakeFocus = GetJMethod(env, clazz, "chromeTakeFocus", "(I)V"); @@ -1360,19 +1360,16 @@ static bool isContentEditable(const WebCore::Node* node) { if (!node) return false; - Frame* frame = node->document()->frame(); - if (!frame) - return false; - return frame->selection()->isContentEditable(); + return node->isContentEditable(); } // Returns true if the node is a textfield, textarea, or contentEditable static bool isTextInput(const WebCore::Node* node) { - if (isContentEditable(node)) - return true; if (!node) return false; + if (isContentEditable(node)) + return true; WebCore::RenderObject* renderer = node->renderer(); return renderer && (renderer->isTextField() || renderer->isTextArea()); } @@ -3327,8 +3324,8 @@ void WebViewCore::initEditField(Node* node) PlatformKeyboardEvent tab(AKEYCODE_TAB, 0, 0, false, false, false, false); PassRefPtr<KeyboardEvent> tabEvent = KeyboardEvent::create(tab, document->defaultView()); - Node* nextFocus = document->nextFocusableNode(node, tabEvent.get()); - bool isNextText = isTextInput(nextFocus); + bool isNextText = isTextInput(document->nextFocusableNode(node, tabEvent.get())); + bool isPrevText = isTextInput(document->previousFocusableNode(node, tabEvent.get())); bool spellCheckEnabled = isSpellCheckEnabled(node); int maxLength = getMaxLength(node); String label = requestLabel(document->frame(), node); @@ -3342,8 +3339,8 @@ void WebViewCore::initEditField(Node* node) SelectText* selectText = createSelectText(focusedFrame()->selection()->selection()); env->CallVoidMethod(javaObject.get(), m_javaGlue->m_initEditField, reinterpret_cast<int>(node), fieldText, inputType, - spellCheckEnabled, autoComplete, isNextText, name, labelText, - start, end, reinterpret_cast<int>(selectText), maxLength, + spellCheckEnabled, autoComplete, isNextText, isPrevText, name, + labelText, start, end, reinterpret_cast<int>(selectText), maxLength, nodeBounds, layerId); checkException(env); } |