Changeset 235149 in webkit
- Timestamp:
- Aug 21, 2018, 5:45:55 PM (7 years ago)
- Location:
- trunk/Source/WebKit
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebKit/ChangeLog
r235148 r235149 1 2018-08-21 Daniel Bates <dabates@apple.com> 2 3 [iOS][WK2] Misspelled words are not underlined 4 https://bugs.webkit.org/show_bug.cgi?id=188800 5 <rdar://problem/34811332> 6 7 Reviewed by Wenson Hsieh. 8 9 Implement enough of TextChecker for iOS to compute the list of misspelled words in a 10 paragraph and advertise support for continuous spell checking. The WebCore editing 11 machinery queries TextChecker for the list of the misspelled words, creating document 12 markers that demarcate the misspelled words. When we paint a line of text we paint 13 the spelling correction dots under each misspelled word. 14 15 On iOS we make use of UITextChecker to perform spell checking of a string. We maintain 16 a side table that maps a "spell document tag" to a UITextChecker* to conform to the 17 shape of the TextChecker interface. 18 19 * Platform/spi/ios/UIKitSPI.h: Forward declare some SPI. 20 * UIProcess/ios/TextCheckerIOS.mm: 21 (WebKit::mutableState): Added. 22 (WebKit::TextChecker::state): Turns around and returns mutableState(). 23 (WebKit::TextChecker::isContinuousSpellCheckingAllowed): Returns true if we are building 24 with USE(UNIFIED_TEXT_CHECKING). Otherwise, do what we do now. 25 (WebKit::TextChecker::setContinuousSpellCheckingEnabled): Update state. 26 (WebKit::TextChecker::continuousSpellCheckingEnabledStateChanged): Ditto. 27 (WebKit::spellDocumentTagMap): Returns HashMap that maps a "spell document tag" (int64_t) to 28 a RetainPtr<UITextChecker>>. 29 (WebKit::TextChecker::uniqueSpellDocumentTag): Generates a unique identifier for the page 30 this text checker is associated with. 31 (WebKit::TextChecker::closeSpellDocumentWithTag): Removes the entry for the specified identifier 32 from the HashMap. 33 (WebKit::textCheckerFor): Query the HashMap for the UITextChecker for the specified spell 34 document tag, if it exists. Otherwise, create a new UITextChecker and add a new map entry 35 that associates it with the specified spell document tag. 36 (WebKit::TextChecker::checkTextOfParagraph): Spell check the specified string and return a list 37 that represents the misspelled words. 38 (WebKit::TextChecker::checkSpellingOfString): Added a comment to explain that iOS does not implement 39 this function and instead implements checkTextOfParagraph(). 40 (WebKit::TextChecker::checkGrammarOfString): Ditto. 41 1 42 2018-08-21 Alex Christensen <achristensen@webkit.org> 2 43 -
trunk/Source/WebKit/Platform/spi/ios/UIKitSPI.h
r233905 r235149 45 45 #import <UIKit/UIInterface_Private.h> 46 46 #import <UIKit/UIKeyboardImpl.h> 47 #import <UIKit/UIKeyboardInputModeController.h> 47 48 #import <UIKit/UIKeyboardIntl.h> 48 49 #import <UIKit/UIKeyboard_Private.h> … … 58 59 #import <UIKit/UITableViewCell_Private.h> 59 60 #import <UIKit/UITapGestureRecognizer_Private.h> 61 #import <UIKit/UITextChecker_Private.h> 60 62 #import <UIKit/UITextEffectsWindow.h> 61 63 #import <UIKit/UITextInput_Private.h> … … 887 889 @end 888 890 891 @interface UITextChecker () 892 - (id)_initWithAsynchronousLoading:(BOOL)asynchronousLoading; 893 - (BOOL)_doneLoading; 894 - (NSRange)rangeOfMisspelledWordInString:(NSString *)stringToCheck range:(NSRange)range startingAt:(NSInteger)startingOffset wrap:(BOOL)wrapFlag languages:(NSArray *)languagesArray; 895 @end 896 897 @interface UIKeyboardInputMode : UITextInputMode <NSCopying> 898 @property (nonatomic, readonly, retain) NSArray <NSString *> *multilingualLanguages; 899 @property (nonatomic, readonly, retain) NSString *languageWithRegion; 900 @end 901 902 @interface UIKeyboardInputModeController : NSObject 903 @end 904 905 @interface UIKeyboardInputModeController () 906 + (UIKeyboardInputModeController *)sharedInputModeController; 907 @property (readwrite, retain) UIKeyboardInputMode *currentInputMode; 908 @end 909 889 910 #if ENABLE(DRAG_SUPPORT) 890 911 -
trunk/Source/WebKit/UIProcess/ios/TextCheckerIOS.mm
r235120 r235149 30 30 31 31 #import "TextCheckerState.h" 32 #import "UIKitSPI.h" 32 33 #import <WebCore/NotImplemented.h> 34 #import <wtf/HashMap.h> 35 #import <wtf/NeverDestroyed.h> 36 #import <wtf/RetainPtr.h> 33 37 #import <wtf/text/StringView.h> 34 38 … … 36 40 37 41 namespace WebKit { 38 39 TextCheckerState textCheckerState; 42 43 static TextCheckerState& mutableState() 44 { 45 static NeverDestroyed<TextCheckerState> state = makeNeverDestroyed([] { 46 TextCheckerState initialState; 47 initialState.isContinuousSpellCheckingEnabled = TextChecker::isContinuousSpellCheckingAllowed(); 48 initialState.isGrammarCheckingEnabled = false; 49 return initialState; 50 }()); 51 return state; 52 } 40 53 41 54 const TextCheckerState& TextChecker::state() 42 55 { 43 notImplemented(); 44 return textCheckerState; 56 return mutableState(); 45 57 } 46 58 47 59 bool TextChecker::isContinuousSpellCheckingAllowed() 48 60 { 49 notImplemented(); 61 #if USE(UNIFIED_TEXT_CHECKING) 62 return true; 63 #else 50 64 return false; 51 } 52 53 void TextChecker::setContinuousSpellCheckingEnabled(bool) 54 { 55 notImplemented(); 65 #endif 66 } 67 68 void TextChecker::setContinuousSpellCheckingEnabled(bool enabled) 69 { 70 mutableState().isContinuousSpellCheckingEnabled = enabled; 56 71 } 57 72 … … 123 138 } 124 139 125 void TextChecker::continuousSpellCheckingEnabledStateChanged(bool )126 { 127 notImplemented();140 void TextChecker::continuousSpellCheckingEnabledStateChanged(bool enabled) 141 { 142 mutableState().isContinuousSpellCheckingEnabled = enabled; 128 143 } 129 144 … … 133 148 } 134 149 150 #if USE(UNIFIED_TEXT_CHECKING) 151 152 static HashMap<int64_t, RetainPtr<UITextChecker>>& spellDocumentTagMap() 153 { 154 static NeverDestroyed<HashMap<int64_t, RetainPtr<UITextChecker>>> tagMap; 155 return tagMap; 156 } 157 158 #endif 159 135 160 int64_t TextChecker::uniqueSpellDocumentTag(WebPageProxy*) 136 161 { 137 notImplemented(); 162 #if USE(UNIFIED_TEXT_CHECKING) 163 static int64_t nextSpellDocumentTag; 164 return ++nextSpellDocumentTag; 165 #else 138 166 return 0; 139 } 140 141 void TextChecker::closeSpellDocumentWithTag(int64_t) 142 { 143 notImplemented(); 144 } 145 146 #if USE(UNIFIED_TEXT_CHECKING) 147 148 Vector<TextCheckingResult> TextChecker::checkTextOfParagraph(int64_t, StringView, int32_t, OptionSet<TextCheckingType>, bool) 149 { 150 notImplemented(); 151 return Vector<TextCheckingResult>(); 167 #endif 168 } 169 170 void TextChecker::closeSpellDocumentWithTag(int64_t spellDocumentTag) 171 { 172 #if USE(UNIFIED_TEXT_CHECKING) 173 spellDocumentTagMap().remove(spellDocumentTag); 174 #else 175 UNUSED_PARAM(spellDocumentTag); 176 #endif 177 } 178 179 #if USE(UNIFIED_TEXT_CHECKING) 180 181 static RetainPtr<UITextChecker> textCheckerFor(int64_t spellDocumentTag) 182 { 183 auto addResult = spellDocumentTagMap().add(spellDocumentTag, nullptr); 184 if (addResult.isNewEntry) 185 addResult.iterator->value = adoptNS([[UITextChecker alloc] _initWithAsynchronousLoading:YES]); 186 return addResult.iterator->value; 187 } 188 189 Vector<TextCheckingResult> TextChecker::checkTextOfParagraph(int64_t spellDocumentTag, StringView text, int32_t /* insertionPoint */, OptionSet<TextCheckingType> checkingTypes, bool /* initialCapitalizationEnabled */) 190 { 191 Vector<TextCheckingResult> results; 192 if (!checkingTypes.contains(TextCheckingType::Spelling)) 193 return results; 194 195 auto textChecker = textCheckerFor(spellDocumentTag); 196 if (![textChecker _doneLoading]) 197 return results; 198 199 NSArray<NSString *> *keyboardLanguages = @[ ]; 200 auto *currentInputMode = [UIKeyboardInputModeController sharedInputModeController].currentInputMode; 201 if (currentInputMode.multilingualLanguages.count) 202 keyboardLanguages = currentInputMode.multilingualLanguages; 203 else if (currentInputMode.primaryLanguage) 204 keyboardLanguages = @[ currentInputMode.languageWithRegion ]; 205 206 auto stringToCheck = text.createNSStringWithoutCopying(); 207 auto range = NSMakeRange(0, [stringToCheck length]); 208 NSUInteger offsetSoFar = 0; 209 do { 210 auto misspelledRange = [textChecker rangeOfMisspelledWordInString:stringToCheck.get() range:range startingAt:offsetSoFar wrap:NO languages:keyboardLanguages]; 211 if (misspelledRange.location == NSNotFound) 212 break; 213 214 TextCheckingResult result; 215 result.type = TextCheckingType::Spelling; 216 result.location = misspelledRange.location; 217 result.length = misspelledRange.length; 218 results.append(WTFMove(result)); 219 220 offsetSoFar = misspelledRange.location + misspelledRange.length; 221 } while (offsetSoFar < [stringToCheck length]); 222 return results; 152 223 } 153 224 … … 156 227 void TextChecker::checkSpellingOfString(int64_t, StringView, int32_t&, int32_t&) 157 228 { 229 // iOS uses checkTextOfParagraph() instead. 158 230 notImplemented(); 159 231 } … … 161 233 void TextChecker::checkGrammarOfString(int64_t, StringView, Vector<WebCore::GrammarDetail>&, int32_t&, int32_t&) 162 234 { 235 // iOS uses checkTextOfParagraph() instead. 163 236 notImplemented(); 164 237 }
Note:
See TracChangeset
for help on using the changeset viewer.