Index: Source/core/frame/FrameView.cpp |
diff --git a/Source/core/frame/FrameView.cpp b/Source/core/frame/FrameView.cpp |
index 9dda0b78d2daa9febf173c629ae0e45f484c5569..57128d9072670c102263070ecad1cb85d9dc3776 100644 |
--- a/Source/core/frame/FrameView.cpp |
+++ b/Source/core/frame/FrameView.cpp |
@@ -32,6 +32,7 @@ |
#include "core/css/FontFaceSet.h" |
#include "core/css/resolver/StyleResolver.h" |
#include "core/dom/DocumentMarkerController.h" |
+#include "core/editing/Editor.h" |
#include "core/editing/FrameSelection.h" |
#include "core/events/OverflowEvent.h" |
#include "core/fetch/ResourceFetcher.h" |
@@ -66,6 +67,7 @@ |
#include "core/rendering/RenderWidget.h" |
#include "core/rendering/TextAutosizer.h" |
#include "core/rendering/compositing/CompositedLayerMapping.h" |
+#include "core/rendering/compositing/CompositedSelectionBound.h" |
#include "core/rendering/compositing/RenderLayerCompositor.h" |
#include "core/rendering/style/RenderStyle.h" |
#include "core/rendering/svg/RenderSVGRoot.h" |
@@ -1696,6 +1698,93 @@ void FrameView::updateFixedElementPaintInvalidationRectsAfterScroll() |
} |
} |
+static bool computeCompositedLayerAndRect(Node* node, IntRect absoluteRect, GraphicsLayer*& layer, IntRect& layerRect) |
+{ |
+ RenderLayer* renderLayer; |
+ GraphicsLayer* graphicsLayer; |
+ if (!RenderLayerCompositor::computeEnclosingCompositingLayer(node, renderLayer, graphicsLayer)) |
+ return false; |
+ |
+ ASSERT(renderLayer); |
+ ASSERT(graphicsLayer); |
+ |
+ absoluteRect.move(-graphicsLayer->offsetFromRenderer()); |
+ FloatQuad absoluteQuad(absoluteRect); |
+ FloatQuad layerQuad; |
+ RenderLayerCompositor::convertTargetSpaceQuadToCompositedLayer(absoluteQuad, node->renderer(), renderLayer->renderer(), layerQuad); |
+ |
+ layer = graphicsLayer; |
+ |
+ // An enclosed rect avoids bounding box rounding outside the layer bounds. |
+ layerRect = enclosedIntRect(layerQuad.boundingBox()); |
+ |
+ // The delivered edge rect should have but a single dimension (height). |
+ // Note that this *should* also hold for the provided |absoluteRect|, but |
+ // zero-ing the width here gives a stronger guarantee. |
+ layerRect.setWidth(0); |
+ |
+ return true; |
+} |
+ |
+static bool computeCompositedSelectionBounds(LocalFrame& frame, CompositedSelectionBound& start, CompositedSelectionBound& end) |
+{ |
+ FrameSelection& selection = frame.selection(); |
+ if (!selection.isCaretOrRange()) |
+ return false; |
+ |
+ if (selection.isCaret()) { |
+ if (!computeCompositedLayerAndRect(selection.rootEditableElementOrDocumentElement(), selection.absoluteCaretBounds(), start.layer, start.edgeRectInLayer)) |
+ return false; |
+ start.type = CompositedSelectionBound::Caret; |
+ end = start; |
+ return true; |
+ } |
+ |
+ RefPtrWillBeRawPtr<Range> selectedRange = selection.toNormalizedRange(); |
+ if (!selectedRange) |
+ return false; |
+ |
+ RefPtrWillBeRawPtr<Range> range(Range::create(selectedRange->startContainer()->document(), |
+ selectedRange->startContainer(), |
+ selectedRange->startOffset(), |
+ selectedRange->startContainer(), |
+ selectedRange->startOffset())); |
+ IntRect startRect = frame.editor().firstRectForRange(range.get()); |
+ if (!computeCompositedLayerAndRect(selection.start().anchorNode(), startRect, start.layer, start.edgeRectInLayer)) |
+ return false; |
+ |
+ range = Range::create(selectedRange->endContainer()->document(), |
+ selectedRange->endContainer(), |
+ selectedRange->endOffset(), |
+ selectedRange->endContainer(), |
+ selectedRange->endOffset()); |
+ IntRect endRect = frame.editor().firstRectForRange(range.get()); |
+ if (!computeCompositedLayerAndRect(selection.end().anchorNode(), endRect, end.layer, end.edgeRectInLayer)) |
+ return false; |
+ |
+ TextDirection startDir = selection.start().primaryDirection(); |
+ TextDirection endDir = selection.end().primaryDirection(); |
+ if (startDir == endDir) { |
+ if (startDir == RTL) { |
+ start.type = CompositedSelectionBound::SelectionRight; |
+ end.type = CompositedSelectionBound::SelectionLeft; |
+ } else { |
+ start.type = CompositedSelectionBound::SelectionLeft; |
+ end.type = CompositedSelectionBound::SelectionRight; |
+ } |
+ } else { |
+ if (startDir == RTL) { |
+ start.type = CompositedSelectionBound::SelectionRight; |
+ end.type = CompositedSelectionBound::SelectionRight; |
+ } else { |
+ start.type = CompositedSelectionBound::SelectionLeft; |
+ end.type = CompositedSelectionBound::SelectionLeft; |
+ } |
+ } |
+ |
+ return true; |
+} |
+ |
void FrameView::updateCompositedSelectionBoundsIfNeeded() |
{ |
if (!RuntimeEnabledFeatures::compositedSelectionUpdatesEnabled()) |
@@ -1704,13 +1793,14 @@ void FrameView::updateCompositedSelectionBoundsIfNeeded() |
Page* page = frame().page(); |
ASSERT(page); |
+ CompositedSelectionBound start, end; |
LocalFrame* frame = toLocalFrame(page->focusController().focusedOrMainFrame()); |
- if (!frame || !frame->selection().isCaretOrRange()) { |
+ if (!frame || !computeCompositedSelectionBounds(*frame, start, end)) { |
page->chrome().client().clearCompositedSelectionBounds(); |
return; |
} |
- // TODO(jdduke): Compute and route selection bounds through ChromeClient. |
+ page->chrome().client().updateCompositedSelectionBounds(start, end); |
} |
bool FrameView::isRubberBandInProgress() const |