diff options
| author | Konstantin Tokarev <annulen@yandex.ru> | 2016-08-25 19:20:41 +0300 |
|---|---|---|
| committer | Konstantin Tokarev <annulen@yandex.ru> | 2017-02-02 12:30:55 +0000 |
| commit | 6882a04fb36642862b11efe514251d32070c3d65 (patch) | |
| tree | b7959826000b061fd5ccc7512035c7478742f7b0 /Source/WebCore/editing/AlternativeTextController.cpp | |
| parent | ab6df191029eeeb0b0f16f127d553265659f739e (diff) | |
| download | qtwebkit-6882a04fb36642862b11efe514251d32070c3d65.tar.gz | |
Imported QtWebKit TP3 (git b57bc6801f1876c3220d5a4bfea33d620d477443)
Change-Id: I3b1d8a2808782c9f34d50240000e20cb38d3680f
Reviewed-by: Konstantin Tokarev <annulen@yandex.ru>
Diffstat (limited to 'Source/WebCore/editing/AlternativeTextController.cpp')
| -rw-r--r-- | Source/WebCore/editing/AlternativeTextController.cpp | 257 |
1 files changed, 120 insertions, 137 deletions
diff --git a/Source/WebCore/editing/AlternativeTextController.cpp b/Source/WebCore/editing/AlternativeTextController.cpp index 9eeee2d05..73102571a 100644 --- a/Source/WebCore/editing/AlternativeTextController.cpp +++ b/Source/WebCore/editing/AlternativeTextController.cpp @@ -11,10 +11,10 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR @@ -27,38 +27,34 @@ #include "config.h" #include "AlternativeTextController.h" -#include "DictationAlternative.h" #include "Document.h" #include "DocumentMarkerController.h" -#include "EditCommand.h" #include "Editor.h" -#include "EditorClient.h" +#include "Element.h" #include "Event.h" #include "ExceptionCodePlaceholder.h" #include "FloatQuad.h" #include "Frame.h" #include "FrameView.h" #include "Page.h" +#include "RenderedDocumentMarker.h" #include "SpellingCorrectionCommand.h" #include "TextCheckerClient.h" #include "TextCheckingHelper.h" #include "TextEvent.h" #include "TextIterator.h" -#include "VisibleSelection.h" #include "VisibleUnits.h" #include "htmlediting.h" #include "markup.h" +#include <wtf/NeverDestroyed.h> namespace WebCore { -using namespace std; -using namespace WTF; - class AutocorrectionAlternativeDetails : public AlternativeTextDetails { public: - static PassRefPtr<AutocorrectionAlternativeDetails> create(const String& replacementString) + static Ref<AutocorrectionAlternativeDetails> create(const String& replacementString) { - return adoptRef(new AutocorrectionAlternativeDetails(replacementString)); + return adoptRef(*new AutocorrectionAlternativeDetails(replacementString)); } const String& replacementString() const { return m_replacementString; } @@ -72,9 +68,9 @@ private: class DictationAlternativeDetails : public AlternativeTextDetails { public: - static PassRefPtr<DictationAlternativeDetails> create(uint64_t dictationContext) + static Ref<DictationAlternativeDetails> create(uint64_t dictationContext) { - return adoptRef(new DictationAlternativeDetails(dictationContext)); + return adoptRef(*new DictationAlternativeDetails(dictationContext)); } uint64_t dictationContext() const { return m_dictationContext; } @@ -91,35 +87,35 @@ private: static const Vector<DocumentMarker::MarkerType>& markerTypesForAutocorrection() { - DEFINE_STATIC_LOCAL(Vector<DocumentMarker::MarkerType>, markerTypesForAutoCorrection, ()); - if (markerTypesForAutoCorrection.isEmpty()) { - markerTypesForAutoCorrection.append(DocumentMarker::Replacement); - markerTypesForAutoCorrection.append(DocumentMarker::CorrectionIndicator); - markerTypesForAutoCorrection.append(DocumentMarker::SpellCheckingExemption); - markerTypesForAutoCorrection.append(DocumentMarker::Autocorrected); + static NeverDestroyed<Vector<DocumentMarker::MarkerType>> markerTypesForAutoCorrection; + if (markerTypesForAutoCorrection.get().isEmpty()) { + markerTypesForAutoCorrection.get().append(DocumentMarker::Replacement); + markerTypesForAutoCorrection.get().append(DocumentMarker::CorrectionIndicator); + markerTypesForAutoCorrection.get().append(DocumentMarker::SpellCheckingExemption); + markerTypesForAutoCorrection.get().append(DocumentMarker::Autocorrected); } return markerTypesForAutoCorrection; } static const Vector<DocumentMarker::MarkerType>& markerTypesForReplacement() { - DEFINE_STATIC_LOCAL(Vector<DocumentMarker::MarkerType>, markerTypesForReplacement, ()); - if (markerTypesForReplacement.isEmpty()) { - markerTypesForReplacement.append(DocumentMarker::Replacement); - markerTypesForReplacement.append(DocumentMarker::SpellCheckingExemption); + static NeverDestroyed<Vector<DocumentMarker::MarkerType>> markerTypesForReplacement; + if (markerTypesForReplacement.get().isEmpty()) { + markerTypesForReplacement.get().append(DocumentMarker::Replacement); + markerTypesForReplacement.get().append(DocumentMarker::SpellCheckingExemption); } return markerTypesForReplacement; } static const Vector<DocumentMarker::MarkerType>& markerTypesForAppliedDictationAlternative() { - DEFINE_STATIC_LOCAL(Vector<DocumentMarker::MarkerType>, markerTypesForAppliedDictationAlternative, ()); - if (markerTypesForAppliedDictationAlternative.isEmpty()) - markerTypesForAppliedDictationAlternative.append(DocumentMarker::SpellCheckingExemption); + static NeverDestroyed<Vector<DocumentMarker::MarkerType>> markerTypesForAppliedDictationAlternative; + if (markerTypesForAppliedDictationAlternative.get().isEmpty()) + markerTypesForAppliedDictationAlternative.get().append(DocumentMarker::SpellCheckingExemption); return markerTypesForAppliedDictationAlternative; } -static bool markersHaveIdenticalDescription(const Vector<DocumentMarker*>& markers) +static bool markersHaveIdenticalDescription(const Vector<RenderedDocumentMarker*>& markers) { if (markers.isEmpty()) return true; @@ -132,8 +128,8 @@ static bool markersHaveIdenticalDescription(const Vector<DocumentMarker*>& marke return true; } -AlternativeTextController::AlternativeTextController(Frame* frame) - : m_timer(this, &AlternativeTextController::timerFired) +AlternativeTextController::AlternativeTextController(Frame& frame) + : m_timer(*this, &AlternativeTextController::timerFired) , m_frame(frame) { } @@ -151,7 +147,7 @@ void AlternativeTextController::startAlternativeTextUITimer(AlternativeTextType // If type is PanelTypeReversion, then the new range has been set. So we shouldn't clear it. if (type == AlternativeTextTypeCorrection) - m_alternativeTextInfo.rangeWithAlternative.clear(); + m_alternativeTextInfo.rangeWithAlternative = nullptr; m_alternativeTextInfo.type = type; m_timer.startOneShot(correctionPanelTimerInterval); } @@ -159,13 +155,13 @@ void AlternativeTextController::startAlternativeTextUITimer(AlternativeTextType void AlternativeTextController::stopAlternativeTextUITimer() { m_timer.stop(); - m_alternativeTextInfo.rangeWithAlternative.clear(); + m_alternativeTextInfo.rangeWithAlternative = nullptr; } void AlternativeTextController::stopPendingCorrection(const VisibleSelection& oldSelection) { // Make sure there's no pending autocorrection before we call markMisspellingsAndBadGrammar() below. - VisibleSelection currentSelection(m_frame->selection()->selection()); + VisibleSelection currentSelection(m_frame.selection().selection()); if (currentSelection == oldSelection) return; @@ -187,7 +183,7 @@ void AlternativeTextController::applyPendingCorrection(const VisibleSelection& s if (doApplyCorrection) handleAlternativeTextUIResult(dismissSoon(ReasonForDismissingAlternativeTextAccepted)); else - m_alternativeTextInfo.rangeWithAlternative.clear(); + m_alternativeTextInfo.rangeWithAlternative = nullptr; } bool AlternativeTextController::hasPendingCorrection() const @@ -197,7 +193,7 @@ bool AlternativeTextController::hasPendingCorrection() const bool AlternativeTextController::isSpellingMarkerAllowed(PassRefPtr<Range> misspellingRange) const { - return !m_frame->document()->markers()->hasMarkers(misspellingRange.get(), DocumentMarker::SpellCheckingExemption); + return !m_frame.document()->markers().hasMarkers(misspellingRange.get(), DocumentMarker::SpellCheckingExemption); } void AlternativeTextController::show(PassRefPtr<Range> rangeToReplace, const String& replacement) @@ -247,10 +243,7 @@ void AlternativeTextController::applyAlternativeTextToRange(const Range* range, if (!range) return; - ExceptionCode ec = 0; - RefPtr<Range> paragraphRangeContainingCorrection = range->cloneRange(ec); - if (ec) - return; + RefPtr<Range> paragraphRangeContainingCorrection = range->cloneRange(); setStart(paragraphRangeContainingCorrection.get(), startOfParagraph(range->startPosition())); setEnd(paragraphRangeContainingCorrection.get(), endOfParagraph(range->endPosition())); @@ -261,12 +254,11 @@ void AlternativeTextController::applyAlternativeTextToRange(const Range* range, // relative to the start position of the containing paragraph. We use correctionStartOffsetInParagraph // to store this value. In order to obtain this offset, we need to first create a range // which spans from the start of paragraph to the start position of rangeWithAlternative. - RefPtr<Range> correctionStartOffsetInParagraphAsRange = Range::create(paragraphRangeContainingCorrection->startContainer(ec)->document(), paragraphRangeContainingCorrection->startPosition(), paragraphRangeContainingCorrection->startPosition()); - if (ec) - return; + RefPtr<Range> correctionStartOffsetInParagraphAsRange = Range::create(paragraphRangeContainingCorrection->startContainer().document(), paragraphRangeContainingCorrection->startPosition(), paragraphRangeContainingCorrection->startPosition()); - Position startPositionOfrangeWithAlternative = range->startPosition(); - correctionStartOffsetInParagraphAsRange->setEnd(startPositionOfrangeWithAlternative.containerNode(), startPositionOfrangeWithAlternative.computeOffsetInContainerNode(), ec); + Position startPositionOfRangeWithAlternative = range->startPosition(); + ExceptionCode ec = 0; + correctionStartOffsetInParagraphAsRange->setEnd(startPositionOfRangeWithAlternative.containerNode(), startPositionOfRangeWithAlternative.computeOffsetInContainerNode(), ec); if (ec) return; @@ -274,14 +266,17 @@ void AlternativeTextController::applyAlternativeTextToRange(const Range* range, int correctionStartOffsetInParagraph = TextIterator::rangeLength(correctionStartOffsetInParagraphAsRange.get()); // Clone the range, since the caller of this method may want to keep the original range around. - RefPtr<Range> rangeWithAlternative = range->cloneRange(ec); - - int paragraphStartIndex = TextIterator::rangeLength(Range::create(m_frame->document(), m_frame->document(), 0, paragraphRangeContainingCorrection.get()->startContainer(), paragraphRangeContainingCorrection.get()->startOffset()).get()); - applyCommand(SpellingCorrectionCommand::create(rangeWithAlternative, alternative)); + Ref<Range> rangeWithAlternative = range->cloneRange(); + + ContainerNode& rootNode = paragraphRangeContainingCorrection.get()->startContainer().treeScope().rootNode(); + int paragraphStartIndex = TextIterator::rangeLength(Range::create(rootNode.document(), &rootNode, 0, ¶graphRangeContainingCorrection->startContainer(), paragraphRangeContainingCorrection->startOffset()).ptr()); + applyCommand(SpellingCorrectionCommand::create(rangeWithAlternative.ptr(), alternative)); // Recalculate pragraphRangeContainingCorrection, since SpellingCorrectionCommand modified the DOM, such that the original paragraphRangeContainingCorrection is no longer valid. Radar: 10305315 Bugzilla: 89526 - paragraphRangeContainingCorrection = TextIterator::rangeFromLocationAndLength(m_frame->document(), paragraphStartIndex, correctionStartOffsetInParagraph + alternative.length()); + paragraphRangeContainingCorrection = TextIterator::rangeFromLocationAndLength(&rootNode, paragraphStartIndex, correctionStartOffsetInParagraph + alternative.length()); + if (!paragraphRangeContainingCorrection) + return; - setEnd(paragraphRangeContainingCorrection.get(), m_frame->selection()->selection().start()); + setEnd(paragraphRangeContainingCorrection.get(), m_frame.selection().selection().start()); RefPtr<Range> replacementRange = TextIterator::subrange(paragraphRangeContainingCorrection.get(), correctionStartOffsetInParagraph, alternative.length()); String newText = plainText(replacementRange.get()); @@ -289,10 +284,10 @@ void AlternativeTextController::applyAlternativeTextToRange(const Range* range, if (newText != alternative) return; - DocumentMarkerController* markers = replacementRange->startContainer()->document()->markers(); - size_t size = markerTypesToAdd.size(); - for (size_t i = 0; i < size; ++i) - markers->addMarker(replacementRange.get(), markerTypesToAdd[i], markerDescriptionForAppliedAlternativeText(alternativeType, markerTypesToAdd[i])); + DocumentMarkerController& markers = replacementRange->startContainer().document().markers(); + + for (auto& markerType : markerTypesToAdd) + markers.addMarker(replacementRange.get(), markerType, markerDescriptionForAppliedAlternativeText(alternativeType, markerType)); } bool AlternativeTextController::applyAutocorrectionBeforeTypingIfAppropriate() @@ -303,7 +298,7 @@ bool AlternativeTextController::applyAutocorrectionBeforeTypingIfAppropriate() if (m_alternativeTextInfo.type != AlternativeTextTypeCorrection) return false; - Position caretPosition = m_frame->selection()->selection().start(); + Position caretPosition = m_frame.selection().selection().start(); if (m_alternativeTextInfo.rangeWithAlternative->endPosition() == caretPosition) { handleAlternativeTextUIResult(dismissSoon(ReasonForDismissingAlternativeTextAccepted)); @@ -320,26 +315,26 @@ void AlternativeTextController::respondToUnappliedSpellCorrection(const VisibleS { if (AlternativeTextClient* client = alternativeTextClient()) client->recordAutocorrectionResponse(AutocorrectionReverted, corrected, correction); - m_frame->document()->updateLayout(); - m_frame->selection()->setSelection(selectionOfCorrected, FrameSelection::CloseTyping | FrameSelection::ClearTypingStyle | FrameSelection::SpellCorrectionTriggered); - RefPtr<Range> range = Range::create(m_frame->document(), m_frame->selection()->selection().start(), m_frame->selection()->selection().end()); + m_frame.document()->updateLayout(); + m_frame.selection().setSelection(selectionOfCorrected, FrameSelection::defaultSetSelectionOptions() | FrameSelection::SpellCorrectionTriggered); + RefPtr<Range> range = Range::create(*m_frame.document(), m_frame.selection().selection().start(), m_frame.selection().selection().end()); - DocumentMarkerController* markers = m_frame->document()->markers(); - markers->removeMarkers(range.get(), DocumentMarker::Spelling | DocumentMarker::Autocorrected, DocumentMarkerController::RemovePartiallyOverlappingMarker); - markers->addMarker(range.get(), DocumentMarker::Replacement); - markers->addMarker(range.get(), DocumentMarker::SpellCheckingExemption); + DocumentMarkerController& markers = m_frame.document()->markers(); + markers.removeMarkers(range.get(), DocumentMarker::Spelling | DocumentMarker::Autocorrected, DocumentMarkerController::RemovePartiallyOverlappingMarker); + markers.addMarker(range.get(), DocumentMarker::Replacement); + markers.addMarker(range.get(), DocumentMarker::SpellCheckingExemption); } -void AlternativeTextController::timerFired(Timer<AlternativeTextController>*) +void AlternativeTextController::timerFired() { m_isDismissedByEditing = false; switch (m_alternativeTextInfo.type) { case AlternativeTextTypeCorrection: { - VisibleSelection selection(m_frame->selection()->selection()); + VisibleSelection selection(m_frame.selection().selection()); VisiblePosition start(selection.start(), selection.affinity()); VisiblePosition p = startOfWord(start, LeftWordIfOnBoundary); VisibleSelection adjacentWords = VisibleSelection(p, start); - m_frame->editor().markAllMisspellingsAndBadGrammarInRanges(TextCheckingTypeSpelling | TextCheckingTypeReplacement | TextCheckingTypeShowCorrectionPanel, adjacentWords.toNormalizedRange().get(), 0); + m_frame.editor().markAllMisspellingsAndBadGrammarInRanges(TextCheckingTypeSpelling | TextCheckingTypeReplacement | TextCheckingTypeShowCorrectionPanel, adjacentWords.toNormalizedRange().get(), 0); } break; case AlternativeTextTypeReversion: { @@ -362,7 +357,7 @@ void AlternativeTextController::timerFired(Timer<AlternativeTextController>*) Vector<String> suggestions; textChecker()->getGuessesForWord(m_alternativeTextInfo.originalText, paragraphText, suggestions); if (suggestions.isEmpty()) { - m_alternativeTextInfo.rangeWithAlternative.clear(); + m_alternativeTextInfo.rangeWithAlternative = nullptr; break; } String topSuggestion = suggestions.first(); @@ -397,7 +392,7 @@ void AlternativeTextController::timerFired(Timer<AlternativeTextController>*) void AlternativeTextController::handleAlternativeTextUIResult(const String& result) { Range* rangeWithAlternative = m_alternativeTextInfo.rangeWithAlternative.get(); - if (!rangeWithAlternative || m_frame->document() != rangeWithAlternative->ownerDocument()) + if (!rangeWithAlternative || m_frame.document() != &rangeWithAlternative->ownerDocument()) return; String currentWord = plainText(rangeWithAlternative); @@ -412,7 +407,7 @@ void AlternativeTextController::handleAlternativeTextUIResult(const String& resu if (result.length()) applyAlternativeTextToRange(rangeWithAlternative, result, m_alternativeTextInfo.type, markerTypesForAutocorrection()); else if (!m_isDismissedByEditing) - rangeWithAlternative->startContainer()->document()->markers()->addMarker(rangeWithAlternative, DocumentMarker::RejectedCorrection, m_alternativeTextInfo.originalText); + rangeWithAlternative->startContainer().document().markers().addMarker(rangeWithAlternative, DocumentMarker::RejectedCorrection, m_alternativeTextInfo.originalText); break; case AlternativeTextTypeReversion: case AlternativeTextTypeSpellingSuggestions: @@ -425,7 +420,7 @@ void AlternativeTextController::handleAlternativeTextUIResult(const String& resu break; } - m_alternativeTextInfo.rangeWithAlternative.clear(); + m_alternativeTextInfo.rangeWithAlternative = nullptr; } bool AlternativeTextController::isAutomaticSpellingCorrectionEnabled() @@ -435,21 +430,20 @@ bool AlternativeTextController::isAutomaticSpellingCorrectionEnabled() FloatRect AlternativeTextController::rootViewRectForRange(const Range* range) const { - FrameView* view = m_frame->view(); + FrameView* view = m_frame.view(); if (!view) return FloatRect(); Vector<FloatQuad> textQuads; - range->textQuads(textQuads); + range->absoluteTextQuads(textQuads); FloatRect boundingRect; - size_t size = textQuads.size(); - for (size_t i = 0; i < size; ++i) - boundingRect.unite(textQuads[i].boundingBox()); + for (auto& textQuad : textQuads) + boundingRect.unite(textQuad.boundingBox()); return view->contentsToRootView(IntRect(boundingRect)); } -void AlternativeTextController::respondToChangedSelection(const VisibleSelection& oldSelection, FrameSelection::SetSelectionOptions options) +void AlternativeTextController::respondToChangedSelection(const VisibleSelection& oldSelection) { - VisibleSelection currentSelection(m_frame->selection()->selection()); + VisibleSelection currentSelection(m_frame.selection().selection()); // When user moves caret to the end of autocorrected word and pauses, we show the panel // containing the original pre-correction word so that user can quickly revert the // undesired autocorrection. Here, we start correction panel timer once we confirm that @@ -473,14 +467,9 @@ void AlternativeTextController::respondToChangedSelection(const VisibleSelection return; Node* node = position.containerNode(); - Vector<DocumentMarker*> markers = node->document()->markers()->markersFor(node); - size_t markerCount = markers.size(); - for (size_t i = 0; i < markerCount; ++i) { - const DocumentMarker* marker = markers[i]; - if (!marker) - continue; - - if (respondToMarkerAtEndOfWord(*marker, position, options)) + for (auto* marker : node->document().markers().markersFor(node)) { + ASSERT(marker); + if (respondToMarkerAtEndOfWord(*marker, position)) break; } } @@ -488,45 +477,41 @@ void AlternativeTextController::respondToChangedSelection(const VisibleSelection void AlternativeTextController::respondToAppliedEditing(CompositeEditCommand* command) { if (command->isTopLevelCommand() && !command->shouldRetainAutocorrectionIndicator()) - m_frame->document()->markers()->removeMarkers(DocumentMarker::CorrectionIndicator); + m_frame.document()->markers().removeMarkers(DocumentMarker::CorrectionIndicator); markPrecedingWhitespaceForDeletedAutocorrectionAfterCommand(command); m_originalStringForLastDeletedAutocorrection = String(); + + dismiss(ReasonForDismissingAlternativeTextIgnored); } void AlternativeTextController::respondToUnappliedEditing(EditCommandComposition* command) { if (!command->wasCreateLinkCommand()) return; - RefPtr<Range> range = Range::create(m_frame->document(), command->startingSelection().start(), command->startingSelection().end()); + RefPtr<Range> range = Range::create(*m_frame.document(), command->startingSelection().start(), command->startingSelection().end()); if (!range) return; - DocumentMarkerController* markers = m_frame->document()->markers(); - markers->addMarker(range.get(), DocumentMarker::Replacement); - markers->addMarker(range.get(), DocumentMarker::SpellCheckingExemption); + DocumentMarkerController& markers = m_frame.document()->markers(); + markers.addMarker(range.get(), DocumentMarker::Replacement); + markers.addMarker(range.get(), DocumentMarker::SpellCheckingExemption); } AlternativeTextClient* AlternativeTextController::alternativeTextClient() { - if (!m_frame) - return 0; - - return m_frame->page() ? m_frame->page()->alternativeTextClient() : 0; + return m_frame.page() ? m_frame.page()->alternativeTextClient() : 0; } EditorClient* AlternativeTextController::editorClient() { - if (!m_frame) - return 0; - - return m_frame->page() ? m_frame->page()->editorClient() : 0; + return m_frame.page() ? &m_frame.page()->editorClient() : nullptr; } TextCheckerClient* AlternativeTextController::textChecker() { if (EditorClient* owner = editorClient()) return owner->textChecker(); - return 0; + return nullptr; } void AlternativeTextController::recordAutocorrectionResponseReversed(const String& replacedString, const String& replacementString) @@ -542,20 +527,18 @@ void AlternativeTextController::recordAutocorrectionResponseReversed(const Strin void AlternativeTextController::markReversed(PassRefPtr<Range> changedRange) { - changedRange->startContainer()->document()->markers()->removeMarkers(changedRange.get(), DocumentMarker::Autocorrected, DocumentMarkerController::RemovePartiallyOverlappingMarker); - changedRange->startContainer()->document()->markers()->addMarker(changedRange.get(), DocumentMarker::SpellCheckingExemption); + changedRange->startContainer().document().markers().removeMarkers(changedRange.get(), DocumentMarker::Autocorrected, DocumentMarkerController::RemovePartiallyOverlappingMarker); + changedRange->startContainer().document().markers().addMarker(changedRange.get(), DocumentMarker::SpellCheckingExemption); } void AlternativeTextController::markCorrection(PassRefPtr<Range> replacedRange, const String& replacedString) { - Vector<DocumentMarker::MarkerType> markerTypesToAdd = markerTypesForAutocorrection(); - DocumentMarkerController* markers = replacedRange->startContainer()->document()->markers(); - for (size_t i = 0; i < markerTypesToAdd.size(); ++i) { - DocumentMarker::MarkerType markerType = markerTypesToAdd[i]; + DocumentMarkerController& markers = replacedRange->startContainer().document().markers(); + for (auto& markerType : markerTypesForAutocorrection()) { if (markerType == DocumentMarker::Replacement || markerType == DocumentMarker::Autocorrected) - markers->addMarker(replacedRange.get(), markerType, replacedString); + markers.addMarker(replacedRange.get(), markerType, replacedString); else - markers->addMarker(replacedRange.get(), markerType); + markers.addMarker(replacedRange.get(), markerType); } } @@ -563,8 +546,8 @@ void AlternativeTextController::recordSpellcheckerResponseForModifiedCorrection( { if (!rangeOfCorrection) return; - DocumentMarkerController* markers = rangeOfCorrection->startContainer()->document()->markers(); - Vector<DocumentMarker*> correctedOnceMarkers = markers->markersInRange(rangeOfCorrection, DocumentMarker::Autocorrected); + DocumentMarkerController& markers = rangeOfCorrection->startContainer().document().markers(); + Vector<RenderedDocumentMarker*> correctedOnceMarkers = markers.markersInRange(rangeOfCorrection, DocumentMarker::Autocorrected); if (correctedOnceMarkers.isEmpty()) return; @@ -577,7 +560,7 @@ void AlternativeTextController::recordSpellcheckerResponseForModifiedCorrection( client->recordAutocorrectionResponse(AutocorrectionEdited, corrected, correction); } - markers->removeMarkers(rangeOfCorrection, DocumentMarker::Autocorrected, DocumentMarkerController::RemovePartiallyOverlappingMarker); + markers.removeMarkers(rangeOfCorrection, DocumentMarker::Autocorrected, DocumentMarkerController::RemovePartiallyOverlappingMarker); } void AlternativeTextController::deletedAutocorrectionAtPosition(const Position& position, const String& originalString) @@ -596,7 +579,7 @@ void AlternativeTextController::markPrecedingWhitespaceForDeletedAutocorrectionA if (endOfSelection == precedingCharacterPosition) return; - RefPtr<Range> precedingCharacterRange = Range::create(m_frame->document(), precedingCharacterPosition, endOfSelection); + RefPtr<Range> precedingCharacterRange = Range::create(*m_frame.document(), precedingCharacterPosition, endOfSelection); String string = plainText(precedingCharacterRange.get()); if (string.isEmpty() || !isWhitespace(string[string.length() - 1])) return; @@ -604,29 +587,31 @@ void AlternativeTextController::markPrecedingWhitespaceForDeletedAutocorrectionA // Mark this whitespace to indicate we have deleted an autocorrection following this // whitespace. So if the user types the same original word again at this position, we // won't autocorrect it again. - m_frame->document()->markers()->addMarker(precedingCharacterRange.get(), DocumentMarker::DeletedAutocorrection, m_originalStringForLastDeletedAutocorrection); + m_frame.document()->markers().addMarker(precedingCharacterRange.get(), DocumentMarker::DeletedAutocorrection, m_originalStringForLastDeletedAutocorrection); } bool AlternativeTextController::processMarkersOnTextToBeReplacedByResult(const TextCheckingResult* result, Range* rangeWithAlternative, const String& stringToBeReplaced) { - DocumentMarkerController* markerController = m_frame->document()->markers(); - if (markerController->hasMarkers(rangeWithAlternative, DocumentMarker::Replacement)) { + DocumentMarkerController& markerController = m_frame.document()->markers(); + if (markerController.hasMarkers(rangeWithAlternative, DocumentMarker::Replacement)) { if (result->type == TextCheckingTypeCorrection) recordSpellcheckerResponseForModifiedCorrection(rangeWithAlternative, stringToBeReplaced, result->replacement); return false; } - if (markerController->hasMarkers(rangeWithAlternative, DocumentMarker::RejectedCorrection)) + if (markerController.hasMarkers(rangeWithAlternative, DocumentMarker::RejectedCorrection)) + return false; + + if (markerController.hasMarkers(rangeWithAlternative, DocumentMarker::AcceptedCandidate)) return false; Position beginningOfRange = rangeWithAlternative->startPosition(); Position precedingCharacterPosition = beginningOfRange.previous(); - RefPtr<Range> precedingCharacterRange = Range::create(m_frame->document(), precedingCharacterPosition, beginningOfRange); + RefPtr<Range> precedingCharacterRange = Range::create(*m_frame.document(), precedingCharacterPosition, beginningOfRange); - Vector<DocumentMarker*> markers = markerController->markersInRange(precedingCharacterRange.get(), DocumentMarker::DeletedAutocorrection); - - for (size_t i = 0; i < markers.size(); ++i) { - if (markers[i]->description() == stringToBeReplaced) + Vector<RenderedDocumentMarker*> markers = markerController.markersInRange(precedingCharacterRange.get(), DocumentMarker::DeletedAutocorrection); + for (const auto* marker : markers) { + if (marker->description() == stringToBeReplaced) return false; } @@ -638,14 +623,12 @@ bool AlternativeTextController::shouldStartTimerFor(const WebCore::DocumentMarke return (((marker.type() == DocumentMarker::Replacement && !marker.description().isNull()) || marker.type() == DocumentMarker::Spelling || marker.type() == DocumentMarker::DictationAlternatives) && static_cast<int>(marker.endOffset()) == endOffset); } -bool AlternativeTextController::respondToMarkerAtEndOfWord(const DocumentMarker& marker, const Position& endOfWordPosition, FrameSelection::SetSelectionOptions options) +bool AlternativeTextController::respondToMarkerAtEndOfWord(const DocumentMarker& marker, const Position& endOfWordPosition) { - if (options & FrameSelection::DictationTriggered) - return false; if (!shouldStartTimerFor(marker, endOfWordPosition.offsetInContainerNode())) return false; Node* node = endOfWordPosition.containerNode(); - RefPtr<Range> wordRange = Range::create(m_frame->document(), node, marker.startOffset(), node, marker.endOffset()); + RefPtr<Range> wordRange = Range::create(*m_frame.document(), node, marker.startOffset(), node, marker.endOffset()); if (!wordRange) return false; String currentWord = plainText(wordRange.get()); @@ -693,32 +676,32 @@ String AlternativeTextController::markerDescriptionForAppliedAlternativeText(Alt bool AlternativeTextController::insertDictatedText(const String& text, const Vector<DictationAlternative>& dictationAlternatives, Event* triggeringEvent) { - if (!m_frame) - return false; EventTarget* target; if (triggeringEvent) target = triggeringEvent->target(); else - target = eventTargetNodeForDocument(m_frame->document()); + target = eventTargetElementForDocument(m_frame.document()); if (!target) return false; - if (FrameView* view = m_frame->view()) - view->resetDeferredRepaintDelay(); + if (FrameView* view = m_frame.view()) + view->disableLayerFlushThrottlingTemporarilyForInteraction(); - RefPtr<TextEvent> event = TextEvent::createForDictation(m_frame->document()->domWindow(), text, dictationAlternatives); + Ref<TextEvent> event = TextEvent::createForDictation(m_frame.document()->domWindow(), text, dictationAlternatives); event->setUnderlyingEvent(triggeringEvent); - target->dispatchEvent(event, IGNORE_EXCEPTION); + target->dispatchEvent(event); return event->defaultHandled(); } void AlternativeTextController::removeDictationAlternativesForMarker(const DocumentMarker* marker) { #if USE(DICTATION_ALTERNATIVES) - DictationMarkerDetails* details = static_cast<DictationMarkerDetails*>(marker->details()); - if (AlternativeTextClient* client = alternativeTextClient()) - client->removeDictationAlternatives(details->dictationContext()); + ASSERT(marker->details()); + if (DictationMarkerDetails* details = static_cast<DictationMarkerDetails*>(marker->details())) { + if (AlternativeTextClient* client = alternativeTextClient()) + client->removeDictationAlternatives(details->dictationContext()); + } #else UNUSED_PARAM(marker); #endif @@ -742,14 +725,14 @@ Vector<String> AlternativeTextController::dictationAlternativesForMarker(const D void AlternativeTextController::applyDictationAlternative(const String& alternativeString) { #if USE(DICTATION_ALTERNATIVES) - Editor& editor = m_frame->editor(); + Editor& editor = m_frame.editor(); RefPtr<Range> selection = editor.selectedRange(); if (!selection || !editor.shouldInsertText(alternativeString, selection.get(), EditorInsertActionPasted)) return; - DocumentMarkerController* markers = selection->startContainer()->document()->markers(); - Vector<DocumentMarker*> dictationAlternativesMarkers = markers->markersInRange(selection.get(), DocumentMarker::DictationAlternatives); - for (size_t i = 0; i < dictationAlternativesMarkers.size(); ++i) - removeDictationAlternativesForMarker(dictationAlternativesMarkers[i]); + DocumentMarkerController& markers = selection->startContainer().document().markers(); + Vector<RenderedDocumentMarker*> dictationAlternativesMarkers = markers.markersInRange(selection.get(), DocumentMarker::DictationAlternatives); + for (auto* marker : dictationAlternativesMarkers) + removeDictationAlternativesForMarker(marker); applyAlternativeTextToRange(selection.get(), alternativeString, AlternativeTextTypeDictationAlternatives, markerTypesForAppliedDictationAlternative()); #else |
