Changeset 101731 in webkit
- Timestamp:
- Dec 1, 2011 6:15:48 PM (12 years ago)
- Location:
- trunk
- Files:
-
- 2 added
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r101730 r101731 1 2011-12-01 Shinya Kawanaka <shinyak@google.com> 2 3 Asynchronous SpellChecker should consider multiple requests. 4 https://bugs.webkit.org/show_bug.cgi?id=72939 5 6 Reviewed by Hajime Morita. 7 8 Tests for multiple spellcheck requests. 9 10 * editing/spelling/spellcheck-queue-expected.txt: Added. 11 * editing/spelling/spellcheck-queue.html: Added. 12 * platform/gtk/Skipped: 13 * platform/qt/Skipped: 14 1 15 2011-12-01 Takashi Toyoshima <toyoshim@chromium.org> 2 16 -
trunk/LayoutTests/platform/gtk/Skipped
r101682 r101731 1217 1217 editing/spelling/spelling-backspace-between-lines.html 1218 1218 editing/spelling/spellcheck-paste.html 1219 editing/spelling/spellcheck-queue.html 1219 1220 1220 1221 # For https://bugs.webkit.org/show_bug.cgi?id=50758 -
trunk/LayoutTests/platform/qt/Skipped
r101682 r101731 1002 1002 # EditorClient::requestCheckingOfString() is not implemented 1003 1003 editing/spelling/spellcheck-paste.html 1004 editing/spelling/spellcheck-queue.html 1004 1005 1005 1006 # [Qt][GTK] editing/spelling/spellcheck-async.html fails -
trunk/Source/WebCore/ChangeLog
r101730 r101731 1 2011-12-01 Shinya Kawanaka <shinyak@google.com> 2 3 Asynchronous SpellChecker should consider multiple requests. 4 https://bugs.webkit.org/show_bug.cgi?id=72939 5 6 Reviewed by Hajime Morita. 7 8 Now SpellChecker saves a request when it is processing the previous spellcheck request. 9 If there is a request having the same root editable element, the older request is replaced by newer request. 10 11 Test: editing/spelling/spellcheck-queue.html 12 13 * editing/SpellChecker.cpp: 14 (WebCore::SpellChecker::SpellCheckRequest::SpellCheckRequest): 15 A structure to have spell check request. 16 (WebCore::SpellChecker::SpellCheckRequest::sequence): 17 (WebCore::SpellChecker::SpellCheckRequest::range): 18 (WebCore::SpellChecker::SpellCheckRequest::text): 19 (WebCore::SpellChecker::SpellCheckRequest::mask): 20 (WebCore::SpellChecker::SpellCheckRequest::rootEditableElement): 21 (WebCore::SpellChecker::SpellChecker): 22 (WebCore::SpellChecker::createRequest): 23 (WebCore::SpellChecker::timerFiredToProcessQueuedRequest): 24 When timer is fired, queued request is processed if any. 25 (WebCore::SpellChecker::canCheckAsynchronously): 26 (WebCore::SpellChecker::requestCheckingFor): 27 When the spellchecker is processing another request, the latest request is queued. 28 (WebCore::SpellChecker::invokeRequest): 29 (WebCore::SpellChecker::enqueueRequest): 30 Enqueues a request. If there is an older request whose root editable element is the same as the request, 31 it will be replaced. 32 (WebCore::SpellChecker::didCheck): 33 * editing/SpellChecker.h: 34 1 35 2011-12-01 Takashi Toyoshima <toyoshim@chromium.org> 2 36 -
trunk/Source/WebCore/editing/SpellChecker.cpp
r100890 r101731 46 46 namespace WebCore { 47 47 48 class SpellChecker::SpellCheckRequest : public RefCounted<SpellChecker::SpellCheckRequest> { 49 public: 50 SpellCheckRequest(int sequence, PassRefPtr<Range> range, const String& text, TextCheckingTypeMask mask) 51 : m_sequence(sequence) 52 , m_range(range) 53 , m_text(text) 54 , m_mask(mask) 55 , m_rootEditableElement(m_range->startContainer()->rootEditableElement()) 56 { 57 } 58 59 int sequence() const { return m_sequence; } 60 Range* range() const { return m_range.get(); } 61 const String& text() const { return m_text; } 62 TextCheckingTypeMask mask() const { return m_mask; } 63 Element* rootEditableElement() const { return m_rootEditableElement; } 64 65 private: 66 int m_sequence; 67 RefPtr<Range> m_range; 68 String m_text; 69 TextCheckingTypeMask m_mask; 70 Element* m_rootEditableElement; 71 }; 72 48 73 SpellChecker::SpellChecker(Frame* frame) 49 74 : m_frame(frame) 50 , m_requestSequence(0) 75 , m_lastRequestedSequence(0) 76 , m_timerToProcessQueuedRequest(this, &SpellChecker::timerFiredToProcessQueuedRequest) 51 77 { 52 78 } … … 64 90 } 65 91 66 bool SpellChecker::initRequest(PassRefPtr<Range> range)92 PassRefPtr<SpellChecker::SpellCheckRequest> SpellChecker::createRequest(TextCheckingTypeMask mask, PassRefPtr<Range> range) 67 93 { 68 94 ASSERT(canCheckAsynchronously(range.get())); … … 70 96 String text = range->text(); 71 97 if (!text.length()) 72 return false; 73 74 m_requestRange = range; 75 m_requestText = text; 76 m_requestSequence++; 77 78 return true; 79 } 80 81 void SpellChecker::clearRequest() 82 { 83 m_requestRange.clear(); 84 m_requestText = String(); 98 return PassRefPtr<SpellCheckRequest>(); 99 100 return adoptRef(new SpellCheckRequest(++m_lastRequestedSequence, range, text, mask)); 101 } 102 103 void SpellChecker::timerFiredToProcessQueuedRequest(Timer<SpellChecker>*) 104 { 105 ASSERT(!m_requestQueue.isEmpty()); 106 if (m_requestQueue.isEmpty()) 107 return; 108 109 invokeRequest(m_requestQueue.takeFirst()); 85 110 } 86 111 … … 92 117 bool SpellChecker::canCheckAsynchronously(Range* range) const 93 118 { 94 return client() && isCheckable(range) && isAsynchronousEnabled() && !isBusy(); 95 } 96 97 bool SpellChecker::isBusy() const 98 { 99 return m_requestRange.get(); 100 } 101 102 bool SpellChecker::isValid(int sequence) const 103 { 104 return m_requestRange.get() && m_requestText.length() && m_requestSequence == sequence; 119 return client() && isCheckable(range) && isAsynchronousEnabled(); 105 120 } 106 121 … … 115 130 return; 116 131 117 doRequestCheckingFor(mask, range); 118 } 119 120 void SpellChecker::doRequestCheckingFor(TextCheckingTypeMask mask, PassRefPtr<Range> range) 121 { 122 ASSERT(canCheckAsynchronously(range.get())); 123 124 if (!initRequest(range)) 125 return; 126 client()->requestCheckingOfString(this, m_requestSequence, mask, m_requestText); 132 RefPtr<SpellCheckRequest> request(createRequest(mask, range)); 133 if (!request) 134 return; 135 136 if (m_timerToProcessQueuedRequest.isActive() || m_processingRequest) { 137 enqueueRequest(request.release()); 138 return; 139 } 140 141 invokeRequest(request.release()); 142 } 143 144 void SpellChecker::invokeRequest(PassRefPtr<SpellCheckRequest> request) 145 { 146 ASSERT(!m_processingRequest); 147 148 client()->requestCheckingOfString(this, request->sequence(), request->mask(), request->text()); 149 m_processingRequest = request; 150 } 151 152 void SpellChecker::enqueueRequest(PassRefPtr<SpellCheckRequest> request) 153 { 154 ASSERT(request); 155 156 for (RequestQueue::iterator it = m_requestQueue.begin(); it != m_requestQueue.end(); ++it) { 157 if (request->rootEditableElement() != (*it)->rootEditableElement()) 158 continue; 159 160 *it = request; 161 return; 162 } 163 164 m_requestQueue.append(request); 127 165 } 128 166 … … 160 198 void SpellChecker::didCheck(int sequence, const Vector<TextCheckingResult>& results) 161 199 { 162 if (!isValid(sequence))163 return; 164 165 if ( !isCheckable(m_requestRange.get())) {166 clearRequest();200 ASSERT(m_processingRequest); 201 202 ASSERT(m_processingRequest->sequence() == sequence); 203 if (m_processingRequest->sequence() != sequence) { 204 m_requestQueue.clear(); 167 205 return; 168 206 } 169 207 170 208 int startOffset = 0; 171 PositionIterator start = m_ requestRange->startPosition();209 PositionIterator start = m_processingRequest->range()->startPosition(); 172 210 for (size_t i = 0; i < results.size(); ++i) { 173 211 if (results[i].type != TextCheckingTypeSpelling && results[i].type != TextCheckingTypeGrammar) … … 187 225 // JavaScript applications, retrieve the words in the specified region and compare them with 188 226 // the original ones. 189 RefPtr<Range> range = Range::create(m_ requestRange->ownerDocument(), start, end);227 RefPtr<Range> range = Range::create(m_processingRequest->range()->ownerDocument(), start, end); 190 228 // FIXME: Use textContent() compatible string conversion. 191 229 String destination = range->text(); 192 String source = m_ requestText.substring(results[i].location, results[i].length);230 String source = m_processingRequest->text().substring(results[i].location, results[i].length); 193 231 if (destination == source) 194 m_ requestRange->ownerDocument()->markers()->addMarker(range.get(), toMarkerType(results[i].type));232 m_processingRequest->range()->ownerDocument()->markers()->addMarker(range.get(), toMarkerType(results[i].type)); 195 233 196 234 startOffset = results[i].location; 197 235 } 198 236 199 clearRequest(); 237 m_processingRequest.clear(); 238 if (!m_requestQueue.isEmpty()) 239 m_timerToProcessQueuedRequest.startOneShot(0); 200 240 } 201 241 -
trunk/Source/WebCore/editing/SpellChecker.h
r100890 r101731 29 29 #include "PlatformString.h" 30 30 #include "TextChecking.h" 31 #include "Timer.h" 32 #include <wtf/Deque.h> 31 33 #include <wtf/RefPtr.h> 32 34 #include <wtf/Noncopyable.h> … … 48 50 49 51 bool isAsynchronousEnabled() const; 50 bool canCheckAsynchronously(Range*) const;51 bool isBusy() const;52 bool isValid(int sequence) const;53 52 bool isCheckable(Range*) const; 54 53 void requestCheckingFor(TextCheckingTypeMask, PassRefPtr<Range>); … … 56 55 57 56 private: 58 bool initRequest(PassRefPtr<Range>); 59 void clearRequest(); 60 void doRequestCheckingFor(TextCheckingTypeMask, PassRefPtr<Range>); 57 class SpellCheckRequest; 58 typedef Deque<RefPtr<SpellCheckRequest> > RequestQueue; 59 60 bool canCheckAsynchronously(Range*) const; 61 PassRefPtr<SpellCheckRequest> createRequest(TextCheckingTypeMask, PassRefPtr<Range>); 61 62 TextCheckerClient* client() const; 63 void timerFiredToProcessQueuedRequest(Timer<SpellChecker>*); 64 void invokeRequest(PassRefPtr<SpellCheckRequest>); 65 void enqueueRequest(PassRefPtr<SpellCheckRequest>); 62 66 63 67 Frame* m_frame; 68 int m_lastRequestedSequence; 64 69 65 RefPtr<Range> m_requestRange; 66 String m_requestText; 67 int m_requestSequence; 70 Timer<SpellChecker> m_timerToProcessQueuedRequest; 71 72 RefPtr<SpellCheckRequest> m_processingRequest; 73 RequestQueue m_requestQueue; 68 74 }; 69 75
Note: See TracChangeset
for help on using the changeset viewer.