Source/WebCore/ChangeLog

 12018-11-29 Megan Gardner <megan_gardner@apple.com>
 2
 3 Move Lookup Code for better cross platform usage
 4 https://bugs.webkit.org/show_bug.cgi?id=191732
 5
 6 Reviewed by Alex Christensen.
 7
 8 Not currenlty testable
 9
 10 DictionaryLookup uses Reveal now, which is slated to be cross-platform.
 11 That patch gates the parts of DictionaryLookup that currently do not have
 12 an available implementation on iOS. Once Reveal is ready, this code will be
 13 replaced or expanded upon, as appropriate.
 14
 15 * editing/mac/DictionaryLookup.h:
 16 * editing/mac/DictionaryLookup.mm:
 17 (WebCore::showPopupOrCreateAnimationController):
 18 (WebCore::DictionaryLookup::showPopup):
 19 (WebCore::DictionaryLookup::hidePopup):
 20 (WebCore::DictionaryLookup::animationControllerForPopup):
 21
1222018-11-29 Justin Michaud <justin_michaud@apple.com>
223
324 CSS Painting API should pass 'this' correctly to paint callback, and repaint when properties change.

Source/WebCore/PAL/ChangeLog

 12018-11-29 Megan Gardner <megan_gardner@apple.com>
 2
 3 Move Lookup Code for better cross platform usage
 4 https://bugs.webkit.org/show_bug.cgi?id=191732
 5
 6 Reviewed by Alex Christensen.
 7
 8 * pal/spi/mac/LookupSPI.h:
 9 * pal/spi/mac/RevealSPI.h:
 10
1112018-11-29 Alexey Proskuryakov <ap@apple.com>
212
313 Modernize the check for kCFURLRequestContentDecoderSkipURLCheck existence

Source/WebKit/ChangeLog

 12018-11-29 Megan Gardner <megan_gardner@apple.com>
 2
 3 Move Lookup Code for better cross platform usage
 4 https://bugs.webkit.org/show_bug.cgi?id=191732
 5
 6 Reviewed by Alex Christensen.
 7
 8 Lookup is being replaced by Reveal. This framework should work on all platforms.
 9 The patch moves the code that we expect will be needed for all platforms to the more
 10 general cocoa area. This patch changes no funcationality, and should not change
 11 anything currently. This work will be build on later when Reveal is ready to support
 12 multiple platforms.
 13
 14 * Platform/spi/ios/UIKitSPI.h:
 15 * UIProcess/Cocoa/WebPageProxyCocoa.mm:
 16 (WebKit::WebPageProxy::performDictionaryLookupAtLocation):
 17 (WebKit::WebPageProxy::performDictionaryLookupOfCurrentSelection):
 18 * UIProcess/ios/WKContentViewInteraction.h:
 19 * UIProcess/ios/WKContentViewInteraction.mm:
 20 (-[WKContentView setupInteraction]):
 21 (-[WKContentView cleanupInteraction]):
 22 (-[WKContentView _removeDefaultGestureRecognizers]):
 23 (-[WKContentView _addDefaultGestureRecognizers]):
 24 (-[WKContentView gestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer:]):
 25 (-[WKContentView _lookupGestureRecognized:]):
 26 * UIProcess/ios/WebPageProxyIOS.mm:
 27 (WebKit::WebPageProxy::performDictionaryLookupAtLocation): Deleted.
 28 * UIProcess/mac/WebPageProxyMac.mm:
 29 (WebKit::WebPageProxy::performDictionaryLookupAtLocation): Deleted.
 30 (WebKit::WebPageProxy::performDictionaryLookupOfCurrentSelection): Deleted.
 31 * WebProcess/WebPage/Cocoa/WebPageCocoa.mm:
 32 (WebKit::WebPage::performDictionaryLookupAtLocation):
 33 (WebKit::WebPage::performDictionaryLookupForSelection):
 34 (WebKit::WebPage::performDictionaryLookupOfCurrentSelection):
 35 (WebKit::WebPage::performDictionaryLookupForRange):
 36 (WebKit::WebPage::dictionaryPopupInfoForRange):
 37 * WebProcess/WebPage/WebPage.messages.in:
 38 * WebProcess/WebPage/ios/WebPageIOS.mm:
 39 (WebKit::WebPage::performDictionaryLookupAtLocation): Deleted.
 40 (WebKit::WebPage::performDictionaryLookupForSelection): Deleted.
 41 (WebKit::WebPage::performDictionaryLookupForRange): Deleted.
 42 * WebProcess/WebPage/mac/WebPageMac.mm:
 43 (WebKit::WebPage::performDictionaryLookupAtLocation): Deleted.
 44 (WebKit::WebPage::performDictionaryLookupForSelection): Deleted.
 45 (WebKit::WebPage::performDictionaryLookupOfCurrentSelection): Deleted.
 46 (WebKit::WebPage::dictionaryPopupInfoForRange): Deleted.
 47 (WebKit::WebPage::performDictionaryLookupForRange): Deleted.
 48
1492018-11-29 Alexey Proskuryakov <ap@apple.com>
250
351 Modernize the check for kCFURLRequestContentDecoderSkipURLCheck existence

Source/WebCore/PAL/PAL.xcodeproj/project.pbxproj

406406 0C2DA1391F3BEB4900DBC317 /* PassKitSPI.h */,
407407 0C2DA13A1F3BEB4900DBC317 /* pthreadSPI.h */,
408408 0C2DA13B1F3BEB4900DBC317 /* QuartzCoreSPI.h */,
 409 442956CC218A72DE0080DB54 /* RevealSPI.h */,
409410 570AB8F020AE2E8D00B8BE87 /* SecKeyProxySPI.h */,
410411 0C2DA13C1F3BEB4900DBC317 /* ServersSPI.h */,
411412 0C2DA12B1F3BEB4900DBC317 /* URLFormattingSPI.h */,

471472 0C7785861F45130F00F4EBB6 /* QTKitSPI.h */,
472473 A102658A1F56748C00B4C844 /* QuickDrawSPI.h */,
473474 0C7785871F45130F00F4EBB6 /* QuickLookMacSPI.h */,
474  442956CC218A72DE0080DB54 /* RevealSPI.h */,
475475 A1175B481F6AFF8E00C4B9F0 /* SpeechSynthesisSPI.h */,
476476 0C7785881F45130F00F4EBB6 /* TUCallSPI.h */,
477477 );

Source/WebCore/PAL/pal/spi/cocoa/RevealSPI.h

 1/*
 2 * Copyright (C) 2018 Apple Inc. All rights reserved.
 3 *
 4 * Redistribution and use in source and binary forms, with or without
 5 * modification, are permitted provided that the following conditions
 6 * are met:
 7 * 1. Redistributions of source code must retain the above copyright
 8 * notice, this list of conditions and the following disclaimer.
 9 * 2. Redistributions in binary form must reproduce the above copyright
 10 * notice, this list of conditions and the following disclaimer in the
 11 * documentation and/or other materials provided with the distribution.
 12 *
 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 24 */
 25
 26#import <objc/runtime.h>
 27#if PLATFORM(MAC)
 28#import <pal/spi/mac/NSImmediateActionGestureRecognizerSPI.h>
 29#endif // PLATFORM(MAC)
 30#import <wtf/SoftLinking.h>
 31
 32SOFT_LINK_PRIVATE_FRAMEWORK(Reveal)
 33SOFT_LINK_PRIVATE_FRAMEWORK(RevealCore)
 34SOFT_LINK_CLASS_OPTIONAL(Reveal, RVPresenter)
 35SOFT_LINK_CLASS_OPTIONAL(Reveal, RVPresentingContext)
 36SOFT_LINK_CLASS_OPTIONAL(RevealCore, RVItem)
 37SOFT_LINK_CLASS_OPTIONAL(RevealCore, RVSelection)
 38
 39#if ENABLE(REVEAL)
 40
 41#if USE(APPLE_INTERNAL_SDK)
 42
 43#if PLATFORM(MAC)
 44#import <Reveal/RVPresenter.h>
 45#import <Reveal/Reveal.h>
 46#endif // PLATFORM(MAC)
 47#import <RevealCore/RVSelection.h>
 48#import <RevealCore/RevealCore.h>
 49
 50#else // USE(APPLE_INTERNAL_SDK)
 51
 52
 53@protocol RVPresenterHighlightDelegate;
 54
 55@interface RVItem : NSObject <NSSecureCoding>
 56- (instancetype)initWithText:(NSString *)text selectedRange:(NSRange)selectedRange NS_DESIGNATED_INITIALIZER;
 57@end
 58
 59@interface RVSelection : NSObject
 60+ (NSRange)revealRangeAtIndex:(NSUInteger)clickIndex selectedRanges:(NSArray <NSValue *> *)selectedRanges shouldUpdateSelection:(BOOL *)shouldUpdateSelection;
 61@end
 62
 63#if PLATFORM(MAC)
 64@interface RVPresentingContext : NSObject
 65- (instancetype)initWithPointerLocationInView:(NSPoint)pointerLocationInView inView:(NSView *)view highlightDelegate:(id<RVPresenterHighlightDelegate>)highlightDelegate;
 66@end
 67#endif
 68
 69@protocol RVPresenterHighlightDelegate <NSObject>
 70@required
 71- (NSArray <NSValue *> *)revealContext:(RVPresentingContext *)context rectsForItem:(RVItem *)item;
 72@optional
 73- (void)revealContext:(RVPresentingContext *)context stopHighlightingItem:(RVItem *)item;
 74- (void)revealContext:(RVPresentingContext *)context drawRectsForItem:(RVItem *)item;
 75@end
 76
 77@interface RVDocumentContext : NSObject < NSSecureCoding >
 78@end
 79
 80@interface RVPresenter : NSObject
 81#if PLATFORM(MAC)
 82- (id<NSImmediateActionAnimationController>)animationControllerForItem:(RVItem *)item documentContext:(RVDocumentContext *)documentContext presentingContext:(RVPresentingContext *)presentingContext options:(NSDictionary *)options;
 83#endif // PLATFORM(MAC)
 84- (BOOL)revealItem:(RVItem *)item documentContext:(RVDocumentContext *)documentContext presentingContext:(RVPresentingContext *)presentingContext options:(NSDictionary *)options;
 85@end
 86
 87#endif // !USE(APPLE_INTERNAL_SDK)
 88
 89#endif // ENABLE(REVEAL)

