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 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
94 FrameSelection::FrameSelection(LocalFrame* frame) | 94 FrameSelection::FrameSelection(LocalFrame* frame) |
95 : m_frame(frame) | 95 : m_frame(frame) |
96 , m_pendingSelection(PendingSelection::create(*this)) | 96 , m_pendingSelection(PendingSelection::create(*this)) |
97 , m_selectionEditor(SelectionEditor::create(*this)) | 97 , m_selectionEditor(SelectionEditor::create(*this)) |
98 , m_granularity(CharacterGranularity) | 98 , m_granularity(CharacterGranularity) |
99 , m_xPosForVerticalArrowNavigation(NoXPosForVerticalArrowNavigation()) | 99 , m_xPosForVerticalArrowNavigation(NoXPosForVerticalArrowNavigation()) |
100 , m_focused(frame->page() && frame->page()->focusController().focusedFrame()
== frame) | 100 , m_focused(frame->page() && frame->page()->focusController().focusedFrame()
== frame) |
101 , m_frameCaret(new FrameCaret(frame)) | 101 , m_frameCaret(new FrameCaret(frame)) |
102 { | 102 { |
103 DCHECK(frame); | 103 DCHECK(frame); |
104 if (shouldAlwaysUseDirectionalSelection(m_frame)) | |
105 m_selectionEditor->setIsDirectional(true); | |
106 } | 104 } |
107 | 105 |
108 FrameSelection::~FrameSelection() | 106 FrameSelection::~FrameSelection() |
109 { | 107 { |
110 } | 108 } |
111 | 109 |
| 110 const Document& FrameSelection::document() const |
| 111 { |
| 112 DCHECK(m_document); |
| 113 return *m_document; |
| 114 } |
| 115 |
| 116 Document& FrameSelection::document() |
| 117 { |
| 118 DCHECK(m_document); |
| 119 return *m_document; |
| 120 } |
| 121 |
112 template <> | 122 template <> |
113 VisiblePosition FrameSelection::originalBase<EditingStrategy>() const | 123 VisiblePosition FrameSelection::originalBase<EditingStrategy>() const |
114 { | 124 { |
115 return m_originalBase; | 125 return m_originalBase; |
116 } | 126 } |
117 | 127 |
118 template <> | 128 template <> |
119 VisiblePositionInFlatTree FrameSelection::originalBase<EditingInFlatTreeStrategy
>() const | 129 VisiblePositionInFlatTree FrameSelection::originalBase<EditingInFlatTreeStrategy
>() const |
120 { | 130 { |
121 return m_originalBaseInFlatTree; | 131 return m_originalBaseInFlatTree; |
(...skipping 10 matching lines...) Expand all Loading... |
132 | 142 |
133 template <> | 143 template <> |
134 const VisibleSelectionInFlatTree& FrameSelection::visibleSelection<EditingInFlat
TreeStrategy>() const | 144 const VisibleSelectionInFlatTree& FrameSelection::visibleSelection<EditingInFlat
TreeStrategy>() const |
135 { | 145 { |
136 return m_selectionEditor->visibleSelection<EditingInFlatTreeStrategy>(); | 146 return m_selectionEditor->visibleSelection<EditingInFlatTreeStrategy>(); |
137 } | 147 } |
138 | 148 |
139 Element* FrameSelection::rootEditableElementOrDocumentElement() const | 149 Element* FrameSelection::rootEditableElementOrDocumentElement() const |
140 { | 150 { |
141 Element* selectionRoot = selection().rootEditableElement(); | 151 Element* selectionRoot = selection().rootEditableElement(); |
142 return selectionRoot ? selectionRoot : m_frame->document()->documentElement(
); | 152 return selectionRoot ? selectionRoot : document().documentElement(); |
143 } | 153 } |
144 | 154 |
145 ContainerNode* FrameSelection::rootEditableElementOrTreeScopeRootNode() const | 155 ContainerNode* FrameSelection::rootEditableElementOrTreeScopeRootNode() const |
146 { | 156 { |
147 Element* selectionRoot = selection().rootEditableElement(); | 157 Element* selectionRoot = selection().rootEditableElement(); |
148 if (selectionRoot) | 158 if (selectionRoot) |
149 return selectionRoot; | 159 return selectionRoot; |
150 | 160 |
151 Node* node = selection().base().computeContainerNode(); | 161 Node* node = selection().base().computeContainerNode(); |
152 return node ? &node->treeScope().rootNode() : 0; | 162 return node ? &node->treeScope().rootNode() : 0; |
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
267 } | 277 } |
268 | 278 |
269 void FrameSelection::setNonDirectionalSelectionIfNeeded(const VisibleSelectionIn
FlatTree& passedNewSelection, TextGranularity granularity, EndPointsAdjustmentMo
de endpointsAdjustmentMode) | 279 void FrameSelection::setNonDirectionalSelectionIfNeeded(const VisibleSelectionIn
FlatTree& passedNewSelection, TextGranularity granularity, EndPointsAdjustmentMo
de endpointsAdjustmentMode) |
270 { | 280 { |
271 setNonDirectionalSelectionIfNeededAlgorithm<EditingInFlatTreeStrategy>(passe
dNewSelection, granularity, endpointsAdjustmentMode); | 281 setNonDirectionalSelectionIfNeededAlgorithm<EditingInFlatTreeStrategy>(passe
dNewSelection, granularity, endpointsAdjustmentMode); |
272 } | 282 } |
273 | 283 |
274 template <typename Strategy> | 284 template <typename Strategy> |
275 void FrameSelection::setSelectionAlgorithm(const VisibleSelectionTemplate<Strate
gy>& newSelection, SetSelectionOptions options, CursorAlignOnScroll align, TextG
ranularity granularity) | 285 void FrameSelection::setSelectionAlgorithm(const VisibleSelectionTemplate<Strate
gy>& newSelection, SetSelectionOptions options, CursorAlignOnScroll align, TextG
ranularity granularity) |
276 { | 286 { |
| 287 DCHECK(isAvailable()); |
| 288 DCHECK(newSelection.isValidFor(document())); |
| 289 const Document& currentDocument = document(); |
277 if (m_granularityStrategy && (options & FrameSelection::DoNotClearStrategy)
== 0) | 290 if (m_granularityStrategy && (options & FrameSelection::DoNotClearStrategy)
== 0) |
278 m_granularityStrategy->Clear(); | 291 m_granularityStrategy->Clear(); |
279 bool closeTyping = options & CloseTyping; | 292 bool closeTyping = options & CloseTyping; |
280 bool shouldClearTypingStyle = options & ClearTypingStyle; | 293 bool shouldClearTypingStyle = options & ClearTypingStyle; |
281 EUserTriggered userTriggered = selectionOptionsToUserTriggered(options); | 294 EUserTriggered userTriggered = selectionOptionsToUserTriggered(options); |
282 | 295 |
283 VisibleSelectionTemplate<Strategy> s = validateSelection(newSelection); | 296 VisibleSelectionTemplate<Strategy> s = validateSelection(newSelection); |
284 if (shouldAlwaysUseDirectionalSelection(m_frame)) | 297 if (shouldAlwaysUseDirectionalSelection(m_frame)) |
285 s.setIsDirectional(true); | 298 s.setIsDirectional(true); |
286 | 299 |
287 // <http://bugs.webkit.org/show_bug.cgi?id=23464>: Infinite recursion at | |
288 // |FrameSelection::setSelection| | |
289 // if |document->frame()| == |m_frame| we can get into an infinite loop | |
290 if (s.base().anchorNode()) { | |
291 Document& document = *s.base().document(); | |
292 // TODO(hajimehoshi): validateSelection already checks if the selection | |
293 // is valid, thus we don't need this 'if' clause any more. | |
294 if (document.frame() && document.frame() != m_frame && document != m_fra
me->document()) { | |
295 document.frame()->selection().setSelection(s, options, align, granul
arity); | |
296 // It's possible that during the above set selection, this | |
297 // |FrameSelection| has been modified by | |
298 // |selectFrameElementInParentIfFullySelected|, but that the | |
299 // selection is no longer valid since the frame is about to be | |
300 // destroyed. If this is the case, clear our selection. | |
301 if (!document.frame()->host() && !selection().isNonOrphanedCaretOrRa
nge()) | |
302 clear(); | |
303 return; | |
304 } | |
305 } | |
306 | |
307 m_granularity = granularity; | 300 m_granularity = granularity; |
308 | 301 |
309 // TODO(yosin): We should move to call |TypingCommand::closeTyping()| to | 302 // TODO(yosin): We should move to call |TypingCommand::closeTyping()| to |
310 // |Editor| class. | 303 // |Editor| class. |
311 if (closeTyping) | 304 if (closeTyping) |
312 TypingCommand::closeTyping(m_frame); | 305 TypingCommand::closeTyping(m_frame); |
313 | 306 |
314 if (shouldClearTypingStyle) | 307 if (shouldClearTypingStyle) |
315 clearTypingStyle(); | 308 clearTypingStyle(); |
316 | 309 |
317 if (m_selectionEditor->visibleSelection<Strategy>() == s) { | 310 if (m_selectionEditor->visibleSelection<Strategy>() == s) { |
318 // Even if selection was not changed, selection offsets may have been | 311 // Even if selection was not changed, selection offsets may have been |
319 // changed. | 312 // changed. |
320 m_frame->inputMethodController().cancelCompositionIfSelectionIsInvalid()
; | 313 m_frame->inputMethodController().cancelCompositionIfSelectionIsInvalid()
; |
321 notifyLayoutObjectOfSelectionChange(userTriggered); | 314 notifyLayoutObjectOfSelectionChange(userTriggered); |
322 return; | 315 return; |
323 } | 316 } |
324 | 317 |
325 const VisibleSelectionTemplate<Strategy> oldSelection = visibleSelection<Str
ategy>(); | 318 const VisibleSelectionTemplate<Strategy> oldSelection = visibleSelection<Str
ategy>(); |
326 const VisibleSelection oldSelectionInDOMTree = selection(); | 319 const VisibleSelection oldSelectionInDOMTree = selection(); |
327 | 320 |
328 m_selectionEditor->setVisibleSelection(s, options); | 321 m_selectionEditor->setVisibleSelection(s, options); |
329 if (s.isCaret()) | 322 if (s.isCaret()) |
330 m_frameCaret->setCaretPosition(PositionWithAffinity(toPositionInDOMTree(
s.start()), s.affinity())); | 323 m_frameCaret->setCaretPosition(PositionWithAffinity(toPositionInDOMTree(
s.start()), s.affinity())); |
331 else | 324 else |
332 m_frameCaret->clear(); | 325 m_frameCaret->clear(); |
333 | 326 |
334 if (!s.isNone() && !(options & DoNotSetFocus)) | 327 if (!s.isNone() && !(options & DoNotSetFocus)) { |
335 setFocusedNodeIfNeeded(); | 328 setFocusedNodeIfNeeded(); |
| 329 // |setFocusedNodeIfNeeded()| dispatches sync events "FocusOut" and |
| 330 // "FocusIn", |m_frame| may associate to another document. |
| 331 if (!isAvailable() || document() != currentDocument) { |
| 332 // Once we get test case to reach here, we should change this |
| 333 // if-statement to |DCHECK()|. |
| 334 NOTREACHED(); |
| 335 return; |
| 336 } |
| 337 } |
336 | 338 |
337 if (!(options & DoNotUpdateAppearance)) { | 339 if (!(options & DoNotUpdateAppearance)) { |
338 // Hits in compositing/overflow/do-not-paint-outline-into-composited-scr
olling-contents.html | 340 // Hits in compositing/overflow/do-not-paint-outline-into-composited-scr
olling-contents.html |
339 DisableCompositingQueryAsserts disabler; | 341 DisableCompositingQueryAsserts disabler; |
340 m_frameCaret->stopCaretBlinkTimer(); | 342 m_frameCaret->stopCaretBlinkTimer(); |
341 updateAppearance(); | 343 updateAppearance(); |
342 } | 344 } |
343 | 345 |
344 // Always clear the x position used for vertical arrow navigation. | 346 // Always clear the x position used for vertical arrow navigation. |
345 // It will be restored by the vertical arrow navigation code if necessary. | 347 // It will be restored by the vertical arrow navigation code if necessary. |
346 m_xPosForVerticalArrowNavigation = NoXPosForVerticalArrowNavigation(); | 348 m_xPosForVerticalArrowNavigation = NoXPosForVerticalArrowNavigation(); |
347 // This may dispatch a synchronous focus-related events. | 349 // This may dispatch a synchronous focus-related events. |
348 selectFrameElementInParentIfFullySelected(); | 350 selectFrameElementInParentIfFullySelected(); |
| 351 if (!isAvailable() || document() != currentDocument) { |
| 352 // editing/selection/selectallchildren-crash.html and |
| 353 // editing/selection/longpress-selection-in-iframe-removed-crash.html |
| 354 // reach here. |
| 355 return; |
| 356 } |
349 notifyLayoutObjectOfSelectionChange(userTriggered); | 357 notifyLayoutObjectOfSelectionChange(userTriggered); |
350 // If the selections are same in the DOM tree but not in the flat tree, | 358 // If the selections are same in the DOM tree but not in the flat tree, |
351 // don't fire events. For example, if the selection crosses shadow tree | 359 // don't fire events. For example, if the selection crosses shadow tree |
352 // boundary, selection for the DOM tree is shrunk while that for the | 360 // boundary, selection for the DOM tree is shrunk while that for the |
353 // flat tree is not. Additionally, this case occurs in some edge cases. | 361 // flat tree is not. Additionally, this case occurs in some edge cases. |
354 // See also: editing/pasteboard/4076267-3.html | 362 // See also: editing/pasteboard/4076267-3.html |
355 if (oldSelection == m_selectionEditor->visibleSelection<Strategy>()) { | 363 if (oldSelection == m_selectionEditor->visibleSelection<Strategy>()) { |
356 m_frame->inputMethodController().cancelCompositionIfSelectionIsInvalid()
; | 364 m_frame->inputMethodController().cancelCompositionIfSelectionIsInvalid()
; |
357 return; | 365 return; |
358 } | 366 } |
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
473 } else { | 481 } else { |
474 const VisibleSelection& selection = m_selectionEditor->visibleSelection<
EditingStrategy>(); | 482 const VisibleSelection& selection = m_selectionEditor->visibleSelection<
EditingStrategy>(); |
475 if (selection.isCaret()) | 483 if (selection.isCaret()) |
476 m_frameCaret->setCaretPosition(PositionWithAffinity(selection.start(
), selection.affinity())); | 484 m_frameCaret->setCaretPosition(PositionWithAffinity(selection.start(
), selection.affinity())); |
477 else | 485 else |
478 m_frameCaret->clear(); | 486 m_frameCaret->clear(); |
479 } | 487 } |
480 | 488 |
481 // TODO(yosin): We should move to call |TypingCommand::closeTyping()| to | 489 // TODO(yosin): We should move to call |TypingCommand::closeTyping()| to |
482 // |Editor| class. | 490 // |Editor| class. |
483 if (!m_frame->document()->isRunningExecCommand()) | 491 if (!document().isRunningExecCommand()) |
484 TypingCommand::closeTyping(m_frame); | 492 TypingCommand::closeTyping(m_frame); |
485 } | 493 } |
486 | 494 |
487 static Position updatePositionAfterAdoptingTextReplacement(const Position& posit
ion, CharacterData* node, unsigned offset, unsigned oldLength, unsigned newLengt
h) | 495 static Position updatePositionAfterAdoptingTextReplacement(const Position& posit
ion, CharacterData* node, unsigned offset, unsigned oldLength, unsigned newLengt
h) |
488 { | 496 { |
489 if (!position.anchorNode() || position.anchorNode() != node || !position.isO
ffsetInAnchor()) | 497 if (!position.anchorNode() || position.anchorNode() != node || !position.isO
ffsetInAnchor()) |
490 return position; | 498 return position; |
491 | 499 |
492 // See: http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#Level-2
-Range-Mutation | 500 // See: http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#Level-2
-Range-Mutation |
493 DCHECK_GE(position.offsetInContainerNode(), 0); | 501 DCHECK_GE(position.offsetInContainerNode(), 0); |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
577 Position end = updatePostionAfterAdoptingTextNodeSplit(selection().end(), ol
dNode); | 585 Position end = updatePostionAfterAdoptingTextNodeSplit(selection().end(), ol
dNode); |
578 updateSelectionIfNeeded(base, extent, start, end); | 586 updateSelectionIfNeeded(base, extent, start, end); |
579 } | 587 } |
580 | 588 |
581 void FrameSelection::updateSelectionIfNeeded(const Position& base, const Positio
n& extent, const Position& start, const Position& end) | 589 void FrameSelection::updateSelectionIfNeeded(const Position& base, const Positio
n& extent, const Position& start, const Position& end) |
582 { | 590 { |
583 if (base == selection().base() && extent == selection().extent() && start ==
selection().start() && end == selection().end()) | 591 if (base == selection().base() && extent == selection().extent() && start ==
selection().start() && end == selection().end()) |
584 return; | 592 return; |
585 // TODO(yosin): We should move to call |TypingCommand::closeTyping()| to | 593 // TODO(yosin): We should move to call |TypingCommand::closeTyping()| to |
586 // |Editor| class. | 594 // |Editor| class. |
587 if (!m_frame->document()->isRunningExecCommand()) | 595 if (!document().isRunningExecCommand()) |
588 TypingCommand::closeTyping(m_frame); | 596 TypingCommand::closeTyping(m_frame); |
589 VisibleSelection newSelection; | 597 VisibleSelection newSelection; |
590 if (selection().isBaseFirst()) | 598 if (selection().isBaseFirst()) |
591 newSelection.setWithoutValidation(start, end); | 599 newSelection.setWithoutValidation(start, end); |
592 else | 600 else |
593 newSelection.setWithoutValidation(end, start); | 601 newSelection.setWithoutValidation(end, start); |
594 setSelection(newSelection, DoNotSetFocus); | 602 setSelection(newSelection, DoNotSetFocus); |
595 } | 603 } |
596 | 604 |
597 void FrameSelection::didChangeFocus() | 605 void FrameSelection::didChangeFocus() |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
656 } | 664 } |
657 | 665 |
658 void FrameSelection::clear() | 666 void FrameSelection::clear() |
659 { | 667 { |
660 m_granularity = CharacterGranularity; | 668 m_granularity = CharacterGranularity; |
661 if (m_granularityStrategy) | 669 if (m_granularityStrategy) |
662 m_granularityStrategy->Clear(); | 670 m_granularityStrategy->Clear(); |
663 setSelection(VisibleSelection()); | 671 setSelection(VisibleSelection()); |
664 } | 672 } |
665 | 673 |
666 void FrameSelection::prepareForDestruction() | 674 void FrameSelection::documentAttached(Document* document) |
667 { | 675 { |
| 676 DCHECK(document); |
| 677 DCHECK(!m_document) << "FrameSelection is already attached to " << m_documen
t; |
| 678 m_document = document; |
| 679 m_selectionEditor->documentAttached(document); |
| 680 } |
| 681 |
| 682 void FrameSelection::documentDetached(const Document& document) |
| 683 { |
| 684 DCHECK_EQ(m_document, document); |
| 685 m_document = nullptr; |
668 m_originalBase = VisiblePosition(); | 686 m_originalBase = VisiblePosition(); |
669 m_originalBaseInFlatTree = VisiblePositionInFlatTree(); | 687 m_originalBaseInFlatTree = VisiblePositionInFlatTree(); |
670 m_granularity = CharacterGranularity; | 688 m_granularity = CharacterGranularity; |
671 | 689 |
672 LayoutViewItem view = m_frame->contentLayoutItem(); | 690 LayoutViewItem view = m_frame->contentLayoutItem(); |
673 if (!view.isNull()) | 691 if (!view.isNull()) |
674 view.clearSelection(); | 692 view.clearSelection(); |
675 | 693 |
676 setSelection(VisibleSelection(), CloseTyping | ClearTypingStyle | DoNotUpdat
eAppearance); | 694 clearTypingStyle(); |
677 m_selectionEditor->dispose(); | 695 m_selectionEditor->documentDetached(document); |
678 m_frameCaret->prepareForDestruction(); | 696 m_frameCaret->documentDetached(); |
679 } | 697 } |
680 | 698 |
681 LayoutBlock* FrameSelection::caretLayoutObject() const | 699 LayoutBlock* FrameSelection::caretLayoutObject() const |
682 { | 700 { |
683 DCHECK(selection().isValidFor(*m_frame->document())); | 701 DCHECK(selection().isValidFor(document())); |
684 if (!isCaret()) | 702 if (!isCaret()) |
685 return nullptr; | 703 return nullptr; |
686 return CaretBase::caretLayoutObject(selection().start().anchorNode()); | 704 return CaretBase::caretLayoutObject(selection().start().anchorNode()); |
687 } | 705 } |
688 | 706 |
689 IntRect FrameSelection::absoluteCaretBounds() | 707 IntRect FrameSelection::absoluteCaretBounds() |
690 { | 708 { |
691 DCHECK(selection().isValidFor(*m_frame->document())); | 709 DCHECK(selection().isValidFor(*m_frame->document())); |
692 return m_frameCaret->absoluteCaretBounds(); | 710 return m_frameCaret->absoluteCaretBounds(); |
693 } | 711 } |
694 | 712 |
695 void FrameSelection::invalidateCaretRect() | 713 void FrameSelection::invalidateCaretRect() |
696 { | 714 { |
697 m_frameCaret->invalidateCaretRect(); | 715 m_frameCaret->invalidateCaretRect(); |
698 } | 716 } |
699 | 717 |
700 void FrameSelection::dataWillChange(const CharacterData& node) | 718 void FrameSelection::dataWillChange(const CharacterData& node) |
701 { | 719 { |
702 m_frameCaret->dataWillChange(node); | 720 m_frameCaret->dataWillChange(node); |
703 } | 721 } |
704 | 722 |
705 void FrameSelection::paintCaret(GraphicsContext& context, const LayoutPoint& pai
ntOffset) | 723 void FrameSelection::paintCaret(GraphicsContext& context, const LayoutPoint& pai
ntOffset) |
706 { | 724 { |
707 m_frameCaret->paintCaret(context, paintOffset); | 725 m_frameCaret->paintCaret(context, paintOffset); |
708 } | 726 } |
709 | 727 |
710 bool FrameSelection::contains(const LayoutPoint& point) | 728 bool FrameSelection::contains(const LayoutPoint& point) |
711 { | 729 { |
712 Document* document = m_frame->document(); | 730 if (document().layoutViewItem().isNull()) |
713 if (document->layoutViewItem().isNull()) | |
714 return false; | 731 return false; |
715 | 732 |
716 // Treat a collapsed selection like no selection. | 733 // Treat a collapsed selection like no selection. |
717 const VisibleSelectionInFlatTree& visibleSelection = this->visibleSelection<
EditingInFlatTreeStrategy>(); | 734 const VisibleSelectionInFlatTree& visibleSelection = this->visibleSelection<
EditingInFlatTreeStrategy>(); |
718 if (!visibleSelection.isRange()) | 735 if (!visibleSelection.isRange()) |
719 return false; | 736 return false; |
720 | 737 |
721 HitTestRequest request(HitTestRequest::ReadOnly | HitTestRequest::Active); | 738 HitTestRequest request(HitTestRequest::ReadOnly | HitTestRequest::Active); |
722 HitTestResult result(request, point); | 739 HitTestResult result(request, point); |
723 document->layoutViewItem().hitTest(result); | 740 document().layoutViewItem().hitTest(result); |
724 Node* innerNode = result.innerNode(); | 741 Node* innerNode = result.innerNode(); |
725 if (!innerNode || !innerNode->layoutObject()) | 742 if (!innerNode || !innerNode->layoutObject()) |
726 return false; | 743 return false; |
727 | 744 |
728 const VisiblePositionInFlatTree& visiblePos = createVisiblePosition(fromPosi
tionInDOMTree<EditingInFlatTreeStrategy>(innerNode->layoutObject()->positionForP
oint(result.localPoint()))); | 745 const VisiblePositionInFlatTree& visiblePos = createVisiblePosition(fromPosi
tionInDOMTree<EditingInFlatTreeStrategy>(innerNode->layoutObject()->positionForP
oint(result.localPoint()))); |
729 if (visiblePos.isNull()) | 746 if (visiblePos.isNull()) |
730 return false; | 747 return false; |
731 | 748 |
732 const VisiblePositionInFlatTree& visibleStart = visibleSelection.visibleStar
t(); | 749 const VisiblePositionInFlatTree& visibleStart = visibleSelection.visibleStar
t(); |
733 const VisiblePositionInFlatTree& visibleEnd = visibleSelection.visibleEnd(); | 750 const VisiblePositionInFlatTree& visibleEnd = visibleSelection.visibleEnd(); |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
796 | 813 |
797 // Returns a shadow tree node for legacy shadow trees, a child of the | 814 // Returns a shadow tree node for legacy shadow trees, a child of the |
798 // ShadowRoot node for new shadow trees, or 0 for non-shadow trees. | 815 // ShadowRoot node for new shadow trees, or 0 for non-shadow trees. |
799 static Node* nonBoundaryShadowTreeRootNode(const Position& position) | 816 static Node* nonBoundaryShadowTreeRootNode(const Position& position) |
800 { | 817 { |
801 return position.anchorNode() && !position.anchorNode()->isShadowRoot() ? pos
ition.anchorNode()->nonBoundaryShadowTreeRootNode() : nullptr; | 818 return position.anchorNode() && !position.anchorNode()->isShadowRoot() ? pos
ition.anchorNode()->nonBoundaryShadowTreeRootNode() : nullptr; |
802 } | 819 } |
803 | 820 |
804 void FrameSelection::selectAll() | 821 void FrameSelection::selectAll() |
805 { | 822 { |
806 Document* document = m_frame->document(); | 823 if (isHTMLSelectElement(document().focusedElement())) { |
807 | 824 HTMLSelectElement* selectElement = toHTMLSelectElement(document().focuse
dElement()); |
808 if (isHTMLSelectElement(document->focusedElement())) { | |
809 HTMLSelectElement* selectElement = toHTMLSelectElement(document->focused
Element()); | |
810 if (selectElement->canSelectAll()) { | 825 if (selectElement->canSelectAll()) { |
811 selectElement->selectAll(); | 826 selectElement->selectAll(); |
812 return; | 827 return; |
813 } | 828 } |
814 } | 829 } |
815 | 830 |
816 Node* root = nullptr; | 831 Node* root = nullptr; |
817 Node* selectStartTarget = nullptr; | 832 Node* selectStartTarget = nullptr; |
818 if (isContentEditable()) { | 833 if (isContentEditable()) { |
819 root = highestEditableRoot(selection().start()); | 834 root = highestEditableRoot(selection().start()); |
820 if (Node* shadowRoot = nonBoundaryShadowTreeRootNode(selection().start()
)) | 835 if (Node* shadowRoot = nonBoundaryShadowTreeRootNode(selection().start()
)) |
821 selectStartTarget = shadowRoot->shadowHost(); | 836 selectStartTarget = shadowRoot->shadowHost(); |
822 else | 837 else |
823 selectStartTarget = root; | 838 selectStartTarget = root; |
824 } else { | 839 } else { |
825 root = nonBoundaryShadowTreeRootNode(selection().start()); | 840 root = nonBoundaryShadowTreeRootNode(selection().start()); |
826 if (root) { | 841 if (root) { |
827 selectStartTarget = root->shadowHost(); | 842 selectStartTarget = root->shadowHost(); |
828 } else { | 843 } else { |
829 root = document->documentElement(); | 844 root = document().documentElement(); |
830 selectStartTarget = document->body(); | 845 selectStartTarget = document().body(); |
831 } | 846 } |
832 } | 847 } |
833 if (!root || editingIgnoresContent(root)) | 848 if (!root || editingIgnoresContent(root)) |
834 return; | 849 return; |
835 | 850 |
836 if (selectStartTarget) { | 851 if (selectStartTarget) { |
| 852 const Document& expectedDocument = document(); |
837 if (selectStartTarget->dispatchEvent(Event::createCancelableBubble(Event
TypeNames::selectstart)) != DispatchEventResult::NotCanceled) | 853 if (selectStartTarget->dispatchEvent(Event::createCancelableBubble(Event
TypeNames::selectstart)) != DispatchEventResult::NotCanceled) |
838 return; | 854 return; |
839 // |root| may be detached due to selectstart event. | 855 // |root| may be detached due to selectstart event. |
840 if (!root->inShadowIncludingDocument() || root->document() != document) | 856 if (!root->inShadowIncludingDocument() || expectedDocument != root->docu
ment()) |
841 return; | 857 return; |
842 } | 858 } |
843 | 859 |
844 VisibleSelection newSelection(VisibleSelection::selectionFromContentsOfNode(
root)); | 860 VisibleSelection newSelection(VisibleSelection::selectionFromContentsOfNode(
root)); |
845 setSelection(newSelection); | 861 setSelection(newSelection); |
846 selectFrameElementInParentIfFullySelected(); | 862 selectFrameElementInParentIfFullySelected(); |
847 notifyLayoutObjectOfSelectionChange(UserTriggered); | 863 notifyLayoutObjectOfSelectionChange(UserTriggered); |
848 } | 864 } |
849 | 865 |
850 bool FrameSelection::setSelectedRange(Range* range, TextAffinity affinity, Selec
tionDirectionalMode directional, SetSelectionOptions options) | 866 bool FrameSelection::setSelectedRange(Range* range, TextAffinity affinity, Selec
tionDirectionalMode directional, SetSelectionOptions options) |
(...skipping 26 matching lines...) Expand all Loading... |
877 | 893 |
878 bool FrameSelection::isInPasswordField() const | 894 bool FrameSelection::isInPasswordField() const |
879 { | 895 { |
880 HTMLTextFormControlElement* textControl = enclosingTextFormControl(start()); | 896 HTMLTextFormControlElement* textControl = enclosingTextFormControl(start()); |
881 return isHTMLInputElement(textControl) && toHTMLInputElement(textControl)->t
ype() == InputTypeNames::password; | 897 return isHTMLInputElement(textControl) && toHTMLInputElement(textControl)->t
ype() == InputTypeNames::password; |
882 } | 898 } |
883 | 899 |
884 void FrameSelection::notifyAccessibilityForSelectionChange() | 900 void FrameSelection::notifyAccessibilityForSelectionChange() |
885 { | 901 { |
886 if (selection().start().isNotNull() && selection().end().isNotNull()) { | 902 if (selection().start().isNotNull() && selection().end().isNotNull()) { |
887 if (AXObjectCache* cache = m_frame->document()->existingAXObjectCache()) | 903 if (AXObjectCache* cache = document().existingAXObjectCache()) |
888 cache->selectionChanged(selection().start().computeContainerNode()); | 904 cache->selectionChanged(selection().start().computeContainerNode()); |
889 } | 905 } |
890 } | 906 } |
891 | 907 |
892 void FrameSelection::notifyCompositorForSelectionChange() | 908 void FrameSelection::notifyCompositorForSelectionChange() |
893 { | 909 { |
894 if (!RuntimeEnabledFeatures::compositedSelectionUpdateEnabled()) | 910 if (!RuntimeEnabledFeatures::compositedSelectionUpdateEnabled()) |
895 return; | 911 return; |
896 | 912 |
897 scheduleVisualUpdate(); | 913 scheduleVisualUpdate(); |
898 } | 914 } |
899 | 915 |
900 void FrameSelection::notifyEventHandlerForSelectionChange() | 916 void FrameSelection::notifyEventHandlerForSelectionChange() |
901 { | 917 { |
902 m_frame->eventHandler().selectionController().notifySelectionChanged(); | 918 m_frame->eventHandler().selectionController().notifySelectionChanged(); |
903 } | 919 } |
904 | 920 |
905 void FrameSelection::focusedOrActiveStateChanged() | 921 void FrameSelection::focusedOrActiveStateChanged() |
906 { | 922 { |
907 bool activeAndFocused = isFocusedAndActive(); | 923 bool activeAndFocused = isFocusedAndActive(); |
908 Document* document = m_frame->document(); | |
909 | 924 |
910 // Trigger style invalidation from the focused element. Even though | 925 // Trigger style invalidation from the focused element. Even though |
911 // the focused element hasn't changed, the evaluation of focus pseudo | 926 // the focused element hasn't changed, the evaluation of focus pseudo |
912 // selectors are dependent on whether the frame is focused and active. | 927 // selectors are dependent on whether the frame is focused and active. |
913 if (Element* element = document->focusedElement()) | 928 if (Element* element = document().focusedElement()) |
914 element->focusStateChanged(); | 929 element->focusStateChanged(); |
915 | 930 |
916 document->updateStyleAndLayoutTree(); | 931 document().updateStyleAndLayoutTree(); |
917 | 932 |
918 // Because LayoutObject::selectionBackgroundColor() and | 933 // Because LayoutObject::selectionBackgroundColor() and |
919 // LayoutObject::selectionForegroundColor() check if the frame is active, | 934 // LayoutObject::selectionForegroundColor() check if the frame is active, |
920 // we have to update places those colors were painted. | 935 // we have to update places those colors were painted. |
921 LayoutViewItem view = document->layoutViewItem(); | 936 LayoutViewItem view = document().layoutViewItem(); |
922 if (!view.isNull()) | 937 if (!view.isNull()) |
923 view.invalidatePaintForSelection(); | 938 view.invalidatePaintForSelection(); |
924 | 939 |
925 // Caret appears in the active frame. | 940 // Caret appears in the active frame. |
926 if (activeAndFocused) | 941 if (activeAndFocused) |
927 setSelectionFromNone(); | 942 setSelectionFromNone(); |
928 else | 943 else |
929 m_frame->spellChecker().spellCheckAfterBlur(); | 944 m_frame->spellChecker().spellCheckAfterBlur(); |
930 m_frameCaret->setCaretVisibility(activeAndFocused ? CaretVisibility::Visible
: CaretVisibility::Hidden); | 945 m_frameCaret->setCaretVisibility(activeAndFocused ? CaretVisibility::Visible
: CaretVisibility::Hidden); |
931 | 946 |
932 // Update for caps lock state | 947 // Update for caps lock state |
933 m_frame->eventHandler().capsLockStateMayHaveChanged(); | 948 m_frame->eventHandler().capsLockStateMayHaveChanged(); |
934 | 949 |
935 // Secure keyboard entry is set by the active frame. | 950 // Secure keyboard entry is set by the active frame. |
936 if (document->useSecureKeyboardEntryWhenActive()) | 951 if (document().useSecureKeyboardEntryWhenActive()) |
937 setUseSecureKeyboardEntry(activeAndFocused); | 952 setUseSecureKeyboardEntry(activeAndFocused); |
938 } | 953 } |
939 | 954 |
940 void FrameSelection::pageActivationChanged() | 955 void FrameSelection::pageActivationChanged() |
941 { | 956 { |
942 focusedOrActiveStateChanged(); | 957 focusedOrActiveStateChanged(); |
943 } | 958 } |
944 | 959 |
945 void FrameSelection::updateSecureKeyboardEntryIfActive() | 960 void FrameSelection::updateSecureKeyboardEntryIfActive() |
946 { | 961 { |
947 if (m_frame->document() && isFocusedAndActive()) | 962 if (isFocusedAndActive()) |
948 setUseSecureKeyboardEntry(m_frame->document()->useSecureKeyboardEntryWhe
nActive()); | 963 setUseSecureKeyboardEntry(document().useSecureKeyboardEntryWhenActive())
; |
949 } | 964 } |
950 | 965 |
951 void FrameSelection::setUseSecureKeyboardEntry(bool enable) | 966 void FrameSelection::setUseSecureKeyboardEntry(bool enable) |
952 { | 967 { |
953 if (enable) | 968 if (enable) |
954 enableSecureTextInput(); | 969 enableSecureTextInput(); |
955 else | 970 else |
956 disableSecureTextInput(); | 971 disableSecureTextInput(); |
957 } | 972 } |
958 | 973 |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1016 bool caretBrowsing = m_frame->settings() && m_frame->settings()->caretBrowsi
ngEnabled(); | 1031 bool caretBrowsing = m_frame->settings() && m_frame->settings()->caretBrowsi
ngEnabled(); |
1017 if (caretBrowsing) { | 1032 if (caretBrowsing) { |
1018 if (Element* anchor = enclosingAnchorElement(base())) { | 1033 if (Element* anchor = enclosingAnchorElement(base())) { |
1019 m_frame->page()->focusController().setFocusedElement(anchor, m_frame
); | 1034 m_frame->page()->focusController().setFocusedElement(anchor, m_frame
); |
1020 return; | 1035 return; |
1021 } | 1036 } |
1022 } | 1037 } |
1023 | 1038 |
1024 if (Element* target = rootEditableElement()) { | 1039 if (Element* target = rootEditableElement()) { |
1025 // Walk up the DOM tree to search for a node to focus. | 1040 // Walk up the DOM tree to search for a node to focus. |
1026 m_frame->document()->updateStyleAndLayoutTreeIgnorePendingStylesheets(); | 1041 document().updateStyleAndLayoutTreeIgnorePendingStylesheets(); |
1027 while (target) { | 1042 while (target) { |
1028 // We don't want to set focus on a subframe when selecting in a pare
nt frame, | 1043 // We don't want to set focus on a subframe when selecting in a pare
nt frame, |
1029 // so add the !isFrameElement check here. There's probably a better
way to make this | 1044 // so add the !isFrameElement check here. There's probably a better
way to make this |
1030 // work in the long term, but this is the safest fix at this time. | 1045 // work in the long term, but this is the safest fix at this time. |
1031 if (target->isMouseFocusable() && !isFrameElement(target)) { | 1046 if (target->isMouseFocusable() && !isFrameElement(target)) { |
1032 m_frame->page()->focusController().setFocusedElement(target, m_f
rame); | 1047 m_frame->page()->focusController().setFocusedElement(target, m_f
rame); |
1033 return; | 1048 return; |
1034 } | 1049 } |
1035 target = target->parentOrShadowHostElement(); | 1050 target = target->parentOrShadowHostElement(); |
1036 } | 1051 } |
1037 m_frame->document()->clearFocusedElement(); | 1052 document().clearFocusedElement(); |
1038 } | 1053 } |
1039 | 1054 |
1040 if (caretBrowsing) | 1055 if (caretBrowsing) |
1041 m_frame->page()->focusController().setFocusedElement(0, m_frame); | 1056 m_frame->page()->focusController().setFocusedElement(0, m_frame); |
1042 } | 1057 } |
1043 | 1058 |
1044 static String extractSelectedText(const FrameSelection& selection, TextIteratorB
ehavior behavior) | 1059 static String extractSelectedText(const FrameSelection& selection, TextIteratorB
ehavior behavior) |
1045 { | 1060 { |
1046 const VisibleSelectionInFlatTree& visibleSelection = selection.visibleSelect
ion<EditingInFlatTreeStrategy>(); | 1061 const VisibleSelectionInFlatTree& visibleSelection = selection.visibleSelect
ion<EditingInFlatTreeStrategy>(); |
1047 const EphemeralRangeInFlatTree& range = visibleSelection.toNormalizedEphemer
alRange(); | 1062 const EphemeralRangeInFlatTree& range = visibleSelection.toNormalizedEphemer
alRange(); |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1112 return frameResult; | 1127 return frameResult; |
1113 } | 1128 } |
1114 } | 1129 } |
1115 return 0; | 1130 return 0; |
1116 } | 1131 } |
1117 | 1132 |
1118 // We look for either the form containing the current focus, or for one immediat
ely after it | 1133 // We look for either the form containing the current focus, or for one immediat
ely after it |
1119 HTMLFormElement* FrameSelection::currentForm() const | 1134 HTMLFormElement* FrameSelection::currentForm() const |
1120 { | 1135 { |
1121 // Start looking either at the active (first responder) node, or where the s
election is. | 1136 // Start looking either at the active (first responder) node, or where the s
election is. |
1122 Node* start = m_frame->document()->focusedElement(); | 1137 Node* start = document().focusedElement(); |
1123 if (!start) | 1138 if (!start) |
1124 start = this->start().anchorNode(); | 1139 start = this->start().anchorNode(); |
1125 if (!start) | 1140 if (!start) |
1126 return 0; | 1141 return 0; |
1127 | 1142 |
1128 // Try walking up the node tree to find a form element. | 1143 // Try walking up the node tree to find a form element. |
1129 for (HTMLElement* element = Traversal<HTMLElement>::firstAncestorOrSelf(*sta
rt); element; element = Traversal<HTMLElement>::firstAncestor(*element)) { | 1144 for (HTMLElement* element = Traversal<HTMLElement>::firstAncestorOrSelf(*sta
rt); element; element = Traversal<HTMLElement>::firstAncestor(*element)) { |
1130 if (HTMLFormElement* form = associatedFormElement(*element)) | 1145 if (HTMLFormElement* form = associatedFormElement(*element)) |
1131 return form; | 1146 return form; |
1132 } | 1147 } |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1231 | 1246 |
1232 void FrameSelection::showTreeForThis() const | 1247 void FrameSelection::showTreeForThis() const |
1233 { | 1248 { |
1234 selection().showTreeForThis(); | 1249 selection().showTreeForThis(); |
1235 } | 1250 } |
1236 | 1251 |
1237 #endif | 1252 #endif |
1238 | 1253 |
1239 DEFINE_TRACE(FrameSelection) | 1254 DEFINE_TRACE(FrameSelection) |
1240 { | 1255 { |
| 1256 visitor->trace(m_document); |
1241 visitor->trace(m_frame); | 1257 visitor->trace(m_frame); |
1242 visitor->trace(m_pendingSelection); | 1258 visitor->trace(m_pendingSelection); |
1243 visitor->trace(m_selectionEditor); | 1259 visitor->trace(m_selectionEditor); |
1244 visitor->trace(m_originalBase); | 1260 visitor->trace(m_originalBase); |
1245 visitor->trace(m_originalBaseInFlatTree); | 1261 visitor->trace(m_originalBaseInFlatTree); |
1246 visitor->trace(m_typingStyle); | 1262 visitor->trace(m_typingStyle); |
1247 visitor->trace(m_frameCaret); | 1263 visitor->trace(m_frameCaret); |
1248 } | 1264 } |
1249 | 1265 |
1250 void FrameSelection::scheduleVisualUpdate() const | 1266 void FrameSelection::scheduleVisualUpdate() const |
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1364 | 1380 |
1365 void showTree(const blink::FrameSelection* sel) | 1381 void showTree(const blink::FrameSelection* sel) |
1366 { | 1382 { |
1367 if (sel) | 1383 if (sel) |
1368 sel->showTreeForThis(); | 1384 sel->showTreeForThis(); |
1369 else | 1385 else |
1370 fprintf(stderr, "Cannot showTree for (nil) FrameSelection.\n"); | 1386 fprintf(stderr, "Cannot showTree for (nil) FrameSelection.\n"); |
1371 } | 1387 } |
1372 | 1388 |
1373 #endif | 1389 #endif |
OLD | NEW |