| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2004, 2008, 2009, 2010 Apple Inc. All rights reserved. | 2 * Copyright (C) 2004, 2008, 2009, 2010 Apple Inc. All rights reserved. |
| 3 * | 3 * |
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions | 5 * modification, are permitted provided that the following conditions |
| 6 * are met: | 6 * are met: |
| 7 * 1. Redistributions of source code must retain the above copyright | 7 * 1. Redistributions of source code must retain the above copyright |
| 8 * notice, this list of conditions and the following disclaimer. | 8 * notice, this list of conditions and the following disclaimer. |
| 9 * 2. Redistributions in binary form must reproduce the above copyright | 9 * 2. Redistributions in binary form must reproduce the above copyright |
| 10 * notice, this list of conditions and the following disclaimer in the | 10 * notice, this list of conditions and the following disclaimer in the |
| (...skipping 413 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 424 return false; | 424 return false; |
| 425 Position start = selection.start().parentAnchoredEquivalent(); | 425 Position start = selection.start().parentAnchoredEquivalent(); |
| 426 Position end = selection.end().parentAnchoredEquivalent(); | 426 Position end = selection.end().parentAnchoredEquivalent(); |
| 427 TrackExceptionState exceptionState; | 427 TrackExceptionState exceptionState; |
| 428 // TODO(yosin) We should avoid to use |Range::intersectsNode()|. | 428 // TODO(yosin) We should avoid to use |Range::intersectsNode()|. |
| 429 return Range::intersectsNode(node, start, end, exceptionState) && !exception
State.hadException(); | 429 return Range::intersectsNode(node, start, end, exceptionState) && !exception
State.hadException(); |
| 430 } | 430 } |
| 431 | 431 |
| 432 void FrameSelection::respondToNodeModification(Node& node, bool baseRemoved, boo
l extentRemoved, bool startRemoved, bool endRemoved) | 432 void FrameSelection::respondToNodeModification(Node& node, bool baseRemoved, boo
l extentRemoved, bool startRemoved, bool endRemoved) |
| 433 { | 433 { |
| 434 ASSERT(node.document().isActive()); | 434 DCHECK(node.document().isActive()); |
| 435 | 435 |
| 436 bool clearLayoutTreeSelection = false; | 436 bool clearLayoutTreeSelection = false; |
| 437 bool clearDOMTreeSelection = false; | 437 bool clearDOMTreeSelection = false; |
| 438 | 438 |
| 439 if (startRemoved || endRemoved) { | 439 if (startRemoved || endRemoved) { |
| 440 Position start = selection().start(); | 440 Position start = selection().start(); |
| 441 Position end = selection().end(); | 441 Position end = selection().end(); |
| 442 if (startRemoved) | 442 if (startRemoved) |
| 443 updatePositionForNodeRemoval(start, node); | 443 updatePositionForNodeRemoval(start, node); |
| 444 if (endRemoved) | 444 if (endRemoved) |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 482 if (!m_frame->document()->isRunningExecCommand()) | 482 if (!m_frame->document()->isRunningExecCommand()) |
| 483 TypingCommand::closeTyping(m_frame); | 483 TypingCommand::closeTyping(m_frame); |
| 484 } | 484 } |
| 485 | 485 |
| 486 static Position updatePositionAfterAdoptingTextReplacement(const Position& posit
ion, CharacterData* node, unsigned offset, unsigned oldLength, unsigned newLengt
h) | 486 static Position updatePositionAfterAdoptingTextReplacement(const Position& posit
ion, CharacterData* node, unsigned offset, unsigned oldLength, unsigned newLengt
h) |
| 487 { | 487 { |
| 488 if (!position.anchorNode() || position.anchorNode() != node || !position.isO
ffsetInAnchor()) | 488 if (!position.anchorNode() || position.anchorNode() != node || !position.isO
ffsetInAnchor()) |
| 489 return position; | 489 return position; |
| 490 | 490 |
| 491 // See: http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#Level-2
-Range-Mutation | 491 // See: http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#Level-2
-Range-Mutation |
| 492 ASSERT(position.offsetInContainerNode() >= 0); | 492 DCHECK_GE(position.offsetInContainerNode(), 0); |
| 493 unsigned positionOffset = static_cast<unsigned>(position.offsetInContainerNo
de()); | 493 unsigned positionOffset = static_cast<unsigned>(position.offsetInContainerNo
de()); |
| 494 // Replacing text can be viewed as a deletion followed by insertion. | 494 // Replacing text can be viewed as a deletion followed by insertion. |
| 495 if (positionOffset >= offset && positionOffset <= offset + oldLength) | 495 if (positionOffset >= offset && positionOffset <= offset + oldLength) |
| 496 positionOffset = offset; | 496 positionOffset = offset; |
| 497 | 497 |
| 498 // Adjust the offset if the position is after the end of the deleted content
s | 498 // Adjust the offset if the position is after the end of the deleted content
s |
| 499 // (positionOffset > offset + oldLength) to avoid having a stale offset. | 499 // (positionOffset > offset + oldLength) to avoid having a stale offset. |
| 500 if (positionOffset > offset + oldLength) | 500 if (positionOffset > offset + oldLength) |
| 501 positionOffset = positionOffset - oldLength + newLength; | 501 positionOffset = positionOffset - oldLength + newLength; |
| 502 | 502 |
| (...skipping 20 matching lines...) Expand all Loading... |
| 523 Position start = updatePositionAfterAdoptingTextReplacement(selection().star
t(), node, offset, oldLength, newLength); | 523 Position start = updatePositionAfterAdoptingTextReplacement(selection().star
t(), node, offset, oldLength, newLength); |
| 524 Position end = updatePositionAfterAdoptingTextReplacement(selection().end(),
node, offset, oldLength, newLength); | 524 Position end = updatePositionAfterAdoptingTextReplacement(selection().end(),
node, offset, oldLength, newLength); |
| 525 updateSelectionIfNeeded(base, extent, start, end); | 525 updateSelectionIfNeeded(base, extent, start, end); |
| 526 } | 526 } |
| 527 | 527 |
| 528 static Position updatePostionAfterAdoptingTextNodesMerged(const Position& positi
on, const Text& oldNode, unsigned offset) | 528 static Position updatePostionAfterAdoptingTextNodesMerged(const Position& positi
on, const Text& oldNode, unsigned offset) |
| 529 { | 529 { |
| 530 if (!position.anchorNode() || !position.isOffsetInAnchor()) | 530 if (!position.anchorNode() || !position.isOffsetInAnchor()) |
| 531 return position; | 531 return position; |
| 532 | 532 |
| 533 ASSERT(position.offsetInContainerNode() >= 0); | 533 DCHECK_GE(position.offsetInContainerNode(), 0); |
| 534 unsigned positionOffset = static_cast<unsigned>(position.offsetInContainerNo
de()); | 534 unsigned positionOffset = static_cast<unsigned>(position.offsetInContainerNo
de()); |
| 535 | 535 |
| 536 if (position.anchorNode() == &oldNode) | 536 if (position.anchorNode() == &oldNode) |
| 537 return Position(toText(oldNode.previousSibling()), positionOffset + offs
et); | 537 return Position(toText(oldNode.previousSibling()), positionOffset + offs
et); |
| 538 | 538 |
| 539 if (position.anchorNode() == oldNode.parentNode() && positionOffset == offse
t) | 539 if (position.anchorNode() == oldNode.parentNode() && positionOffset == offse
t) |
| 540 return Position(toText(oldNode.previousSibling()), offset); | 540 return Position(toText(oldNode.previousSibling()), offset); |
| 541 | 541 |
| 542 return position; | 542 return position; |
| 543 } | 543 } |
| 544 | 544 |
| 545 void FrameSelection::didMergeTextNodes(const Text& oldNode, unsigned offset) | 545 void FrameSelection::didMergeTextNodes(const Text& oldNode, unsigned offset) |
| 546 { | 546 { |
| 547 if (isNone() || !oldNode.inShadowIncludingDocument()) | 547 if (isNone() || !oldNode.inShadowIncludingDocument()) |
| 548 return; | 548 return; |
| 549 Position base = updatePostionAfterAdoptingTextNodesMerged(selection().base()
, oldNode, offset); | 549 Position base = updatePostionAfterAdoptingTextNodesMerged(selection().base()
, oldNode, offset); |
| 550 Position extent = updatePostionAfterAdoptingTextNodesMerged(selection().exte
nt(), oldNode, offset); | 550 Position extent = updatePostionAfterAdoptingTextNodesMerged(selection().exte
nt(), oldNode, offset); |
| 551 Position start = updatePostionAfterAdoptingTextNodesMerged(selection().start
(), oldNode, offset); | 551 Position start = updatePostionAfterAdoptingTextNodesMerged(selection().start
(), oldNode, offset); |
| 552 Position end = updatePostionAfterAdoptingTextNodesMerged(selection().end(),
oldNode, offset); | 552 Position end = updatePostionAfterAdoptingTextNodesMerged(selection().end(),
oldNode, offset); |
| 553 updateSelectionIfNeeded(base, extent, start, end); | 553 updateSelectionIfNeeded(base, extent, start, end); |
| 554 } | 554 } |
| 555 | 555 |
| 556 static Position updatePostionAfterAdoptingTextNodeSplit(const Position& position
, const Text& oldNode) | 556 static Position updatePostionAfterAdoptingTextNodeSplit(const Position& position
, const Text& oldNode) |
| 557 { | 557 { |
| 558 if (!position.anchorNode() || position.anchorNode() != &oldNode || !position
.isOffsetInAnchor()) | 558 if (!position.anchorNode() || position.anchorNode() != &oldNode || !position
.isOffsetInAnchor()) |
| 559 return position; | 559 return position; |
| 560 // See: http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#Level-2
-Range-Mutation | 560 // See: http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#Level-2
-Range-Mutation |
| 561 ASSERT(position.offsetInContainerNode() >= 0); | 561 DCHECK_GE(position.offsetInContainerNode(), 0); |
| 562 unsigned positionOffset = static_cast<unsigned>(position.offsetInContainerNo
de()); | 562 unsigned positionOffset = static_cast<unsigned>(position.offsetInContainerNo
de()); |
| 563 unsigned oldLength = oldNode.length(); | 563 unsigned oldLength = oldNode.length(); |
| 564 if (positionOffset <= oldLength) | 564 if (positionOffset <= oldLength) |
| 565 return position; | 565 return position; |
| 566 return Position(toText(oldNode.nextSibling()), positionOffset - oldLength); | 566 return Position(toText(oldNode.nextSibling()), positionOffset - oldLength); |
| 567 } | 567 } |
| 568 | 568 |
| 569 void FrameSelection::didSplitTextNode(const Text& oldNode) | 569 void FrameSelection::didSplitTextNode(const Text& oldNode) |
| 570 { | 570 { |
| 571 if (isNone() || !oldNode.inShadowIncludingDocument()) | 571 if (isNone() || !oldNode.inShadowIncludingDocument()) |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 675 setSelection(VisibleSelection(selection().base(), pos.deepEquivalent(), pos.
affinity(), selectionHasDirection), CloseTyping | ClearTypingStyle | userTrigger
ed); | 675 setSelection(VisibleSelection(selection().base(), pos.deepEquivalent(), pos.
affinity(), selectionHasDirection), CloseTyping | ClearTypingStyle | userTrigger
ed); |
| 676 } | 676 } |
| 677 | 677 |
| 678 static bool isTextFormControl(const VisibleSelection& selection) | 678 static bool isTextFormControl(const VisibleSelection& selection) |
| 679 { | 679 { |
| 680 return enclosingTextFormControl(selection.start()); | 680 return enclosingTextFormControl(selection.start()); |
| 681 } | 681 } |
| 682 | 682 |
| 683 LayoutBlock* FrameSelection::caretLayoutObject() const | 683 LayoutBlock* FrameSelection::caretLayoutObject() const |
| 684 { | 684 { |
| 685 ASSERT(selection().isValidFor(*m_frame->document())); | 685 DCHECK(selection().isValidFor(*m_frame->document())); |
| 686 if (!isCaret()) | 686 if (!isCaret()) |
| 687 return nullptr; | 687 return nullptr; |
| 688 return CaretBase::caretLayoutObject(selection().start().anchorNode()); | 688 return CaretBase::caretLayoutObject(selection().start().anchorNode()); |
| 689 } | 689 } |
| 690 | 690 |
| 691 IntRect FrameSelection::absoluteCaretBounds() | 691 IntRect FrameSelection::absoluteCaretBounds() |
| 692 { | 692 { |
| 693 ASSERT(selection().isValidFor(*m_frame->document())); | 693 DCHECK(selection().isValidFor(*m_frame->document())); |
| 694 ASSERT(m_frame->document()->lifecycle().state() != DocumentLifecycle::InPain
tInvalidation); | 694 DCHECK_NE(m_frame->document()->lifecycle().state(), DocumentLifecycle::InPai
ntInvalidation); |
| 695 m_frame->document()->updateLayoutIgnorePendingStylesheets(); | 695 m_frame->document()->updateLayoutIgnorePendingStylesheets(); |
| 696 if (!isCaret()) { | 696 if (!isCaret()) { |
| 697 m_caretBase->clearCaretRect(); | 697 m_caretBase->clearCaretRect(); |
| 698 } else { | 698 } else { |
| 699 if (isTextFormControl(selection())) | 699 if (isTextFormControl(selection())) |
| 700 m_caretBase->updateCaretRect(PositionWithAffinity(isVisuallyEquivale
ntCandidate(selection().start()) ? selection().start() : Position(), selection()
.affinity())); | 700 m_caretBase->updateCaretRect(PositionWithAffinity(isVisuallyEquivale
ntCandidate(selection().start()) ? selection().start() : Position(), selection()
.affinity())); |
| 701 else | 701 else |
| 702 m_caretBase->updateCaretRect(createVisiblePosition(selection().start
(), selection().affinity())); | 702 m_caretBase->updateCaretRect(createVisiblePosition(selection().start
(), selection().affinity())); |
| 703 } | 703 } |
| 704 return m_caretBase->absoluteBoundsForLocalRect(selection().start().anchorNod
e(), m_caretBase->localCaretRectWithoutUpdate()); | 704 return m_caretBase->absoluteBoundsForLocalRect(selection().start().anchorNod
e(), m_caretBase->localCaretRectWithoutUpdate()); |
| 705 } | 705 } |
| 706 | 706 |
| 707 void FrameSelection::invalidateCaretRect() | 707 void FrameSelection::invalidateCaretRect() |
| 708 { | 708 { |
| 709 if (!m_caretRectDirty) | 709 if (!m_caretRectDirty) |
| 710 return; | 710 return; |
| 711 m_caretRectDirty = false; | 711 m_caretRectDirty = false; |
| 712 | 712 |
| 713 ASSERT(selection().isValidFor(*m_frame->document())); | 713 DCHECK(selection().isValidFor(*m_frame->document())); |
| 714 LayoutObject* layoutObject = nullptr; | 714 LayoutObject* layoutObject = nullptr; |
| 715 LayoutRect newRect; | 715 LayoutRect newRect; |
| 716 if (selection().isCaret()) | 716 if (selection().isCaret()) |
| 717 newRect = localCaretRectOfPosition(PositionWithAffinity(selection().star
t(), selection().affinity()), layoutObject); | 717 newRect = localCaretRectOfPosition(PositionWithAffinity(selection().star
t(), selection().affinity()), layoutObject); |
| 718 Node* newNode = layoutObject ? layoutObject->node() : nullptr; | 718 Node* newNode = layoutObject ? layoutObject->node() : nullptr; |
| 719 | 719 |
| 720 if (!m_caretBlinkTimer.isActive() | 720 if (!m_caretBlinkTimer.isActive() |
| 721 && newNode == m_previousCaretNode | 721 && newNode == m_previousCaretNode |
| 722 && newRect == m_previousCaretRect | 722 && newRect == m_previousCaretRect |
| 723 && m_caretBase->getCaretVisibility() == m_previousCaretVisibility) | 723 && m_caretBase->getCaretVisibility() == m_previousCaretVisibility) |
| (...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 871 VisibleSelection newSelection(VisibleSelection::selectionFromContentsOfNode(
root.get())); | 871 VisibleSelection newSelection(VisibleSelection::selectionFromContentsOfNode(
root.get())); |
| 872 setSelection(newSelection); | 872 setSelection(newSelection); |
| 873 selectFrameElementInParentIfFullySelected(); | 873 selectFrameElementInParentIfFullySelected(); |
| 874 notifyLayoutObjectOfSelectionChange(UserTriggered); | 874 notifyLayoutObjectOfSelectionChange(UserTriggered); |
| 875 } | 875 } |
| 876 | 876 |
| 877 bool FrameSelection::setSelectedRange(Range* range, TextAffinity affinity, Selec
tionDirectionalMode directional, SetSelectionOptions options) | 877 bool FrameSelection::setSelectedRange(Range* range, TextAffinity affinity, Selec
tionDirectionalMode directional, SetSelectionOptions options) |
| 878 { | 878 { |
| 879 if (!range || !range->inShadowIncludingDocument()) | 879 if (!range || !range->inShadowIncludingDocument()) |
| 880 return false; | 880 return false; |
| 881 ASSERT(range->startContainer()->document() == range->endContainer()->documen
t()); | 881 DCHECK_EQ(range->startContainer()->document(), range->endContainer()->docume
nt()); |
| 882 return setSelectedRange(EphemeralRange(range), affinity, directional, option
s); | 882 return setSelectedRange(EphemeralRange(range), affinity, directional, option
s); |
| 883 } | 883 } |
| 884 | 884 |
| 885 bool FrameSelection::setSelectedRange(const EphemeralRange& range, TextAffinity
affinity, SelectionDirectionalMode directional, SetSelectionOptions options) | 885 bool FrameSelection::setSelectedRange(const EphemeralRange& range, TextAffinity
affinity, SelectionDirectionalMode directional, SetSelectionOptions options) |
| 886 { | 886 { |
| 887 return m_selectionEditor->setSelectedRange(range, affinity, directional, opt
ions); | 887 return m_selectionEditor->setSelectedRange(range, affinity, directional, opt
ions); |
| 888 } | 888 } |
| 889 | 889 |
| 890 RawPtr<Range> FrameSelection::firstRange() const | 890 RawPtr<Range> FrameSelection::firstRange() const |
| 891 { | 891 { |
| (...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1053 | 1053 |
| 1054 Element* focusedElement = root->document().focusedElement(); | 1054 Element* focusedElement = root->document().focusedElement(); |
| 1055 if (!focusedElement) | 1055 if (!focusedElement) |
| 1056 return false; | 1056 return false; |
| 1057 | 1057 |
| 1058 return focusedElement->isShadowIncludingInclusiveAncestorOf(selection().star
t().anchorNode()); | 1058 return focusedElement->isShadowIncludingInclusiveAncestorOf(selection().star
t().anchorNode()); |
| 1059 } | 1059 } |
| 1060 | 1060 |
| 1061 void FrameSelection::caretBlinkTimerFired(Timer<FrameSelection>*) | 1061 void FrameSelection::caretBlinkTimerFired(Timer<FrameSelection>*) |
| 1062 { | 1062 { |
| 1063 ASSERT(m_caretBase->caretIsVisible()); | 1063 DCHECK(m_caretBase->caretIsVisible()); |
| 1064 ASSERT(isCaret()); | 1064 DCHECK(isCaret()); |
| 1065 if (isCaretBlinkingSuspended() && m_shouldPaintCaret) | 1065 if (isCaretBlinkingSuspended() && m_shouldPaintCaret) |
| 1066 return; | 1066 return; |
| 1067 m_shouldPaintCaret = !m_shouldPaintCaret; | 1067 m_shouldPaintCaret = !m_shouldPaintCaret; |
| 1068 setCaretRectNeedsUpdate(); | 1068 setCaretRectNeedsUpdate(); |
| 1069 } | 1069 } |
| 1070 | 1070 |
| 1071 void FrameSelection::stopCaretBlinkTimer() | 1071 void FrameSelection::stopCaretBlinkTimer() |
| 1072 { | 1072 { |
| 1073 if (m_caretBlinkTimer.isActive() || m_shouldPaintCaret) | 1073 if (m_caretBlinkTimer.isActive() || m_shouldPaintCaret) |
| 1074 setCaretRectNeedsUpdate(); | 1074 setCaretRectNeedsUpdate(); |
| (...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1231 return; | 1231 return; |
| 1232 case CaretSelection: | 1232 case CaretSelection: |
| 1233 rect = LayoutRect(absoluteCaretBounds()); | 1233 rect = LayoutRect(absoluteCaretBounds()); |
| 1234 break; | 1234 break; |
| 1235 case RangeSelection: | 1235 case RangeSelection: |
| 1236 rect = LayoutRect(revealExtentOption == RevealExtent ? absoluteCaretBoun
dsOf(createVisiblePosition(extent())) : enclosingIntRect(unclippedBounds())); | 1236 rect = LayoutRect(revealExtentOption == RevealExtent ? absoluteCaretBoun
dsOf(createVisiblePosition(extent())) : enclosingIntRect(unclippedBounds())); |
| 1237 break; | 1237 break; |
| 1238 } | 1238 } |
| 1239 | 1239 |
| 1240 Position start = this->start(); | 1240 Position start = this->start(); |
| 1241 ASSERT(start.anchorNode()); | 1241 DCHECK(start.anchorNode()); |
| 1242 if (start.anchorNode() && start.anchorNode()->layoutObject()) { | 1242 if (start.anchorNode() && start.anchorNode()->layoutObject()) { |
| 1243 // FIXME: This code only handles scrolling the startContainer's layer, b
ut | 1243 // FIXME: This code only handles scrolling the startContainer's layer, b
ut |
| 1244 // the selection rect could intersect more than just that. | 1244 // the selection rect could intersect more than just that. |
| 1245 if (DocumentLoader* documentLoader = m_frame->loader().documentLoader()) | 1245 if (DocumentLoader* documentLoader = m_frame->loader().documentLoader()) |
| 1246 documentLoader->initialScrollState().wasScrolledByUser = true; | 1246 documentLoader->initialScrollState().wasScrolledByUser = true; |
| 1247 if (start.anchorNode()->layoutObject()->scrollRectToVisible(rect, alignm
ent, alignment)) | 1247 if (start.anchorNode()->layoutObject()->scrollRectToVisible(rect, alignm
ent, alignment)) |
| 1248 updateAppearance(); | 1248 updateAppearance(); |
| 1249 } | 1249 } |
| 1250 } | 1250 } |
| 1251 | 1251 |
| (...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1421 | 1421 |
| 1422 void showTree(const blink::FrameSelection* sel) | 1422 void showTree(const blink::FrameSelection* sel) |
| 1423 { | 1423 { |
| 1424 if (sel) | 1424 if (sel) |
| 1425 sel->showTreeForThis(); | 1425 sel->showTreeForThis(); |
| 1426 else | 1426 else |
| 1427 fprintf(stderr, "Cannot showTree for (nil) FrameSelection.\n"); | 1427 fprintf(stderr, "Cannot showTree for (nil) FrameSelection.\n"); |
| 1428 } | 1428 } |
| 1429 | 1429 |
| 1430 #endif | 1430 #endif |
| OLD | NEW |