Source/WebCore/PAL/pal/spi/mac/LookupSPI.h

2323 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2424 */
2525
 26
 27#if PLATFORM(MAC)
 28
2629#import <objc/runtime.h>
2730#import <pal/spi/mac/NSImmediateActionGestureRecognizerSPI.h>
2831#import <wtf/SoftLinking.h>
2932
30 #if PLATFORM(MAC)
31 
3233SOFT_LINK_PRIVATE_FRAMEWORK_OPTIONAL(Lookup)
3334SOFT_LINK_CLASS_OPTIONAL(Lookup, LULookupDefinitionModule)
3435

Source/WebCore/PAL/pal/spi/mac/RevealSPI.h

1 /*
2  * Copyright (C) 2018 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  * notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  * notice, this list of conditions and the following disclaimer in the
11  * documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25 
26 #import <objc/runtime.h>
27 #import <pal/spi/mac/NSImmediateActionGestureRecognizerSPI.h>
28 #import <wtf/SoftLinking.h>
29 
30 SOFT_LINK_PRIVATE_FRAMEWORK(Reveal)
31 SOFT_LINK_PRIVATE_FRAMEWORK(RevealCore)
32 SOFT_LINK_CLASS_OPTIONAL(Reveal, RVPresenter)
33 SOFT_LINK_CLASS_OPTIONAL(Reveal, RVPresentingContext)
34 SOFT_LINK_CLASS_OPTIONAL(RevealCore, RVItem)
35 SOFT_LINK_CLASS_OPTIONAL(RevealCore, RVSelection)
36 
37 #if USE(APPLE_INTERNAL_SDK)
38 
39 #import <Reveal/RVPresenter.h>
40 #import <Reveal/Reveal.h>
41 #import <RevealCore/RVSelection.h>
42 #import <RevealCore/RevealCore.h>
43 
44 
45 #else
46 
47 @interface RVItem : NSObject <NSSecureCoding>
48 - (instancetype)initWithText:(NSString *)text selectedRange:(NSRange)selectedRange NS_DESIGNATED_INITIALIZER;
49 @end
50 
51 @interface RVSelection : NSObject
52 + (NSRange)revealRangeAtIndex:(NSUInteger)clickIndex selectedRanges:(NSArray <NSValue *> *)selectedRanges shouldUpdateSelection:(BOOL *)shouldUpdateSelection;
53 @end
54 
55 @interface RVPresenter : NSObject
56 - (id<NSImmediateActionAnimationController>)animationControllerForItem:(RVItem *)item documentContext:(RVDocumentContext *)documentContext presentingContext:(RVPresentingContext *)presentingContext options:(NSDictionary *)options;
57 - (BOOL)revealItem:(RVItem *)item documentContext:(RVDocumentContext *)documentContext presentingContext:(RVPresentingContext *)presentingContext options:(NSDictionary *)options;
58 @end
59 
60 #endif // !USE(APPLE_INTERNAL_SDK)

Source/WebCore/SourcesCocoa.txt

@@editing/SelectionRectGatherer.cpp
7777editing/SmartReplaceCF.cpp
7878
7979editing/cocoa/DataDetection.mm
 80editing/cocoa/DictionaryLookup.mm
8081editing/cocoa/EditorCocoa.mm
8182editing/cocoa/FontAttributeChangesCocoa.mm
8283editing/cocoa/FontAttributesCocoa.mm

@@editing/ios/DictationCommandIOS.cpp
9091editing/ios/EditorIOS.mm
9192
9293editing/mac/AlternativeTextUIController.mm
93 editing/mac/DictionaryLookup.mm
9494editing/mac/DictionaryLookupLegacy.mm
9595editing/mac/EditorMac.mm
9696editing/mac/FrameSelectionMac.mm

Source/WebCore/WebCore.xcodeproj/project.pbxproj

2052320523 children = (
2052420524 C5227DEF1C3C6DD700F5ED54 /* DataDetection.h */,
2052520525 C5227DF01C3C6DD700F5ED54 /* DataDetection.mm */,
 20526 937FF3D61A10131B008EBA31 /* DictionaryLookup.mm */,
2052620527 9B55EEE81B3E8898005342BC /* EditorCocoa.mm */,
2052720528 F42CEB54214031EE002DCA72 /* FontAttributeChangesCocoa.mm */,
2052820529 F48D2A752156FE5700C6752B /* FontAttributesCocoa.mm */,

2622926230 CE7B2DAF1586ABAD0098B3FA /* AlternativeTextUIController.h */,
2623026231 CE7B2DB01586ABAD0098B3FA /* AlternativeTextUIController.mm */,
2623126232 937FF3D41A1012D6008EBA31 /* DictionaryLookup.h */,
26232  937FF3D61A10131B008EBA31 /* DictionaryLookup.mm */,
2623326233 442956CA218A6D300080DB54 /* DictionaryLookupLegacy.mm */,
2623426234 ED501DC50B249F2900AE18D9 /* EditorMac.mm */,
2623526235 4A8C96EA0BE69032004EEFF0 /* FrameSelectionMac.mm */,

