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

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

Issue 2720193002: Implement hot mode invocation for idle time spell checker (Closed)
Patch Set: style fix Created 3 years, 9 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
(Empty)
1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "core/editing/spellcheck/HotModeSpellCheckRequester.h"
6
7 #include "core/editing/EditingUtilities.h"
8 #include "core/editing/Editor.h"
9 #include "core/editing/VisiblePosition.h"
10 #include "core/editing/commands/CompositeEditCommand.h"
11 #include "core/editing/commands/TypingCommand.h"
12 #include "core/editing/iterators/BackwardsCharacterIterator.h"
13 #include "core/editing/iterators/CharacterIterator.h"
14 #include "core/editing/spellcheck/SpellCheckRequester.h"
15 #include "core/editing/spellcheck/SpellChecker.h"
16
17 namespace blink {
18
19 namespace {
20
21 const int kHotModeChunkSize = 1024;
22
23 bool isInOrAdjacentToWord(const Position& pos) {
24 const VisiblePosition& visiblePos = createVisiblePosition(pos);
25 const VisiblePosition& wordStart = previousWordPosition(visiblePos);
26 if (wordStart.isNull())
27 return false;
28 const VisiblePosition& wordEnd = endOfWord(wordStart);
29 if (wordEnd.isNull())
30 return false;
31 return comparePositions(visiblePos, wordEnd) <= 0;
32 }
33
34 bool isTypingInPartialWord(const Element& editable) {
35 const LocalFrame& frame = *editable.document().frame();
36 const SelectionInDOMTree& selection = frame.selection().selectionInDOMTree();
37 if (!selection.isCaret())
38 return false;
39 if (rootEditableElementOf(selection.base()) != &editable)
40 return false;
41
42 CompositeEditCommand* typingCommand =
43 frame.editor().lastTypingCommandIfStillOpenForTyping();
44 if (!typingCommand)
45 return false;
46 if (typingCommand->endingSelection().asSelection() != selection)
47 return false;
48 return isInOrAdjacentToWord(selection.base());
49 }
50
51 bool shouldCheckRootEditableInHotMode(const Element& editable,
52 const Position& position) {
53 if (!editable.isSpellCheckingEnabled() &&
54 !SpellChecker::isSpellCheckingEnabledAt(position))
55 return false;
56 if (editable.visibleBoundsInVisualViewport().isEmpty())
57 return false;
58 // TODO(xiaochengh): Design more aggressive strategies to reduce checking when
59 // we are just moving selection around without modifying anything.
60 return !isTypingInPartialWord(editable);
61 }
62
63 EphemeralRange calculateHotModeCheckingRange(const Element& editable,
64 const Position& position) {
65 const EphemeralRange& fullRange = EphemeralRange::rangeOfContents(editable);
66 const int fullLength = TextIterator::rangeLength(fullRange.startPosition(),
67 fullRange.endPosition());
68 if (fullLength <= kHotModeChunkSize)
69 return fullRange;
70
71 TextIteratorBehavior behavior = TextIteratorBehavior::Builder()
72 .setEmitsObjectReplacementCharacter(true)
73 .build();
74 BackwardsCharacterIterator backwardIterator(fullRange.startPosition(),
75 position, behavior);
76 backwardIterator.advance(kHotModeChunkSize / 2);
77 const Position& chunkStart = backwardIterator.endPosition();
78 CharacterIterator forwardIterator(position, fullRange.endPosition(),
79 behavior);
80 forwardIterator.advance(kHotModeChunkSize / 2);
81 const Position& chunkEnd = forwardIterator.endPosition();
82 return expandRangeToSentenceBoundary(EphemeralRange(chunkStart, chunkEnd));
83 }
84
85 } // namespace
86
87 HotModeSpellCheckRequester::HotModeSpellCheckRequester(
88 SpellCheckRequester& requester)
89 : m_requester(requester) {}
90
91 void HotModeSpellCheckRequester::checkSpellingAt(const Position& position) {
92 const Element* rootEditable = rootEditableElementOf(position);
93 if (!rootEditable || !rootEditable->isConnected())
94 return;
95
96 if (m_processedRootEditables.contains(rootEditable))
97 return;
98 m_processedRootEditables.push_back(rootEditable);
99
100 if (!shouldCheckRootEditableInHotMode(*rootEditable, position))
101 return;
102
103 SpellCheckRequest* request = SpellCheckRequest::create(
104 calculateHotModeCheckingRange(*rootEditable, position));
105 m_requester->requestCheckingFor(request);
106 }
107
108 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698