Diff
Modified: trunk/Source/WebCore/ChangeLog (243353 => 243354)
--- trunk/Source/WebCore/ChangeLog 2019-03-22 01:58:13 UTC (rev 243353)
+++ trunk/Source/WebCore/ChangeLog 2019-03-22 02:26:09 UTC (rev 243354)
@@ -1,3 +1,22 @@
+2019-03-21 Tim Horton <timothy_hor...@apple.com>
+
+ Adopt UIWKDocumentContext
+ https://bugs.webkit.org/show_bug.cgi?id=196040
+ <rdar://problem/48642440>
+
+ Reviewed by Ryosuke Niwa.
+
+ New API test: WebKit.DocumentEditingContext
+
+ * dom/Range.h:
+ * editing/TextGranularity.h:
+ Make TextGranularity encodable by providing EnumTraits.
+
+ * editing/TextIterator.cpp:
+ (WebCore::plainTextReplacingNoBreakSpace):
+ * editing/TextIterator.h:
+ Expose an nbsp-replacing variant of plainText that takes Positions instead of Ranges.
+
2019-03-21 Sihui Liu <sihui_...@apple.com>
Fix key path extraction code in IndexedDB to check own property
Modified: trunk/Source/WebCore/dom/Range.h (243353 => 243354)
--- trunk/Source/WebCore/dom/Range.h 2019-03-22 01:58:13 UTC (rev 243353)
+++ trunk/Source/WebCore/dom/Range.h 2019-03-22 02:26:09 UTC (rev 243354)
@@ -176,7 +176,7 @@
WEBCORE_EXPORT Ref<Range> rangeOfContents(Node&);
WEBCORE_EXPORT bool areRangesEqual(const Range*, const Range*);
-bool rangesOverlap(const Range*, const Range*);
+WEBCORE_EXPORT bool rangesOverlap(const Range*, const Range*);
inline bool documentOrderComparator(const Node* a, const Node* b)
{
Modified: trunk/Source/WebCore/editing/TextGranularity.h (243353 => 243354)
--- trunk/Source/WebCore/editing/TextGranularity.h 2019-03-22 01:58:13 UTC (rev 243353)
+++ trunk/Source/WebCore/editing/TextGranularity.h 2019-03-22 02:26:09 UTC (rev 243354)
@@ -43,3 +43,23 @@
};
} // namespace WebCore
+
+namespace WTF {
+
+template<> struct EnumTraits<WebCore::TextGranularity> {
+ using values = EnumValues<
+ WebCore::TextGranularity,
+ WebCore::TextGranularity::CharacterGranularity,
+ WebCore::TextGranularity::WordGranularity,
+ WebCore::TextGranularity::SentenceGranularity,
+ WebCore::TextGranularity::LineGranularity,
+ WebCore::TextGranularity::ParagraphGranularity,
+ WebCore::TextGranularity::DocumentGranularity,
+ WebCore::TextGranularity::SentenceBoundary,
+ WebCore::TextGranularity::LineBoundary,
+ WebCore::TextGranularity::ParagraphBoundary,
+ WebCore::TextGranularity::DocumentBoundary
+ >;
+};
+
+}
Modified: trunk/Source/WebCore/editing/TextIterator.cpp (243353 => 243354)
--- trunk/Source/WebCore/editing/TextIterator.cpp 2019-03-22 01:58:13 UTC (rev 243353)
+++ trunk/Source/WebCore/editing/TextIterator.cpp 2019-03-22 02:26:09 UTC (rev 243354)
@@ -2684,6 +2684,11 @@
return result;
}
+String plainTextReplacingNoBreakSpace(Position start, Position end, TextIteratorBehavior defaultBehavior, bool isDisplayString)
+{
+ return plainText(start, end, defaultBehavior, isDisplayString).replace(noBreakSpace, ' ');
+}
+
String plainText(const Range* range, TextIteratorBehavior defaultBehavior, bool isDisplayString)
{
if (!range)
Modified: trunk/Source/WebCore/editing/TextIterator.h (243353 => 243354)
--- trunk/Source/WebCore/editing/TextIterator.h 2019-03-22 01:58:13 UTC (rev 243353)
+++ trunk/Source/WebCore/editing/TextIterator.h 2019-03-22 02:26:09 UTC (rev 243354)
@@ -44,6 +44,7 @@
}
WEBCORE_EXPORT String plainText(Position start, Position end, TextIteratorBehavior = TextIteratorDefaultBehavior, bool isDisplayString = false);
+WEBCORE_EXPORT String plainTextReplacingNoBreakSpace(Position start, Position end, TextIteratorBehavior = TextIteratorDefaultBehavior, bool isDisplayString = false);
WEBCORE_EXPORT String plainText(const Range*, TextIteratorBehavior = TextIteratorDefaultBehavior, bool isDisplayString = false);
WEBCORE_EXPORT String plainTextReplacingNoBreakSpace(const Range*, TextIteratorBehavior = TextIteratorDefaultBehavior, bool isDisplayString = false);
@@ -102,7 +103,7 @@
class TextIterator {
WTF_MAKE_FAST_ALLOCATED;
public:
- explicit TextIterator(Position start, Position end, TextIteratorBehavior = TextIteratorDefaultBehavior);
+ WEBCORE_EXPORT explicit TextIterator(Position start, Position end, TextIteratorBehavior = TextIteratorDefaultBehavior);
WEBCORE_EXPORT explicit TextIterator(const Range*, TextIteratorBehavior = TextIteratorDefaultBehavior);
WEBCORE_EXPORT ~TextIterator();
Modified: trunk/Source/WebKit/ChangeLog (243353 => 243354)
--- trunk/Source/WebKit/ChangeLog 2019-03-22 01:58:13 UTC (rev 243353)
+++ trunk/Source/WebKit/ChangeLog 2019-03-22 02:26:09 UTC (rev 243354)
@@ -1,3 +1,59 @@
+2019-03-21 Tim Horton <timothy_hor...@apple.com>
+
+ Adopt UIWKDocumentContext
+ https://bugs.webkit.org/show_bug.cgi?id=196040
+ <rdar://problem/48642440>
+
+ Reviewed by Ryosuke Niwa.
+
+ * Platform/spi/ios/UIKitSPI.h:
+ * Scripts/webkit/messages.py:
+ * Shared/DocumentEditingContext.h: Added.
+ * Shared/DocumentEditingContext.mm: Added.
+ (WebKit::toNSRange):
+ (WebKit::DocumentEditingContext::toPlatformContext):
+ (IPC::ArgumentCoder<WebKit::DocumentEditingContext::Range>::encode):
+ (IPC::ArgumentCoder<WebKit::DocumentEditingContext::Range>::decode):
+ (IPC::ArgumentCoder<WebKit::DocumentEditingContext::TextRect>::encode):
+ (IPC::ArgumentCoder<WebKit::DocumentEditingContext::TextRect>::decode):
+ (IPC::ArgumentCoder<WebKit::DocumentEditingContext>::encode):
+ (IPC::ArgumentCoder<WebKit::DocumentEditingContext>::decode):
+ (IPC::ArgumentCoder<WebKit::DocumentEditingContextRequest>::encode):
+ (IPC::ArgumentCoder<WebKit::DocumentEditingContextRequest>::decode):
+ Add DocumentEditingContext(Request), and coders.
+ Also expose DocumentEditingContext::toPlatformContext, which populates
+ a UIWKDocumentContext with the relevant values.
+
+ * SourcesCocoa.txt:
+ * UIProcess/WebPageProxy.h:
+ * UIProcess/ios/WKContentViewInteraction.mm:
+ (toWebDocumentRequestOptions):
+ (toWebRequest):
+ (-[WKContentView adjustSelectionWithDelta:completionHandler:]):
+ (-[WKContentView requestDocumentContext:completionHandler:]):
+ (-[WKContentView selectPositionAtPoint:withContextRequest:completionHandler:]):
+ * UIProcess/ios/WebPageProxyIOS.mm:
+ (WebKit::WebPageProxy::adjustSelectionWithDelta):
+ (WebKit::WebPageProxy::requestDocumentEditingContext):
+ * WebKit.xcodeproj/project.pbxproj:
+ * WebProcess/WebPage/WebPage.h:
+ * WebProcess/WebPage/WebPage.messages.in:
+ Plumb DocumentEditingContext(Request) around.
+
+ * WebProcess/WebPage/ios/WebPageIOS.mm:
+ (WebKit::WebPage::adjustSelectionWithDelta):
+ Adjust the current selection given deltas to apply to the location and length.
+
+ (WebKit::visiblePositionAdjacentToVisiblePosition):
+ (WebKit::visiblePositionForPointInRootViewCoordinates):
+ (WebKit::WebPage::requestDocumentEditingContext):
+ Retrieve the relevant part of the selection, as well as the context,
+ given either the selection, or a rect.
+ If we're collecting context for a rect, we split the context between
+ before and after (except for the part that intersects the selection).
+ The three strings will always be directly adjacent, and any of the three
+ can sometimes be null.
+
2019-03-21 James Magahern <jmagah...@apple.com>
Long press gesture recognizers in WKWebView are conflicting with internal scroll view long press gesture recognizers
Modified: trunk/Source/WebKit/Platform/spi/ios/UIKitSPI.h (243353 => 243354)
--- trunk/Source/WebKit/Platform/spi/ios/UIKitSPI.h 2019-03-22 01:58:13 UTC (rev 243353)
+++ trunk/Source/WebKit/Platform/spi/ios/UIKitSPI.h 2019-03-22 02:26:09 UTC (rev 243354)
@@ -1140,6 +1140,36 @@
#endif
}
+@interface UIWKDocumentContext : NSObject
+
+@property (nonatomic, copy) NSObject *contextBefore;
+@property (nonatomic, copy) NSObject *selectedText;
+@property (nonatomic, copy) NSObject *contextAfter;
+@property (nonatomic, copy) NSObject *markedText;
+@property (nonatomic, assign) NSRange selectedRangeInMarkedText;
+@property (nonatomic, copy) NSAttributedString *annotatedText;
+
+- (void)addTextRect:(CGRect)rect forCharacterRange:(NSRange)range;
+
+@end
+
+typedef NS_OPTIONS(NSInteger, UIWKDocumentRequestFlags) {
+ UIWKDocumentRequestNone = 0,
+ UIWKDocumentRequestText = 1 << 0,
+ UIWKDocumentRequestAttributed = 1 << 1,
+ UIWKDocumentRequestRects = 1 << 2,
+ UIWKDocumentRequestSpatial = 1 << 3,
+ UIWKDocumentRequestAnnotation = 1 << 4,
+};
+
+@interface UIWKDocumentRequest : NSObject
+@property (nonatomic, assign) UIWKDocumentRequestFlags flags;
+@property (nonatomic, assign) UITextGranularity surroundingGranularity;
+@property (nonatomic, assign) NSInteger granularityCount;
+@property (nonatomic, assign) CGRect documentRect;
+@property (nonatomic, retain) id <NSCopying> inputElementIdentifier;
+@end
+
WTF_EXTERN_C_BEGIN
BOOL UIKeyboardEnabledInputModesAllowOneToManyShortcuts(void);
Modified: trunk/Source/WebKit/Scripts/webkit/messages.py (243353 => 243354)
--- trunk/Source/WebKit/Scripts/webkit/messages.py 2019-03-22 01:58:13 UTC (rev 243353)
+++ trunk/Source/WebKit/Scripts/webkit/messages.py 2019-03-22 02:26:09 UTC (rev 243354)
@@ -397,6 +397,7 @@
'PAL::SessionID': ['<pal/SessionID.h>'],
'WebCore::AutoplayEventFlags': ['<WebCore/AutoplayEvent.h>'],
'WebCore::DOMPasteAccessResponse': ['<WebCore/DOMPasteAccess.h>'],
+ 'WebKit::DocumentEditingContextRequest': ['"DocumentEditingContext.h"'],
'WebCore::DragHandlingMethod': ['<WebCore/DragActions.h>'],
'WebCore::ExceptionDetails': ['<WebCore/JSDOMExceptionHandling.h>'],
'WebCore::FileChooserSettings': ['<WebCore/FileChooser.h>'],
Added: trunk/Source/WebKit/Shared/DocumentEditingContext.h (0 => 243354)
--- trunk/Source/WebKit/Shared/DocumentEditingContext.h (rev 0)
+++ trunk/Source/WebKit/Shared/DocumentEditingContext.h 2019-03-22 02:26:09 UTC (rev 243354)
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2019 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#if PLATFORM(IOS_FAMILY)
+
+#include "ArgumentCoders.h"
+#include "AttributedString.h"
+#include "TextInputContext.h"
+#include <WebCore/FloatRect.h>
+#include <WebCore/TextGranularity.h>
+#include <wtf/OptionSet.h>
+#include <wtf/Optional.h>
+#include <wtf/Vector.h>
+
+OBJC_CLASS UIWKDocumentContext;
+
+namespace WebKit {
+
+struct DocumentEditingContextRequest {
+ enum class Options : uint8_t {
+ Text = 1 << 0,
+ AttributedText = 1 << 1,
+ Rects = 1 << 2,
+ Spatial = 1 << 3,
+ Annotation = 1 << 4,
+ };
+
+ OptionSet<Options> options;
+
+ WebCore::TextGranularity surroundingGranularity { WebCore::CharacterGranularity };
+ int64_t granularityCount { 0 };
+
+ WebCore::FloatRect rect;
+
+ Optional<WebKit::TextInputContext> textInputContext;
+};
+
+struct DocumentEditingContext {
+ UIWKDocumentContext *toPlatformContext(OptionSet<WebKit::DocumentEditingContextRequest::Options>);
+
+ AttributedString contextBefore;
+ AttributedString selectedText;
+ AttributedString contextAfter;
+ AttributedString markedText;
+ AttributedString annotatedText;
+
+ struct Range {
+ uint64_t location { 0 };
+ uint64_t length { 0 };
+ };
+
+ Range selectedRangeInMarkedText;
+
+ struct TextRectAndRange {
+ WebCore::FloatRect rect;
+ Range range;
+ };
+
+ Vector<TextRectAndRange> textRects;
+};
+
+}
+
+namespace IPC {
+template<> struct ArgumentCoder<WebKit::DocumentEditingContext::Range> {
+ static void encode(Encoder&, const WebKit::DocumentEditingContext::Range&);
+ static Optional<WebKit::DocumentEditingContext::Range> decode(Decoder&);
+};
+
+template<> struct ArgumentCoder<WebKit::DocumentEditingContext::TextRectAndRange> {
+ static void encode(Encoder&, const WebKit::DocumentEditingContext::TextRectAndRange&);
+ static Optional<WebKit::DocumentEditingContext::TextRectAndRange> decode(Decoder&);
+};
+
+template<> struct ArgumentCoder<WebKit::DocumentEditingContext> {
+ static void encode(Encoder&, const WebKit::DocumentEditingContext&);
+ static Optional<WebKit::DocumentEditingContext> decode(Decoder&);
+};
+
+template<> struct ArgumentCoder<WebKit::DocumentEditingContextRequest> {
+ static void encode(Encoder&, const WebKit::DocumentEditingContextRequest&);
+ static Optional<WebKit::DocumentEditingContextRequest> decode(Decoder&);
+};
+}
+
+#endif
Added: trunk/Source/WebKit/Shared/DocumentEditingContext.mm (0 => 243354)
--- trunk/Source/WebKit/Shared/DocumentEditingContext.mm (rev 0)
+++ trunk/Source/WebKit/Shared/DocumentEditingContext.mm 2019-03-22 02:26:09 UTC (rev 243354)
@@ -0,0 +1,208 @@
+/*
+ * Copyright (C) 2019 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "DocumentEditingContext.h"
+
+#if PLATFORM(IOS_FAMILY)
+
+#include "TextInputContext.h"
+#include "UIKitSPI.h"
+#include "WebCoreArgumentCoders.h"
+
+namespace WebKit {
+
+static inline NSRange toNSRange(DocumentEditingContext::Range range)
+{
+ return NSMakeRange(range.location, range.length);
+}
+
+UIWKDocumentContext *DocumentEditingContext::toPlatformContext(OptionSet<DocumentEditingContextRequest::Options> options)
+{
+ RetainPtr<UIWKDocumentContext> platformContext = adoptNS([[NSClassFromString(@"UIWKDocumentContext") alloc] init]);
+
+ if (options.contains(DocumentEditingContextRequest::Options::AttributedText)) {
+ [platformContext setContextBefore:contextBefore.string.get()];
+ [platformContext setSelectedText:selectedText.string.get()];
+ [platformContext setContextAfter:contextAfter.string.get()];
+ [platformContext setMarkedText:markedText.string.get()];
+ } else if (options.contains(DocumentEditingContextRequest::Options::Text)) {
+ [platformContext setContextBefore:[contextBefore.string string]];
+ [platformContext setSelectedText:[selectedText.string string]];
+ [platformContext setContextAfter:[contextAfter.string string]];
+ [platformContext setMarkedText:[markedText.string string]];
+ }
+
+ [platformContext setSelectedRangeInMarkedText:toNSRange(selectedRangeInMarkedText)];
+
+ for (const auto& rect : textRects)
+ [platformContext addTextRect:rect.rect forCharacterRange:toNSRange(rect.range)];
+
+ [platformContext setAnnotatedText:annotatedText.string.get()];
+
+ return platformContext.autorelease();
+}
+
+}
+
+namespace IPC {
+
+void ArgumentCoder<WebKit::DocumentEditingContext::Range>::encode(Encoder& encoder, const WebKit::DocumentEditingContext::Range& range)
+{
+ encoder << range.location;
+ encoder << range.length;
+}
+
+Optional<WebKit::DocumentEditingContext::Range> ArgumentCoder<WebKit::DocumentEditingContext::Range>::decode(Decoder& decoder)
+{
+ WebKit::DocumentEditingContext::Range range;
+
+ if (!decoder.decode(range.location))
+ return WTF::nullopt;
+ if (!decoder.decode(range.length))
+ return WTF::nullopt;
+
+ return range;
+}
+
+void ArgumentCoder<WebKit::DocumentEditingContext::TextRectAndRange>::encode(Encoder& encoder, const WebKit::DocumentEditingContext::TextRectAndRange& rect)
+{
+ encoder << rect.rect;
+ encoder << rect.range;
+}
+
+Optional<WebKit::DocumentEditingContext::TextRectAndRange> ArgumentCoder<WebKit::DocumentEditingContext::TextRectAndRange>::decode(Decoder& decoder)
+{
+ WebKit::DocumentEditingContext::TextRectAndRange rect;
+
+ if (!decoder.decode(rect.rect))
+ return WTF::nullopt;
+
+ Optional<WebKit::DocumentEditingContext::Range> range;
+ decoder >> range;
+ if (!range)
+ return WTF::nullopt;
+ rect.range = *range;
+
+ return rect;
+}
+
+void ArgumentCoder<WebKit::DocumentEditingContext>::encode(Encoder& encoder, const WebKit::DocumentEditingContext& context)
+{
+ encoder << context.contextBefore;
+ encoder << context.selectedText;
+ encoder << context.contextAfter;
+ encoder << context.markedText;
+ encoder << context.annotatedText;
+
+ encoder << context.selectedRangeInMarkedText;
+
+ encoder << context.textRects;
+}
+
+Optional<WebKit::DocumentEditingContext> ArgumentCoder<WebKit::DocumentEditingContext>::decode(Decoder& decoder)
+{
+ WebKit::DocumentEditingContext context;
+
+ Optional<WebKit::AttributedString> contextBefore;
+ decoder >> contextBefore;
+ if (!contextBefore)
+ return WTF::nullopt;
+ context.contextBefore = *contextBefore;
+
+ Optional<WebKit::AttributedString> selectedText;
+ decoder >> selectedText;
+ if (!selectedText)
+ return WTF::nullopt;
+ context.selectedText = *selectedText;
+
+ Optional<WebKit::AttributedString> contextAfter;
+ decoder >> contextAfter;
+ if (!contextAfter)
+ return WTF::nullopt;
+ context.contextAfter = *contextAfter;
+
+ Optional<WebKit::AttributedString> markedText;
+ decoder >> markedText;
+ if (!markedText)
+ return WTF::nullopt;
+ context.markedText = *markedText;
+
+ Optional<WebKit::AttributedString> annotatedText;
+ decoder >> annotatedText;
+ if (!annotatedText)
+ return WTF::nullopt;
+ context.annotatedText = *annotatedText;
+
+ Optional<WebKit::DocumentEditingContext::Range> selectedRangeInMarkedText;
+ decoder >> selectedRangeInMarkedText;
+ if (!selectedRangeInMarkedText)
+ return WTF::nullopt;
+ context.selectedRangeInMarkedText = *selectedRangeInMarkedText;
+
+ if (!decoder.decode(context.textRects))
+ return WTF::nullopt;
+
+ return context;
+}
+
+void ArgumentCoder<WebKit::DocumentEditingContextRequest>::encode(Encoder& encoder, const WebKit::DocumentEditingContextRequest& request)
+{
+ encoder << request.options;
+ encoder << request.surroundingGranularity;
+ encoder << request.granularityCount;
+ encoder << request.rect;
+ encoder << request.textInputContext;
+}
+
+Optional<WebKit::DocumentEditingContextRequest> ArgumentCoder<WebKit::DocumentEditingContextRequest>::decode(Decoder& decoder)
+{
+ WebKit::DocumentEditingContextRequest request;
+
+ if (!decoder.decode(request.options))
+ return WTF::nullopt;
+
+ if (!decoder.decode(request.surroundingGranularity))
+ return WTF::nullopt;
+
+ if (!decoder.decode(request.granularityCount))
+ return WTF::nullopt;
+
+ if (!decoder.decode(request.rect))
+ return WTF::nullopt;
+
+ Optional<Optional<WebKit::TextInputContext>> optionalTextInputContext;
+ decoder >> optionalTextInputContext;
+ if (!optionalTextInputContext)
+ return WTF::nullopt;
+
+ request.textInputContext = optionalTextInputContext.value();
+
+ return request;
+}
+
+}
+
+#endif
Modified: trunk/Source/WebKit/SourcesCocoa.txt (243353 => 243354)
--- trunk/Source/WebKit/SourcesCocoa.txt 2019-03-22 01:58:13 UTC (rev 243353)
+++ trunk/Source/WebKit/SourcesCocoa.txt 2019-03-22 02:26:09 UTC (rev 243354)
@@ -125,6 +125,7 @@
Shared/APIWebArchive.mm
Shared/APIWebArchiveResource.mm
+Shared/DocumentEditingContext.mm
Shared/FocusedElementInformation.cpp
Shared/VisibleContentRectUpdateInfo.cpp
Shared/WebSQLiteDatabaseTracker.cpp
Modified: trunk/Source/WebKit/UIProcess/WebPageProxy.h (243353 => 243354)
--- trunk/Source/WebKit/UIProcess/WebPageProxy.h 2019-03-22 01:58:13 UTC (rev 243353)
+++ trunk/Source/WebKit/UIProcess/WebPageProxy.h 2019-03-22 02:26:09 UTC (rev 243354)
@@ -276,6 +276,8 @@
struct AttributedString;
struct ColorSpaceData;
+struct DocumentEditingContext;
+struct DocumentEditingContextRequest;
struct EditingRange;
struct EditorState;
struct FrameInfoData;
@@ -708,6 +710,8 @@
void hardwareKeyboardAvailabilityChanged(bool keyboardIsAttached);
bool isScrollingOrZooming() const { return m_isScrollingOrZooming; }
void requestEvasionRectsAboveSelection(CompletionHandler<void(const Vector<WebCore::FloatRect>&)>&&);
+ void updateSelectionWithDelta(int64_t locationDelta, int64_t lengthDelta, CompletionHandler<void()>&&);
+ void requestDocumentEditingContext(WebKit::DocumentEditingContextRequest, CompletionHandler<void(WebKit::DocumentEditingContext)>&&);
#if ENABLE(DATA_INTERACTION)
void didHandleDragStartRequest(bool started);
void didHandleAdditionalDragItemsRequest(bool added);
Modified: trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm (243353 => 243354)
--- trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm 2019-03-22 01:58:13 UTC (rev 243353)
+++ trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm 2019-03-22 02:26:09 UTC (rev 243354)
@@ -29,6 +29,7 @@
#if PLATFORM(IOS_FAMILY)
#import "APIUIClient.h"
+#import "DocumentEditingContext.h"
#import "EditableImageController.h"
#import "EditingRange.h"
#import "InputViewUpdateDeferrer.h"
@@ -73,6 +74,7 @@
#import "_WKElementAction.h"
#import "_WKFocusedElementInfo.h"
#import "_WKInputDelegate.h"
+#import "_WKTextInputContextInternal.h"
#import <CoreText/CTFont.h>
#import <CoreText/CTFontDescriptor.h>
#import <MobileCoreServices/UTCoreTypes.h>
@@ -6282,6 +6284,68 @@
return nil;
}
+
+static inline OptionSet<WebKit::DocumentEditingContextRequest::Options> toWebDocumentRequestOptions(UIWKDocumentRequestFlags flags)
+{
+ OptionSet<WebKit::DocumentEditingContextRequest::Options> options;
+
+ if (flags & UIWKDocumentRequestText)
+ options.add(WebKit::DocumentEditingContextRequest::Options::Text);
+ if (flags & UIWKDocumentRequestAttributed)
+ options.add(WebKit::DocumentEditingContextRequest::Options::AttributedText);
+ if (flags & UIWKDocumentRequestRects)
+ options.add(WebKit::DocumentEditingContextRequest::Options::Rects);
+ if (flags & UIWKDocumentRequestSpatial)
+ options.add(WebKit::DocumentEditingContextRequest::Options::Spatial);
+ if (flags & UIWKDocumentRequestAnnotation)
+ options.add(WebKit::DocumentEditingContextRequest::Options::Annotation);
+
+ return options;
+}
+
+static WebKit::DocumentEditingContextRequest toWebRequest(UIWKDocumentRequest *request)
+{
+ WebKit::DocumentEditingContextRequest webRequest = {
+ .options = toWebDocumentRequestOptions(request.flags),
+ .surroundingGranularity = toWKTextGranularity(request.surroundingGranularity),
+ .granularityCount = request.granularityCount,
+ .rect = request.documentRect
+ };
+
+ if (auto textInputContext = dynamic_objc_cast<_WKTextInputContext>(request.inputElementIdentifier))
+ webRequest.textInputContext = [textInputContext _textInputContext];
+
+ return webRequest;
+}
+
+- (void)adjustSelectionWithDelta:(NSRange)deltaRange completionHandler:(void (^)(void))completionHandler
+{
+ // UIKit is putting casted signed integers into NSRange. Cast them back to reveal any negative values.
+ _page->updateSelectionWithDelta(static_cast<int64_t>(deltaRange.location), static_cast<int64_t>(deltaRange.length), [capturedCompletionHandler = makeBlockPtr(completionHandler)] {
+ capturedCompletionHandler();
+ });
+}
+
+- (void)requestDocumentContext:(UIWKDocumentRequest *)request completionHandler:(void (^)(UIWKDocumentContext *))completionHandler
+{
+ auto webRequest = toWebRequest(request);
+ OptionSet<WebKit::DocumentEditingContextRequest::Options> options = webRequest.options;
+ _page->requestDocumentEditingContext(webRequest, [capturedCompletionHandler = makeBlockPtr(completionHandler), options] (WebKit::DocumentEditingContext editingContext) {
+ capturedCompletionHandler(editingContext.toPlatformContext(options));
+ });
+}
+
+- (void)selectPositionAtPoint:(CGPoint)point withContextRequest:(UIWKDocumentRequest *)request completionHandler:(void (^)(UIWKDocumentContext *))completionHandler
+{
+ // FIXME: Reduce to 1 message.
+ [self selectPositionAtPoint:point completionHandler:^{
+ [self requestDocumentContext:request completionHandler:^(UIWKDocumentContext *context) {
+ completionHandler(context);
+ }];
+ }];
+}
+
+
#pragma mark - UIDragInteractionDelegate
- (BOOL)_dragInteraction:(UIDragInteraction *)interaction shouldDelayCompetingGestureRecognizer:(UIGestureRecognizer *)competingGestureRecognizer
Modified: trunk/Source/WebKit/UIProcess/ios/WebPageProxyIOS.mm (243353 => 243354)
--- trunk/Source/WebKit/UIProcess/ios/WebPageProxyIOS.mm 2019-03-22 01:58:13 UTC (rev 243353)
+++ trunk/Source/WebKit/UIProcess/ios/WebPageProxyIOS.mm 2019-03-22 02:26:09 UTC (rev 243354)
@@ -31,6 +31,7 @@
#import "APIUIClient.h"
#import "Connection.h"
#import "DataReference.h"
+#import "DocumentEditingContext.h"
#import "EditingRange.h"
#import "GlobalFindInPageState.h"
#import "InteractionInformationAtPosition.h"
@@ -1137,6 +1138,26 @@
m_process->connection()->sendWithAsyncReply(Messages::WebPage::RequestEvasionRectsAboveSelection(), WTFMove(callback), m_pageID);
}
+void WebPageProxy::updateSelectionWithDelta(int64_t locationDelta, int64_t lengthDelta, CompletionHandler<void()>&& completionHandler)
+{
+ if (!hasRunningProcess()) {
+ completionHandler();
+ return;
+ }
+
+ m_process->connection()->sendWithAsyncReply(Messages::WebPage::UpdateSelectionWithDelta(locationDelta, lengthDelta), WTFMove(completionHandler), m_pageID);
+}
+
+void WebPageProxy::requestDocumentEditingContext(WebKit::DocumentEditingContextRequest request, CompletionHandler<void(WebKit::DocumentEditingContext)>&& completionHandler)
+{
+ if (!hasRunningProcess()) {
+ completionHandler({ });
+ return;
+ }
+
+ m_process->connection()->sendWithAsyncReply(Messages::WebPage::RequestDocumentEditingContext(request), WTFMove(completionHandler), m_pageID);
+}
+
#if ENABLE(DATA_INTERACTION)
void WebPageProxy::didHandleDragStartRequest(bool started)
Modified: trunk/Source/WebKit/WebKit.xcodeproj/project.pbxproj (243353 => 243354)
--- trunk/Source/WebKit/WebKit.xcodeproj/project.pbxproj 2019-03-22 01:58:13 UTC (rev 243353)
+++ trunk/Source/WebKit/WebKit.xcodeproj/project.pbxproj 2019-03-22 02:26:09 UTC (rev 243354)
@@ -2709,6 +2709,8 @@
2D7DEE2721269E4E00B9F73C /* UnifiedSource13.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = UnifiedSource13.cpp; path = "DerivedSources/WebKit2/unified-sources/UnifiedSource13.cpp"; sourceTree = BUILT_PRODUCTS_DIR; };
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; };
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; };
+ 2D7FD190223C730F007887F1 /* DocumentEditingContext.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DocumentEditingContext.h; sourceTree = "<group>"; };
+ 2D7FD191223C7310007887F1 /* DocumentEditingContext.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = DocumentEditingContext.mm; sourceTree = "<group>"; };
2D819B99186275B3001F03D1 /* ViewGestureGeometryCollector.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ViewGestureGeometryCollector.cpp; sourceTree = "<group>"; };
2D819B9A186275B3001F03D1 /* ViewGestureGeometryCollector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ViewGestureGeometryCollector.h; sourceTree = "<group>"; };
2D819B9B186275B3001F03D1 /* ViewGestureGeometryCollector.messages.in */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = ViewGestureGeometryCollector.messages.in; sourceTree = "<group>"; };
@@ -5082,6 +5084,8 @@
5106D7BF18BDBE73000AB166 /* ContextMenuContextData.cpp */,
5106D7C018BDBE73000AB166 /* ContextMenuContextData.h */,
99F642D21FABE378009621E9 /* CoordinateSystem.h */,
+ 2D7FD190223C730F007887F1 /* DocumentEditingContext.h */,
+ 2D7FD191223C7310007887F1 /* DocumentEditingContext.mm */,
C517388012DF8F4F00EE3F47 /* DragControllerAction.h */,
0FB659221208B4DB0044816C /* DrawingAreaInfo.h */,
2D9CD5EE21FA75EE0029ACFA /* EditingRange.cpp */,
Modified: trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp (243353 => 243354)
--- trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp 2019-03-22 01:58:13 UTC (rev 243353)
+++ trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp 2019-03-22 02:26:09 UTC (rev 243354)
@@ -6587,25 +6587,27 @@
void WebPage::focusTextInputContext(const TextInputContext& textInputContext, CompletionHandler<void(bool)>&& completionHandler)
{
- completionHandler([&] {
- if (textInputContext.webPageIdentifier != m_pageID)
- return false;
+ RefPtr<Element> element = elementForTextInputContext(textInputContext);
- auto* document = Document::allDocumentsMap().get(textInputContext.documentIdentifier);
- if (!document)
- return false;
+ if (element)
+ element->focus();
- if (document->page() != m_page.get())
- return false;
+ completionHandler(element);
+}
- auto* element = document->searchForElementByIdentifier(textInputContext.elementIdentifier);
- if (!element)
- return false;
+Element* WebPage::elementForTextInputContext(const TextInputContext& textInputContext)
+{
+ if (textInputContext.webPageIdentifier != m_pageID)
+ return nullptr;
- element->focus();
+ auto* document = Document::allDocumentsMap().get(textInputContext.documentIdentifier);
+ if (!document)
+ return nullptr;
- return true;
- }());
+ if (document->page() != m_page.get())
+ return nullptr;
+
+ return document->searchForElementByIdentifier(textInputContext.elementIdentifier);
}
void WebPage::configureLoggingChannel(const String& channelName, WTFLogChannelState state, WTFLogLevel level)
Modified: trunk/Source/WebKit/WebProcess/WebPage/WebPage.h (243353 => 243354)
--- trunk/Source/WebKit/WebProcess/WebPage/WebPage.h 2019-03-22 01:58:13 UTC (rev 243353)
+++ trunk/Source/WebKit/WebProcess/WebPage/WebPage.h 2019-03-22 02:26:09 UTC (rev 243354)
@@ -686,6 +686,9 @@
bool forceAlwaysUserScalable() const { return m_forceAlwaysUserScalable; }
void setForceAlwaysUserScalable(bool);
+
+ void updateSelectionWithDelta(int64_t locationDelta, int64_t lengthDelta, CompletionHandler<void()>&&);
+ void requestDocumentEditingContext(WebKit::DocumentEditingContextRequest, CompletionHandler<void(WebKit::DocumentEditingContext)>&&);
#endif
#if PLATFORM(IOS_FAMILY) && ENABLE(IOS_TOUCH_EVENTS)
@@ -1166,6 +1169,8 @@
void configureLoggingChannel(const String&, WTFLogChannelState, WTFLogLevel);
+ WebCore::Element* elementForTextInputContext(const TextInputContext&);
+
#if ENABLE(APPLE_PAY)
WebPaymentCoordinator* paymentCoordinator();
#endif
Modified: trunk/Source/WebKit/WebProcess/WebPage/WebPage.messages.in (243353 => 243354)
--- trunk/Source/WebKit/WebProcess/WebPage/WebPage.messages.in 2019-03-22 01:58:13 UTC (rev 243353)
+++ trunk/Source/WebKit/WebProcess/WebPage/WebPage.messages.in 2019-03-22 02:26:09 UTC (rev 243354)
@@ -110,6 +110,8 @@
RequestFocusedElementInformation(WebKit::CallbackID callbackID)
HardwareKeyboardAvailabilityChanged(bool keyboardIsAttached)
SetIsShowingInputViewForFocusedElement(bool showingInputView)
+ UpdateSelectionWithDelta(int64_t locationDelta, int64_t lengthDelta) -> () Async
+ RequestDocumentEditingContext(struct WebKit::DocumentEditingContextRequest request) -> (struct WebKit::DocumentEditingContext response) Async
#endif
SetControlledByAutomation(bool controlled)
Modified: trunk/Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm (243353 => 243354)
--- trunk/Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm 2019-03-22 01:58:13 UTC (rev 243353)
+++ trunk/Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm 2019-03-22 02:26:09 UTC (rev 243354)
@@ -30,6 +30,7 @@
#import "AccessibilityIOS.h"
#import "DataReference.h"
+#import "DocumentEditingContext.h"
#import "DrawingArea.h"
#import "EditingRange.h"
#import "EditorState.h"
@@ -3312,6 +3313,222 @@
#endif
}
+void WebPage::updateSelectionWithDelta(int64_t locationDelta, int64_t lengthDelta, CompletionHandler<void()>&& completionHandler)
+{
+ Ref<Frame> frame = corePage()->focusController().focusedOrMainFrame();
+ VisibleSelection selection = frame->selection().selection();
+ if (selection.isNone()) {
+ completionHandler();
+ return;
+ }
+
+ auto root = frame->selection().rootEditableElementOrDocumentElement();
+ auto range = selection.toNormalizedRange();
+ if (!root || !range) {
+ completionHandler();
+ return;
+ }
+
+ size_t selectionLocation;
+ size_t selectionLength;
+ TextIterator::getLocationAndLengthFromRange(root, range.get(), selectionLocation, selectionLength);
+
+ CheckedInt64 newSelectionLocation { selectionLocation };
+ CheckedInt64 newSelectionLength { selectionLength };
+ newSelectionLocation += locationDelta;
+ newSelectionLength += lengthDelta;
+
+ if (newSelectionLocation.hasOverflowed() || newSelectionLength.hasOverflowed()) {
+ completionHandler();
+ return;
+ }
+
+ if (auto range = TextIterator::rangeFromLocationAndLength(root, newSelectionLocation.unsafeGet(), newSelectionLength.unsafeGet()))
+ frame->selection().setSelectedRange(range.get(), DOWNSTREAM, WebCore::FrameSelection::ShouldCloseTyping::Yes, UserTriggered);
+
+ completionHandler();
+}
+
+static VisiblePosition moveByGranularityRespectingWordBoundary(Frame& frame, VisiblePosition& position, TextGranularity granularity, uint64_t granularityCount, SelectionDirection direction)
+{
+ bool backwards = direction == DirectionBackward;
+ auto farthestPositionInDirection = backwards ? startOfEditableContent(position) : endOfEditableContent(position);
+ if (position == farthestPositionInDirection)
+ return { };
+
+ VisiblePosition currentPosition = position;
+ VisiblePosition nextPosition;
+ for (unsigned i = 0; i < granularityCount + 1; ++i) {
+ nextPosition = positionOfNextBoundaryOfGranularity(currentPosition, granularity, direction);
+ // FIXME (196127): We shouldn't need to do this, but have seen previousParagraphPosition go forwards.
+ if ((backwards && nextPosition > currentPosition) || (!backwards && nextPosition < currentPosition))
+ break;
+ if (nextPosition.isNull())
+ break;
+ currentPosition = nextPosition;
+ }
+
+ return backwards ? startOfWord(currentPosition) : endOfWord(currentPosition);
+}
+
+static VisiblePosition visiblePositionForPointInRootViewCoordinates(Frame& frame, FloatPoint pointInRootViewCoordinates)
+{
+ auto pointInDocument = frame.view()->rootViewToContents(roundedIntPoint(pointInRootViewCoordinates));
+ return frame.visiblePositionForPoint(pointInDocument);
+}
+
+void WebPage::requestDocumentEditingContext(DocumentEditingContextRequest request, CompletionHandler<void(DocumentEditingContext)>&& completionHandler)
+{
+ if (!request.options.contains(DocumentEditingContextRequest::Options::Text) && !request.options.contains(DocumentEditingContextRequest::Options::AttributedText)) {
+ completionHandler({ });
+ return;
+ }
+
+ m_page->focusController().focusedOrMainFrame().document()->updateLayoutIgnorePendingStylesheets();
+
+ Ref<Frame> frame = m_page->focusController().focusedOrMainFrame();
+ VisibleSelection selection = frame->selection().selection();
+
+ VisiblePosition rangeOfInterestStart;
+ VisiblePosition rangeOfInterestEnd;
+ VisiblePosition selectionStart = selection.visibleStart();
+ VisiblePosition selectionEnd = selection.visibleEnd();
+
+ bool isSpatialRequest = request.options.contains(DocumentEditingContextRequest::Options::Spatial);
+ bool wantsRects = request.options.contains(DocumentEditingContextRequest::Options::Rects);
+
+ if (auto textInputContext = request.textInputContext) {
+ RefPtr<Element> element = elementForTextInputContext(*textInputContext);
+ if (!element) {
+ completionHandler({ });
+ return;
+ }
+ if (is<HTMLTextFormControlElement>(element)) {
+ auto& textFormControlElement = downcast<HTMLTextFormControlElement>(*element);
+ rangeOfInterestStart = textFormControlElement.visiblePositionForIndex(0);
+ rangeOfInterestEnd = textFormControlElement.visiblePositionForIndex(textFormControlElement.value().length());
+ } else {
+ rangeOfInterestStart = firstPositionInOrBeforeNode(element.get());
+ rangeOfInterestEnd = lastPositionInOrAfterNode(element.get());
+ }
+ } else if (isSpatialRequest) {
+ // FIXME: We might need to be a bit more careful that we get something useful (test the other corners?).
+ rangeOfInterestStart = visiblePositionForPointInRootViewCoordinates(frame.get(), request.rect.minXMinYCorner());
+ rangeOfInterestEnd = visiblePositionForPointInRootViewCoordinates(frame.get(), request.rect.maxXMaxYCorner());
+ if (rangeOfInterestEnd < rangeOfInterestStart)
+ std::exchange(rangeOfInterestStart, rangeOfInterestEnd);
+ } else if (!selection.isNone()) {
+ rangeOfInterestStart = selectionStart;
+ rangeOfInterestEnd = selectionEnd;
+ }
+
+ if (rangeOfInterestStart.isNull() || rangeOfInterestStart.isOrphan() || rangeOfInterestEnd.isNull() || rangeOfInterestEnd.isOrphan()) {
+ completionHandler({ });
+ return;
+ }
+
+ DocumentEditingContext context;
+
+ // The subset of the selection that is inside the range of interest.
+ VisiblePosition startOfRangeOfInterestInSelection;
+ VisiblePosition endOfRangeOfInterestInSelection;
+
+ auto selectionRange = selection.toNormalizedRange();
+ auto rangeOfInterest = makeRange(rangeOfInterestStart, rangeOfInterestEnd);
+ if (selectionRange && rangesOverlap(rangeOfInterest.get(), selectionRange.get())) {
+ startOfRangeOfInterestInSelection = rangeOfInterestStart > selectionStart ? rangeOfInterestStart : selectionStart;
+ endOfRangeOfInterestInSelection = rangeOfInterestEnd < selectionEnd ? rangeOfInterestEnd : selectionEnd;
+ } else {
+ size_t rangeOfInterestLocation;
+ size_t rangeOfInterestLength;
+ RefPtr<Node> rootNode = rangeOfInterest->commonAncestorContainer();
+ if (!rootNode) {
+ completionHandler({ });
+ return;
+ }
+
+ RefPtr<ContainerNode> rootContainerNode = rootNode->isContainerNode() ? downcast<ContainerNode>(rootNode.get()) : rootNode->parentNode();
+ TextIterator::getLocationAndLengthFromRange(rootContainerNode.get(), rangeOfInterest.get(), rangeOfInterestLocation, rangeOfInterestLength);
+
+ CheckedSize midpointLocation { rangeOfInterestLocation };
+ midpointLocation += rangeOfInterestLength / 2;
+ if (midpointLocation.hasOverflowed()) {
+ completionHandler({ });
+ return;
+ }
+
+ auto midpointRange = TextIterator::rangeFromLocationAndLength(rootContainerNode.get(), midpointLocation.unsafeGet(), 0);
+
+ auto midpoint = midpointRange->startPosition();
+ startOfRangeOfInterestInSelection = startOfWord(midpoint);
+ if (startOfRangeOfInterestInSelection < rangeOfInterestStart) {
+ startOfRangeOfInterestInSelection = endOfWord(midpoint);
+ if (startOfRangeOfInterestInSelection > rangeOfInterestEnd)
+ startOfRangeOfInterestInSelection = midpoint;
+ }
+
+ endOfRangeOfInterestInSelection = startOfRangeOfInterestInSelection;
+ }
+
+ VisiblePosition contextBeforeStart;
+ VisiblePosition contextAfterEnd;
+ if (request.granularityCount) {
+ contextBeforeStart = moveByGranularityRespectingWordBoundary(frame.get(), rangeOfInterestStart, request.surroundingGranularity, request.granularityCount, DirectionBackward);
+ contextAfterEnd = moveByGranularityRespectingWordBoundary(frame.get(), rangeOfInterestEnd, request.surroundingGranularity, request.granularityCount, DirectionForward);
+ } else {
+ contextBeforeStart = rangeOfInterestStart;
+ contextAfterEnd = rangeOfInterestEnd;
+ }
+
+ auto makeString = [&](VisiblePosition& start, VisiblePosition& end) -> NSAttributedString * {
+ if (start.isNull() || end.isNull() || start == end)
+ return nil;
+ // FIXME: This should return editing-offset-compatible attributed strings if that option is requested.
+ return adoptNS([[NSAttributedString alloc] initWithString:plainTextReplacingNoBreakSpace(start.deepEquivalent(), end.deepEquivalent())]).autorelease();
+ };
+
+ context.contextBefore = makeString(contextBeforeStart, startOfRangeOfInterestInSelection);
+ context.selectedText = makeString(startOfRangeOfInterestInSelection, endOfRangeOfInterestInSelection);
+ context.contextAfter = makeString(endOfRangeOfInterestInSelection, contextAfterEnd);
+
+ auto compositionRange = frame->editor().compositionRange();
+ if (compositionRange && rangesOverlap(rangeOfInterest.get(), compositionRange.get())) {
+ VisiblePosition compositionStart(compositionRange->startPosition());
+ VisiblePosition compositionEnd(compositionRange->endPosition());
+
+ VisiblePosition relevantCompositionStart = rangeOfInterestStart > compositionStart ? rangeOfInterestStart : compositionStart;
+ VisiblePosition relevantCompositionEnd = rangeOfInterestEnd < compositionEnd ? rangeOfInterestEnd : compositionEnd;
+
+ context.markedText = makeString(relevantCompositionStart, relevantCompositionEnd);
+ context.selectedRangeInMarkedText.location = distanceBetweenPositions(relevantCompositionStart, startOfRangeOfInterestInSelection);
+ context.selectedRangeInMarkedText.length = [context.selectedText.string length];
+ }
+
+ if (wantsRects) {
+ TextIterator contextIterator(contextBeforeStart.deepEquivalent(), contextAfterEnd.deepEquivalent());
+ unsigned currentLocation = 0;
+ while (!contextIterator.atEnd()) {
+ unsigned length = contextIterator.text().length();
+ if (!length) {
+ contextIterator.advance();
+ continue;
+ }
+
+ DocumentEditingContext::TextRectAndRange rect;
+ rect.rect = contextIterator.range()->absoluteBoundingBox();
+ rect.range = { currentLocation, length };
+ context.textRects.append(rect);
+
+ currentLocation += length;
+ contextIterator.advance();
+ }
+ }
+
+ // FIXME: Support Annotation option.
+
+ completionHandler(context);
+}
+
} // namespace WebKit
#endif // PLATFORM(IOS_FAMILY)
Modified: trunk/Tools/ChangeLog (243353 => 243354)
--- trunk/Tools/ChangeLog 2019-03-22 01:58:13 UTC (rev 243353)
+++ trunk/Tools/ChangeLog 2019-03-22 02:26:09 UTC (rev 243354)
@@ -1,3 +1,30 @@
+2019-03-21 Tim Horton <timothy_hor...@apple.com>
+
+ Adopt UIWKDocumentContext
+ https://bugs.webkit.org/show_bug.cgi?id=196040
+ <rdar://problem/48642440>
+
+ Reviewed by Ryosuke Niwa.
+
+ * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
+ * TestWebKitAPI/Tests/WebKitCocoa/DocumentEditingContext.mm: Added.
+ (makeRequest):
+ (-[TestWKWebView synchronouslyRequestDocumentContext:]):
+ (-[TestWKWebView synchronouslyAdjustSelectionWithDelta:]):
+ (applyStyle):
+ (TEST):
+ Add tests for UIWKDocumentContext.
+
+ * TestWebKitAPI/Tests/WebKitCocoa/WKContentViewEditingActions.mm:
+ (TEST):
+ (recursiveFindWKContentView): Deleted.
+ * TestWebKitAPI/cocoa/TestWKWebView.h:
+ * TestWebKitAPI/cocoa/TestWKWebView.mm:
+ (recursiveFindWKContentView):
+ (-[TestWKWebView wkContentView]):
+ * TestWebKitAPI/ios/UIKitSPI.h:
+ Share the WKContentView finding code between tests.
+
2019-03-21 Simon Fraser <simon.fra...@apple.com>
[iOS WK2] Turn on async overflow scrolling by default
Modified: trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj (243353 => 243354)
--- trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj 2019-03-22 01:58:13 UTC (rev 243353)
+++ trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj 2019-03-22 02:26:09 UTC (rev 243354)
@@ -98,6 +98,7 @@
2D51A0C71C8BF00C00765C45 /* DOMHTMLVideoElementWrapper.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2D51A0C51C8BF00400765C45 /* DOMHTMLVideoElementWrapper.mm */; };
2D70059621EDA0C6003463CB /* TabOutOfWebView.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2D70059521EDA0C6003463CB /* TabOutOfWebView.mm */; };
2D70059921EDA4D0003463CB /* OffscreenWindow.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2D70059721EDA4D0003463CB /* OffscreenWindow.mm */; };
+ 2D7FD19322419087007887F1 /* DocumentEditingContext.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2D7FD19222419087007887F1 /* DocumentEditingContext.mm */; };
2D838B1F1EEF3A5C009B980E /* WKContentViewEditingActions.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2D838B1E1EEF3A5B009B980E /* WKContentViewEditingActions.mm */; };
2DADF26321CB8F32003D3E3A /* GetResourceData.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2DADF26221CB8F32003D3E3A /* GetResourceData.mm */; };
2DB0232F1E4E871800707123 /* InteractionDeadlockAfterCrash.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2DB0232E1E4E871800707123 /* InteractionDeadlockAfterCrash.mm */; };
@@ -1453,6 +1454,7 @@
2D70059521EDA0C6003463CB /* TabOutOfWebView.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = TabOutOfWebView.mm; sourceTree = "<group>"; };
2D70059721EDA4D0003463CB /* OffscreenWindow.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = OffscreenWindow.mm; sourceTree = "<group>"; };
2D70059821EDA4D0003463CB /* OffscreenWindow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OffscreenWindow.h; sourceTree = "<group>"; };
+ 2D7FD19222419087007887F1 /* DocumentEditingContext.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = DocumentEditingContext.mm; sourceTree = "<group>"; };
2D8104CB1BEC13E70020DA46 /* FindInPage.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = FindInPage.mm; sourceTree = "<group>"; };
2D838B1E1EEF3A5B009B980E /* WKContentViewEditingActions.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WKContentViewEditingActions.mm; sourceTree = "<group>"; };
2D9A53AE1B31FA8D0074D5AA /* ShrinkToFit.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ShrinkToFit.mm; sourceTree = "<group>"; };
@@ -2548,6 +2550,7 @@
46918EFB2237283500468DFE /* DeviceOrientation.mm */,
CEA7F57B20895F5B0078EF6E /* DidResignInputElementStrongPasswordAppearance.mm */,
518EE51A20A78CFB00E024F3 /* DoAfterNextPresentationUpdateAfterCrash.mm */,
+ 2D7FD19222419087007887F1 /* DocumentEditingContext.mm */,
518EE51620A78CDF00E024F3 /* DoubleDefersLoading.mm */,
518EE51720A78CDF00E024F3 /* DoubleDefersLoadingPlugin.mm */,
A1A4FE5D18DD3DB700B5EA8A /* Download.mm */,
@@ -4071,6 +4074,7 @@
7CCE7EEA1A411AE600447C4C /* DidNotHandleKeyDown.cpp in Sources */,
AD57AC211DA7465B00FF1BDE /* DidRemoveFrameFromHiearchyInPageCache.cpp in Sources */,
518EE51B20A78D0000E024F3 /* DoAfterNextPresentationUpdateAfterCrash.mm in Sources */,
+ 2D7FD19322419087007887F1 /* DocumentEditingContext.mm in Sources */,
7CCE7EEB1A411AE600447C4C /* DocumentStartUserScriptAlertCrash.cpp in Sources */,
7CCE7EBB1A411A7E00447C4C /* DOMHTMLTableCellCellAbove.mm in Sources */,
2D51A0C71C8BF00C00765C45 /* DOMHTMLVideoElementWrapper.mm in Sources */,
Added: trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/DocumentEditingContext.mm (0 => 243354)
--- trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/DocumentEditingContext.mm (rev 0)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/DocumentEditingContext.mm 2019-03-22 02:26:09 UTC (rev 243354)
@@ -0,0 +1,239 @@
+/*
+ * Copyright (C) 2019 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import "config.h"
+
+#if PLATFORM(IOS_FAMILY)
+
+#import "PlatformUtilities.h"
+#import "Test.h"
+#import "TestNavigationDelegate.h"
+#import "TestWKWebView.h"
+#import "UIKitSPI.h"
+#import <WebKit/WKPreferencesRefPrivate.h>
+#import <WebKit/WKWebViewPrivate.h>
+#import <WebKit/WebKit.h>
+#import <WebKit/_WKTextInputContext.h>
+#import <wtf/RetainPtr.h>
+
+#define EXPECT_NSSTRING_EQ(expected, actual) \
+ EXPECT_TRUE([actual isKindOfClass:[NSString class]]); \
+ EXPECT_WK_STREQ(expected, (NSString *)actual);
+
+#define EXPECT_ATTRIBUTED_STRING_EQ(expected, actual) \
+ EXPECT_TRUE([actual isKindOfClass:[NSAttributedString class]]); \
+ EXPECT_WK_STREQ(expected, [(NSAttributedString *)actual string]);
+
+#define EXPECT_RECT_EQ(xExpected, yExpected, widthExpected, heightExpected, rect) \
+ EXPECT_DOUBLE_EQ(xExpected, rect.origin.x); \
+ EXPECT_DOUBLE_EQ(yExpected, rect.origin.y); \
+ EXPECT_DOUBLE_EQ(widthExpected, rect.size.width); \
+ EXPECT_DOUBLE_EQ(heightExpected, rect.size.height);
+
+@interface WKContentView ()
+- (void)requestDocumentContext:(UIWKDocumentRequest *)request completionHandler:(void (^)(UIWKDocumentContext *))completionHandler;
+- (void)adjustSelectionWithDelta:(NSRange)deltaRange completionHandler:(void (^)(void))completionHandler;
+@end
+
+static UIWKDocumentRequest *makeRequest(UIWKDocumentRequestFlags flags, UITextGranularity granularity, NSInteger granularityCount, CGRect documentRect = CGRectZero, id <NSCopying> inputElementIdentifier = nil)
+{
+ RetainPtr<UIWKDocumentRequest> request = adoptNS([[NSClassFromString(@"UIWKDocumentRequest") alloc] init]);
+ [request setFlags:flags];
+ [request setSurroundingGranularity:granularity];
+ [request setGranularityCount:granularityCount];
+ [request setDocumentRect:documentRect];
+ [request setInputElementIdentifier:inputElementIdentifier];
+ return request.autorelease();
+}
+
+@implementation TestWKWebView (SynchronousDocumentContext)
+
+- (UIWKDocumentContext *)synchronouslyRequestDocumentContext:(UIWKDocumentRequest *)request
+{
+ __block bool finished = false;
+ __block RetainPtr<UIWKDocumentContext> result;
+ [[self wkContentView] requestDocumentContext:request completionHandler:^(UIWKDocumentContext *context) {
+ result = context;
+ finished = true;
+ }];
+ TestWebKitAPI::Util::run(&finished);
+ return result.autorelease();
+}
+
+- (void)synchronouslyAdjustSelectionWithDelta:(NSRange)range
+{
+ __block bool finished = false;
+ [[self wkContentView] adjustSelectionWithDelta:range completionHandler:^() {
+ finished = true;
+ }];
+ TestWebKitAPI::Util::run(&finished);
+}
+
+- (NSArray<_WKTextInputContext *> *)synchronouslyRequestTextInputContextsInRect:(CGRect)rect
+{
+ __block bool finished = false;
+ __block RetainPtr<NSArray<_WKTextInputContext *>> result;
+ [self _requestTextInputContextsInRect:rect completionHandler:^(NSArray<_WKTextInputContext *> *contexts) {
+ result = contexts;
+ finished = true;
+ }];
+ TestWebKitAPI::Util::run(&finished);
+ return result.autorelease();
+}
+
+@end
+
+static NSString *applyStyle(NSString *HTMLString)
+{
+ return [@"<style>body { margin: 0; } iframe { border: none; }</style><meta name='viewport' content='initial-scale=1'>" stringByAppendingString:HTMLString];
+}
+
+static NSString *applyAhemStyle(NSString *HTMLString)
+{
+ return [@"<style>@font-face { font-family: customFont; src: url(Ahem.ttf); } body { margin: 0; font-family: customFont; } iframe { border: none; }</style><meta name='viewport' content='initial-scale=1'>" stringByAppendingString:HTMLString];
+}
+
+TEST(WebKit, DocumentEditingContext)
+{
+ if (!NSClassFromString(@"UIWKDocumentRequest"))
+ return;
+
+ RetainPtr<TestWKWebView> webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600)]);
+
+ UIWKDocumentContext *context;
+
+ [webView synchronouslyLoadHTMLString:applyStyle(@"<span id='the'>The</span> quick brown fox <span id='jumps'>jumps</span> over the lazy <span id='dog'>dog.</span>")];
+ [webView stringByEvaluatingJavaScript:@"getSelection().setBaseAndExtent(jumps, 0, jumps, 1)"];
+
+ context = [webView synchronouslyRequestDocumentContext:makeRequest(UIWKDocumentRequestText, UITextGranularityWord, 1)];
+ EXPECT_NOT_NULL(context);
+ EXPECT_NSSTRING_EQ("fox ", context.contextBefore);
+ EXPECT_NSSTRING_EQ("jumps", context.selectedText);
+ EXPECT_NSSTRING_EQ(" over", context.contextAfter);
+
+ context = [webView synchronouslyRequestDocumentContext:makeRequest(UIWKDocumentRequestText, UITextGranularityWord, 2)];
+ EXPECT_NOT_NULL(context);
+ EXPECT_NSSTRING_EQ("brown fox ", context.contextBefore);
+ EXPECT_NSSTRING_EQ("jumps", context.selectedText);
+ EXPECT_NSSTRING_EQ(" over the", context.contextAfter);
+
+ context = [webView synchronouslyRequestDocumentContext:makeRequest(UIWKDocumentRequestText, UITextGranularityParagraph, 1)];
+ EXPECT_NOT_NULL(context);
+ EXPECT_NSSTRING_EQ("The quick brown fox ", context.contextBefore);
+ EXPECT_NSSTRING_EQ("jumps", context.selectedText);
+ EXPECT_NSSTRING_EQ(" over the lazy dog.", context.contextAfter);
+
+ // Attributed strings.
+ // FIXME: Currently we don't test the attributes... because we don't set any.
+ context = [webView synchronouslyRequestDocumentContext:makeRequest(UIWKDocumentRequestAttributed, UITextGranularityWord, 1)];
+ EXPECT_NOT_NULL(context);
+ EXPECT_ATTRIBUTED_STRING_EQ("fox ", context.contextBefore);
+ EXPECT_ATTRIBUTED_STRING_EQ("jumps", context.selectedText);
+ EXPECT_ATTRIBUTED_STRING_EQ(" over", context.contextAfter);
+
+ // Extremities of the document.
+ [webView stringByEvaluatingJavaScript:@"getSelection().setBaseAndExtent(the, 0, the, 1)"];
+ context = [webView synchronouslyRequestDocumentContext:makeRequest(UIWKDocumentRequestText, UITextGranularityWord, 1)];
+ EXPECT_NOT_NULL(context);
+ EXPECT_NULL(context.contextBefore);
+ EXPECT_NSSTRING_EQ("The", context.selectedText);
+ EXPECT_NSSTRING_EQ(" quick", context.contextAfter);
+
+ [webView stringByEvaluatingJavaScript:@"getSelection().setBaseAndExtent(dog, 0, dog, 1)"];
+ context = [webView synchronouslyRequestDocumentContext:makeRequest(UIWKDocumentRequestText, UITextGranularitySentence, 1)];
+ EXPECT_NOT_NULL(context);
+ EXPECT_NSSTRING_EQ("The quick brown fox jumps over the lazy ", context.contextBefore);
+ EXPECT_NSSTRING_EQ("dog.", context.selectedText);
+ EXPECT_NULL(context.contextAfter);
+
+ // Spatial requests.
+ context = [webView synchronouslyRequestDocumentContext:makeRequest(UIWKDocumentRequestText | UIWKDocumentRequestSpatial, UITextGranularityWord, 1, CGRectMake(0, 0, 10, 10))];
+ EXPECT_NOT_NULL(context);
+ EXPECT_NULL(context.contextBefore);
+ EXPECT_NULL(context.selectedText);
+ EXPECT_NSSTRING_EQ("The quick", context.contextAfter);
+
+ context = [webView synchronouslyRequestDocumentContext:makeRequest(UIWKDocumentRequestText | UIWKDocumentRequestSpatial, UITextGranularityWord, 1, CGRectMake(0, 0, 800, 600))];
+ EXPECT_NOT_NULL(context);
+ EXPECT_NSSTRING_EQ("The quick brown fox jumps over the lazy ", context.contextBefore);
+ EXPECT_NSSTRING_EQ("dog.", context.selectedText);
+ EXPECT_NULL(context.contextAfter);
+
+ [webView stringByEvaluatingJavaScript:@"getSelection().removeAllRanges()"];
+ context = [webView synchronouslyRequestDocumentContext:makeRequest(UIWKDocumentRequestText | UIWKDocumentRequestSpatial, UITextGranularityWord, 1, CGRectMake(0, 0, 800, 600))];
+ EXPECT_NOT_NULL(context);
+ EXPECT_NSSTRING_EQ("The quick brown fox ", context.contextBefore);
+ EXPECT_NULL(context.selectedText);
+ EXPECT_NSSTRING_EQ("jumps over the lazy dog.", context.contextAfter);
+
+ // Selection adjustment.
+ [webView stringByEvaluatingJavaScript:@"getSelection().setBaseAndExtent(jumps, 0, jumps, 1)"];
+ [webView synchronouslyAdjustSelectionWithDelta:NSMakeRange(6, -1)];
+ context = [webView synchronouslyRequestDocumentContext:makeRequest(UIWKDocumentRequestText, UITextGranularityWord, 1)];
+ EXPECT_NOT_NULL(context);
+ EXPECT_NSSTRING_EQ("over", context.selectedText);
+
+ [webView synchronouslyAdjustSelectionWithDelta:NSMakeRange(-6, 1)];
+ context = [webView synchronouslyRequestDocumentContext:makeRequest(UIWKDocumentRequestText, UITextGranularityWord, 1)];
+ EXPECT_NOT_NULL(context);
+ EXPECT_NSSTRING_EQ("jumps", context.selectedText);
+
+ // Text rects.
+ [webView synchronouslyLoadHTMLString:applyAhemStyle(@"<span id='four'>MMMM</span> MMM MM M")];
+ [webView stringByEvaluatingJavaScript:@"getSelection().setBaseAndExtent(four, 0, four, 1)"];
+ context = [webView synchronouslyRequestDocumentContext:makeRequest(UIWKDocumentRequestText | UIWKDocumentRequestRects, UITextGranularityWord, 0)];
+ EXPECT_NOT_NULL(context);
+ EXPECT_NULL(context.contextBefore);
+ EXPECT_NSSTRING_EQ("MMMM", context.selectedText);
+ EXPECT_NULL(context.contextAfter);
+
+ NSArray<NSValue *> *rects = [context characterRectsForCharacterRange:NSMakeRange(0, 1)];
+ EXPECT_EQ(1UL, rects.count);
+ EXPECT_RECT_EQ(0, 0, 92, 24, rects.firstObject.CGRectValue);
+ rects = [context characterRectsForCharacterRange:NSMakeRange(5, 1)];
+ EXPECT_EQ(0UL, rects.count);
+
+ context = [webView synchronouslyRequestDocumentContext:makeRequest(UIWKDocumentRequestText | UIWKDocumentRequestRects, UITextGranularityWord, 1)];
+ EXPECT_NSSTRING_EQ(" MMM", context.contextAfter);
+ rects = [context characterRectsForCharacterRange:NSMakeRange(0, 1)];
+ EXPECT_EQ(1UL, rects.count);
+ EXPECT_RECT_EQ(0, 0, 92, 24, rects.firstObject.CGRectValue);
+ rects = [context characterRectsForCharacterRange:NSMakeRange(6, 1)];
+ EXPECT_EQ(1UL, rects.count);
+ EXPECT_RECT_EQ(92, 0, 92, 24, rects.firstObject.CGRectValue);
+
+ // Text Input Context
+ [webView synchronouslyLoadHTMLString:applyStyle(@"<input type='text' style='width: 50px; height: 50px;' value='hello, world'>")];
+ NSArray<_WKTextInputContext *> *textInputContexts = [webView synchronouslyRequestTextInputContextsInRect:[webView frame]];
+ EXPECT_EQ(1UL, textInputContexts.count);
+ EXPECT_RECT_EQ(0, 0, 50, 50, textInputContexts[0].boundingRect);
+
+ context = [webView synchronouslyRequestDocumentContext:makeRequest(UIWKDocumentRequestText, UITextGranularityWord, 0, CGRectZero, textInputContexts[0])];
+ EXPECT_NSSTRING_EQ("hello,", context.contextBefore);
+ EXPECT_NULL(context.selectedText);
+ EXPECT_NSSTRING_EQ(" world", context.contextAfter);
+}
+
+#endif // PLATFORM(IOS_FAMILY)
Modified: trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/WKContentViewEditingActions.mm (243353 => 243354)
--- trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/WKContentViewEditingActions.mm 2019-03-22 01:58:13 UTC (rev 243353)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/WKContentViewEditingActions.mm 2019-03-22 02:26:09 UTC (rev 243354)
@@ -34,20 +34,6 @@
#import <WebKit/WebKit.h>
#import <wtf/RetainPtr.h>
-static UIView *recursiveFindWKContentView(UIView *view)
-{
- if ([view isKindOfClass:NSClassFromString(@"WKContentView")])
- return view;
-
- for (UIView *subview in view.subviews) {
- UIView *contentView = recursiveFindWKContentView(subview);
- if (contentView)
- return contentView;
- }
-
- return nil;
-}
-
TEST(WebKit, WKContentViewEditingActions)
{
[UIPasteboard generalPasteboard].items = @[];
@@ -58,7 +44,7 @@
[webView stringByEvaluatingJavaScript:@"selectPlainText()"];
- UIView *contentView = recursiveFindWKContentView(webView.get());
+ UIView *contentView = [webView wkContentView];
__block bool done = false;
Modified: trunk/Tools/TestWebKitAPI/cocoa/TestWKWebView.h (243353 => 243354)
--- trunk/Tools/TestWebKitAPI/cocoa/TestWKWebView.h 2019-03-22 01:58:13 UTC (rev 243353)
+++ trunk/Tools/TestWebKitAPI/cocoa/TestWKWebView.h 2019-03-22 02:26:09 UTC (rev 243354)
@@ -79,6 +79,9 @@
@end
#if PLATFORM(IOS_FAMILY)
+@interface WKContentView : UIView
+@end
+
@interface TestWKWebView (IOSOnly)
@property (nonatomic, readonly) UIView <UITextInputPrivate, UITextInputMultiDocument> *textInputContentView;
@property (nonatomic, readonly) RetainPtr<NSArray> selectionRectsAfterPresentationUpdate;
@@ -86,6 +89,7 @@
@property (nonatomic, readonly) NSArray<NSValue *> *selectionViewRectsInContentCoordinates;
- (_WKActivatedElementInfo *)activatedElementAtPosition:(CGPoint)position;
- (void)evaluateJavaScriptAndWaitForInputSessionToChange:(NSString *)script;
+- (WKContentView *)wkContentView;
@end
#endif
Modified: trunk/Tools/TestWebKitAPI/cocoa/TestWKWebView.mm (243353 => 243354)
--- trunk/Tools/TestWebKitAPI/cocoa/TestWKWebView.mm 2019-03-22 01:58:13 UTC (rev 243353)
+++ trunk/Tools/TestWebKitAPI/cocoa/TestWKWebView.mm 2019-03-22 02:26:09 UTC (rev 243354)
@@ -509,6 +509,25 @@
return info.autorelease();
}
+static WKContentView *recursiveFindWKContentView(UIView *view)
+{
+ if ([view isKindOfClass:NSClassFromString(@"WKContentView")])
+ return (WKContentView *)view;
+
+ for (UIView *subview in view.subviews) {
+ WKContentView *contentView = recursiveFindWKContentView(subview);
+ if (contentView)
+ return contentView;
+ }
+
+ return nil;
+}
+
+- (WKContentView *)wkContentView
+{
+ return recursiveFindWKContentView(self);
+}
+
@end
#endif
Modified: trunk/Tools/TestWebKitAPI/ios/UIKitSPI.h (243353 => 243354)
--- trunk/Tools/TestWebKitAPI/ios/UIKitSPI.h 2019-03-22 01:58:13 UTC (rev 243353)
+++ trunk/Tools/TestWebKitAPI/ios/UIKitSPI.h 2019-03-22 02:26:09 UTC (rev 243354)
@@ -141,4 +141,36 @@
+ (BOOL)isInHardwareKeyboardMode;
@end
+@interface UIWKDocumentContext : NSObject
+
+@property (nonatomic, copy) NSObject *contextBefore;
+@property (nonatomic, copy) NSObject *selectedText;
+@property (nonatomic, copy) NSObject *contextAfter;
+@property (nonatomic, copy) NSObject *markedText;
+@property (nonatomic, assign) NSRange selectedRangeInMarkedText;
+@property (nonatomic, copy) NSAttributedString *annotatedText;
+
+- (NSArray<NSValue *> *)characterRectsForCharacterRange:(NSRange)range;
+
+@end
+
+typedef NS_OPTIONS(NSInteger, UIWKDocumentRequestFlags) {
+ UIWKDocumentRequestNone = 0,
+ UIWKDocumentRequestText = 1 << 0,
+ UIWKDocumentRequestAttributed = 1 << 1,
+ UIWKDocumentRequestRects = 1 << 2,
+ UIWKDocumentRequestSpatial = 1 << 3,
+ UIWKDocumentRequestAnnotation = 1 << 4,
+};
+
+@interface UIWKDocumentRequest : NSObject
+
+@property (nonatomic, assign) UIWKDocumentRequestFlags flags;
+@property (nonatomic, assign) UITextGranularity surroundingGranularity;
+@property (nonatomic, assign) NSInteger granularityCount;
+@property (nonatomic, assign) CGRect documentRect;
+@property (nonatomic, retain) id <NSCopying> inputElementIdentifier;
+
+@end
+
#endif // PLATFORM(IOS_FAMILY)