Source/WebCore/editing/cocoa/DictionaryLookup.mm

 1/*
 2 * Copyright (C) 2014-2018 Apple Inc. All rights reserved.
 3 *
 4 * Redistribution and use in source and binary forms, with or without
 5 * modification, are permitted provided that the following conditions
 6 * are met:
 7 * 1. Redistributions of source code must retain the above copyright
 8 * notice, this list of conditions and the following disclaimer.
 9 * 2. Redistributions in binary form must reproduce the above copyright
 10 * notice, this list of conditions and the following disclaimer in the
 11 * documentation and/or other materials provided with the distribution.
 12 *
 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
 14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
 17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 23 * THE POSSIBILITY OF SUCH DAMAGE.
 24 */
 25
 26#import "config.h"
 27#import "DictionaryLookup.h"
 28
 29#if PLATFORM(COCOA)
 30
 31#if ENABLE(REVEAL)
 32
 33#import "Document.h"
 34#import "Editing.h"
 35#import "FocusController.h"
 36#import "Frame.h"
 37#import "FrameSelection.h"
 38#import "HTMLConverter.h"
 39#import "HitTestResult.h"
 40#import "NotImplemented.h"
 41#import "Page.h"
 42#import "Range.h"
 43#import "RenderObject.h"
 44#import "TextIterator.h"
 45#import "VisiblePosition.h"
 46#import "VisibleSelection.h"
 47#import "VisibleUnits.h"
 48#import <pal/spi/cocoa/RevealSPI.h>
 49#import <pal/spi/mac/LookupSPI.h>
 50#import <wtf/BlockObjCExceptions.h>
 51#import <wtf/RefPtr.h>
 52
 53#if !PLATFORM(WATCH)
 54
 55#import <PDFKit/PDFKit.h>
 56
 57#endif // !PLATFORM(WATCH)
 58
 59#if PLATFORM(MAC)
 60
 61@interface WebRevealHighlight <RVPresenterHighlightDelegate> : NSObject {
 62@private
 63 Function<void()> _clearTextIndicator;
 64 NSRect _highlightRect;
 65 BOOL _useDefaultHighlight;
 66 NSAttributedString *_attributedString;
 67}
 68
 69@property (nonatomic, readonly) NSRect highlightRect;
 70@property (nonatomic, readonly) BOOL useDefaultHighlight;
 71@property (nonatomic, readonly) NSAttributedString *attributedString;
 72
 73- (instancetype)initWithHighlightRect:(NSRect)highlightRect useDefaultHighlight:(BOOL)useDefaultHighlight attributedString:(NSAttributedString *) attributedString;
 74- (void)setClearTextIndicator:(Function<void()>&&)clearTextIndicator;
 75
 76@end
 77
 78@implementation WebRevealHighlight
 79
 80@synthesize highlightRect=_highlightRect;
 81@synthesize useDefaultHighlight=_useDefaultHighlight;
 82@synthesize attributedString=_attributedString;
 83
 84- (instancetype)initWithHighlightRect:(NSRect)highlightRect useDefaultHighlight:(BOOL)useDefaultHighlight attributedString:(NSAttributedString *) attributedString
 85{
 86 if (!(self = [super init]))
 87 return nil;
 88
 89 _highlightRect = highlightRect;
 90 _useDefaultHighlight = useDefaultHighlight;
 91 _attributedString = attributedString;
 92
 93 return self;
 94}
 95
 96- (void)setClearTextIndicator:(Function<void()>&&)clearTextIndicator
 97{
 98 _clearTextIndicator = WTFMove(clearTextIndicator);
 99}
 100
 101- (NSArray<NSValue *> *)revealContext:(RVPresentingContext *)context rectsForItem:(RVItem *)item
 102{
 103 UNUSED_PARAM(context);
 104 UNUSED_PARAM(item);
 105 return @[[NSValue valueWithRect:self.highlightRect]];
 106}
 107
 108- (void)revealContext:(RVPresentingContext *)context drawRectsForItem:(RVItem *)item
 109{
 110 UNUSED_PARAM(item);
 111
 112 for (NSValue *rectVal in context.itemRectsInView) {
 113 NSRect rect = rectVal.rectValue;
 114
 115 // Get current font attributes from the attributed string above, and add paragraph style attribute in order to center text.
 116 RetainPtr<NSMutableDictionary> attributes = adoptNS([[NSMutableDictionary alloc] initWithDictionary:[self.attributedString fontAttributesInRange:NSMakeRange(0, [self.attributedString length])]]);
 117 RetainPtr<NSMutableParagraphStyle> paragraph = adoptNS([[NSMutableParagraphStyle alloc] init]);
 118 [paragraph setAlignment:NSTextAlignmentCenter];
 119 [attributes setObject:paragraph.get() forKey:NSParagraphStyleAttributeName];
 120
 121 RetainPtr<NSAttributedString> string = adoptNS([[NSAttributedString alloc] initWithString:[self.attributedString string] attributes:attributes.get()]);
 122 [string drawInRect:rect];
 123 }
 124}
 125
 126- (BOOL)revealContext:(RVPresentingContext *)context shouldUseDefaultHighlightForItem:(RVItem *)item
 127{
 128 UNUSED_PARAM(context);
 129 UNUSED_PARAM(item);
 130 return self.useDefaultHighlight;
 131}
 132
 133- (void)revealContext:(RVPresentingContext *)context stopHighlightingItem:(RVItem *)item
 134{
 135 UNUSED_PARAM(context);
 136 UNUSED_PARAM(item);
 137 auto block = WTFMove(_clearTextIndicator);
 138 if (block)
 139 block();
 140}
 141
 142@end
 143
 144#endif // PLATFORM(MAC)
 145
 146#endif // ENABLE(REVEAL)
 147
 148namespace WebCore {
 149
 150#if ENABLE(REVEAL)
 151
 152std::tuple<RefPtr<Range>, NSDictionary *> DictionaryLookup::rangeForSelection(const VisibleSelection& selection)
 153{
 154 BEGIN_BLOCK_OBJC_EXCEPTIONS;
 155
 156 if (!getRVItemClass())
 157 return { nullptr, nil };
 158
 159 auto selectedRange = selection.toNormalizedRange();
 160 if (!selectedRange)
 161 return { nullptr, nil };
 162
 163 // Since we already have the range we want, we just need to grab the returned options.
 164 auto selectionStart = selection.visibleStart();
 165 auto selectionEnd = selection.visibleEnd();
 166
 167 // As context, we are going to use the surrounding paragraphs of text.
 168 auto paragraphStart = startOfParagraph(selectionStart);
 169 auto paragraphEnd = endOfParagraph(selectionEnd);
 170
 171 int lengthToSelectionStart = TextIterator::rangeLength(makeRange(paragraphStart, selectionStart).get());
 172 int lengthToSelectionEnd = TextIterator::rangeLength(makeRange(paragraphStart, selectionEnd).get());
 173 NSRange rangeToPass = NSMakeRange(lengthToSelectionStart, lengthToSelectionEnd - lengthToSelectionStart);
 174
 175 RefPtr<Range> fullCharacterRange = makeRange(paragraphStart, paragraphEnd);
 176 String itemString = plainText(fullCharacterRange.get());
 177 RetainPtr<RVItem> item = adoptNS([allocRVItemInstance() initWithText:itemString selectedRange:rangeToPass]);
 178 NSRange highlightRange = item.get().highlightRange;
 179
 180 return { TextIterator::subrange(*fullCharacterRange, highlightRange.location, highlightRange.length), nil };
 181
 182 END_BLOCK_OBJC_EXCEPTIONS;
 183
 184 return { nullptr, nil };
 185}
 186
 187std::tuple<RefPtr<Range>, NSDictionary *> DictionaryLookup::rangeAtHitTestResult(const HitTestResult& hitTestResult)
 188{
 189 BEGIN_BLOCK_OBJC_EXCEPTIONS;
 190
 191 if (!getRVItemClass())
 192 return { nullptr, nil };
 193
 194 auto* node = hitTestResult.innerNonSharedNode();
 195 if (!node || !node->renderer())
 196 return { nullptr, nil };
 197
 198 auto* frame = node->document().frame();
 199 if (!frame)
 200 return { nullptr, nil };
 201
 202 // Don't do anything if there is no character at the point.
 203 auto framePoint = hitTestResult.roundedPointInInnerNodeFrame();
 204 if (!frame->rangeForPoint(framePoint))
 205 return { nullptr, nil };
 206
 207 auto position = frame->visiblePositionForPoint(framePoint);
 208 if (position.isNull())
 209 position = firstPositionInOrBeforeNode(node);
 210
 211 auto selection = frame->page()->focusController().focusedOrMainFrame().selection().selection();
 212 NSRange selectionRange;
 213 int hitIndex;
 214 RefPtr<Range> fullCharacterRange;
 215
 216 if (selection.selectionType() == VisibleSelection::RangeSelection) {
 217 auto selectionStart = selection.visibleStart();
 218 auto selectionEnd = selection.visibleEnd();
 219
 220 // As context, we are going to use the surrounding paragraphs of text.
 221 auto paragraphStart = startOfParagraph(selectionStart);
 222 auto paragraphEnd = endOfParagraph(selectionEnd);
 223
 224 auto rangeToSelectionStart = makeRange(paragraphStart, selectionStart);
 225 auto rangeToSelectionEnd = makeRange(paragraphStart, selectionEnd);
 226
 227 fullCharacterRange = makeRange(paragraphStart, paragraphEnd);
 228
 229 selectionRange = NSMakeRange(TextIterator::rangeLength(rangeToSelectionStart.get()), TextIterator::rangeLength(makeRange(selectionStart, selectionEnd).get()));
 230
 231 hitIndex = TextIterator::rangeLength(makeRange(paragraphStart, position).get());
 232 } else {
 233 VisibleSelection selectionAccountingForLineRules { position };
 234 selectionAccountingForLineRules.expandUsingGranularity(WordGranularity);
 235 position = selectionAccountingForLineRules.start();
 236 // As context, we are going to use 250 characters of text before and after the point.
 237 fullCharacterRange = rangeExpandedAroundPositionByCharacters(position, 250);
 238
 239 if (!fullCharacterRange)
 240 return { nullptr, nil };
 241
 242 selectionRange = NSMakeRange(NSNotFound, 0);
 243 hitIndex = TextIterator::rangeLength(makeRange(fullCharacterRange->startPosition(), position).get());
 244 }
 245
 246 NSRange selectedRange = [getRVSelectionClass() revealRangeAtIndex:hitIndex selectedRanges:@[[NSValue valueWithRange:selectionRange]] shouldUpdateSelection:nil];
 247
 248 String itemString = plainText(fullCharacterRange.get());
 249 RetainPtr<RVItem> item = adoptNS([allocRVItemInstance() initWithText:itemString selectedRange:selectedRange]);
 250 NSRange highlightRange = item.get().highlightRange;
 251
 252 if (highlightRange.location == NSNotFound || !highlightRange.length)
 253 return { nullptr, nil };
 254
 255 return { TextIterator::subrange(*fullCharacterRange, highlightRange.location, highlightRange.length), nil };
 256
 257 END_BLOCK_OBJC_EXCEPTIONS;
 258
 259 return { nullptr, nil };
 260
 261}
 262
 263#if !PLATFORM(WATCH)
 264
 265static void expandSelectionByCharacters(PDFSelection *selection, NSInteger numberOfCharactersToExpand, NSInteger& charactersAddedBeforeStart, NSInteger& charactersAddedAfterEnd)
 266{
 267 BEGIN_BLOCK_OBJC_EXCEPTIONS;
 268
 269 size_t originalLength = selection.string.length;
 270 [selection extendSelectionAtStart:numberOfCharactersToExpand];
 271
 272 charactersAddedBeforeStart = selection.string.length - originalLength;
 273
 274 [selection extendSelectionAtEnd:numberOfCharactersToExpand];
 275 charactersAddedAfterEnd = selection.string.length - originalLength - charactersAddedBeforeStart;
 276
 277 END_BLOCK_OBJC_EXCEPTIONS;
 278}
 279
 280std::tuple<NSString *, NSDictionary *> DictionaryLookup::stringForPDFSelection(PDFSelection *selection)
 281{
 282 BEGIN_BLOCK_OBJC_EXCEPTIONS;
 283
 284 if (!getRVItemClass())
 285 return { nullptr, nil };
 286
 287 // Don't do anything if there is no character at the point.
 288 if (!selection || !selection.string.length)
 289 return { @"", nil };
 290
 291 RetainPtr<PDFSelection> selectionForLookup = adoptNS([selection copy]);
 292
 293 // As context, we are going to use 250 characters of text before and after the point.
 294 auto originalLength = [selectionForLookup string].length;
 295 NSInteger charactersAddedBeforeStart = 0;
 296 NSInteger charactersAddedAfterEnd = 0;
 297 expandSelectionByCharacters(selectionForLookup.get(), 250, charactersAddedBeforeStart, charactersAddedAfterEnd);
 298
 299 auto fullPlainTextString = [selectionForLookup string];
 300 auto rangeToPass = NSMakeRange(charactersAddedBeforeStart, 0);
 301
 302 RetainPtr<RVItem> item = adoptNS([allocRVItemInstance() initWithText:fullPlainTextString selectedRange:rangeToPass]);
 303 NSRange extractedRange = item.get().highlightRange;
 304
 305 if (extractedRange.location == NSNotFound)
 306 return { selection.string, nil };
 307
 308 NSInteger lookupAddedBefore = rangeToPass.location - extractedRange.location;
 309 NSInteger lookupAddedAfter = (extractedRange.location + extractedRange.length) - (rangeToPass.location + originalLength);
 310
 311 [selection extendSelectionAtStart:lookupAddedBefore];
 312 [selection extendSelectionAtEnd:lookupAddedAfter];
 313
 314 ASSERT([selection.string isEqualToString:[fullPlainTextString substringWithRange:extractedRange]]);
 315 return { selection.string, nil };
 316
 317 END_BLOCK_OBJC_EXCEPTIONS;
 318
 319 return { @"", nil };
 320}
 321
 322#endif // !PLATFORM(WATCH)
 323
 324static WKRevealController showPopupOrCreateAnimationController(bool createAnimationController, const DictionaryPopupInfo& dictionaryPopupInfo, NSView *view, const WTF::Function<void(TextIndicator&)>& textIndicatorInstallationCallback, const WTF::Function<FloatRect(FloatRect)>& rootViewToViewConversionCallback, WTF::Function<void()>&& clearTextIndicator)
 325{
 326 BEGIN_BLOCK_OBJC_EXCEPTIONS;
 327
 328#if PLATFORM(MAC)
 329
 330 if (!getRVItemClass() || !getRVPresenterClass())
 331 return nil;
 332
 333 RetainPtr<NSMutableDictionary> mutableOptions = adoptNS([[NSMutableDictionary alloc] init]);
 334 if (NSDictionary *options = dictionaryPopupInfo.options.get())
 335 [mutableOptions addEntriesFromDictionary:options];
 336
 337 auto textIndicator = TextIndicator::create(dictionaryPopupInfo.textIndicator);
 338
 339 RetainPtr<RVPresenter> presenter = adoptNS([allocRVPresenterInstance() init]);
 340
 341 NSRect highlightRect;
 342 NSPoint pointerLocation;
 343
 344 if (textIndicator.get().contentImage()) {
 345 textIndicatorInstallationCallback(textIndicator.get());
 346
 347 FloatRect firstTextRectInViewCoordinates = textIndicator.get().textRectsInBoundingRectCoordinates()[0];
 348 FloatRect textBoundingRectInViewCoordinates = textIndicator.get().textBoundingRectInRootViewCoordinates();
 349 FloatRect selectionBoundingRectInViewCoordinates = textIndicator.get().selectionRectInRootViewCoordinates();
 350
 351 if (rootViewToViewConversionCallback) {
 352 textBoundingRectInViewCoordinates = rootViewToViewConversionCallback(textBoundingRectInViewCoordinates);
 353 selectionBoundingRectInViewCoordinates = rootViewToViewConversionCallback(selectionBoundingRectInViewCoordinates);
 354 }
 355
 356 firstTextRectInViewCoordinates.moveBy(textBoundingRectInViewCoordinates.location());
 357 highlightRect = selectionBoundingRectInViewCoordinates;
 358 pointerLocation = firstTextRectInViewCoordinates.location();
 359
 360 } else {
 361 NSPoint textBaselineOrigin = dictionaryPopupInfo.origin;
 362
 363 highlightRect = textIndicator->selectionRectInRootViewCoordinates();
 364 pointerLocation = [view convertPoint:textBaselineOrigin toView:nil];
 365 }
 366
 367 RetainPtr<WebRevealHighlight> webHighlight = adoptNS([[WebRevealHighlight alloc] initWithHighlightRect: highlightRect useDefaultHighlight:!textIndicator.get().contentImage() attributedString:dictionaryPopupInfo.attributedString.get()]);
 368 RetainPtr<RVPresentingContext> context = adoptNS([allocRVPresentingContextInstance() initWithPointerLocationInView:pointerLocation inView:view highlightDelegate:(id<RVPresenterHighlightDelegate>) webHighlight.get()]);
 369
 370 RetainPtr<RVItem> item = adoptNS([allocRVItemInstance() initWithText:dictionaryPopupInfo.attributedString.get().string selectedRange:NSMakeRange(0, 0)]);
 371
 372 [webHighlight setClearTextIndicator:[webHighlight = WTFMove(webHighlight), clearTextIndicator = WTFMove(clearTextIndicator)] {
 373 if (clearTextIndicator)
 374 clearTextIndicator();
 375 }];
 376
 377 if (createAnimationController)
 378 return [presenter animationControllerForItem:item.get() documentContext:nil presentingContext:context.get() options:nil];
 379 [presenter revealItem:item.get() documentContext:nil presentingContext:context.get() options:nil];
 380 return nil;
 381
 382#else // PLATFORM(MAC)
 383
 384 UNUSED_PARAM(createAnimationController);
 385 UNUSED_PARAM(dictionaryPopupInfo);
 386 UNUSED_PARAM(view);
 387 UNUSED_PARAM(textIndicatorInstallationCallback);
 388 UNUSED_PARAM(rootViewToViewConversionCallback);
 389 UNUSED_PARAM(clearTextIndicator);
 390
 391 return nil;
 392#endif // PLATFORM(MAC)
 393
 394 END_BLOCK_OBJC_EXCEPTIONS;
 395
 396}
 397
 398void DictionaryLookup::showPopup(const DictionaryPopupInfo& dictionaryPopupInfo, NSView *view, const WTF::Function<void(TextIndicator&)>& textIndicatorInstallationCallback, const WTF::Function<FloatRect(FloatRect)>& rootViewToViewConversionCallback, WTF::Function<void()>&& clearTextIndicator)
 399{
 400 showPopupOrCreateAnimationController(false, dictionaryPopupInfo, view, textIndicatorInstallationCallback, rootViewToViewConversionCallback, WTFMove(clearTextIndicator));
 401}
 402
 403void DictionaryLookup::hidePopup()
 404{
 405 notImplemented();
 406}
 407
 408#if PLATFORM(MAC)
 409
 410WKRevealController DictionaryLookup::animationControllerForPopup(const DictionaryPopupInfo& dictionaryPopupInfo, NSView *view, const WTF::Function<void(TextIndicator&)>& textIndicatorInstallationCallback, const WTF::Function<FloatRect(FloatRect)>& rootViewToViewConversionCallback, WTF::Function<void()>&& clearTextIndicator)
 411{
 412 return showPopupOrCreateAnimationController(true, dictionaryPopupInfo, view, textIndicatorInstallationCallback, rootViewToViewConversionCallback, WTFMove(clearTextIndicator));
 413}
 414
 415#endif // PLATFORM(MAC)
 416
 417#elif PLATFORM(IOS_FAMILY) // ENABLE(REVEAL)
 418
 419std::tuple<RefPtr<Range>, NSDictionary *> DictionaryLookup::rangeForSelection(const VisibleSelection&)
 420{
 421 return { nullptr, nil };
 422}
 423
 424std::tuple<RefPtr<Range>, NSDictionary *> DictionaryLookup::rangeAtHitTestResult(const HitTestResult&)
 425{
 426 return { nullptr, nil };
 427}
 428
 429#endif // ENABLE(REVEAL)
 430
 431} // namespace WebCore
 432
 433#endif // PLATFORM(COCOA)

