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 21 matching lines...) Expand all Loading... | |
| 32 #include "core/dom/AXObjectCache.h" | 32 #include "core/dom/AXObjectCache.h" |
| 33 #include "core/dom/CharacterData.h" | 33 #include "core/dom/CharacterData.h" |
| 34 #include "core/dom/Document.h" | 34 #include "core/dom/Document.h" |
| 35 #include "core/dom/Element.h" | 35 #include "core/dom/Element.h" |
| 36 #include "core/dom/ElementTraversal.h" | 36 #include "core/dom/ElementTraversal.h" |
| 37 #include "core/dom/NodeTraversal.h" | 37 #include "core/dom/NodeTraversal.h" |
| 38 #include "core/dom/Text.h" | 38 #include "core/dom/Text.h" |
| 39 #include "core/editing/CaretBase.h" | 39 #include "core/editing/CaretBase.h" |
| 40 #include "core/editing/EditingUtilities.h" | 40 #include "core/editing/EditingUtilities.h" |
| 41 #include "core/editing/Editor.h" | 41 #include "core/editing/Editor.h" |
| 42 #include "core/editing/FrameCaret.h" | |
| 42 #include "core/editing/GranularityStrategy.h" | 43 #include "core/editing/GranularityStrategy.h" |
| 43 #include "core/editing/InputMethodController.h" | 44 #include "core/editing/InputMethodController.h" |
| 44 #include "core/editing/PendingSelection.h" | 45 #include "core/editing/PendingSelection.h" |
| 45 #include "core/editing/RenderedPosition.h" | 46 #include "core/editing/RenderedPosition.h" |
| 46 #include "core/editing/SelectionController.h" | 47 #include "core/editing/SelectionController.h" |
| 47 #include "core/editing/SelectionEditor.h" | 48 #include "core/editing/SelectionEditor.h" |
| 48 #include "core/editing/SelectionModifier.h" | 49 #include "core/editing/SelectionModifier.h" |
| 49 #include "core/editing/TextAffinity.h" | 50 #include "core/editing/TextAffinity.h" |
| 50 #include "core/editing/VisibleUnits.h" | 51 #include "core/editing/VisibleUnits.h" |
| 51 #include "core/editing/commands/TypingCommand.h" | 52 #include "core/editing/commands/TypingCommand.h" |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 91 { | 92 { |
| 92 return !frame || frame->editor().behavior().shouldConsiderSelectionAsDirecti onal(); | 93 return !frame || frame->editor().behavior().shouldConsiderSelectionAsDirecti onal(); |
| 93 } | 94 } |
| 94 | 95 |
| 95 FrameSelection::FrameSelection(LocalFrame* frame) | 96 FrameSelection::FrameSelection(LocalFrame* frame) |
| 96 : m_frame(frame) | 97 : m_frame(frame) |
| 97 , m_pendingSelection(PendingSelection::create(*this)) | 98 , m_pendingSelection(PendingSelection::create(*this)) |
| 98 , m_selectionEditor(SelectionEditor::create(*this)) | 99 , m_selectionEditor(SelectionEditor::create(*this)) |
| 99 , m_granularity(CharacterGranularity) | 100 , m_granularity(CharacterGranularity) |
| 100 , m_xPosForVerticalArrowNavigation(NoXPosForVerticalArrowNavigation()) | 101 , m_xPosForVerticalArrowNavigation(NoXPosForVerticalArrowNavigation()) |
| 101 , m_previousCaretVisibility(CaretVisibility::Hidden) | |
| 102 , m_caretBlinkTimer(this, &FrameSelection::caretBlinkTimerFired) | |
| 103 , m_caretRectDirty(true) | |
| 104 , m_shouldPaintCaret(true) | |
| 105 , m_isCaretBlinkingSuspended(false) | |
| 106 , m_focused(frame && frame->page() && frame->page()->focusController().focus edFrame() == frame) | 102 , m_focused(frame && frame->page() && frame->page()->focusController().focus edFrame() == frame) |
| 107 , m_shouldShowBlockCursor(false) | 103 , m_shouldShowBlockCursor(false) |
| 108 , m_caretBase(adoptPtr(new CaretBase)) | 104 , m_frameCaret(new FrameCaret(frame)) |
| 109 { | 105 { |
| 110 // TODO(yosin): We should remove null check for |m_frame| in | 106 // TODO(yosin): We should remove null check for |m_frame| in |
| 111 // "FrameSelection.cpp", since it never be null. | 107 // "FrameSelection.cpp", since it never be null. |
| 112 DCHECK(frame); | 108 DCHECK(frame); |
| 113 if (shouldAlwaysUseDirectionalSelection(m_frame)) | 109 if (shouldAlwaysUseDirectionalSelection(m_frame)) |
| 114 m_selectionEditor->setIsDirectional(true); | 110 m_selectionEditor->setIsDirectional(true); |
| 115 } | 111 } |
| 116 | 112 |
| 117 FrameSelection::~FrameSelection() | 113 FrameSelection::~FrameSelection() |
| 118 { | 114 { |
| (...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 332 | 328 |
| 333 m_selectionEditor->setVisibleSelection(s, options); | 329 m_selectionEditor->setVisibleSelection(s, options); |
| 334 setCaretRectNeedsUpdate(); | 330 setCaretRectNeedsUpdate(); |
| 335 | 331 |
| 336 if (!s.isNone() && !(options & DoNotSetFocus)) | 332 if (!s.isNone() && !(options & DoNotSetFocus)) |
| 337 setFocusedNodeIfNeeded(); | 333 setFocusedNodeIfNeeded(); |
| 338 | 334 |
| 339 if (!(options & DoNotUpdateAppearance)) { | 335 if (!(options & DoNotUpdateAppearance)) { |
| 340 // Hits in compositing/overflow/do-not-paint-outline-into-composited-scr olling-contents.html | 336 // Hits in compositing/overflow/do-not-paint-outline-into-composited-scr olling-contents.html |
| 341 DisableCompositingQueryAsserts disabler; | 337 DisableCompositingQueryAsserts disabler; |
| 342 stopCaretBlinkTimer(); | 338 m_frameCaret->stopCaretBlinkTimer(); |
| 343 updateAppearance(); | 339 updateAppearance(); |
| 344 } | 340 } |
| 345 | 341 |
| 346 // Always clear the x position used for vertical arrow navigation. | 342 // Always clear the x position used for vertical arrow navigation. |
| 347 // It will be restored by the vertical arrow navigation code if necessary. | 343 // It will be restored by the vertical arrow navigation code if necessary. |
| 348 m_xPosForVerticalArrowNavigation = NoXPosForVerticalArrowNavigation(); | 344 m_xPosForVerticalArrowNavigation = NoXPosForVerticalArrowNavigation(); |
| 349 // This may dispatch a synchronous focus-related events. | 345 // This may dispatch a synchronous focus-related events. |
| 350 selectFrameElementInParentIfFullySelected(); | 346 selectFrameElementInParentIfFullySelected(); |
| 351 notifyLayoutObjectOfSelectionChange(userTriggered); | 347 notifyLayoutObjectOfSelectionChange(userTriggered); |
| 352 // If the selections are same in the DOM tree but not in the flat tree, | 348 // If the selections are same in the DOM tree but not in the flat tree, |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 394 if (position.anchorNode() == node) | 390 if (position.anchorNode() == node) |
| 395 return true; | 391 return true; |
| 396 | 392 |
| 397 if (!node.isElementNode()) | 393 if (!node.isElementNode()) |
| 398 return false; | 394 return false; |
| 399 | 395 |
| 400 Element& element = toElement(node); | 396 Element& element = toElement(node); |
| 401 return element.isShadowIncludingInclusiveAncestorOf(position.anchorNode()); | 397 return element.isShadowIncludingInclusiveAncestorOf(position.anchorNode()); |
| 402 } | 398 } |
| 403 | 399 |
| 400 // TODO(yoiciho): We should move this function to FrameCaret.cpp | |
| 401 void FrameCaret::nodeWillBeRemoved(Node& node) | |
| 402 { | |
| 403 if (node != m_previousCaretNode) | |
| 404 return; | |
| 405 // Hits in ManualTests/caret-paint-after-last-text-is-removed.html | |
| 406 DisableCompositingQueryAsserts disabler; | |
| 407 invalidateLocalCaretRect(m_previousCaretNode.get(), m_previousCaretRect); | |
| 408 m_previousCaretNode = nullptr; | |
| 409 m_previousCaretRect = LayoutRect(); | |
| 410 m_previousCaretVisibility = CaretVisibility::Hidden; | |
| 411 } | |
| 412 | |
| 404 void FrameSelection::nodeWillBeRemoved(Node& node) | 413 void FrameSelection::nodeWillBeRemoved(Node& node) |
| 405 { | 414 { |
| 406 // There can't be a selection inside a fragment, so if a fragment's node is being removed, | 415 // There can't be a selection inside a fragment, so if a fragment's node is being removed, |
| 407 // the selection in the document that created the fragment needs no adjustme nt. | 416 // the selection in the document that created the fragment needs no adjustme nt. |
| 408 if (isNone() || !node.inActiveDocument()) | 417 if (isNone() || !node.inActiveDocument()) |
| 409 return; | 418 return; |
| 410 | 419 |
| 411 respondToNodeModification(node, removingNodeRemovesPosition(node, selection( ).base()), removingNodeRemovesPosition(node, selection().extent()), | 420 respondToNodeModification(node, removingNodeRemovesPosition(node, selection( ).base()), removingNodeRemovesPosition(node, selection().extent()), |
| 412 removingNodeRemovesPosition(node, selection().start()), removingNodeRemo vesPosition(node, selection().end())); | 421 removingNodeRemovesPosition(node, selection().start()), removingNodeRemo vesPosition(node, selection().end())); |
| 413 | 422 |
| 414 if (node == m_previousCaretNode) { | 423 m_frameCaret->nodeWillBeRemoved(node); |
| 415 // Hits in ManualTests/caret-paint-after-last-text-is-removed.html | |
| 416 DisableCompositingQueryAsserts disabler; | |
| 417 m_caretBase->invalidateLocalCaretRect(m_previousCaretNode.get(), m_previ ousCaretRect); | |
| 418 m_previousCaretNode = nullptr; | |
| 419 m_previousCaretRect = LayoutRect(); | |
| 420 m_previousCaretVisibility = CaretVisibility::Hidden; | |
| 421 } | |
| 422 } | 424 } |
| 423 | 425 |
| 424 static bool intersectsNode(const VisibleSelection& selection, Node* node) | 426 static bool intersectsNode(const VisibleSelection& selection, Node* node) |
| 425 { | 427 { |
| 426 if (selection.isNone()) | 428 if (selection.isNone()) |
| 427 return false; | 429 return false; |
| 428 Position start = selection.start().parentAnchoredEquivalent(); | 430 Position start = selection.start().parentAnchoredEquivalent(); |
| 429 Position end = selection.end().parentAnchoredEquivalent(); | 431 Position end = selection.end().parentAnchoredEquivalent(); |
| 430 TrackExceptionState exceptionState; | 432 TrackExceptionState exceptionState; |
| 431 // TODO(yosin) We should avoid to use |Range::intersectsNode()|. | 433 // TODO(yosin) We should avoid to use |Range::intersectsNode()|. |
| (...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 627 | 629 |
| 628 const SetSelectionOptions options = CloseTyping | ClearTypingStyle | userTri ggered; | 630 const SetSelectionOptions options = CloseTyping | ClearTypingStyle | userTri ggered; |
| 629 setSelection(selectionModifier.selection(), options); | 631 setSelection(selectionModifier.selection(), options); |
| 630 | 632 |
| 631 if (granularity == LineGranularity || granularity == ParagraphGranularity) | 633 if (granularity == LineGranularity || granularity == ParagraphGranularity) |
| 632 m_xPosForVerticalArrowNavigation = selectionModifier.xPosForVerticalArro wNavigation(); | 634 m_xPosForVerticalArrowNavigation = selectionModifier.xPosForVerticalArro wNavigation(); |
| 633 | 635 |
| 634 if (userTriggered == UserTriggered) | 636 if (userTriggered == UserTriggered) |
| 635 m_granularity = CharacterGranularity; | 637 m_granularity = CharacterGranularity; |
| 636 | 638 |
| 637 setCaretRectNeedsUpdate(); | 639 m_frameCaret->setCaretRectNeedsUpdate(); |
| 638 | 640 |
| 639 return true; | 641 return true; |
| 640 } | 642 } |
| 641 | 643 |
| 642 bool FrameSelection::modify(EAlteration alter, unsigned verticalDistance, Vertic alDirection direction, EUserTriggered userTriggered, CursorAlignOnScroll align) | 644 bool FrameSelection::modify(EAlteration alter, unsigned verticalDistance, Vertic alDirection direction, EUserTriggered userTriggered, CursorAlignOnScroll align) |
| 643 { | 645 { |
| 644 SelectionModifier selectionModifier(*frame(), selection()); | 646 SelectionModifier selectionModifier(*frame(), selection()); |
| 645 if (!selectionModifier.modifyWithPageGranularity(alter, verticalDistance, di rection)) | 647 if (!selectionModifier.modifyWithPageGranularity(alter, verticalDistance, di rection)) |
| 646 return false; | 648 return false; |
| 647 | 649 |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 658 } | 660 } |
| 659 | 661 |
| 660 void FrameSelection::clear() | 662 void FrameSelection::clear() |
| 661 { | 663 { |
| 662 m_granularity = CharacterGranularity; | 664 m_granularity = CharacterGranularity; |
| 663 if (m_granularityStrategy) | 665 if (m_granularityStrategy) |
| 664 m_granularityStrategy->Clear(); | 666 m_granularityStrategy->Clear(); |
| 665 setSelection(VisibleSelection()); | 667 setSelection(VisibleSelection()); |
| 666 } | 668 } |
| 667 | 669 |
| 670 // TODO(yoiciho): We should move this function to FrameCaret.cpp | |
| 671 void FrameCaret::prepareForDestruction() | |
| 672 { | |
| 673 m_caretBlinkTimer.stop(); | |
| 674 m_previousCaretNode.clear(); | |
| 675 } | |
| 676 | |
| 668 void FrameSelection::prepareForDestruction() | 677 void FrameSelection::prepareForDestruction() |
| 669 { | 678 { |
| 670 m_granularity = CharacterGranularity; | 679 m_granularity = CharacterGranularity; |
| 671 | 680 |
| 672 m_caretBlinkTimer.stop(); | |
| 673 | |
| 674 LayoutViewItem view = m_frame->contentLayoutItem(); | 681 LayoutViewItem view = m_frame->contentLayoutItem(); |
| 675 if (!view.isNull()) | 682 if (!view.isNull()) |
| 676 view.clearSelection(); | 683 view.clearSelection(); |
| 677 | 684 |
| 678 setSelection(VisibleSelection(), CloseTyping | ClearTypingStyle | DoNotUpdat eAppearance); | 685 setSelection(VisibleSelection(), CloseTyping | ClearTypingStyle | DoNotUpdat eAppearance); |
| 679 m_selectionEditor->dispose(); | 686 m_selectionEditor->dispose(); |
| 680 m_previousCaretNode.clear(); | 687 m_frameCaret->prepareForDestruction(); |
| 681 } | 688 } |
| 682 | 689 |
| 683 void FrameSelection::setBase(const VisiblePosition &pos, EUserTriggered userTrig gered) | 690 void FrameSelection::setBase(const VisiblePosition &pos, EUserTriggered userTrig gered) |
| 684 { | 691 { |
| 685 const bool selectionHasDirection = true; | 692 const bool selectionHasDirection = true; |
| 686 setSelection(VisibleSelection(pos.deepEquivalent(), selection().extent(), po s.affinity(), selectionHasDirection), CloseTyping | ClearTypingStyle | userTrigg ered); | 693 setSelection(VisibleSelection(pos.deepEquivalent(), selection().extent(), po s.affinity(), selectionHasDirection), CloseTyping | ClearTypingStyle | userTrigg ered); |
| 687 } | 694 } |
| 688 | 695 |
| 689 void FrameSelection::setExtent(const VisiblePosition &pos, EUserTriggered userTr iggered) | 696 void FrameSelection::setExtent(const VisiblePosition &pos, EUserTriggered userTr iggered) |
| 690 { | 697 { |
| 691 const bool selectionHasDirection = true; | 698 const bool selectionHasDirection = true; |
| 692 setSelection(VisibleSelection(selection().base(), pos.deepEquivalent(), pos. affinity(), selectionHasDirection), CloseTyping | ClearTypingStyle | userTrigger ed); | 699 setSelection(VisibleSelection(selection().base(), pos.deepEquivalent(), pos. affinity(), selectionHasDirection), CloseTyping | ClearTypingStyle | userTrigger ed); |
| 693 } | 700 } |
| 694 | 701 |
| 695 static bool isTextFormControl(const VisibleSelection& selection) | 702 static bool isTextFormControl(const VisibleSelection& selection) |
| 696 { | 703 { |
| 697 return enclosingTextFormControl(selection.start()); | 704 return enclosingTextFormControl(selection.start()); |
| 698 } | 705 } |
| 699 | 706 |
| 700 LayoutBlock* FrameSelection::caretLayoutObject() const | 707 LayoutBlock* FrameSelection::caretLayoutObject() const |
| 701 { | 708 { |
| 702 DCHECK(selection().isValidFor(*m_frame->document())); | 709 DCHECK(selection().isValidFor(*m_frame->document())); |
| 703 if (!isCaret()) | 710 if (!isCaret()) |
| 704 return nullptr; | 711 return nullptr; |
| 705 return CaretBase::caretLayoutObject(selection().start().anchorNode()); | 712 return CaretBase::caretLayoutObject(selection().start().anchorNode()); |
| 706 } | 713 } |
| 707 | 714 |
| 715 // TODO(yoichio): All of functionality should be in FrameCaret. | |
| 716 // FrameCaret should have PositionWithAffnity and FrameSelection set in | |
| 717 // setSelecitonAlgorithm. | |
| 708 IntRect FrameSelection::absoluteCaretBounds() | 718 IntRect FrameSelection::absoluteCaretBounds() |
| 709 { | 719 { |
| 710 DCHECK(selection().isValidFor(*m_frame->document())); | 720 DCHECK(selection().isValidFor(*m_frame->document())); |
| 711 DCHECK_NE(m_frame->document()->lifecycle().state(), DocumentLifecycle::InPai ntInvalidation); | 721 DCHECK_NE(m_frame->document()->lifecycle().state(), DocumentLifecycle::InPai ntInvalidation); |
| 712 m_frame->document()->updateStyleAndLayoutIgnorePendingStylesheets(); | 722 m_frame->document()->updateStyleAndLayoutIgnorePendingStylesheets(); |
| 713 if (!isCaret()) { | 723 if (!isCaret()) { |
| 714 m_caretBase->clearCaretRect(); | 724 m_frameCaret->clearCaretRect(); |
| 715 } else { | 725 } else { |
| 716 if (isTextFormControl(selection())) | 726 if (isTextFormControl(selection())) |
| 717 m_caretBase->updateCaretRect(PositionWithAffinity(isVisuallyEquivale ntCandidate(selection().start()) ? selection().start() : Position(), selection() .affinity())); | 727 m_frameCaret->updateCaretRect(PositionWithAffinity(isVisuallyEquival entCandidate(selection().start()) ? selection().start() : Position(), selection( ).affinity())); |
| 718 else | 728 else |
| 719 m_caretBase->updateCaretRect(createVisiblePosition(selection().start (), selection().affinity())); | 729 m_frameCaret->updateCaretRect(createVisiblePosition(selection().star t(), selection().affinity())); |
| 720 } | 730 } |
| 721 return m_caretBase->absoluteBoundsForLocalRect(selection().start().anchorNod e(), m_caretBase->localCaretRectWithoutUpdate()); | 731 return m_frameCaret->absoluteBoundsForLocalRect(selection().start().anchorNo de(), m_frameCaret->localCaretRectWithoutUpdate()); |
| 722 } | 732 } |
| 723 | 733 |
| 724 void FrameSelection::invalidateCaretRect() | 734 // TODO(yoiciho): We should move this function to FrameCaret.cpp |
| 735 void FrameCaret::invalidateCaretRect(const VisibleSelection& selection) | |
| 725 { | 736 { |
| 726 if (!m_caretRectDirty) | 737 if (!m_caretRectDirty) |
| 727 return; | 738 return; |
| 728 m_caretRectDirty = false; | 739 m_caretRectDirty = false; |
| 729 | 740 |
| 730 DCHECK(selection().isValidFor(*m_frame->document())); | 741 DCHECK(selection.isValidFor(*m_frame->document())); |
| 731 LayoutObject* layoutObject = nullptr; | 742 LayoutObject* layoutObject = nullptr; |
| 732 LayoutRect newRect; | 743 LayoutRect newRect; |
| 733 if (selection().isCaret()) | 744 if (selection.isCaret()) |
| 734 newRect = localCaretRectOfPosition(PositionWithAffinity(selection().star t(), selection().affinity()), layoutObject); | 745 newRect = localCaretRectOfPosition(PositionWithAffinity(selection.start( ), selection.affinity()), layoutObject); |
| 735 Node* newNode = layoutObject ? layoutObject->node() : nullptr; | 746 Node* newNode = layoutObject ? layoutObject->node() : nullptr; |
| 736 | 747 |
| 737 if (!m_caretBlinkTimer.isActive() | 748 if (!m_caretBlinkTimer.isActive() |
| 738 && newNode == m_previousCaretNode | 749 && newNode == m_previousCaretNode |
| 739 && newRect == m_previousCaretRect | 750 && newRect == m_previousCaretRect |
| 740 && m_caretBase->getCaretVisibility() == m_previousCaretVisibility) | 751 && getCaretVisibility() == m_previousCaretVisibility) |
| 741 return; | 752 return; |
| 742 | 753 |
| 743 LayoutViewItem view = m_frame->document()->layoutViewItem(); | 754 LayoutViewItem view = m_frame->document()->layoutViewItem(); |
| 744 if (m_previousCaretNode && (m_caretBase->shouldRepaintCaret(*m_previousCaret Node) || m_caretBase->shouldRepaintCaret(view))) | 755 if (m_previousCaretNode && (shouldRepaintCaret(*m_previousCaretNode) || shou ldRepaintCaret(view))) |
| 745 m_caretBase->invalidateLocalCaretRect(m_previousCaretNode.get(), m_previ ousCaretRect); | 756 invalidateLocalCaretRect(m_previousCaretNode.get(), m_previousCaretRect) ; |
| 746 if (newNode && (m_caretBase->shouldRepaintCaret(*newNode) || m_caretBase->sh ouldRepaintCaret(view))) | 757 if (newNode && (shouldRepaintCaret(*newNode) || shouldRepaintCaret(view))) |
| 747 m_caretBase->invalidateLocalCaretRect(newNode, newRect); | 758 invalidateLocalCaretRect(newNode, newRect); |
| 748 m_previousCaretNode = newNode; | 759 m_previousCaretNode = newNode; |
| 749 m_previousCaretRect = newRect; | 760 m_previousCaretRect = newRect; |
| 750 m_previousCaretVisibility = m_caretBase->getCaretVisibility(); | 761 m_previousCaretVisibility = getCaretVisibility(); |
| 762 } | |
| 763 | |
| 764 void FrameSelection::invalidateCaretRect() | |
| 765 { | |
| 766 m_frameCaret->invalidateCaretRect(selection()); | |
| 767 } | |
| 768 | |
| 769 // TODO(yoiciho): We should move this function to FrameCaret.cpp | |
| 770 void FrameCaret::dataWillChange(const CharacterData& node) | |
| 771 { | |
| 772 if (node == m_previousCaretNode) { | |
| 773 // This invalidation is eager, and intentionally uses stale state. | |
| 774 DisableCompositingQueryAsserts disabler; | |
| 775 invalidateLocalCaretRect(m_previousCaretNode.get(), m_previousCaretRect) ; | |
| 776 } | |
| 751 } | 777 } |
| 752 | 778 |
| 753 void FrameSelection::dataWillChange(const CharacterData& node) | 779 void FrameSelection::dataWillChange(const CharacterData& node) |
| 754 { | 780 { |
| 755 if (node == m_previousCaretNode) { | 781 m_frameCaret->dataWillChange(node); |
| 756 // This invalidation is eager, and intentionally uses stale state. | 782 } |
| 757 DisableCompositingQueryAsserts disabler; | 783 |
| 758 m_caretBase->invalidateLocalCaretRect(m_previousCaretNode.get(), m_previ ousCaretRect); | 784 // TODO(yoiciho): We should move this function to FrameCaret.cpp |
| 785 void FrameCaret::paintCaret(GraphicsContext& context, const LayoutPoint& paintOf fset, const VisibleSelection& selection) | |
| 786 { | |
| 787 if (selection.isCaret() && m_shouldPaintCaret) { | |
| 788 updateCaretRect(PositionWithAffinity(selection.start(), selection.affini ty())); | |
| 789 CaretBase::paintCaret(selection.start().anchorNode(), context, paintOffs et); | |
| 759 } | 790 } |
| 760 } | 791 } |
| 761 | 792 |
| 762 void FrameSelection::paintCaret(GraphicsContext& context, const LayoutPoint& pai ntOffset) | 793 void FrameSelection::paintCaret(GraphicsContext& context, const LayoutPoint& pai ntOffset) |
| 763 { | 794 { |
| 764 if (selection().isCaret() && m_shouldPaintCaret) { | 795 m_frameCaret->paintCaret(context, paintOffset, selection()); |
| 765 m_caretBase->updateCaretRect(PositionWithAffinity(selection().start(), s election().affinity())); | |
| 766 m_caretBase->paintCaret(selection().start().anchorNode(), context, paint Offset); | |
| 767 } | |
| 768 } | 796 } |
| 769 | 797 |
| 770 bool FrameSelection::contains(const LayoutPoint& point) | 798 bool FrameSelection::contains(const LayoutPoint& point) |
| 771 { | 799 { |
| 772 Document* document = m_frame->document(); | 800 Document* document = m_frame->document(); |
| 773 if (document->layoutViewItem().isNull()) | 801 if (document->layoutViewItem().isNull()) |
| 774 return false; | 802 return false; |
| 775 | 803 |
| 776 // Treat a collapsed selection like no selection. | 804 // Treat a collapsed selection like no selection. |
| 777 const VisibleSelectionInFlatTree& visibleSelection = this->visibleSelection< EditingInFlatTreeStrategy>(); | 805 const VisibleSelectionInFlatTree& visibleSelection = this->visibleSelection< EditingInFlatTreeStrategy>(); |
| (...skipping 253 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1031 bool FrameSelection::isAppearanceDirty() const | 1059 bool FrameSelection::isAppearanceDirty() const |
| 1032 { | 1060 { |
| 1033 return m_pendingSelection->hasPendingSelection(); | 1061 return m_pendingSelection->hasPendingSelection(); |
| 1034 } | 1062 } |
| 1035 | 1063 |
| 1036 void FrameSelection::commitAppearanceIfNeeded(LayoutView& layoutView) | 1064 void FrameSelection::commitAppearanceIfNeeded(LayoutView& layoutView) |
| 1037 { | 1065 { |
| 1038 return m_pendingSelection->commit(layoutView); | 1066 return m_pendingSelection->commit(layoutView); |
| 1039 } | 1067 } |
| 1040 | 1068 |
| 1069 // TODO(yoiciho): We should move this function to FrameCaret.cpp | |
| 1070 void FrameCaret::startBlinkCaret() | |
| 1071 { | |
| 1072 // Start blinking with a black caret. Be sure not to restart if we're | |
| 1073 // already blinking in the right location. | |
| 1074 if (m_caretBlinkTimer.isActive()) | |
| 1075 return; | |
| 1076 | |
| 1077 if (double blinkInterval = LayoutTheme::theme().caretBlinkInterval()) | |
| 1078 m_caretBlinkTimer.startRepeating(blinkInterval, BLINK_FROM_HERE); | |
| 1079 | |
| 1080 m_shouldPaintCaret = true; | |
| 1081 setCaretRectNeedsUpdate(); | |
| 1082 | |
| 1083 } | |
| 1084 | |
| 1085 // TODO(yoichio): All of functionality should be in FrameCaret. | |
| 1086 // FrameCaret should have PositionWithAffnity and FrameSelection set in | |
| 1087 // setSelecitonAlgorithm. | |
| 1041 void FrameSelection::updateAppearance() | 1088 void FrameSelection::updateAppearance() |
| 1042 { | 1089 { |
| 1043 // Paint a block cursor instead of a caret in overtype mode unless the caret is at the end of a line (in this case | 1090 // Paint a block cursor instead of a caret in overtype mode unless the caret is at the end of a line (in this case |
| 1044 // the FrameSelection will paint a blinking caret as usual). | 1091 // the FrameSelection will paint a blinking caret as usual). |
| 1045 bool paintBlockCursor = m_shouldShowBlockCursor && selection().isCaret() && !isLogicalEndOfLine(selection().visibleEnd()); | 1092 bool paintBlockCursor = m_shouldShowBlockCursor && selection().isCaret() && !isLogicalEndOfLine(selection().visibleEnd()); |
| 1046 | 1093 |
| 1047 bool shouldBlink = !paintBlockCursor && shouldBlinkCaret(); | 1094 bool shouldBlink = !paintBlockCursor && shouldBlinkCaret(); |
| 1048 | 1095 |
| 1049 // If the caret moved, stop the blink timer so we can restart with a | 1096 // If the caret moved, stop the blink timer so we can restart with a |
| 1050 // black caret in the new location. | 1097 // black caret in the new location. |
| 1051 if (!shouldBlink || shouldStopBlinkingDueToTypingCommand(m_frame)) | 1098 if (!shouldBlink || shouldStopBlinkingDueToTypingCommand(m_frame)) |
| 1052 stopCaretBlinkTimer(); | 1099 m_frameCaret->stopCaretBlinkTimer(); |
| 1053 | 1100 |
| 1054 // Start blinking with a black caret. Be sure not to restart if we're | 1101 // Start blinking with a black caret. Be sure not to restart if we're |
| 1055 // already blinking in the right location. | 1102 // already blinking in the right location. |
| 1056 if (shouldBlink && !m_caretBlinkTimer.isActive()) { | 1103 if (shouldBlink) |
| 1057 if (double blinkInterval = LayoutTheme::theme().caretBlinkInterval()) | 1104 m_frameCaret->startBlinkCaret(); |
| 1058 m_caretBlinkTimer.startRepeating(blinkInterval, BLINK_FROM_HERE); | |
| 1059 | |
| 1060 m_shouldPaintCaret = true; | |
| 1061 setCaretRectNeedsUpdate(); | |
| 1062 } | |
| 1063 | 1105 |
| 1064 if (m_frame->contentLayoutItem().isNull()) | 1106 if (m_frame->contentLayoutItem().isNull()) |
| 1065 return; | 1107 return; |
| 1066 m_pendingSelection->setHasPendingSelection(); | 1108 m_pendingSelection->setHasPendingSelection(); |
| 1067 } | 1109 } |
| 1068 | 1110 |
| 1111 // TODO(yoichio): All of functionality should be in FrameCaret. | |
| 1112 // FrameCaret should have PositionWithAffnity and FrameSelection set in | |
| 1113 // setSelecitonAlgorithm. | |
| 1069 void FrameSelection::setCaretVisibility(CaretVisibility visibility) | 1114 void FrameSelection::setCaretVisibility(CaretVisibility visibility) |
| 1070 { | 1115 { |
| 1071 if (m_caretBase->getCaretVisibility() == visibility) | 1116 if (m_frameCaret->getCaretVisibility() == visibility) |
| 1072 return; | 1117 return; |
| 1073 | 1118 |
| 1074 m_caretBase->setCaretVisibility(visibility); | 1119 m_frameCaret->setCaretVisibility(visibility); |
| 1075 | 1120 |
| 1076 updateAppearance(); | 1121 updateAppearance(); |
| 1077 } | 1122 } |
| 1078 | 1123 |
| 1079 bool FrameSelection::shouldBlinkCaret() const | 1124 bool FrameSelection::shouldBlinkCaret() const |
| 1080 { | 1125 { |
| 1081 if (!m_caretBase->caretIsVisible() || !isCaret()) | 1126 if (!m_frameCaret->caretIsVisible() || !isCaret()) |
| 1082 return false; | 1127 return false; |
| 1083 | 1128 |
| 1084 if (m_frame->settings() && m_frame->settings()->caretBrowsingEnabled()) | 1129 if (m_frame->settings() && m_frame->settings()->caretBrowsingEnabled()) |
| 1085 return false; | 1130 return false; |
| 1086 | 1131 |
| 1087 Element* root = rootEditableElement(); | 1132 Element* root = rootEditableElement(); |
| 1088 if (!root) | 1133 if (!root) |
| 1089 return false; | 1134 return false; |
| 1090 | 1135 |
| 1091 Element* focusedElement = root->document().focusedElement(); | 1136 Element* focusedElement = root->document().focusedElement(); |
| 1092 if (!focusedElement) | 1137 if (!focusedElement) |
| 1093 return false; | 1138 return false; |
| 1094 | 1139 |
| 1095 return focusedElement->isShadowIncludingInclusiveAncestorOf(selection().star t().anchorNode()); | 1140 return focusedElement->isShadowIncludingInclusiveAncestorOf(selection().star t().anchorNode()); |
| 1096 } | 1141 } |
| 1097 | 1142 |
| 1098 void FrameSelection::caretBlinkTimerFired(Timer<FrameSelection>*) | 1143 // TODO(yoiciho): We should move this function to FrameCaret.cpp |
| 1144 void FrameCaret::caretBlinkTimerFired(Timer<FrameCaret>*) | |
| 1099 { | 1145 { |
| 1100 DCHECK(m_caretBase->caretIsVisible()); | 1146 DCHECK(caretIsVisible()); |
| 1101 DCHECK(isCaret()); | |
| 1102 if (isCaretBlinkingSuspended() && m_shouldPaintCaret) | 1147 if (isCaretBlinkingSuspended() && m_shouldPaintCaret) |
| 1103 return; | 1148 return; |
| 1104 m_shouldPaintCaret = !m_shouldPaintCaret; | 1149 m_shouldPaintCaret = !m_shouldPaintCaret; |
| 1105 setCaretRectNeedsUpdate(); | 1150 setCaretRectNeedsUpdate(); |
| 1106 } | 1151 } |
| 1107 | 1152 |
| 1108 void FrameSelection::stopCaretBlinkTimer() | 1153 // TODO(yoiciho): We should move this function to FrameCaret.cpp |
| 1154 void FrameCaret::stopCaretBlinkTimer() | |
| 1109 { | 1155 { |
| 1110 if (m_caretBlinkTimer.isActive() || m_shouldPaintCaret) | 1156 if (m_caretBlinkTimer.isActive() || m_shouldPaintCaret) |
| 1111 setCaretRectNeedsUpdate(); | 1157 setCaretRectNeedsUpdate(); |
| 1112 m_shouldPaintCaret = false; | 1158 m_shouldPaintCaret = false; |
| 1113 m_caretBlinkTimer.stop(); | 1159 m_caretBlinkTimer.stop(); |
| 1114 } | 1160 } |
| 1115 | 1161 |
| 1116 void FrameSelection::notifyLayoutObjectOfSelectionChange(EUserTriggered userTrig gered) | 1162 void FrameSelection::notifyLayoutObjectOfSelectionChange(EUserTriggered userTrig gered) |
| 1117 { | 1163 { |
| 1118 if (HTMLTextFormControlElement* textControl = enclosingTextFormControl(start ())) | 1164 if (HTMLTextFormControlElement* textControl = enclosingTextFormControl(start ())) |
| (...skipping 230 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1349 | 1395 |
| 1350 #endif | 1396 #endif |
| 1351 | 1397 |
| 1352 DEFINE_TRACE(FrameSelection) | 1398 DEFINE_TRACE(FrameSelection) |
| 1353 { | 1399 { |
| 1354 visitor->trace(m_frame); | 1400 visitor->trace(m_frame); |
| 1355 visitor->trace(m_pendingSelection); | 1401 visitor->trace(m_pendingSelection); |
| 1356 visitor->trace(m_selectionEditor); | 1402 visitor->trace(m_selectionEditor); |
| 1357 visitor->trace(m_originalBase); | 1403 visitor->trace(m_originalBase); |
| 1358 visitor->trace(m_originalBaseInFlatTree); | 1404 visitor->trace(m_originalBaseInFlatTree); |
| 1359 visitor->trace(m_previousCaretNode); | |
| 1360 visitor->trace(m_typingStyle); | 1405 visitor->trace(m_typingStyle); |
| 1406 visitor->trace(m_frameCaret); | |
| 1361 } | 1407 } |
| 1362 | 1408 |
| 1363 void FrameSelection::setCaretRectNeedsUpdate() | 1409 // TODO(yoiciho): We should move this function to FrameCaret.cpp |
| 1410 void FrameCaret::setCaretRectNeedsUpdate() | |
| 1364 { | 1411 { |
| 1365 if (m_caretRectDirty) | 1412 if (m_caretRectDirty) |
| 1366 return; | 1413 return; |
| 1367 m_caretRectDirty = true; | 1414 m_caretRectDirty = true; |
| 1368 | 1415 |
| 1369 scheduleVisualUpdate(); | 1416 if (!m_frame) |
|
yosin_UTC9
2016/05/20 07:53:13
Since |m_frame| can't be null, we don't need to ch
yoichio
2016/05/20 08:58:09
Done.
| |
| 1417 return; | |
| 1418 if (Page* page = m_frame->page()) | |
| 1419 page->animator().scheduleVisualUpdate(m_frame->localFrameRoot()); | |
| 1370 } | 1420 } |
| 1371 | 1421 |
| 1372 void FrameSelection::scheduleVisualUpdate() const | 1422 void FrameSelection::scheduleVisualUpdate() const |
| 1373 { | 1423 { |
| 1374 if (!m_frame) | 1424 if (!m_frame) |
| 1375 return; | 1425 return; |
| 1376 if (Page* page = m_frame->page()) | 1426 if (Page* page = m_frame->page()) |
| 1377 page->animator().scheduleVisualUpdate(m_frame->localFrameRoot()); | 1427 page->animator().scheduleVisualUpdate(m_frame->localFrameRoot()); |
| 1378 } | 1428 } |
| 1379 | 1429 |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1440 void FrameSelection::updateIfNeeded() | 1490 void FrameSelection::updateIfNeeded() |
| 1441 { | 1491 { |
| 1442 m_selectionEditor->updateIfNeeded(); | 1492 m_selectionEditor->updateIfNeeded(); |
| 1443 } | 1493 } |
| 1444 | 1494 |
| 1445 void FrameSelection::setCaretVisible(bool caretIsVisible) | 1495 void FrameSelection::setCaretVisible(bool caretIsVisible) |
| 1446 { | 1496 { |
| 1447 setCaretVisibility(caretIsVisible ? CaretVisibility::Visible : CaretVisibili ty::Hidden); | 1497 setCaretVisibility(caretIsVisible ? CaretVisibility::Visible : CaretVisibili ty::Hidden); |
| 1448 } | 1498 } |
| 1449 | 1499 |
| 1500 bool FrameSelection::shouldPaintCaretForTesting() const | |
| 1501 { | |
| 1502 return m_frameCaret->shouldPaintCaretForTesting(); | |
| 1503 } | |
| 1504 | |
| 1505 bool FrameSelection::isPreviousCaretDirtyForTesting() const | |
| 1506 { | |
| 1507 return m_frameCaret->isPreviousCaretDirtyForTesting(); | |
| 1508 } | |
| 1509 | |
| 1510 bool FrameSelection::isCaretBoundsDirty() const | |
| 1511 { | |
| 1512 return m_frameCaret->isCaretBoundsDirty(); | |
| 1513 } | |
| 1514 | |
| 1515 void FrameSelection::setCaretRectNeedsUpdate() | |
| 1516 { | |
| 1517 m_frameCaret->setCaretRectNeedsUpdate(); | |
| 1518 } | |
| 1519 | |
| 1520 void FrameSelection::setCaretBlinkingSuspended(bool suspended) | |
| 1521 { | |
| 1522 m_frameCaret->setCaretBlinkingSuspended(suspended); | |
| 1523 } | |
| 1524 | |
| 1525 bool FrameSelection::isCaretBlinkingSuspended() const | |
| 1526 { | |
| 1527 return m_frameCaret->isCaretBlinkingSuspended(); | |
| 1528 } | |
| 1529 | |
| 1450 } // namespace blink | 1530 } // namespace blink |
| 1451 | 1531 |
| 1452 #ifndef NDEBUG | 1532 #ifndef NDEBUG |
| 1453 | 1533 |
| 1454 void showTree(const blink::FrameSelection& sel) | 1534 void showTree(const blink::FrameSelection& sel) |
| 1455 { | 1535 { |
| 1456 sel.showTreeForThis(); | 1536 sel.showTreeForThis(); |
| 1457 } | 1537 } |
| 1458 | 1538 |
| 1459 void showTree(const blink::FrameSelection* sel) | 1539 void showTree(const blink::FrameSelection* sel) |
| 1460 { | 1540 { |
| 1461 if (sel) | 1541 if (sel) |
| 1462 sel->showTreeForThis(); | 1542 sel->showTreeForThis(); |
| 1463 else | 1543 else |
| 1464 fprintf(stderr, "Cannot showTree for (nil) FrameSelection.\n"); | 1544 fprintf(stderr, "Cannot showTree for (nil) FrameSelection.\n"); |
| 1465 } | 1545 } |
| 1466 | 1546 |
| 1467 #endif | 1547 #endif |
| OLD | NEW |