Changeset 243354 in webkit
- Timestamp:
- Mar 21, 2019, 7:26:09 PM (7 years ago)
- Location:
- trunk
- Files:
-
- 3 added
- 23 edited
-
Source/WebCore/ChangeLog (modified) (1 diff)
-
Source/WebCore/dom/Range.h (modified) (1 diff)
-
Source/WebCore/editing/TextGranularity.h (modified) (1 diff)
-
Source/WebCore/editing/TextIterator.cpp (modified) (1 diff)
-
Source/WebCore/editing/TextIterator.h (modified) (2 diffs)
-
Source/WebKit/ChangeLog (modified) (1 diff)
-
Source/WebKit/Platform/spi/ios/UIKitSPI.h (modified) (1 diff)
-
Source/WebKit/Scripts/webkit/messages.py (modified) (1 diff)
-
Source/WebKit/Shared/DocumentEditingContext.h (added)
-
Source/WebKit/Shared/DocumentEditingContext.mm (added)
-
Source/WebKit/SourcesCocoa.txt (modified) (1 diff)
-
Source/WebKit/UIProcess/WebPageProxy.h (modified) (2 diffs)
-
Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm (modified) (3 diffs)
-
Source/WebKit/UIProcess/ios/WebPageProxyIOS.mm (modified) (2 diffs)
-
Source/WebKit/WebKit.xcodeproj/project.pbxproj (modified) (2 diffs)
-
Source/WebKit/WebProcess/WebPage/WebPage.cpp (modified) (1 diff)
-
Source/WebKit/WebProcess/WebPage/WebPage.h (modified) (2 diffs)
-
Source/WebKit/WebProcess/WebPage/WebPage.messages.in (modified) (1 diff)
-
Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm (modified) (2 diffs)
-
Tools/ChangeLog (modified) (1 diff)
-
Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj (modified) (4 diffs)
-
Tools/TestWebKitAPI/Tests/WebKitCocoa/DocumentEditingContext.mm (added)
-
Tools/TestWebKitAPI/Tests/WebKitCocoa/WKContentViewEditingActions.mm (modified) (2 diffs)
-
Tools/TestWebKitAPI/cocoa/TestWKWebView.h (modified) (2 diffs)
-
Tools/TestWebKitAPI/cocoa/TestWKWebView.mm (modified) (1 diff)
-
Tools/TestWebKitAPI/ios/UIKitSPI.h (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r243348 r243354 1 2019-03-21 Tim Horton <timothy_horton@apple.com> 2 3 Adopt UIWKDocumentContext 4 https://bugs.webkit.org/show_bug.cgi?id=196040 5 <rdar://problem/48642440> 6 7 Reviewed by Ryosuke Niwa. 8 9 New API test: WebKit.DocumentEditingContext 10 11 * dom/Range.h: 12 * editing/TextGranularity.h: 13 Make TextGranularity encodable by providing EnumTraits. 14 15 * editing/TextIterator.cpp: 16 (WebCore::plainTextReplacingNoBreakSpace): 17 * editing/TextIterator.h: 18 Expose an nbsp-replacing variant of plainText that takes Positions instead of Ranges. 19 1 20 2019-03-21 Sihui Liu <sihui_liu@apple.com> 2 21 -
trunk/Source/WebCore/dom/Range.h
r240237 r243354 177 177 178 178 WEBCORE_EXPORT bool areRangesEqual(const Range*, const Range*); 179 bool rangesOverlap(const Range*, const Range*);179 WEBCORE_EXPORT bool rangesOverlap(const Range*, const Range*); 180 180 181 181 inline bool documentOrderComparator(const Node* a, const Node* b) -
trunk/Source/WebCore/editing/TextGranularity.h
r208646 r243354 44 44 45 45 } // namespace WebCore 46 47 namespace WTF { 48 49 template<> struct EnumTraits<WebCore::TextGranularity> { 50 using values = EnumValues< 51 WebCore::TextGranularity, 52 WebCore::TextGranularity::CharacterGranularity, 53 WebCore::TextGranularity::WordGranularity, 54 WebCore::TextGranularity::SentenceGranularity, 55 WebCore::TextGranularity::LineGranularity, 56 WebCore::TextGranularity::ParagraphGranularity, 57 WebCore::TextGranularity::DocumentGranularity, 58 WebCore::TextGranularity::SentenceBoundary, 59 WebCore::TextGranularity::LineBoundary, 60 WebCore::TextGranularity::ParagraphBoundary, 61 WebCore::TextGranularity::DocumentBoundary 62 >; 63 }; 64 65 } -
trunk/Source/WebCore/editing/TextIterator.cpp
r243163 r243354 2685 2685 } 2686 2686 2687 String plainTextReplacingNoBreakSpace(Position start, Position end, TextIteratorBehavior defaultBehavior, bool isDisplayString) 2688 { 2689 return plainText(start, end, defaultBehavior, isDisplayString).replace(noBreakSpace, ' '); 2690 } 2691 2687 2692 String plainText(const Range* range, TextIteratorBehavior defaultBehavior, bool isDisplayString) 2688 2693 { -
trunk/Source/WebCore/editing/TextIterator.h
r241183 r243354 45 45 46 46 WEBCORE_EXPORT String plainText(Position start, Position end, TextIteratorBehavior = TextIteratorDefaultBehavior, bool isDisplayString = false); 47 WEBCORE_EXPORT String plainTextReplacingNoBreakSpace(Position start, Position end, TextIteratorBehavior = TextIteratorDefaultBehavior, bool isDisplayString = false); 47 48 48 49 WEBCORE_EXPORT String plainText(const Range*, TextIteratorBehavior = TextIteratorDefaultBehavior, bool isDisplayString = false); … … 103 104 WTF_MAKE_FAST_ALLOCATED; 104 105 public: 105 explicit TextIterator(Position start, Position end, TextIteratorBehavior = TextIteratorDefaultBehavior);106 WEBCORE_EXPORT explicit TextIterator(Position start, Position end, TextIteratorBehavior = TextIteratorDefaultBehavior); 106 107 WEBCORE_EXPORT explicit TextIterator(const Range*, TextIteratorBehavior = TextIteratorDefaultBehavior); 107 108 WEBCORE_EXPORT ~TextIterator(); -
trunk/Source/WebKit/ChangeLog
r243351 r243354 1 2019-03-21 Tim Horton <timothy_horton@apple.com> 2 3 Adopt UIWKDocumentContext 4 https://bugs.webkit.org/show_bug.cgi?id=196040 5 <rdar://problem/48642440> 6 7 Reviewed by Ryosuke Niwa. 8 9 * Platform/spi/ios/UIKitSPI.h: 10 * Scripts/webkit/messages.py: 11 * Shared/DocumentEditingContext.h: Added. 12 * Shared/DocumentEditingContext.mm: Added. 13 (WebKit::toNSRange): 14 (WebKit::DocumentEditingContext::toPlatformContext): 15 (IPC::ArgumentCoder<WebKit::DocumentEditingContext::Range>::encode): 16 (IPC::ArgumentCoder<WebKit::DocumentEditingContext::Range>::decode): 17 (IPC::ArgumentCoder<WebKit::DocumentEditingContext::TextRect>::encode): 18 (IPC::ArgumentCoder<WebKit::DocumentEditingContext::TextRect>::decode): 19 (IPC::ArgumentCoder<WebKit::DocumentEditingContext>::encode): 20 (IPC::ArgumentCoder<WebKit::DocumentEditingContext>::decode): 21 (IPC::ArgumentCoder<WebKit::DocumentEditingContextRequest>::encode): 22 (IPC::ArgumentCoder<WebKit::DocumentEditingContextRequest>::decode): 23 Add DocumentEditingContext(Request), and coders. 24 Also expose DocumentEditingContext::toPlatformContext, which populates 25 a UIWKDocumentContext with the relevant values. 26 27 * SourcesCocoa.txt: 28 * UIProcess/WebPageProxy.h: 29 * UIProcess/ios/WKContentViewInteraction.mm: 30 (toWebDocumentRequestOptions): 31 (toWebRequest): 32 (-[WKContentView adjustSelectionWithDelta:completionHandler:]): 33 (-[WKContentView requestDocumentContext:completionHandler:]): 34 (-[WKContentView selectPositionAtPoint:withContextRequest:completionHandler:]): 35 * UIProcess/ios/WebPageProxyIOS.mm: 36 (WebKit::WebPageProxy::adjustSelectionWithDelta): 37 (WebKit::WebPageProxy::requestDocumentEditingContext): 38 * WebKit.xcodeproj/project.pbxproj: 39 * WebProcess/WebPage/WebPage.h: 40 * WebProcess/WebPage/WebPage.messages.in: 41 Plumb DocumentEditingContext(Request) around. 42 43 * WebProcess/WebPage/ios/WebPageIOS.mm: 44 (WebKit::WebPage::adjustSelectionWithDelta): 45 Adjust the current selection given deltas to apply to the location and length. 46 47 (WebKit::visiblePositionAdjacentToVisiblePosition): 48 (WebKit::visiblePositionForPointInRootViewCoordinates): 49 (WebKit::WebPage::requestDocumentEditingContext): 50 Retrieve the relevant part of the selection, as well as the context, 51 given either the selection, or a rect. 52 If we're collecting context for a rect, we split the context between 53 before and after (except for the part that intersects the selection). 54 The three strings will always be directly adjacent, and any of the three 55 can sometimes be null. 56 1 57 2019-03-21 James Magahern <jmagahern@apple.com> 2 58 -
trunk/Source/WebKit/Platform/spi/ios/UIKitSPI.h
r243113 r243354 1141 1141 } 1142 1142 1143 @interface UIWKDocumentContext : NSObject 1144 1145 @property (nonatomic, copy) NSObject *contextBefore; 1146 @property (nonatomic, copy) NSObject *selectedText; 1147 @property (nonatomic, copy) NSObject *contextAfter; 1148 @property (nonatomic, copy) NSObject *markedText; 1149 @property (nonatomic, assign) NSRange selectedRangeInMarkedText; 1150 @property (nonatomic, copy) NSAttributedString *annotatedText; 1151 1152 - (void)addTextRect:(CGRect)rect forCharacterRange:(NSRange)range; 1153 1154 @end 1155 1156 typedef NS_OPTIONS(NSInteger, UIWKDocumentRequestFlags) { 1157 UIWKDocumentRequestNone = 0, 1158 UIWKDocumentRequestText = 1 << 0, 1159 UIWKDocumentRequestAttributed = 1 << 1, 1160 UIWKDocumentRequestRects = 1 << 2, 1161 UIWKDocumentRequestSpatial = 1 << 3, 1162 UIWKDocumentRequestAnnotation = 1 << 4, 1163 }; 1164 1165 @interface UIWKDocumentRequest : NSObject 1166 @property (nonatomic, assign) UIWKDocumentRequestFlags flags; 1167 @property (nonatomic, assign) UITextGranularity surroundingGranularity; 1168 @property (nonatomic, assign) NSInteger granularityCount; 1169 @property (nonatomic, assign) CGRect documentRect; 1170 @property (nonatomic, retain) id <NSCopying> inputElementIdentifier; 1171 @end 1172 1143 1173 WTF_EXTERN_C_BEGIN 1144 1174 -
trunk/Source/WebKit/Scripts/webkit/messages.py
r243345 r243354 398 398 'WebCore::AutoplayEventFlags': ['<WebCore/AutoplayEvent.h>'], 399 399 'WebCore::DOMPasteAccessResponse': ['<WebCore/DOMPasteAccess.h>'], 400 'WebKit::DocumentEditingContextRequest': ['"DocumentEditingContext.h"'], 400 401 'WebCore::DragHandlingMethod': ['<WebCore/DragActions.h>'], 401 402 'WebCore::ExceptionDetails': ['<WebCore/JSDOMExceptionHandling.h>'], -
trunk/Source/WebKit/SourcesCocoa.txt
r243319 r243354 126 126 Shared/APIWebArchive.mm 127 127 Shared/APIWebArchiveResource.mm 128 Shared/DocumentEditingContext.mm 128 129 Shared/FocusedElementInformation.cpp 129 130 Shared/VisibleContentRectUpdateInfo.cpp -
trunk/Source/WebKit/UIProcess/WebPageProxy.h
r243328 r243354 277 277 struct AttributedString; 278 278 struct ColorSpaceData; 279 struct DocumentEditingContext; 280 struct DocumentEditingContextRequest; 279 281 struct EditingRange; 280 282 struct EditorState; … … 709 711 bool isScrollingOrZooming() const { return m_isScrollingOrZooming; } 710 712 void requestEvasionRectsAboveSelection(CompletionHandler<void(const Vector<WebCore::FloatRect>&)>&&); 713 void updateSelectionWithDelta(int64_t locationDelta, int64_t lengthDelta, CompletionHandler<void()>&&); 714 void requestDocumentEditingContext(WebKit::DocumentEditingContextRequest, CompletionHandler<void(WebKit::DocumentEditingContext)>&&); 711 715 #if ENABLE(DATA_INTERACTION) 712 716 void didHandleDragStartRequest(bool started); -
trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm
r243351 r243354 30 30 31 31 #import "APIUIClient.h" 32 #import "DocumentEditingContext.h" 32 33 #import "EditableImageController.h" 33 34 #import "EditingRange.h" … … 74 75 #import "_WKFocusedElementInfo.h" 75 76 #import "_WKInputDelegate.h" 77 #import "_WKTextInputContextInternal.h" 76 78 #import <CoreText/CTFont.h> 77 79 #import <CoreText/CTFontDescriptor.h> … … 6283 6285 } 6284 6286 6287 6288 static inline OptionSet<WebKit::DocumentEditingContextRequest::Options> toWebDocumentRequestOptions(UIWKDocumentRequestFlags flags) 6289 { 6290 OptionSet<WebKit::DocumentEditingContextRequest::Options> options; 6291 6292 if (flags & UIWKDocumentRequestText) 6293 options.add(WebKit::DocumentEditingContextRequest::Options::Text); 6294 if (flags & UIWKDocumentRequestAttributed) 6295 options.add(WebKit::DocumentEditingContextRequest::Options::AttributedText); 6296 if (flags & UIWKDocumentRequestRects) 6297 options.add(WebKit::DocumentEditingContextRequest::Options::Rects); 6298 if (flags & UIWKDocumentRequestSpatial) 6299 options.add(WebKit::DocumentEditingContextRequest::Options::Spatial); 6300 if (flags & UIWKDocumentRequestAnnotation) 6301 options.add(WebKit::DocumentEditingContextRequest::Options::Annotation); 6302 6303 return options; 6304 } 6305 6306 static WebKit::DocumentEditingContextRequest toWebRequest(UIWKDocumentRequest *request) 6307 { 6308 WebKit::DocumentEditingContextRequest webRequest = { 6309 .options = toWebDocumentRequestOptions(request.flags), 6310 .surroundingGranularity = toWKTextGranularity(request.surroundingGranularity), 6311 .granularityCount = request.granularityCount, 6312 .rect = request.documentRect 6313 }; 6314 6315 if (auto textInputContext = dynamic_objc_cast<_WKTextInputContext>(request.inputElementIdentifier)) 6316 webRequest.textInputContext = [textInputContext _textInputContext]; 6317 6318 return webRequest; 6319 } 6320 6321 - (void)adjustSelectionWithDelta:(NSRange)deltaRange completionHandler:(void (^)(void))completionHandler 6322 { 6323 // UIKit is putting casted signed integers into NSRange. Cast them back to reveal any negative values. 6324 _page->updateSelectionWithDelta(static_cast<int64_t>(deltaRange.location), static_cast<int64_t>(deltaRange.length), [capturedCompletionHandler = makeBlockPtr(completionHandler)] { 6325 capturedCompletionHandler(); 6326 }); 6327 } 6328 6329 - (void)requestDocumentContext:(UIWKDocumentRequest *)request completionHandler:(void (^)(UIWKDocumentContext *))completionHandler 6330 { 6331 auto webRequest = toWebRequest(request); 6332 OptionSet<WebKit::DocumentEditingContextRequest::Options> options = webRequest.options; 6333 _page->requestDocumentEditingContext(webRequest, [capturedCompletionHandler = makeBlockPtr(completionHandler), options] (WebKit::DocumentEditingContext editingContext) { 6334 capturedCompletionHandler(editingContext.toPlatformContext(options)); 6335 }); 6336 } 6337 6338 - (void)selectPositionAtPoint:(CGPoint)point withContextRequest:(UIWKDocumentRequest *)request completionHandler:(void (^)(UIWKDocumentContext *))completionHandler 6339 { 6340 // FIXME: Reduce to 1 message. 6341 [self selectPositionAtPoint:point completionHandler:^{ 6342 [self requestDocumentContext:request completionHandler:^(UIWKDocumentContext *context) { 6343 completionHandler(context); 6344 }]; 6345 }]; 6346 } 6347 6348 6285 6349 #pragma mark - UIDragInteractionDelegate 6286 6350 -
trunk/Source/WebKit/UIProcess/ios/WebPageProxyIOS.mm
r243327 r243354 32 32 #import "Connection.h" 33 33 #import "DataReference.h" 34 #import "DocumentEditingContext.h" 34 35 #import "EditingRange.h" 35 36 #import "GlobalFindInPageState.h" … … 1138 1139 } 1139 1140 1141 void WebPageProxy::updateSelectionWithDelta(int64_t locationDelta, int64_t lengthDelta, CompletionHandler<void()>&& completionHandler) 1142 { 1143 if (!hasRunningProcess()) { 1144 completionHandler(); 1145 return; 1146 } 1147 1148 m_process->connection()->sendWithAsyncReply(Messages::WebPage::UpdateSelectionWithDelta(locationDelta, lengthDelta), WTFMove(completionHandler), m_pageID); 1149 } 1150 1151 void WebPageProxy::requestDocumentEditingContext(WebKit::DocumentEditingContextRequest request, CompletionHandler<void(WebKit::DocumentEditingContext)>&& completionHandler) 1152 { 1153 if (!hasRunningProcess()) { 1154 completionHandler({ }); 1155 return; 1156 } 1157 1158 m_process->connection()->sendWithAsyncReply(Messages::WebPage::RequestDocumentEditingContext(request), WTFMove(completionHandler), m_pageID); 1159 } 1160 1140 1161 #if ENABLE(DATA_INTERACTION) 1141 1162 -
trunk/Source/WebKit/WebKit.xcodeproj/project.pbxproj
r243319 r243354 2710 2710 2D7DEE2E21269E4E00B9F73C /* UnifiedSource57-mm.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = "UnifiedSource57-mm.mm"; path = "DerivedSources/WebKit2/unified-sources/UnifiedSource57-mm.mm"; sourceTree = BUILT_PRODUCTS_DIR; }; 2711 2711 2D7DEE3121269E4E00B9F73C /* UnifiedSource12-mm.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = "UnifiedSource12-mm.mm"; path = "DerivedSources/WebKit2/unified-sources/UnifiedSource12-mm.mm"; sourceTree = BUILT_PRODUCTS_DIR; }; 2712 2D7FD190223C730F007887F1 /* DocumentEditingContext.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DocumentEditingContext.h; sourceTree = "<group>"; }; 2713 2D7FD191223C7310007887F1 /* DocumentEditingContext.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = DocumentEditingContext.mm; sourceTree = "<group>"; }; 2712 2714 2D819B99186275B3001F03D1 /* ViewGestureGeometryCollector.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ViewGestureGeometryCollector.cpp; sourceTree = "<group>"; }; 2713 2715 2D819B9A186275B3001F03D1 /* ViewGestureGeometryCollector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ViewGestureGeometryCollector.h; sourceTree = "<group>"; }; … … 5083 5085 5106D7C018BDBE73000AB166 /* ContextMenuContextData.h */, 5084 5086 99F642D21FABE378009621E9 /* CoordinateSystem.h */, 5087 2D7FD190223C730F007887F1 /* DocumentEditingContext.h */, 5088 2D7FD191223C7310007887F1 /* DocumentEditingContext.mm */, 5085 5089 C517388012DF8F4F00EE3F47 /* DragControllerAction.h */, 5086 5090 0FB659221208B4DB0044816C /* DrawingAreaInfo.h */, -
trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp
r243328 r243354 6588 6588 void WebPage::focusTextInputContext(const TextInputContext& textInputContext, CompletionHandler<void(bool)>&& completionHandler) 6589 6589 { 6590 completionHandler([&] { 6591 if (textInputContext.webPageIdentifier != m_pageID) 6592 return false; 6593 6594 auto* document = Document::allDocumentsMap().get(textInputContext.documentIdentifier); 6595 if (!document) 6596 return false; 6597 6598 if (document->page() != m_page.get()) 6599 return false; 6600 6601 auto* element = document->searchForElementByIdentifier(textInputContext.elementIdentifier); 6602 if (!element) 6603 return false; 6604 6590 RefPtr<Element> element = elementForTextInputContext(textInputContext); 6591 6592 if (element) 6605 6593 element->focus(); 6606 6594 6607 return true; 6608 }()); 6595 completionHandler(element); 6596 } 6597 6598 Element* WebPage::elementForTextInputContext(const TextInputContext& textInputContext) 6599 { 6600 if (textInputContext.webPageIdentifier != m_pageID) 6601 return nullptr; 6602 6603 auto* document = Document::allDocumentsMap().get(textInputContext.documentIdentifier); 6604 if (!document) 6605 return nullptr; 6606 6607 if (document->page() != m_page.get()) 6608 return nullptr; 6609 6610 return document->searchForElementByIdentifier(textInputContext.elementIdentifier); 6609 6611 } 6610 6612 -
trunk/Source/WebKit/WebProcess/WebPage/WebPage.h
r243328 r243354 687 687 bool forceAlwaysUserScalable() const { return m_forceAlwaysUserScalable; } 688 688 void setForceAlwaysUserScalable(bool); 689 690 void updateSelectionWithDelta(int64_t locationDelta, int64_t lengthDelta, CompletionHandler<void()>&&); 691 void requestDocumentEditingContext(WebKit::DocumentEditingContextRequest, CompletionHandler<void(WebKit::DocumentEditingContext)>&&); 689 692 #endif 690 693 … … 1166 1169 1167 1170 void configureLoggingChannel(const String&, WTFLogChannelState, WTFLogLevel); 1171 1172 WebCore::Element* elementForTextInputContext(const TextInputContext&); 1168 1173 1169 1174 #if ENABLE(APPLE_PAY) -
trunk/Source/WebKit/WebProcess/WebPage/WebPage.messages.in
r243345 r243354 111 111 HardwareKeyboardAvailabilityChanged(bool keyboardIsAttached) 112 112 SetIsShowingInputViewForFocusedElement(bool showingInputView) 113 UpdateSelectionWithDelta(int64_t locationDelta, int64_t lengthDelta) -> () Async 114 RequestDocumentEditingContext(struct WebKit::DocumentEditingContextRequest request) -> (struct WebKit::DocumentEditingContext response) Async 113 115 #endif 114 116 -
trunk/Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm
r243326 r243354 31 31 #import "AccessibilityIOS.h" 32 32 #import "DataReference.h" 33 #import "DocumentEditingContext.h" 33 34 #import "DrawingArea.h" 34 35 #import "EditingRange.h" … … 3313 3314 } 3314 3315 3316 void WebPage::updateSelectionWithDelta(int64_t locationDelta, int64_t lengthDelta, CompletionHandler<void()>&& completionHandler) 3317 { 3318 Ref<Frame> frame = corePage()->focusController().focusedOrMainFrame(); 3319 VisibleSelection selection = frame->selection().selection(); 3320 if (selection.isNone()) { 3321 completionHandler(); 3322 return; 3323 } 3324 3325 auto root = frame->selection().rootEditableElementOrDocumentElement(); 3326 auto range = selection.toNormalizedRange(); 3327 if (!root || !range) { 3328 completionHandler(); 3329 return; 3330 } 3331 3332 size_t selectionLocation; 3333 size_t selectionLength; 3334 TextIterator::getLocationAndLengthFromRange(root, range.get(), selectionLocation, selectionLength); 3335 3336 CheckedInt64 newSelectionLocation { selectionLocation }; 3337 CheckedInt64 newSelectionLength { selectionLength }; 3338 newSelectionLocation += locationDelta; 3339 newSelectionLength += lengthDelta; 3340 3341 if (newSelectionLocation.hasOverflowed() || newSelectionLength.hasOverflowed()) { 3342 completionHandler(); 3343 return; 3344 } 3345 3346 if (auto range = TextIterator::rangeFromLocationAndLength(root, newSelectionLocation.unsafeGet(), newSelectionLength.unsafeGet())) 3347 frame->selection().setSelectedRange(range.get(), DOWNSTREAM, WebCore::FrameSelection::ShouldCloseTyping::Yes, UserTriggered); 3348 3349 completionHandler(); 3350 } 3351 3352 static VisiblePosition moveByGranularityRespectingWordBoundary(Frame& frame, VisiblePosition& position, TextGranularity granularity, uint64_t granularityCount, SelectionDirection direction) 3353 { 3354 bool backwards = direction == DirectionBackward; 3355 auto farthestPositionInDirection = backwards ? startOfEditableContent(position) : endOfEditableContent(position); 3356 if (position == farthestPositionInDirection) 3357 return { }; 3358 3359 VisiblePosition currentPosition = position; 3360 VisiblePosition nextPosition; 3361 for (unsigned i = 0; i < granularityCount + 1; ++i) { 3362 nextPosition = positionOfNextBoundaryOfGranularity(currentPosition, granularity, direction); 3363 // FIXME (196127): We shouldn't need to do this, but have seen previousParagraphPosition go forwards. 3364 if ((backwards && nextPosition > currentPosition) || (!backwards && nextPosition < currentPosition)) 3365 break; 3366 if (nextPosition.isNull()) 3367 break; 3368 currentPosition = nextPosition; 3369 } 3370 3371 return backwards ? startOfWord(currentPosition) : endOfWord(currentPosition); 3372 } 3373 3374 static VisiblePosition visiblePositionForPointInRootViewCoordinates(Frame& frame, FloatPoint pointInRootViewCoordinates) 3375 { 3376 auto pointInDocument = frame.view()->rootViewToContents(roundedIntPoint(pointInRootViewCoordinates)); 3377 return frame.visiblePositionForPoint(pointInDocument); 3378 } 3379 3380 void WebPage::requestDocumentEditingContext(DocumentEditingContextRequest request, CompletionHandler<void(DocumentEditingContext)>&& completionHandler) 3381 { 3382 if (!request.options.contains(DocumentEditingContextRequest::Options::Text) && !request.options.contains(DocumentEditingContextRequest::Options::AttributedText)) { 3383 completionHandler({ }); 3384 return; 3385 } 3386 3387 m_page->focusController().focusedOrMainFrame().document()->updateLayoutIgnorePendingStylesheets(); 3388 3389 Ref<Frame> frame = m_page->focusController().focusedOrMainFrame(); 3390 VisibleSelection selection = frame->selection().selection(); 3391 3392 VisiblePosition rangeOfInterestStart; 3393 VisiblePosition rangeOfInterestEnd; 3394 VisiblePosition selectionStart = selection.visibleStart(); 3395 VisiblePosition selectionEnd = selection.visibleEnd(); 3396 3397 bool isSpatialRequest = request.options.contains(DocumentEditingContextRequest::Options::Spatial); 3398 bool wantsRects = request.options.contains(DocumentEditingContextRequest::Options::Rects); 3399 3400 if (auto textInputContext = request.textInputContext) { 3401 RefPtr<Element> element = elementForTextInputContext(*textInputContext); 3402 if (!element) { 3403 completionHandler({ }); 3404 return; 3405 } 3406 if (is<HTMLTextFormControlElement>(element)) { 3407 auto& textFormControlElement = downcast<HTMLTextFormControlElement>(*element); 3408 rangeOfInterestStart = textFormControlElement.visiblePositionForIndex(0); 3409 rangeOfInterestEnd = textFormControlElement.visiblePositionForIndex(textFormControlElement.value().length()); 3410 } else { 3411 rangeOfInterestStart = firstPositionInOrBeforeNode(element.get()); 3412 rangeOfInterestEnd = lastPositionInOrAfterNode(element.get()); 3413 } 3414 } else if (isSpatialRequest) { 3415 // FIXME: We might need to be a bit more careful that we get something useful (test the other corners?). 3416 rangeOfInterestStart = visiblePositionForPointInRootViewCoordinates(frame.get(), request.rect.minXMinYCorner()); 3417 rangeOfInterestEnd = visiblePositionForPointInRootViewCoordinates(frame.get(), request.rect.maxXMaxYCorner()); 3418 if (rangeOfInterestEnd < rangeOfInterestStart) 3419 std::exchange(rangeOfInterestStart, rangeOfInterestEnd); 3420 } else if (!selection.isNone()) { 3421 rangeOfInterestStart = selectionStart; 3422 rangeOfInterestEnd = selectionEnd; 3423 } 3424 3425 if (rangeOfInterestStart.isNull() || rangeOfInterestStart.isOrphan() || rangeOfInterestEnd.isNull() || rangeOfInterestEnd.isOrphan()) { 3426 completionHandler({ }); 3427 return; 3428 } 3429 3430 DocumentEditingContext context; 3431 3432 // The subset of the selection that is inside the range of interest. 3433 VisiblePosition startOfRangeOfInterestInSelection; 3434 VisiblePosition endOfRangeOfInterestInSelection; 3435 3436 auto selectionRange = selection.toNormalizedRange(); 3437 auto rangeOfInterest = makeRange(rangeOfInterestStart, rangeOfInterestEnd); 3438 if (selectionRange && rangesOverlap(rangeOfInterest.get(), selectionRange.get())) { 3439 startOfRangeOfInterestInSelection = rangeOfInterestStart > selectionStart ? rangeOfInterestStart : selectionStart; 3440 endOfRangeOfInterestInSelection = rangeOfInterestEnd < selectionEnd ? rangeOfInterestEnd : selectionEnd; 3441 } else { 3442 size_t rangeOfInterestLocation; 3443 size_t rangeOfInterestLength; 3444 RefPtr<Node> rootNode = rangeOfInterest->commonAncestorContainer(); 3445 if (!rootNode) { 3446 completionHandler({ }); 3447 return; 3448 } 3449 3450 RefPtr<ContainerNode> rootContainerNode = rootNode->isContainerNode() ? downcast<ContainerNode>(rootNode.get()) : rootNode->parentNode(); 3451 TextIterator::getLocationAndLengthFromRange(rootContainerNode.get(), rangeOfInterest.get(), rangeOfInterestLocation, rangeOfInterestLength); 3452 3453 CheckedSize midpointLocation { rangeOfInterestLocation }; 3454 midpointLocation += rangeOfInterestLength / 2; 3455 if (midpointLocation.hasOverflowed()) { 3456 completionHandler({ }); 3457 return; 3458 } 3459 3460 auto midpointRange = TextIterator::rangeFromLocationAndLength(rootContainerNode.get(), midpointLocation.unsafeGet(), 0); 3461 3462 auto midpoint = midpointRange->startPosition(); 3463 startOfRangeOfInterestInSelection = startOfWord(midpoint); 3464 if (startOfRangeOfInterestInSelection < rangeOfInterestStart) { 3465 startOfRangeOfInterestInSelection = endOfWord(midpoint); 3466 if (startOfRangeOfInterestInSelection > rangeOfInterestEnd) 3467 startOfRangeOfInterestInSelection = midpoint; 3468 } 3469 3470 endOfRangeOfInterestInSelection = startOfRangeOfInterestInSelection; 3471 } 3472 3473 VisiblePosition contextBeforeStart; 3474 VisiblePosition contextAfterEnd; 3475 if (request.granularityCount) { 3476 contextBeforeStart = moveByGranularityRespectingWordBoundary(frame.get(), rangeOfInterestStart, request.surroundingGranularity, request.granularityCount, DirectionBackward); 3477 contextAfterEnd = moveByGranularityRespectingWordBoundary(frame.get(), rangeOfInterestEnd, request.surroundingGranularity, request.granularityCount, DirectionForward); 3478 } else { 3479 contextBeforeStart = rangeOfInterestStart; 3480 contextAfterEnd = rangeOfInterestEnd; 3481 } 3482 3483 auto makeString = [&](VisiblePosition& start, VisiblePosition& end) -> NSAttributedString * { 3484 if (start.isNull() || end.isNull() || start == end) 3485 return nil; 3486 // FIXME: This should return editing-offset-compatible attributed strings if that option is requested. 3487 return adoptNS([[NSAttributedString alloc] initWithString:plainTextReplacingNoBreakSpace(start.deepEquivalent(), end.deepEquivalent())]).autorelease(); 3488 }; 3489 3490 context.contextBefore = makeString(contextBeforeStart, startOfRangeOfInterestInSelection); 3491 context.selectedText = makeString(startOfRangeOfInterestInSelection, endOfRangeOfInterestInSelection); 3492 context.contextAfter = makeString(endOfRangeOfInterestInSelection, contextAfterEnd); 3493 3494 auto compositionRange = frame->editor().compositionRange(); 3495 if (compositionRange && rangesOverlap(rangeOfInterest.get(), compositionRange.get())) { 3496 VisiblePosition compositionStart(compositionRange->startPosition()); 3497 VisiblePosition compositionEnd(compositionRange->endPosition()); 3498 3499 VisiblePosition relevantCompositionStart = rangeOfInterestStart > compositionStart ? rangeOfInterestStart : compositionStart; 3500 VisiblePosition relevantCompositionEnd = rangeOfInterestEnd < compositionEnd ? rangeOfInterestEnd : compositionEnd; 3501 3502 context.markedText = makeString(relevantCompositionStart, relevantCompositionEnd); 3503 context.selectedRangeInMarkedText.location = distanceBetweenPositions(relevantCompositionStart, startOfRangeOfInterestInSelection); 3504 context.selectedRangeInMarkedText.length = [context.selectedText.string length]; 3505 } 3506 3507 if (wantsRects) { 3508 TextIterator contextIterator(contextBeforeStart.deepEquivalent(), contextAfterEnd.deepEquivalent()); 3509 unsigned currentLocation = 0; 3510 while (!contextIterator.atEnd()) { 3511 unsigned length = contextIterator.text().length(); 3512 if (!length) { 3513 contextIterator.advance(); 3514 continue; 3515 } 3516 3517 DocumentEditingContext::TextRectAndRange rect; 3518 rect.rect = contextIterator.range()->absoluteBoundingBox(); 3519 rect.range = { currentLocation, length }; 3520 context.textRects.append(rect); 3521 3522 currentLocation += length; 3523 contextIterator.advance(); 3524 } 3525 } 3526 3527 // FIXME: Support Annotation option. 3528 3529 completionHandler(context); 3530 } 3531 3315 3532 } // namespace WebKit 3316 3533 -
trunk/Tools/ChangeLog
r243347 r243354 1 2019-03-21 Tim Horton <timothy_horton@apple.com> 2 3 Adopt UIWKDocumentContext 4 https://bugs.webkit.org/show_bug.cgi?id=196040 5 <rdar://problem/48642440> 6 7 Reviewed by Ryosuke Niwa. 8 9 * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj: 10 * TestWebKitAPI/Tests/WebKitCocoa/DocumentEditingContext.mm: Added. 11 (makeRequest): 12 (-[TestWKWebView synchronouslyRequestDocumentContext:]): 13 (-[TestWKWebView synchronouslyAdjustSelectionWithDelta:]): 14 (applyStyle): 15 (TEST): 16 Add tests for UIWKDocumentContext. 17 18 * TestWebKitAPI/Tests/WebKitCocoa/WKContentViewEditingActions.mm: 19 (TEST): 20 (recursiveFindWKContentView): Deleted. 21 * TestWebKitAPI/cocoa/TestWKWebView.h: 22 * TestWebKitAPI/cocoa/TestWKWebView.mm: 23 (recursiveFindWKContentView): 24 (-[TestWKWebView wkContentView]): 25 * TestWebKitAPI/ios/UIKitSPI.h: 26 Share the WKContentView finding code between tests. 27 1 28 2019-03-21 Simon Fraser <simon.fraser@apple.com> 2 29 -
trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj
r243324 r243354 99 99 2D70059621EDA0C6003463CB /* TabOutOfWebView.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2D70059521EDA0C6003463CB /* TabOutOfWebView.mm */; }; 100 100 2D70059921EDA4D0003463CB /* OffscreenWindow.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2D70059721EDA4D0003463CB /* OffscreenWindow.mm */; }; 101 2D7FD19322419087007887F1 /* DocumentEditingContext.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2D7FD19222419087007887F1 /* DocumentEditingContext.mm */; }; 101 102 2D838B1F1EEF3A5C009B980E /* WKContentViewEditingActions.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2D838B1E1EEF3A5B009B980E /* WKContentViewEditingActions.mm */; }; 102 103 2DADF26321CB8F32003D3E3A /* GetResourceData.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2DADF26221CB8F32003D3E3A /* GetResourceData.mm */; }; … … 1454 1455 2D70059721EDA4D0003463CB /* OffscreenWindow.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = OffscreenWindow.mm; sourceTree = "<group>"; }; 1455 1456 2D70059821EDA4D0003463CB /* OffscreenWindow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OffscreenWindow.h; sourceTree = "<group>"; }; 1457 2D7FD19222419087007887F1 /* DocumentEditingContext.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = DocumentEditingContext.mm; sourceTree = "<group>"; }; 1456 1458 2D8104CB1BEC13E70020DA46 /* FindInPage.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = FindInPage.mm; sourceTree = "<group>"; }; 1457 1459 2D838B1E1EEF3A5B009B980E /* WKContentViewEditingActions.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WKContentViewEditingActions.mm; sourceTree = "<group>"; }; … … 2549 2551 CEA7F57B20895F5B0078EF6E /* DidResignInputElementStrongPasswordAppearance.mm */, 2550 2552 518EE51A20A78CFB00E024F3 /* DoAfterNextPresentationUpdateAfterCrash.mm */, 2553 2D7FD19222419087007887F1 /* DocumentEditingContext.mm */, 2551 2554 518EE51620A78CDF00E024F3 /* DoubleDefersLoading.mm */, 2552 2555 518EE51720A78CDF00E024F3 /* DoubleDefersLoadingPlugin.mm */, … … 4072 4075 AD57AC211DA7465B00FF1BDE /* DidRemoveFrameFromHiearchyInPageCache.cpp in Sources */, 4073 4076 518EE51B20A78D0000E024F3 /* DoAfterNextPresentationUpdateAfterCrash.mm in Sources */, 4077 2D7FD19322419087007887F1 /* DocumentEditingContext.mm in Sources */, 4074 4078 7CCE7EEB1A411AE600447C4C /* DocumentStartUserScriptAlertCrash.cpp in Sources */, 4075 4079 7CCE7EBB1A411A7E00447C4C /* DOMHTMLTableCellCellAbove.mm in Sources */, -
trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/WKContentViewEditingActions.mm
r237266 r243354 35 35 #import <wtf/RetainPtr.h> 36 36 37 static UIView *recursiveFindWKContentView(UIView *view)38 {39 if ([view isKindOfClass:NSClassFromString(@"WKContentView")])40 return view;41 42 for (UIView *subview in view.subviews) {43 UIView *contentView = recursiveFindWKContentView(subview);44 if (contentView)45 return contentView;46 }47 48 return nil;49 }50 51 37 TEST(WebKit, WKContentViewEditingActions) 52 38 { … … 59 45 [webView stringByEvaluatingJavaScript:@"selectPlainText()"]; 60 46 61 UIView *contentView = recursiveFindWKContentView(webView.get());47 UIView *contentView = [webView wkContentView]; 62 48 63 49 __block bool done = false; -
trunk/Tools/TestWebKitAPI/cocoa/TestWKWebView.h
r242339 r243354 80 80 81 81 #if PLATFORM(IOS_FAMILY) 82 @interface WKContentView : UIView 83 @end 84 82 85 @interface TestWKWebView (IOSOnly) 83 86 @property (nonatomic, readonly) UIView <UITextInputPrivate, UITextInputMultiDocument> *textInputContentView; … … 87 90 - (_WKActivatedElementInfo *)activatedElementAtPosition:(CGPoint)position; 88 91 - (void)evaluateJavaScriptAndWaitForInputSessionToChange:(NSString *)script; 92 - (WKContentView *)wkContentView; 89 93 @end 90 94 #endif -
trunk/Tools/TestWebKitAPI/cocoa/TestWKWebView.mm
r242339 r243354 510 510 } 511 511 512 static WKContentView *recursiveFindWKContentView(UIView *view) 513 { 514 if ([view isKindOfClass:NSClassFromString(@"WKContentView")]) 515 return (WKContentView *)view; 516 517 for (UIView *subview in view.subviews) { 518 WKContentView *contentView = recursiveFindWKContentView(subview); 519 if (contentView) 520 return contentView; 521 } 522 523 return nil; 524 } 525 526 - (WKContentView *)wkContentView 527 { 528 return recursiveFindWKContentView(self); 529 } 530 512 531 @end 513 532 -
trunk/Tools/TestWebKitAPI/ios/UIKitSPI.h
r239026 r243354 142 142 @end 143 143 144 @interface UIWKDocumentContext : NSObject 145 146 @property (nonatomic, copy) NSObject *contextBefore; 147 @property (nonatomic, copy) NSObject *selectedText; 148 @property (nonatomic, copy) NSObject *contextAfter; 149 @property (nonatomic, copy) NSObject *markedText; 150 @property (nonatomic, assign) NSRange selectedRangeInMarkedText; 151 @property (nonatomic, copy) NSAttributedString *annotatedText; 152 153 - (NSArray<NSValue *> *)characterRectsForCharacterRange:(NSRange)range; 154 155 @end 156 157 typedef NS_OPTIONS(NSInteger, UIWKDocumentRequestFlags) { 158 UIWKDocumentRequestNone = 0, 159 UIWKDocumentRequestText = 1 << 0, 160 UIWKDocumentRequestAttributed = 1 << 1, 161 UIWKDocumentRequestRects = 1 << 2, 162 UIWKDocumentRequestSpatial = 1 << 3, 163 UIWKDocumentRequestAnnotation = 1 << 4, 164 }; 165 166 @interface UIWKDocumentRequest : NSObject 167 168 @property (nonatomic, assign) UIWKDocumentRequestFlags flags; 169 @property (nonatomic, assign) UITextGranularity surroundingGranularity; 170 @property (nonatomic, assign) NSInteger granularityCount; 171 @property (nonatomic, assign) CGRect documentRect; 172 @property (nonatomic, retain) id <NSCopying> inputElementIdentifier; 173 174 @end 175 144 176 #endif // PLATFORM(IOS_FAMILY)
Note:
See TracChangeset
for help on using the changeset viewer.