69
69
, m_lastChangeWasHorizontalExtension(false)
70
70
, m_isDragCaretController(isDragCaretController)
71
71
, m_isCaretBlinkingSuspended(false)
72
, m_focused(frame && frame->page() && frame->page()->focusController()->focusedFrame() == frame)
76
76
void SelectionController::moveTo(const VisiblePosition &pos, bool userTriggered)
78
setSelection(Selection(pos.deepEquivalent(), pos.deepEquivalent(), pos.affinity()), true, true, userTriggered);
78
setSelection(VisibleSelection(pos.deepEquivalent(), pos.deepEquivalent(), pos.affinity()), true, true, userTriggered);
81
81
void SelectionController::moveTo(const VisiblePosition &base, const VisiblePosition &extent, bool userTriggered)
83
setSelection(Selection(base.deepEquivalent(), extent.deepEquivalent(), base.affinity()), true, true, userTriggered);
83
setSelection(VisibleSelection(base.deepEquivalent(), extent.deepEquivalent(), base.affinity()), true, true, userTriggered);
86
86
void SelectionController::moveTo(const Position &pos, EAffinity affinity, bool userTriggered)
88
setSelection(Selection(pos, affinity), true, true, userTriggered);
88
setSelection(VisibleSelection(pos, affinity), true, true, userTriggered);
91
91
void SelectionController::moveTo(const Range *r, EAffinity affinity, bool userTriggered)
93
setSelection(Selection(startPosition(r), endPosition(r), affinity), true, true, userTriggered);
93
VisibleSelection selection = r ? VisibleSelection(r->startPosition(), r->endPosition(), affinity) : VisibleSelection(Position(), Position(), affinity);
94
setSelection(selection, true, true, userTriggered);
96
97
void SelectionController::moveTo(const Position &base, const Position &extent, EAffinity affinity, bool userTriggered)
98
setSelection(Selection(base, extent, affinity), true, true, userTriggered);
99
setSelection(VisibleSelection(base, extent, affinity), true, true, userTriggered);
101
void SelectionController::setSelection(const Selection& s, bool closeTyping, bool clearTypingStyle, bool userTriggered)
102
void SelectionController::setSelection(const VisibleSelection& s, bool closeTyping, bool clearTypingStyle, bool userTriggered)
104
m_lastChangeWasHorizontalExtension = false;
103
106
if (m_isDragCaretController) {
104
107
invalidateCaretRect();
118
Node* baseNode = s.base().node();
119
Document* document = 0;
121
document = baseNode->document();
115
if (s.base().node() && s.base().node()->document() != m_frame->document()) {
116
s.base().node()->document()->frame()->selection()->setSelection(s, closeTyping, clearTypingStyle, userTriggered);
123
// <http://bugs.webkit.org/show_bug.cgi?id=23464>: Infinite recursion at SelectionController::setSelection
124
// if document->frame() == m_frame we can get into an infinite loop
125
if (document && document->frame() != m_frame && document != m_frame->document()) {
126
document->frame()->selection()->setSelection(s, closeTyping, clearTypingStyle, userTriggered);
196
206
m_sel.setWithoutValidation(m_sel.end(), m_sel.start());
197
207
// FIXME: This could be more efficient if we had an isNodeInRange function on Ranges.
198
} else if (Range::compareBoundaryPoints(m_sel.start(), Position(node, 0)) == -1 &&
199
Range::compareBoundaryPoints(m_sel.end(), Position(node, 0)) == 1) {
208
} else if (comparePositions(m_sel.start(), Position(node, 0)) == -1 && comparePositions(m_sel.end(), Position(node, 0)) == 1) {
200
209
// If we did nothing here, when this node's renderer was destroyed, the rect that it
201
210
// occupied would be invalidated, but, selection gaps that change as a result of
202
211
// the removal wouldn't be invalidated.
207
216
if (clearRenderTreeSelection) {
208
217
RefPtr<Document> document = m_sel.start().node()->document();
209
document->updateRendering();
210
if (RenderView* view = static_cast<RenderView*>(document->renderer()))
218
document->updateStyleIfNeeded();
219
if (RenderView* view = toRenderView(document->renderer()))
211
220
view->clearSelection();
214
223
if (clearDOMTreeSelection)
215
setSelection(Selection(), false, false);
224
setSelection(VisibleSelection(), false, false);
218
227
void SelectionController::willBeModified(EAlteration alter, EDirection direction)
222
m_lastChangeWasHorizontalExtension = false;
225
if (!m_lastChangeWasHorizontalExtension) {
226
m_lastChangeWasHorizontalExtension = true;
227
Position start = m_sel.start();
228
Position end = m_sel.end();
230
// FIXME: right for bidi?
233
m_sel.setBase(start);
234
m_sel.setExtent(end);
239
m_sel.setExtent(start);
247
VisiblePosition SelectionController::modifyExtendingRightForward(TextGranularity granularity)
231
if (m_lastChangeWasHorizontalExtension)
234
Position start = m_sel.start();
235
Position end = m_sel.end();
236
// FIXME: This is probably not correct for right and left when the direction is RTL.
240
m_sel.setBase(start);
241
m_sel.setExtent(end);
246
m_sel.setExtent(start);
251
TextDirection SelectionController::directionOfEnclosingBlock()
253
Node* n = m_sel.extent().node();
254
Node* enclosingBlockNode = enclosingBlock(n);
255
if (!enclosingBlockNode)
257
RenderObject* renderer = enclosingBlockNode->renderer();
259
return renderer->style()->direction();
263
VisiblePosition SelectionController::modifyExtendingRight(TextGranularity granularity)
265
VisiblePosition pos(m_sel.extent(), m_sel.affinity());
267
// The difference between modifyExtendingRight and modifyExtendingForward is:
268
// modifyExtendingForward always extends forward logically.
269
// modifyExtendingRight behaves the same as modifyExtendingForward except for extending character or word,
270
// it extends forward logically if the enclosing block is LTR direction,
271
// but it extends backward logically if the enclosing block is RTL direction.
272
switch (granularity) {
273
case CharacterGranularity:
274
if (directionOfEnclosingBlock() == LTR)
275
pos = pos.next(true);
277
pos = pos.previous(true);
279
case WordGranularity:
280
if (directionOfEnclosingBlock() == LTR)
281
pos = nextWordPosition(pos);
283
pos = previousWordPosition(pos);
285
case SentenceGranularity:
286
case LineGranularity:
287
case ParagraphGranularity:
288
case SentenceBoundary:
290
case ParagraphBoundary:
291
case DocumentBoundary:
292
// FIXME: implement all of the above?
293
pos = modifyExtendingForward(granularity);
298
VisiblePosition SelectionController::modifyExtendingForward(TextGranularity granularity)
249
300
VisiblePosition pos(m_sel.extent(), m_sel.affinity());
250
301
switch (granularity) {
361
VisiblePosition SelectionController::modifyExtendingLeftBackward(TextGranularity granularity)
363
VisiblePosition pos(m_sel.extent(), m_sel.affinity());
412
VisiblePosition SelectionController::modifyExtendingLeft(TextGranularity granularity)
414
VisiblePosition pos(m_sel.extent(), m_sel.affinity());
416
// The difference between modifyExtendingLeft and modifyExtendingBackward is:
417
// modifyExtendingBackward always extends backward logically.
418
// modifyExtendingLeft behaves the same as modifyExtendingBackward except for extending character or word,
419
// it extends backward logically if the enclosing block is LTR direction,
420
// but it extends forward logically if the enclosing block is RTL direction.
421
switch (granularity) {
422
case CharacterGranularity:
423
if (directionOfEnclosingBlock() == LTR)
424
pos = pos.previous(true);
426
pos = pos.next(true);
428
case WordGranularity:
429
if (directionOfEnclosingBlock() == LTR)
430
pos = previousWordPosition(pos);
432
pos = nextWordPosition(pos);
434
case SentenceGranularity:
435
case LineGranularity:
436
case ParagraphGranularity:
437
case SentenceBoundary:
439
case ParagraphBoundary:
440
case DocumentBoundary:
441
pos = modifyExtendingBackward(granularity);
446
VisiblePosition SelectionController::modifyExtendingBackward(TextGranularity granularity)
448
VisiblePosition pos(m_sel.extent(), m_sel.affinity());
365
450
// Extending a selection backward by word or character from just after a table selects
366
451
// the table. This "makes sense" from the user perspective, esp. when deleting.
367
452
// It was done here instead of in VisiblePosition because we want VPs to iterate
693
781
void SelectionController::clear()
695
setSelection(Selection());
783
setSelection(VisibleSelection());
698
786
void SelectionController::setBase(const VisiblePosition &pos, bool userTriggered)
700
setSelection(Selection(pos.deepEquivalent(), m_sel.extent(), pos.affinity()), true, true, userTriggered);
788
setSelection(VisibleSelection(pos.deepEquivalent(), m_sel.extent(), pos.affinity()), true, true, userTriggered);
703
791
void SelectionController::setExtent(const VisiblePosition &pos, bool userTriggered)
705
setSelection(Selection(m_sel.base(), pos.deepEquivalent(), pos.affinity()), true, true, userTriggered);
793
setSelection(VisibleSelection(m_sel.base(), pos.deepEquivalent(), pos.affinity()), true, true, userTriggered);
708
796
void SelectionController::setBase(const Position &pos, EAffinity affinity, bool userTriggered)
710
setSelection(Selection(pos, m_sel.extent(), affinity), true, true, userTriggered);
798
setSelection(VisibleSelection(pos, m_sel.extent(), affinity), true, true, userTriggered);
713
801
void SelectionController::setExtent(const Position &pos, EAffinity affinity, bool userTriggered)
715
setSelection(Selection(m_sel.base(), pos, affinity), true, true, userTriggered);
803
setSelection(VisibleSelection(m_sel.base(), pos, affinity), true, true, userTriggered);
718
806
void SelectionController::setNeedsLayout(bool flag)
812
909
IntRect SelectionController::caretRepaintRect() const
814
IntRect localRect = repaintRectForCaret(localCaretRect());
816
RenderObject* caretPainter = caretRenderer();
818
return caretPainter->localToAbsoluteQuad(FloatRect(localRect)).enclosingBoundingBox();
911
return absoluteBoundsForLocalRect(repaintRectForCaret(localCaretRect()));
823
914
bool SelectionController::recomputeCaretRect()
825
if (!m_frame || !m_frame->document())
828
919
FrameView* v = m_frame->document()->view();
835
926
IntRect oldRect = m_caretRect;
836
m_needsLayout = true;
837
927
IntRect newRect = localCaretRect();
838
928
if (oldRect == newRect && !m_absCaretBoundsDirty)
841
IntRect oldAbsRepaintRect = m_absCaretBounds;
842
m_absCaretBounds = caretRepaintRect();
931
IntRect oldAbsCaretBounds = m_absCaretBounds;
932
// FIXME: Rename m_caretRect to m_localCaretRect.
933
m_absCaretBounds = absoluteBoundsForLocalRect(m_caretRect);
843
934
m_absCaretBoundsDirty = false;
845
if (oldAbsRepaintRect == m_absCaretBounds)
936
if (oldAbsCaretBounds == m_absCaretBounds)
939
IntRect oldAbsoluteCaretRepaintBounds = m_absoluteCaretRepaintBounds;
940
// We believe that we need to inflate the local rect before transforming it to obtain the repaint bounds.
941
m_absoluteCaretRepaintBounds = caretRepaintRect();
848
if (RenderView* view = static_cast<RenderView*>(m_frame->document()->renderer())) {
849
view->repaintViewRectangle(oldAbsRepaintRect, false);
850
view->repaintViewRectangle(m_absCaretBounds, false);
943
if (RenderView* view = toRenderView(m_frame->document()->renderer())) {
944
// FIXME: make caret repainting container-aware.
945
view->repaintRectangleInViewAndCompositedLayers(oldAbsoluteCaretRepaintBounds, false);
946
view->repaintRectangleInViewAndCompositedLayers(m_absoluteCaretRepaintBounds, false);
925
1021
if (r->node() == m_sel.start().node())
926
offset = m_sel.start().offset();
1022
offset = m_sel.start().deprecatedEditingOffset();
927
1023
else if (r->node() == m_sel.end().node())
928
offset = m_sel.end().offset();
1024
offset = m_sel.end().deprecatedEditingOffset();
931
1027
InlineTextBox *box = textRenderer->findNextInlineTextBox(offset, pos);
932
text = text.substring(box->m_start, box->m_len);
1028
text = text.substring(box->start(), box->len());
935
1031
int mid = max / 2;
987
1083
if (!document->renderer())
990
HitTestRequest request(true, true);
1086
HitTestRequest request(HitTestRequest::ReadOnly |
1087
HitTestRequest::Active);
991
1088
HitTestResult result(point);
992
document->renderer()->layer()->hitTest(request, result);
1089
document->renderView()->layer()->hitTest(request, result);
993
1090
Node* innerNode = result.innerNode();
994
1091
if (!innerNode || !innerNode->renderer())
1052
1147
VisiblePosition afterOwnerElement(VisiblePosition(ownerElementParent, ownerElementNodeIndex + 1, VP_UPSTREAM_IF_POSSIBLE));
1054
1149
// Focus on the parent frame, and then select from before this element to after.
1055
Selection newSelection(beforeOwnerElement, afterOwnerElement);
1150
VisibleSelection newSelection(beforeOwnerElement, afterOwnerElement);
1056
1151
if (parent->shouldChangeSelection(newSelection)) {
1057
1152
page->focusController()->setFocusedFrame(parent);
1058
1153
parent->selection()->setSelection(newSelection);
1124
1217
// FIXME: Can we provide extentAffinity?
1125
1218
VisiblePosition visibleStart(startContainer, startOffset, collapsed ? affinity : DOWNSTREAM);
1126
1219
VisiblePosition visibleEnd(endContainer, endOffset, SEL_DEFAULT_AFFINITY);
1127
setSelection(Selection(visibleStart, visibleEnd), closeTyping);
1220
setSelection(VisibleSelection(visibleStart, visibleEnd), closeTyping);
1158
1251
// Because RenderObject::selectionBackgroundColor() and
1159
1252
// RenderObject::selectionForegroundColor() check if the frame is active,
1160
1253
// we have to update places those colors were painted.
1161
if (RenderView* view = static_cast<RenderView*>(m_frame->document()->renderer()))
1162
view->repaintViewRectangle(enclosingIntRect(m_frame->selectionBounds()));
1254
if (RenderView* view = toRenderView(m_frame->document()->renderer()))
1255
view->repaintRectangleInViewAndCompositedLayers(enclosingIntRect(m_frame->selectionBounds()));
1164
1257
// Caret appears in the active frame.
1165
1258
if (activeAndFocused)
1173
1266
// RenderTheme::isFocused() check if the frame is active, we have to
1174
1267
// update style and theme state that depended on those.
1175
1268
if (Node* node = m_frame->document()->focusedNode()) {
1269
node->setNeedsStyleRecalc();
1177
1270
if (RenderObject* renderer = node->renderer())
1178
1271
if (renderer && renderer->style()->hasAppearance())
1179
theme()->stateChanged(renderer, FocusState);
1272
renderer->theme()->stateChanged(renderer, FocusState);
1182
1275
// Secure keyboard entry is set by the active frame.