Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(433)

Side by Side Diff: third_party/WebKit/Source/core/editing/spellcheck/SpellChecker.cpp

Issue 2931443003: Add support for Android spellcheck menu in Chrome/WebViews (Closed)
Patch Set: Respond to yosin@'s comments Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2006, 2007, 2008, 2011 Apple Inc. All rights reserved. 2 * Copyright (C) 2006, 2007, 2008, 2011 Apple Inc. All rights reserved.
3 * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) 3 * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
4 * 4 *
5 * Redistribution and use in source and binary forms, with or without 5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions 6 * modification, are permitted provided that the following conditions
7 * are met: 7 * are met:
8 * 1. Redistributions of source code must retain the above copyright 8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer. 9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright 10 * 2. Redistributions in binary form must reproduce the above copyright
(...skipping 25 matching lines...) Expand all
36 #include "core/dom/Range.h" 36 #include "core/dom/Range.h"
37 #include "core/editing/EditingUtilities.h" 37 #include "core/editing/EditingUtilities.h"
38 #include "core/editing/Editor.h" 38 #include "core/editing/Editor.h"
39 #include "core/editing/EphemeralRange.h" 39 #include "core/editing/EphemeralRange.h"
40 #include "core/editing/VisibleUnits.h" 40 #include "core/editing/VisibleUnits.h"
41 #include "core/editing/commands/CompositeEditCommand.h" 41 #include "core/editing/commands/CompositeEditCommand.h"
42 #include "core/editing/commands/ReplaceSelectionCommand.h" 42 #include "core/editing/commands/ReplaceSelectionCommand.h"
43 #include "core/editing/commands/TypingCommand.h" 43 #include "core/editing/commands/TypingCommand.h"
44 #include "core/editing/iterators/CharacterIterator.h" 44 #include "core/editing/iterators/CharacterIterator.h"
45 #include "core/editing/markers/DocumentMarkerController.h" 45 #include "core/editing/markers/DocumentMarkerController.h"
46 #include "core/editing/markers/SpellCheckMarker.h"
46 #include "core/editing/spellcheck/IdleSpellCheckCallback.h" 47 #include "core/editing/spellcheck/IdleSpellCheckCallback.h"
47 #include "core/editing/spellcheck/SpellCheckRequester.h" 48 #include "core/editing/spellcheck/SpellCheckRequester.h"
48 #include "core/editing/spellcheck/SpellCheckerClient.h" 49 #include "core/editing/spellcheck/SpellCheckerClient.h"
49 #include "core/editing/spellcheck/TextCheckingParagraph.h" 50 #include "core/editing/spellcheck/TextCheckingParagraph.h"
50 #include "core/frame/LocalFrame.h" 51 #include "core/frame/LocalFrame.h"
51 #include "core/frame/Settings.h" 52 #include "core/frame/Settings.h"
52 #include "core/html/HTMLInputElement.h" 53 #include "core/html/HTMLInputElement.h"
53 #include "core/layout/LayoutTextControl.h" 54 #include "core/layout/LayoutTextControl.h"
54 #include "core/loader/EmptyClients.h" 55 #include "core/loader/EmptyClients.h"
55 #include "core/page/Page.h" 56 #include "core/page/Page.h"
(...skipping 747 matching lines...) Expand 10 before | Expand all | Expand 10 after
803 804
804 DocumentMarker::MarkerTypes marker_types(DocumentMarker::kSpelling); 805 DocumentMarker::MarkerTypes marker_types(DocumentMarker::kSpelling);
805 marker_types.Add(DocumentMarker::kGrammar); 806 marker_types.Add(DocumentMarker::kGrammar);
806 for (Node& node : NodeTraversal::InclusiveDescendantsOf(element)) { 807 for (Node& node : NodeTraversal::InclusiveDescendantsOf(element)) {
807 if (elements_type == ElementsType::kAll || !HasEditableStyle(node)) { 808 if (elements_type == ElementsType::kAll || !HasEditableStyle(node)) {
808 GetFrame().GetDocument()->Markers().RemoveMarkersForNode(&node, 809 GetFrame().GetDocument()->Markers().RemoveMarkersForNode(&node,
809 marker_types); 810 marker_types);
810 } 811 }
811 } 812 }
812 } 813 }
813 814
yosin_UTC9 2017/06/08 01:50:09 Could you move spell checker changes into another
815 namespace {
816
817 EphemeralRange ExpandSelectionRangeIfNecessary(
818 const VisibleSelection& selection) {
819 DCHECK(!selection.IsNone());
820
821 // If some text is actually selected, we can use the selection range as-is to
822 // check for a marker. If no text is selected (we just have a caret
823 // somewhere), we need to expand one character on either side so we can find
824 // a spelling marker immediately before or after the caret.
825
826 // (The spelling markers on these words may be anchored to a different node
827 // than the collapsed selection's Position is, but once we expand the
828 // selection, if we're next to a marker, either the start or end point should
829 // now be anchored relative to the same text node as that marker.)
830
831 // Some text is actually selected
832 if (selection.IsRange())
833 return EphemeralRange(selection.Start(), selection.End());
834
835 // No text is actually selected, need to expand the selection range
836 const VisiblePosition& caret_pos = selection.VisibleStart();
837
838 Position range_to_check_start =
839 PreviousPositionOf(caret_pos).DeepEquivalent();
840 if (range_to_check_start.IsNull())
841 range_to_check_start = caret_pos.DeepEquivalent();
842
843 Position range_to_check_end = NextPositionOf(caret_pos).DeepEquivalent();
844 if (range_to_check_end.IsNull())
845 range_to_check_end = caret_pos.DeepEquivalent();
846
847 return EphemeralRange(range_to_check_start, range_to_check_end);
848 }
849
850 } // namespace
851
852 Optional<std::pair<Node*, SpellCheckMarker*>>
853 SpellChecker::GetSpellCheckMarkerTouchingSelection() {
854 const VisibleSelection& selection =
855 GetFrame().Selection().ComputeVisibleSelectionInDOMTree();
856 if (selection.IsNone())
857 return Optional<std::pair<Node*, SpellCheckMarker*>>();
858
859 const EphemeralRange& range_to_check =
860 ExpandSelectionRangeIfNecessary(selection);
861
862 Node* start_container = range_to_check.StartPosition().ComputeContainerNode();
863 const unsigned start_offset =
864 range_to_check.StartPosition().ComputeOffsetInContainerNode();
865 Node* end_container = range_to_check.EndPosition().ComputeContainerNode();
866 const unsigned end_offset =
867 range_to_check.EndPosition().ComputeOffsetInContainerNode();
868
869 for (Node& node : range_to_check.Nodes()) {
870 const DocumentMarkerVector& markers_in_node =
871 GetFrame().GetDocument()->Markers().MarkersFor(
872 &node, DocumentMarker::MisspellingMarkers());
873 for (DocumentMarker* marker : markers_in_node) {
874 if (node == start_container && marker->EndOffset() <= start_offset)
875 continue;
876 if (node == end_container && marker->StartOffset() >= end_offset)
877 continue;
878
879 return std::make_pair(&node, &ToSpellCheckMarker(*marker));
880 }
881 }
882
883 // No marker found
884 return Optional<std::pair<Node*, SpellCheckMarker*>>();
885 }
886
814 void SpellChecker::ReplaceMisspelledRange(const String& text) { 887 void SpellChecker::ReplaceMisspelledRange(const String& text) {
815 EphemeralRange caret_range = GetFrame() 888 const Optional<std::pair<Node*, SpellCheckMarker*>>& node_and_marker =
816 .Selection() 889 GetSpellCheckMarkerTouchingSelection();
817 .ComputeVisibleSelectionInDOMTree() 890 if (!node_and_marker)
818 .ToNormalizedEphemeralRange();
819 if (caret_range.IsNull())
820 return; 891 return;
821 892
822 Node* const caret_start_container = 893 Node* const container_node = node_and_marker.value().first;
823 caret_range.StartPosition().ComputeContainerNode(); 894 const SpellCheckMarker* const marker = node_and_marker.value().second;
824 Node* const caret_end_container =
825 caret_range.EndPosition().ComputeContainerNode();
826 895
827 // We don't currently support the case where a misspelling spans multiple 896 const EphemeralRange misspelled_range(
828 // nodes 897 Position(container_node, marker->StartOffset()),
829 if (caret_start_container != caret_end_container) 898 Position(container_node, marker->EndOffset()));
830 return;
831
832 const unsigned caret_start_offset =
833 caret_range.StartPosition().ComputeOffsetInContainerNode();
834 const unsigned caret_end_offset =
835 caret_range.EndPosition().ComputeOffsetInContainerNode();
836
837 const DocumentMarkerVector& markers_in_node =
838 GetFrame().GetDocument()->Markers().MarkersFor(
839 caret_start_container, DocumentMarker::MisspellingMarkers());
840
841 const auto marker_it =
842 std::find_if(markers_in_node.begin(), markers_in_node.end(),
843 [=](const DocumentMarker* marker) {
844 return marker->StartOffset() < caret_end_offset &&
845 marker->EndOffset() > caret_start_offset;
846 });
847 if (marker_it == markers_in_node.end())
848 return;
849
850 const DocumentMarker* found_marker = *marker_it;
851 EphemeralRange marker_range = EphemeralRange(
852 Position(caret_start_container, found_marker->StartOffset()),
853 Position(caret_start_container, found_marker->EndOffset()));
854 if (marker_range.IsNull())
855 return;
856 899
857 GetFrame().Selection().SetSelection( 900 GetFrame().Selection().SetSelection(
858 SelectionInDOMTree::Builder().SetBaseAndExtent(marker_range).Build()); 901 SelectionInDOMTree::Builder().SetBaseAndExtent(misspelled_range).Build());
859 902
860 Document& current_document = *GetFrame().GetDocument(); 903 Document& current_document = *GetFrame().GetDocument();
861 904
862 // Dispatch 'beforeinput'. 905 // Dispatch 'beforeinput'.
863 Element* const target = GetFrame().GetEditor().FindEventTargetFromSelection(); 906 Element* const target = GetFrame().GetEditor().FindEventTargetFromSelection();
864 DataTransfer* const data_transfer = DataTransfer::Create( 907 DataTransfer* const data_transfer = DataTransfer::Create(
865 DataTransfer::DataTransferType::kInsertReplacementText, 908 DataTransfer::DataTransferType::kInsertReplacementText,
866 DataTransferAccessPolicy::kDataTransferReadable, 909 DataTransferAccessPolicy::kDataTransferReadable,
867 DataObject::CreateFromString(text)); 910 DataObject::CreateFromString(text));
868 911
(...skipping 370 matching lines...) Expand 10 before | Expand all | Expand 10 after
1239 if (!input.IsFocusedElementInDocument()) 1282 if (!input.IsFocusedElementInDocument())
1240 return false; 1283 return false;
1241 } 1284 }
1242 } 1285 }
1243 HTMLElement* element = 1286 HTMLElement* element =
1244 Traversal<HTMLElement>::FirstAncestorOrSelf(*position.AnchorNode()); 1287 Traversal<HTMLElement>::FirstAncestorOrSelf(*position.AnchorNode());
1245 return element && element->IsSpellCheckingEnabled(); 1288 return element && element->IsSpellCheckingEnabled();
1246 } 1289 }
1247 1290
1248 } // namespace blink 1291 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698