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