Source/WebCore/editing/cocoa/WebContentReaderCocoa.mm

3434#import "Document.h"
3535#import "DocumentFragment.h"
3636#import "DocumentLoader.h"
 37#import "Editor.h"
 38#import "EditorClient.h"
3739#import "File.h"
3840#import "FileSystem.h"
3941#import "Frame.h"

Source/WebCore/editing/mac/DictionaryLookup.h

2323 * THE POSSIBILITY OF SUCH DAMAGE.
2424 */
2525
26 #if PLATFORM(MAC)
 26#pragma once
 27
 28#if PLATFORM(COCOA)
2729
2830#include "DictionaryPopupInfo.h"
29 #include <pal/spi/mac/NSImmediateActionGestureRecognizerSPI.h>
 31#if PLATFORM(MAC)
 32#import <pal/spi/mac/NSImmediateActionGestureRecognizerSPI.h>
 33#endif // PLATFORM(MAC)
3034#include <wtf/Function.h>
3135
3236OBJC_CLASS NSView;
3337OBJC_CLASS PDFSelection;
3438
 39#if PLATFORM(MAC)
 40typedef id <NSImmediateActionAnimationController> WKRevealController;
 41#else
 42typedef id WKRevealController;
 43#endif // PLATFORM(MAC)
 44
3545namespace WebCore {
3646
3747class HitTestResult;

@@public:
4858
4959 WEBCORE_EXPORT static void showPopup(const DictionaryPopupInfo&, NSView *, const WTF::Function<void(TextIndicator&)>& textIndicatorInstallationCallback, const WTF::Function<FloatRect(FloatRect)>& rootViewToViewConversionCallback = nullptr, WTF::Function<void()>&& clearTextIndicator = nullptr);
5060 WEBCORE_EXPORT static void hidePopup();
51 
52  WEBCORE_EXPORT static id <NSImmediateActionAnimationController> animationControllerForPopup(const DictionaryPopupInfo&, NSView *, const WTF::Function<void(TextIndicator&)>& textIndicatorInstallationCallback, const WTF::Function<FloatRect(FloatRect)>& rootViewToViewConversionCallback = nullptr, WTF::Function<void()>&& clearTextIndicator = nullptr);
 61
 62#if PLATFORM(MAC)
 63 WEBCORE_EXPORT static WKRevealController animationControllerForPopup(const DictionaryPopupInfo&, NSView *, const WTF::Function<void(TextIndicator&)>& textIndicatorInstallationCallback, const WTF::Function<FloatRect(FloatRect)>& rootViewToViewConversionCallback = nullptr, WTF::Function<void()>&& clearTextIndicator = nullptr);
 64#endif // PLATFORM(MAC)
 65
5366};
5467
5568} // namespace WebCore

Source/WebCore/editing/mac/DictionaryLookup.mm

