Index: Source/core/rendering/RenderObject.cpp |
diff --git a/Source/core/rendering/RenderObject.cpp b/Source/core/rendering/RenderObject.cpp |
index a08b09ea579df1363cce8c85ad388e62bab2db78..05056d340300993bb5801f676ed48140178f79e7 100644 |
--- a/Source/core/rendering/RenderObject.cpp |
+++ b/Source/core/rendering/RenderObject.cpp |
@@ -34,6 +34,7 @@ |
#include "core/editing/FrameSelection.h" |
#include "core/editing/htmlediting.h" |
#include "core/html/HTMLElement.h" |
+#include "core/html/HTMLFrameOwnerElement.h" |
#include "core/page/EventHandler.h" |
#include "core/page/Frame.h" |
#include "core/page/FrameView.h" |
@@ -639,6 +640,53 @@ RenderNamedFlowThread* RenderObject::renderNamedFlowThreadWrapper() const |
return object && object->isRenderNamedFlowThread() ? toRenderNamedFlowThread(object) : 0; |
} |
+void RenderObject::enclosingCompositedLayerAndOffset(const RenderLayer** enclosingCompositedLayer, LayoutPoint& offset) const |
+{ |
+ // Determine the new compositing layer and the offset from it. |
+ RenderLayer* layer = enclosingLayer(); |
+ *enclosingCompositedLayer = layer->enclosingCompositingLayerForRepaint(); |
+ |
+ if (!*enclosingCompositedLayer) { |
+ if (document()) { |
+ if (HTMLFrameOwnerElement* ownerElement = document()->ownerElement()) { |
+ if (RenderObject* parentDocRenderer = ownerElement->renderer()) { |
+ // Nearest composited layer is in another document. |
+ // TODO There must be a simpler way to achieve this! |
+ // Would it be simpler to use FrameView::contentsToWindow/windowToContents as in |
+ // convertTargetSpaceQuadToCompositedLayer in LinkHighlight.cpp? |
+ |
+ // First get the offset of this frame within the composited layer. |
+ parentDocRenderer->enclosingCompositedLayerAndOffset(enclosingCompositedLayer, offset); |
+ |
+ // Add the offset of the frame contents within the frame (i.e. border+padding). |
+ if (parentDocRenderer->isBox()) |
+ offset.moveBy(toRenderBox(parentDocRenderer)->contentBoxRect().location()); |
+ |
+ // Now add the offset of this object within our frame. |
+ TransformState transformState(TransformState::ApplyTransformDirection, FloatPoint()); |
+ mapLocalToContainer(view(), transformState, ApplyContainerFlip | UseTransforms); |
+ transformState.flatten(); |
+ offset.moveBy(LayoutPoint(transformState.lastPlanarPoint())); |
+ |
+ // And subtract the scroll offset of this frame. |
+ offset -= frame()->view()->scrollOffset(); |
+ } |
+ } |
+ } |
+ return; |
+ } |
+ |
+ // Self-painting layers subtract the renderer's location. Otherwise, we need to map our location to layer space. |
+ if ((*enclosingCompositedLayer)->renderer() == this) { |
+ offset = LayoutPoint(); |
+ } else { |
+ TransformState transformState(TransformState::ApplyTransformDirection, FloatPoint()); |
+ mapLocalToContainer((*enclosingCompositedLayer)->renderer(), transformState, ApplyContainerFlip | UseTransforms); |
+ transformState.flatten(); |
+ offset = LayoutPoint(transformState.lastPlanarPoint()); |
+ } |
+} |
+ |
RenderBlock* RenderObject::firstLineBlock() const |
{ |
return 0; |
@@ -2267,6 +2315,49 @@ LayoutRect RenderObject::localCaretRect(InlineBox*, int, LayoutUnit* extraWidthT |
return LayoutRect(); |
} |
+void RenderObject::computeLayerHitTestRects(LayerHitTestRects& layerRects) const |
+{ |
+ // Figure out what composited layer our container is in. Any offset (or new layer) for this |
+ // renderer within it's container will be applied in addLayerHitTestRects. |
+ LayoutPoint layerOffset; |
+ const RenderLayer* currentCompositedLayer; |
+ if (container()) |
+ container()->enclosingCompositedLayerAndOffset(¤tCompositedLayer, layerOffset); |
+ else |
+ enclosingCompositedLayerAndOffset(¤tCompositedLayer, layerOffset); |
+ if (!currentCompositedLayer) |
+ return; |
+ |
+ this->addLayerHitTestRects(layerRects, currentCompositedLayer, layerOffset); |
+} |
+ |
+void RenderObject::addLayerHitTestRects(LayerHitTestRects& layerRects, const RenderLayer* currentCompositedLayer, const LayoutPoint& layerOffset) const |
+{ |
+ ASSERT(currentCompositedLayer); |
+ |
+ // If it's possible for children to have rects outside our bounds, then we need to descend into the |
+ // children and compute them. |
+ // TODO: Any tighter guarantee on when we don't need to descend into children? |
leviw_travelin_and_unemployed
2013/07/10 01:51:16
I don't think there's any tighter guarantee, but g
|
+ // TODO: Should I improve Region and use it? https://bugs.webkit.org/show_bug.cgi?id=100814 |
+ if (!isRoot()) { |
+ for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling()) { |
+ // TODO: levi's original patch excluded curr->isText(), curr->isListMarker() and !curr->isBox(). Why? |
leviw_travelin_and_unemployed
2013/07/10 01:51:16
I can't recall on the latter two, but text nodes a
|
+ curr->addLayerHitTestRects(layerRects, currentCompositedLayer, layerOffset); |
+ } |
+ } |
+ |
+ // Compute the rects for this renderer only and add them to the results. |
+ // TODO: We could avoid passing the offset here and instead offset each result. |
+ Vector<IntRect> ownRects; |
+ computeOwnHitTestRects(ownRects, layerOffset); |
+ |
+ LayerHitTestRects::iterator iter = layerRects.find(currentCompositedLayer); |
+ if (iter == layerRects.end()) |
+ layerRects.add(currentCompositedLayer, ownRects); |
+ else |
+ iter->value.append(ownRects); |
+} |
+ |
bool RenderObject::isRooted(RenderView** view) const |
{ |
const RenderObject* o = this; |