1 /*
2  * Copyright (C) 2014-2018 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  * notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  * notice, this list of conditions and the following disclaimer in the
11  * documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25 
26 #import "config.h"
27 #import "DictionaryLookup.h"
28 
29 #if PLATFORM(MAC) && ENABLE(REVEAL)
30 
31 #import "Document.h"
32 #import "Editing.h"
33 #import "FocusController.h"
34 #import "Frame.h"
35 #import "FrameSelection.h"
36 #import "HTMLConverter.h"
37 #import "HitTestResult.h"
38 #import "Page.h"
39 #import "Range.h"
40 #import "RenderObject.h"
41 #import "TextIterator.h"
42 #import "VisiblePosition.h"
43 #import "VisibleSelection.h"
44 #import "VisibleUnits.h"
45 #import <PDFKit/PDFKit.h>
46 #import <pal/spi/mac/LookupSPI.h>
47 #import <pal/spi/mac/NSImmediateActionGestureRecognizerSPI.h>
48 #import <pal/spi/mac/RevealSPI.h>
49 #import <wtf/BlockObjCExceptions.h>
50 #import <wtf/RefPtr.h>
51 
52 @interface WebRevealHighlight <RVPresenterHighlightDelegate> : NSObject {
53 @private
54  Function<void()> _clearTextIndicator;
55  NSRect _highlightRect;
56  BOOL _useDefaultHighlight;
57  NSAttributedString *_attributedString;
58 }
59 
60 @property (nonatomic, readonly) NSRect highlightRect;
61 @property (nonatomic, readonly) BOOL useDefaultHighlight;
62 @property (nonatomic, readonly) NSAttributedString *attributedString;
63 
64 - (instancetype)initWithHighlightRect:(NSRect)highlightRect useDefaultHighlight:(BOOL)useDefaultHighlight attributedString:(NSAttributedString *) attributedString;
65 - (void)setClearTextIndicator:(Function<void()>&&)clearTextIndicator;
66 
67 @end
68 
69 @implementation WebRevealHighlight
70 
71 @synthesize highlightRect=_highlightRect;
72 @synthesize useDefaultHighlight=_useDefaultHighlight;
73 @synthesize attributedString=_attributedString;
74 
75 - (instancetype)initWithHighlightRect:(NSRect)highlightRect useDefaultHighlight:(BOOL)useDefaultHighlight attributedString:(NSAttributedString *) attributedString
76 {
77  if (!(self = [super init]))
78  return nil;
79 
80  _highlightRect = highlightRect;
81  _useDefaultHighlight = useDefaultHighlight;
82  _attributedString = attributedString;
83 
84  return self;
85 }
86 
87 - (void)setClearTextIndicator:(Function<void()>&&)clearTextIndicator
88 {
89  _clearTextIndicator = WTFMove(clearTextIndicator);
90 }
91 
92 - (NSArray<NSValue *> *)revealContext:(RVPresentingContext *)context rectsForItem:(RVItem *)item
93 {
94  UNUSED_PARAM(context);
95  UNUSED_PARAM(item);
96  return @[[NSValue valueWithRect:self.highlightRect]];
97 }
98 
99 - (void)revealContext:(RVPresentingContext *)context drawRectsForItem:(RVItem *)item
100 {
101  UNUSED_PARAM(item);
102 
103  for (NSValue *rectVal in context.itemRectsInView) {
104  NSRect rect = rectVal.rectValue;
105 
106  // Get current font attributes from the attributed string above, and add paragraph style attribute in order to center text.
107  RetainPtr<NSMutableDictionary> attributes = adoptNS([[NSMutableDictionary alloc] initWithDictionary:[self.attributedString fontAttributesInRange:NSMakeRange(0, [self.attributedString length])]]);
108  RetainPtr<NSMutableParagraphStyle> paragraph = adoptNS([[NSMutableParagraphStyle alloc] init]);
109  [paragraph setAlignment:NSTextAlignmentCenter];
110  [attributes setObject:paragraph.get() forKey:NSParagraphStyleAttributeName];
111 
112  RetainPtr<NSAttributedString> string = adoptNS([[NSAttributedString alloc] initWithString:[self.attributedString string] attributes:attributes.get()]);
113  [string drawInRect:rect];
114  }
115 }
116 
117 - (BOOL)revealContext:(RVPresentingContext *)context shouldUseDefaultHighlightForItem:(RVItem *)item
118 {
119  UNUSED_PARAM(context);
120  UNUSED_PARAM(item);
121  return self.useDefaultHighlight;
122 }
123 
124 - (void)revealContext:(RVPresentingContext *)context stopHighlightingItem:(RVItem *)item
125 {
126  UNUSED_PARAM(context);
127  UNUSED_PARAM(item);
128  auto block = WTFMove(_clearTextIndicator);
129  if (block)
130  block();
131 }
132 
133 @end
134 
135 namespace WebCore {
136 
137 std::tuple<RefPtr<Range>, NSDictionary *> DictionaryLookup::rangeForSelection(const VisibleSelection& selection)
138 {
139  BEGIN_BLOCK_OBJC_EXCEPTIONS;
140 
141  if (!getRVItemClass())
142  return { nullptr, nil };
143 
144  auto selectedRange = selection.toNormalizedRange();
145  if (!selectedRange)
146  return { nullptr, nil };
147 
148  // Since we already have the range we want, we just need to grab the returned options.
149  auto selectionStart = selection.visibleStart();
150  auto selectionEnd = selection.visibleEnd();
151 
152  // As context, we are going to use the surrounding paragraphs of text.
153  auto paragraphStart = startOfParagraph(selectionStart);
154  auto paragraphEnd = endOfParagraph(selectionEnd);
155 
156  int lengthToSelectionStart = TextIterator::rangeLength(makeRange(paragraphStart, selectionStart).get());
157  int lengthToSelectionEnd = TextIterator::rangeLength(makeRange(paragraphStart, selectionEnd).get());
158  NSRange rangeToPass = NSMakeRange(lengthToSelectionStart, lengthToSelectionEnd - lengthToSelectionStart);
159 
160  RefPtr<Range> fullCharacterRange = makeRange(paragraphStart, paragraphEnd);
161  String itemString = plainText(fullCharacterRange.get());
162  RetainPtr<RVItem> item = adoptNS([allocRVItemInstance() initWithText:itemString selectedRange:rangeToPass]);
163  NSRange highlightRange = item.get().highlightRange;
164 
165  return { TextIterator::subrange(*fullCharacterRange, highlightRange.location, highlightRange.length), nil };
166 
167  END_BLOCK_OBJC_EXCEPTIONS;
168 
169  return { nullptr, nil };
170 }
171 
172 std::tuple<RefPtr<Range>, NSDictionary *> DictionaryLookup::rangeAtHitTestResult(const HitTestResult& hitTestResult)
173 {
174  BEGIN_BLOCK_OBJC_EXCEPTIONS;
175 
176  if (!getRVItemClass())
177  return { nullptr, nil };
178 
179  auto* node = hitTestResult.innerNonSharedNode();
180  if (!node || !node->renderer())
181  return { nullptr, nil };
182 
183  auto* frame = node->document().frame();
184  if (!frame)
185  return { nullptr, nil };
186 
187  // Don't do anything if there is no character at the point.
188  auto framePoint = hitTestResult.roundedPointInInnerNodeFrame();
189  if (!frame->rangeForPoint(framePoint))
190  return { nullptr, nil };
191 
192  auto position = frame->visiblePositionForPoint(framePoint);
193  if (position.isNull())
194  position = firstPositionInOrBeforeNode(node);
195 
196  auto selection = frame->page()->focusController().focusedOrMainFrame().selection().selection();
197  NSRange selectionRange;
198  int hitIndex;
199  RefPtr<Range> fullCharacterRange;
200 
201  if (selection.selectionType() == VisibleSelection::RangeSelection) {
202  auto selectionStart = selection.visibleStart();
203  auto selectionEnd = selection.visibleEnd();
204 
205  // As context, we are going to use the surrounding paragraphs of text.
206  auto paragraphStart = startOfParagraph(selectionStart);
207  auto paragraphEnd = endOfParagraph(selectionEnd);
208 
209  auto rangeToSelectionStart = makeRange(paragraphStart, selectionStart);
210  auto rangeToSelectionEnd = makeRange(paragraphStart, selectionEnd);
211 
212  fullCharacterRange = makeRange(paragraphStart, paragraphEnd);
213 
214  selectionRange = NSMakeRange(TextIterator::rangeLength(rangeToSelectionStart.get()), TextIterator::rangeLength(makeRange(selectionStart, selectionEnd).get()));
215 
216  hitIndex = TextIterator::rangeLength(makeRange(paragraphStart, position).get());
217  } else {
218  VisibleSelection selectionAccountingForLineRules { position };
219  selectionAccountingForLineRules.expandUsingGranularity(WordGranularity);
220  position = selectionAccountingForLineRules.start();
221  // As context, we are going to use 250 characters of text before and after the point.
222  fullCharacterRange = rangeExpandedAroundPositionByCharacters(position, 250);
223 
224  if (!fullCharacterRange)
225  return { nullptr, nil };
226 
227  selectionRange = NSMakeRange(NSNotFound, 0);
228  hitIndex = TextIterator::rangeLength(makeRange(fullCharacterRange->startPosition(), position).get());
229  }
230 
231  NSRange selectedRange = [getRVSelectionClass() revealRangeAtIndex:hitIndex selectedRanges:@[[NSValue valueWithRange:selectionRange]] shouldUpdateSelection:nil];
232 
233  String itemString = plainText(fullCharacterRange.get());
234  RetainPtr<RVItem> item = adoptNS([allocRVItemInstance() initWithText:itemString selectedRange:selectedRange]);
235  NSRange highlightRange = item.get().highlightRange;
236 
237  if (highlightRange.location == NSNotFound || !highlightRange.length)
238  return { nullptr, nil };
239 
240  return { TextIterator::subrange(*fullCharacterRange, highlightRange.location, highlightRange.length), nil };
241 
242  END_BLOCK_OBJC_EXCEPTIONS;
243 
244  return { nullptr, nil };
245 
246 }
247 
248 static void expandSelectionByCharacters(PDFSelection *selection, NSInteger numberOfCharactersToExpand, NSInteger& charactersAddedBeforeStart, NSInteger& charactersAddedAfterEnd)
249 {
250  BEGIN_BLOCK_OBJC_EXCEPTIONS;
251 
252  size_t originalLength = selection.string.length;
253  [selection extendSelectionAtStart:numberOfCharactersToExpand];
254 
255  charactersAddedBeforeStart = selection.string.length - originalLength;
256 
257  [selection extendSelectionAtEnd:numberOfCharactersToExpand];
258  charactersAddedAfterEnd = selection.string.length - originalLength - charactersAddedBeforeStart;
259 
260  END_BLOCK_OBJC_EXCEPTIONS;
261 }
262 
263 std::tuple<NSString *, NSDictionary *> DictionaryLookup::stringForPDFSelection(PDFSelection *selection)
264 {
265  BEGIN_BLOCK_OBJC_EXCEPTIONS;
266 
267  if (!getRVItemClass())
268  return { nullptr, nil };
269 
270  // Don't do anything if there is no character at the point.
271  if (!selection || !selection.string.length)
272  return { @"", nil };
273 
274  RetainPtr<PDFSelection> selectionForLookup = adoptNS([selection copy]);
275 
276  // As context, we are going to use 250 characters of text before and after the point.
277  auto originalLength = [selectionForLookup string].length;
278  NSInteger charactersAddedBeforeStart = 0;
279  NSInteger charactersAddedAfterEnd = 0;
280  expandSelectionByCharacters(selectionForLookup.get(), 250, charactersAddedBeforeStart, charactersAddedAfterEnd);
281 
282  auto fullPlainTextString = [selectionForLookup string];
283  auto rangeToPass = NSMakeRange(charactersAddedBeforeStart, 0);
284 
285  RetainPtr<RVItem> item = adoptNS([allocRVItemInstance() initWithText:fullPlainTextString selectedRange:rangeToPass]);
286  NSRange extractedRange = item.get().highlightRange;
287 
288  if (extractedRange.location == NSNotFound)
289  return { selection.string, nil };
290 
291  NSInteger lookupAddedBefore = rangeToPass.location - extractedRange.location;
292  NSInteger lookupAddedAfter = (extractedRange.location + extractedRange.length) - (rangeToPass.location + originalLength);
293 
294  [selection extendSelectionAtStart:lookupAddedBefore];
295  [selection extendSelectionAtEnd:lookupAddedAfter];
296 
297  ASSERT([selection.string isEqualToString:[fullPlainTextString substringWithRange:extractedRange]]);
298  return { selection.string, nil };
299 
300  END_BLOCK_OBJC_EXCEPTIONS;
301 
302  return { @"", nil };
303 }
304 
305 static id <NSImmediateActionAnimationController> showPopupOrCreateAnimationController(bool createAnimationController, const DictionaryPopupInfo& dictionaryPopupInfo, NSView *view, const WTF::Function<void(TextIndicator&)>& textIndicatorInstallationCallback, const WTF::Function<FloatRect(FloatRect)>& rootViewToViewConversionCallback, WTF::Function<void()>&& clearTextIndicator)
306 {
307  BEGIN_BLOCK_OBJC_EXCEPTIONS;
308 
309  if (!getRVItemClass())
310  return nil;
311 
312  RetainPtr<NSMutableDictionary> mutableOptions = adoptNS([[NSMutableDictionary alloc] init]);
313  if (NSDictionary *options = dictionaryPopupInfo.options.get())
314  [mutableOptions addEntriesFromDictionary:options];
315 
316  auto textIndicator = TextIndicator::create(dictionaryPopupInfo.textIndicator);
317 
318  RetainPtr<RVPresenter> presenter = adoptNS([allocRVPresenterInstance() init]);
319 
320  NSRect highlightRect;
321  NSPoint pointerLocation;
322 
323  if (textIndicator.get().contentImage()) {
324  textIndicatorInstallationCallback(textIndicator.get());
325 
326  FloatRect firstTextRectInViewCoordinates = textIndicator.get().textRectsInBoundingRectCoordinates()[0];
327  FloatRect textBoundingRectInViewCoordinates = textIndicator.get().textBoundingRectInRootViewCoordinates();
328  FloatRect selectionBoundingRectInViewCoordinates = textIndicator.get().selectionRectInRootViewCoordinates();
329 
330  if (rootViewToViewConversionCallback) {
331  textBoundingRectInViewCoordinates = rootViewToViewConversionCallback(textBoundingRectInViewCoordinates);
332  selectionBoundingRectInViewCoordinates = rootViewToViewConversionCallback(selectionBoundingRectInViewCoordinates);
333  }
334 
335  firstTextRectInViewCoordinates.moveBy(textBoundingRectInViewCoordinates.location());
336  highlightRect = selectionBoundingRectInViewCoordinates;
337  pointerLocation = firstTextRectInViewCoordinates.location();
338 
339  } else {
340  NSPoint textBaselineOrigin = dictionaryPopupInfo.origin;
341 
342  highlightRect = textIndicator->selectionRectInRootViewCoordinates();
343  pointerLocation = [view convertPoint:textBaselineOrigin toView:nil];
344  }
345 
346  RetainPtr<WebRevealHighlight> webHighlight = adoptNS([[WebRevealHighlight alloc] initWithHighlightRect: highlightRect useDefaultHighlight:!textIndicator.get().contentImage() attributedString:dictionaryPopupInfo.attributedString.get()]);
347  RetainPtr<RVPresentingContext> context = adoptNS([allocRVPresentingContextInstance() initWithPointerLocationInView:pointerLocation inView:view highlightDelegate:(id<RVPresenterHighlightDelegate>) webHighlight.get()]);
348 
349  RetainPtr<RVItem> item = adoptNS([allocRVItemInstance() initWithText:dictionaryPopupInfo.attributedString.get().string selectedRange:NSMakeRange(0, 0)]);
350 
351  [webHighlight setClearTextIndicator:[webHighlight = WTFMove(webHighlight), clearTextIndicator = WTFMove(clearTextIndicator)] {
352  if (clearTextIndicator)
353  clearTextIndicator();
354  }];
355 
356  if (createAnimationController)
357  return [presenter animationControllerForItem:item.get() documentContext:nil presentingContext:context.get() options:nil];
358  [presenter revealItem:item.get() documentContext:nil presentingContext:context.get() options:nil];
359  return nil;
360 
361  END_BLOCK_OBJC_EXCEPTIONS;
362  return nil;
363 }
364 
365 void DictionaryLookup::showPopup(const DictionaryPopupInfo& dictionaryPopupInfo, NSView *view, const WTF::Function<void(TextIndicator&)>& textIndicatorInstallationCallback, const WTF::Function<FloatRect(FloatRect)>& rootViewToViewConversionCallback, WTF::Function<void()>&& clearTextIndicator)
366 {
367  showPopupOrCreateAnimationController(false, dictionaryPopupInfo, view, textIndicatorInstallationCallback, rootViewToViewConversionCallback, WTFMove(clearTextIndicator));
368 }
369 
370 void DictionaryLookup::hidePopup()
371 {
372  BEGIN_BLOCK_OBJC_EXCEPTIONS;
373 
374  if (!getLULookupDefinitionModuleClass())
375  return;
376  [getLULookupDefinitionModuleClass() hideDefinition];
377 
378  END_BLOCK_OBJC_EXCEPTIONS;
379 }
380 
381 id <NSImmediateActionAnimationController> DictionaryLookup::animationControllerForPopup(const DictionaryPopupInfo& dictionaryPopupInfo, NSView *view, const WTF::Function<void(TextIndicator&)>& textIndicatorInstallationCallback, const WTF::Function<FloatRect(FloatRect)>& rootViewToViewConversionCallback, WTF::Function<void()>&& clearTextIndicator)
382 {
383  return showPopupOrCreateAnimationController(true, dictionaryPopupInfo, view, textIndicatorInstallationCallback, rootViewToViewConversionCallback, WTFMove(clearTextIndicator));
384 }
385 
386 } // namespace WebCore
387 
388 #endif // PLATFORM(MAC)

Source/WebKit/Platform/spi/ios/UIKitSPI.h

@@struct _UIWebTouchEvent {
733733 bool isPotentialTap;
734734};
735735
 736@interface _UILookupGestureRecognizer : UIGestureRecognizer
 737@end
 738
736739@class UIWebTouchEventsGestureRecognizer;
737740
738741@protocol UIWebTouchEventsGestureRecognizerDelegate <NSObject>

Source/WebKit/UIProcess/Cocoa/WebPageProxyCocoa.mm

3333#import "PageClient.h"
3434#import "SafeBrowsingSPI.h"
3535#import "SafeBrowsingWarning.h"
 36#import "WebPageMessages.h"
3637#import "WebProcessProxy.h"
3738#import <WebCore/DragItem.h>
3839#import <WebCore/NotImplemented.h>

@@void WebPageProxy::platformCloneAttachment(Ref<API::Attachment>&& fromAttachment
189190}
190191
191192#endif // ENABLE(ATTACHMENT_ELEMENT)
 193
 194void WebPageProxy::performDictionaryLookupAtLocation(const WebCore::FloatPoint& point)
 195{
 196 if (!isValid())
 197 return;
 198
 199 process().send(Messages::WebPage::PerformDictionaryLookupAtLocation(point), m_pageID);
 200}
192201
 202void WebPageProxy::performDictionaryLookupOfCurrentSelection()
 203{
 204 if (!isValid())
 205 return;
 206
 207 process().send(Messages::WebPage::PerformDictionaryLookupOfCurrentSelection(), m_pageID);
193208}
 209
 210} // namespace WebKit

Source/WebKit/UIProcess/ios/WKContentViewInteraction.h

@@class WebOpenPanelResultListenerProxy;
8787class WebPageProxy;
8888}
8989
 90@class _UILookupGestureRecognizer;
9091@class _UIHighlightView;
9192@class _UIWebHighlightLongPressGestureRecognizer;
9293@class UIHoverGestureRecognizer;

@@struct WKAutoCorrectionData {
215216
216217#if PLATFORM(IOSMAC)
217218 RetainPtr<UIHoverGestureRecognizer> _hoverGestureRecognizer;
 219 RetainPtr<_UILookupGestureRecognizer> _lookupGestureRecognizer;
218220#endif
219221
220222 RetainPtr<UIWKTextInteractionAssistant> _textSelectionAssistant;

Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm

112112#if PLATFORM(IOSMAC)
113113#import "NativeWebMouseEvent.h"
114114#import <UIKit/UIHoverGestureRecognizer.h>
 115#import <UIKit/_UILookupGestureRecognizer.h>
115116#import <pal/spi/ios/GraphicsServicesSPI.h>
116117#endif
117118

@@- (void)setupInteraction
649650 _hoverGestureRecognizer = adoptNS([[UIHoverGestureRecognizer alloc] initWithTarget:self action:@selector(_hoverGestureRecognizerChanged:)]);
650651 [_hoverGestureRecognizer setDelegate:self];
651652 [self addGestureRecognizer:_hoverGestureRecognizer.get()];
 653
 654 _lookupGestureRecognizer = adoptNS([[_UILookupGestureRecognizer alloc] initWithTarget:self action:@selector(_lookupGestureRecognized:)]);
 655 [_lookupGestureRecognizer setDelegate:self];
 656 [self addGestureRecognizer:_lookupGestureRecognizer.get()];
 657
652658#endif
653659
654660 _singleTapGestureRecognizer = adoptNS([[WKSyntheticClickTapGestureRecognizer alloc] initWithTarget:self action:@selector(_singleTapCommited:)]);

@@- (void)cleanupInteraction
759765#if PLATFORM(IOSMAC)
760766 [_hoverGestureRecognizer setDelegate:nil];
761767 [self removeGestureRecognizer:_hoverGestureRecognizer.get()];
 768
 769 [_lookupGestureRecognizer setDelegate:nil];
 770 [self removeGestureRecognizer:_lookupGestureRecognizer.get()];
762771#endif
763772
764773 [_singleTapGestureRecognizer setDelegate:nil];

@@- (void)_removeDefaultGestureRecognizers
846855 [self removeGestureRecognizer:_stylusSingleTapGestureRecognizer.get()];
847856#if PLATFORM(IOSMAC)
848857 [self removeGestureRecognizer:_hoverGestureRecognizer.get()];
 858 [self removeGestureRecognizer:_lookupGestureRecognizer.get()];
849859#endif
850860}
851861

@@- (void)_addDefaultGestureRecognizers
861871 [self addGestureRecognizer:_stylusSingleTapGestureRecognizer.get()];
862872#if PLATFORM(IOSMAC)
863873 [self addGestureRecognizer:_hoverGestureRecognizer.get()];
 874 [self addGestureRecognizer:_lookupGestureRecognizer.get()];
864875#endif
865876}
866877

@@- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecogni
14671478
14681479 if ([gestureRecognizer isKindOfClass:[UIHoverGestureRecognizer class]] || [otherGestureRecognizer isKindOfClass:[UIHoverGestureRecognizer class]])
14691480 return YES;
 1481
 1482 if (([gestureRecognizer isKindOfClass:[_UILookupGestureRecognizer class]] && [otherGestureRecognizer isKindOfClass:[UILongPressGestureRecognizer class]]) || ([otherGestureRecognizer isKindOfClass:[UILongPressGestureRecognizer class]] && [gestureRecognizer isKindOfClass:[_UILookupGestureRecognizer class]]))
 1483 return YES;
 1484
14701485#endif
14711486 if (isSamePair(gestureRecognizer, otherGestureRecognizer, _highlightLongPressGestureRecognizer.get(), _textSelectionAssistant.get().forcePressGesture))
14721487 return YES;

@@- (BOOL)allowsDictationInputForListViewController:(PUICQuickboardViewController
60576072#endif // PLATFORM(WATCHOS)
60586073
60596074#if PLATFORM(IOSMAC)
 6075- (void)_lookupGestureRecognized:(UIGestureRecognizer *)gestureRecognizer
 6076{
 6077 NSPoint locationInViewCoordinates = [gestureRecognizer locationInView:self];
 6078 _page->performDictionaryLookupAtLocation(WebCore::FloatPoint(locationInViewCoordinates));
 6079}
 6080
60606081- (void)_hoverGestureRecognizerChanged:(UIGestureRecognizer *)gestureRecognizer
60616082{
60626083 if (!_page->isValid())

Source/WebKit/UIProcess/ios/WebPageProxyIOS.mm

@@bool WebPageProxy::readSelectionFromPasteboard(const String&)
121121 return false;
122122}
123123
124 void WebPageProxy::performDictionaryLookupAtLocation(const WebCore::FloatPoint&)
125 {
126  notImplemented();
127 }
128 
129124void WebPageProxy::gestureCallback(const WebCore::IntPoint& point, uint32_t gestureType, uint32_t gestureState, uint32_t flags, CallbackID callbackID)
130125{
131126 auto callback = m_callbacks.take<GestureCallback>(callbackID);

Source/WebKit/UIProcess/mac/WebPageProxyMac.mm

@@void WebPageProxy::setPromisedDataForImage(const String& pasteboardName, const S
323323
324324#endif
325325
326 void WebPageProxy::performDictionaryLookupAtLocation(const WebCore::FloatPoint& point)
327 {
328  if (!isValid())
329  return;
330 
331  process().send(Messages::WebPage::PerformDictionaryLookupAtLocation(point), m_pageID);
332 }
333 
334 void WebPageProxy::performDictionaryLookupOfCurrentSelection()
335 {
336  if (!isValid())
337  return;
338 
339  process().send(Messages::WebPage::PerformDictionaryLookupOfCurrentSelection(), m_pageID);
340 }
341 
342326// Complex text input support for plug-ins.
343327void WebPageProxy::sendComplexTextInputToPlugin(uint64_t pluginComplexTextInputIdentifier, const String& textInput)
344328{

Source/WebKit/WebProcess/WebPage/Cocoa/WebPageCocoa.mm

2626#import "config.h"
2727#import "WebPage.h"
2828
 29
2930#import "LoadParameters.h"
 31#import "PluginView.h"
3032#import "WebPageProxyMessages.h"
 33#import <WebCore/DictionaryLookup.h>
 34#import <WebCore/Editor.h>
 35#import <WebCore/EventHandler.h>
 36#import <WebCore/FocusController.h>
 37#import <WebCore/HTMLConverter.h>
 38#import <WebCore/HitTestResult.h>
 39#import <WebCore/NodeRenderStyle.h>
3140#import <WebCore/PlatformMediaSessionManager.h>
 41#import <WebCore/RenderElement.h>
 42#import <WebCore/RenderObject.h>
3243
3344#if PLATFORM(COCOA)
3445

@@void WebPage::requestActiveNowPlayingSessionInfo(CallbackID callbackID)
5970
6071 send(Messages::WebPageProxy::NowPlayingInfoCallback(hasActiveSession, registeredAsNowPlayingApplication, title, duration, elapsedTime, uniqueIdentifier, callbackID));
6172}
 73
 74void WebPage::performDictionaryLookupAtLocation(const FloatPoint& floatPoint)
 75{
 76 if (auto* pluginView = pluginViewForFrame(&m_page->mainFrame())) {
 77 if (pluginView->performDictionaryLookupAtLocation(floatPoint))
 78 return;
 79 }
 80
 81 // Find the frame the point is over.
 82 HitTestResult result = m_page->mainFrame().eventHandler().hitTestResultAtPoint(m_page->mainFrame().view()->windowToContents(roundedIntPoint(floatPoint)));
 83 RefPtr<Range> range;
 84 NSDictionary *options;
 85 std::tie(range, options) = DictionaryLookup::rangeAtHitTestResult(result);
 86 if (!range)
 87 return;
 88
 89 auto* frame = result.innerNonSharedNode() ? result.innerNonSharedNode()->document().frame() : &m_page->focusController().focusedOrMainFrame();
 90 if (!frame)
 91 return;
 92
 93 performDictionaryLookupForRange(*frame, *range, options, TextIndicatorPresentationTransition::Bounce);
 94}
 95
 96void WebPage::performDictionaryLookupForSelection(Frame& frame, const VisibleSelection& selection, TextIndicatorPresentationTransition presentationTransition)
 97{
 98 RefPtr<Range> selectedRange;
 99 NSDictionary *options;
 100 std::tie(selectedRange, options) = DictionaryLookup::rangeForSelection(selection);
 101 if (selectedRange)
 102 performDictionaryLookupForRange(frame, *selectedRange, options, presentationTransition);
 103}
 104
 105void WebPage::performDictionaryLookupOfCurrentSelection()
 106{
 107 auto& frame = m_page->focusController().focusedOrMainFrame();
 108 performDictionaryLookupForSelection(frame, frame.selection().selection(), TextIndicatorPresentationTransition::BounceAndCrossfade);
 109}
 110
 111void WebPage::performDictionaryLookupForRange(Frame& frame, Range& range, NSDictionary *options, TextIndicatorPresentationTransition presentationTransition)
 112{
 113 send(Messages::WebPageProxy::DidPerformDictionaryLookup(dictionaryPopupInfoForRange(frame, range, options, presentationTransition)));
 114}
 115
 116DictionaryPopupInfo WebPage::dictionaryPopupInfoForRange(Frame& frame, Range& range, NSDictionary *options, TextIndicatorPresentationTransition presentationTransition)
 117{
 118 Editor& editor = frame.editor();
 119 editor.setIsGettingDictionaryPopupInfo(true);
 120
 121 DictionaryPopupInfo dictionaryPopupInfo;
 122 if (range.text().stripWhiteSpace().isEmpty()) {
 123 editor.setIsGettingDictionaryPopupInfo(false);
 124 return dictionaryPopupInfo;
 125 }
 126
 127 Vector<FloatQuad> quads;
 128 range.absoluteTextQuads(quads);
 129 if (quads.isEmpty()) {
 130 editor.setIsGettingDictionaryPopupInfo(false);
 131 return dictionaryPopupInfo;
 132 }
 133
 134 IntRect rangeRect = frame.view()->contentsToWindow(quads[0].enclosingBoundingBox());
 135
 136 const RenderStyle* style = range.startContainer().renderStyle();
 137 float scaledAscent = style ? style->fontMetrics().ascent() * pageScaleFactor() : 0;
 138 dictionaryPopupInfo.origin = FloatPoint(rangeRect.x(), rangeRect.y() + scaledAscent);
 139 dictionaryPopupInfo.options = options;
 140
 141#if PLATFORM(MAC)
 142
 143 NSAttributedString *nsAttributedString = editingAttributedStringFromRange(range, IncludeImagesInAttributedString::No);
 144
 145 RetainPtr<NSMutableAttributedString> scaledNSAttributedString = adoptNS([[NSMutableAttributedString alloc] initWithString:[nsAttributedString string]]);
 146
 147 NSFontManager *fontManager = [NSFontManager sharedFontManager];
 148
 149 [nsAttributedString enumerateAttributesInRange:NSMakeRange(0, [nsAttributedString length]) options:0 usingBlock:^(NSDictionary *attributes, NSRange range, BOOL *stop) {
 150 RetainPtr<NSMutableDictionary> scaledAttributes = adoptNS([attributes mutableCopy]);
 151
 152 NSFont *font = [scaledAttributes objectForKey:NSFontAttributeName];
 153 if (font)
 154 font = [fontManager convertFont:font toSize:font.pointSize * pageScaleFactor()];
 155 if (font)
 156 [scaledAttributes setObject:font forKey:NSFontAttributeName];
 157
 158 [scaledNSAttributedString addAttributes:scaledAttributes.get() range:range];
 159 }];
 160
 161#endif // PLATFORM(MAC)
 162
 163 TextIndicatorOptions indicatorOptions = TextIndicatorOptionUseBoundingRectAndPaintAllContentForComplexRanges;
 164 if (presentationTransition == TextIndicatorPresentationTransition::BounceAndCrossfade)
 165 indicatorOptions |= TextIndicatorOptionIncludeSnapshotWithSelectionHighlight;
 166
 167 RefPtr<TextIndicator> textIndicator = TextIndicator::createWithRange(range, indicatorOptions, presentationTransition);
 168 if (!textIndicator) {
 169 editor.setIsGettingDictionaryPopupInfo(false);
 170 return dictionaryPopupInfo;
 171 }
 172
 173 dictionaryPopupInfo.textIndicator = textIndicator->data();
 174#if PLATFORM(MAC)
 175 dictionaryPopupInfo.attributedString = scaledNSAttributedString;
 176#endif // PLATFORM(MAC)
 177
 178 editor.setIsGettingDictionaryPopupInfo(false);
 179 return dictionaryPopupInfo;
 180}
62181
63182} // namespace WebKit
64183

Source/WebKit/WebProcess/WebPage/WebPage.messages.in

@@messages -> WebPage LegacyReceiver {
191191
192192#if PLATFORM(COCOA)
193193 # Dictionary support.
 194 PerformDictionaryLookupOfCurrentSelection()
194195 PerformDictionaryLookupAtLocation(WebCore::FloatPoint point)
195196#endif
196197

@@messages -> WebPage LegacyReceiver {
199200 RemoveDataDetectedLinks() -> (struct WebKit::DataDetectionResult result) Async
200201#endif
201202
202 #if PLATFORM(MAC)
203  PerformDictionaryLookupOfCurrentSelection()
204 #endif
205 
206203 ChangeFont(WebCore::FontChanges changes)
207204 ChangeFontAttributes(WebCore::FontAttributeChanges changes)
208205

Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm

@@void WebPage::sendComplexTextInputToPlugin(uint64_t, const String&)
417417 notImplemented();
418418}
419419
420 void WebPage::performDictionaryLookupAtLocation(const FloatPoint&)
421 {
422  notImplemented();
423 }
424 
425 void WebPage::performDictionaryLookupForSelection(Frame&, const VisibleSelection&, TextIndicatorPresentationTransition)
426 {
427  notImplemented();
428 }
429 
430 void WebPage::performDictionaryLookupForRange(Frame&, Range&, NSDictionary *, TextIndicatorPresentationTransition)
431 {
432  notImplemented();
433 }
434 
435420bool WebPage::performNonEditingBehaviorForSelector(const String&, WebCore::KeyboardEvent*)
436421{
437422 notImplemented();

Source/WebKit/WebProcess/WebPage/mac/WebPageMac.mm

@@void WebPage::fontAtSelection(CallbackID callbackID)
389389 send(Messages::WebPageProxy::FontAtSelectionCallback(fontName, fontSize, selectionHasMultipleFonts, callbackID));
390390}
391391
392 void WebPage::performDictionaryLookupAtLocation(const FloatPoint& floatPoint)
393 {
394  if (auto* pluginView = pluginViewForFrame(&m_page->mainFrame())) {
395  if (pluginView->performDictionaryLookupAtLocation(floatPoint))
396  return;
397  }
398 
399  // Find the frame the point is over.
400  HitTestResult result = m_page->mainFrame().eventHandler().hitTestResultAtPoint(m_page->mainFrame().view()->windowToContents(roundedIntPoint(floatPoint)));
401  RefPtr<Range> range;
402  NSDictionary *options;
403  std::tie(range, options) = DictionaryLookup::rangeAtHitTestResult(result);
404  if (!range)
405  return;
406 
407  auto* frame = result.innerNonSharedNode() ? result.innerNonSharedNode()->document().frame() : &m_page->focusController().focusedOrMainFrame();
408  if (!frame)
409  return;
410 
411  performDictionaryLookupForRange(*frame, *range, options, TextIndicatorPresentationTransition::Bounce);
412 }
413 
414 void WebPage::performDictionaryLookupForSelection(Frame& frame, const VisibleSelection& selection, TextIndicatorPresentationTransition presentationTransition)
415 {
416  RefPtr<Range> selectedRange;
417  NSDictionary *options;
418  std::tie(selectedRange, options) = DictionaryLookup::rangeForSelection(selection);
419  if (selectedRange)
420  performDictionaryLookupForRange(frame, *selectedRange, options, presentationTransition);
421 }
422392
423 void WebPage::performDictionaryLookupOfCurrentSelection()
424 {
425  auto& frame = m_page->focusController().focusedOrMainFrame();
426  performDictionaryLookupForSelection(frame, frame.selection().selection(), TextIndicatorPresentationTransition::BounceAndCrossfade);
427 }
428 
429 DictionaryPopupInfo WebPage::dictionaryPopupInfoForRange(Frame& frame, Range& range, NSDictionary *options, TextIndicatorPresentationTransition presentationTransition)
430 {
431  Editor& editor = frame.editor();
432  editor.setIsGettingDictionaryPopupInfo(true);
433 
434  DictionaryPopupInfo dictionaryPopupInfo;
435  if (range.text().stripWhiteSpace().isEmpty()) {
436  editor.setIsGettingDictionaryPopupInfo(false);
437  return dictionaryPopupInfo;
438  }
439 
440  Vector<FloatQuad> quads;
441  range.absoluteTextQuads(quads);
442  if (quads.isEmpty()) {
443  editor.setIsGettingDictionaryPopupInfo(false);
444  return dictionaryPopupInfo;
445  }
446 
447  IntRect rangeRect = frame.view()->contentsToWindow(quads[0].enclosingBoundingBox());
448 
449  const RenderStyle* style = range.startContainer().renderStyle();
450  float scaledAscent = style ? style->fontMetrics().ascent() * pageScaleFactor() : 0;
451  dictionaryPopupInfo.origin = FloatPoint(rangeRect.x(), rangeRect.y() + scaledAscent);
452  dictionaryPopupInfo.options = options;
453 
454  NSAttributedString *nsAttributedString = editingAttributedStringFromRange(range, IncludeImagesInAttributedString::No);
455 
456  RetainPtr<NSMutableAttributedString> scaledNSAttributedString = adoptNS([[NSMutableAttributedString alloc] initWithString:[nsAttributedString string]]);
457 
458  NSFontManager *fontManager = [NSFontManager sharedFontManager];
459 
460  [nsAttributedString enumerateAttributesInRange:NSMakeRange(0, [nsAttributedString length]) options:0 usingBlock:^(NSDictionary *attributes, NSRange range, BOOL *stop) {
461  RetainPtr<NSMutableDictionary> scaledAttributes = adoptNS([attributes mutableCopy]);
462 
463  NSFont *font = [scaledAttributes objectForKey:NSFontAttributeName];
464  if (font)
465  font = [fontManager convertFont:font toSize:font.pointSize * pageScaleFactor()];
466  if (font)
467  [scaledAttributes setObject:font forKey:NSFontAttributeName];
468 
469  [scaledNSAttributedString addAttributes:scaledAttributes.get() range:range];
470  }];
471 
472  TextIndicatorOptions indicatorOptions = TextIndicatorOptionUseBoundingRectAndPaintAllContentForComplexRanges;
473  if (presentationTransition == TextIndicatorPresentationTransition::BounceAndCrossfade)
474  indicatorOptions |= TextIndicatorOptionIncludeSnapshotWithSelectionHighlight;
475 
476  RefPtr<TextIndicator> textIndicator = TextIndicator::createWithRange(range, indicatorOptions, presentationTransition);
477  if (!textIndicator) {
478  editor.setIsGettingDictionaryPopupInfo(false);
479  return dictionaryPopupInfo;
480  }
481 
482  dictionaryPopupInfo.textIndicator = textIndicator->data();
483  dictionaryPopupInfo.attributedString = scaledNSAttributedString;
484 
485  editor.setIsGettingDictionaryPopupInfo(false);
486  return dictionaryPopupInfo;
487 }
488393
489394#if ENABLE(PDFKIT_PLUGIN)
490395

@@DictionaryPopupInfo WebPage::dictionaryPopupInfoForSelectionInPDFPlugin(PDFSelec
539444
540445#endif
541446
542 void WebPage::performDictionaryLookupForRange(Frame& frame, Range& range, NSDictionary *options, TextIndicatorPresentationTransition presentationTransition)
543 {
544  send(Messages::WebPageProxy::DidPerformDictionaryLookup(dictionaryPopupInfoForRange(frame, range, options, presentationTransition)));
545 }
546 
547447bool WebPage::performNonEditingBehaviorForSelector(const String& selector, KeyboardEvent* event)
548448{
549449 // First give accessibility a chance to handle the event.