Adopt Reveal Framework to replace Lookup
authormegan_gardner@apple.com <megan_gardner@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 9 Nov 2018 01:59:10 +0000 (01:59 +0000)
committermegan_gardner@apple.com <megan_gardner@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 9 Nov 2018 01:59:10 +0000 (01:59 +0000)
https://bugs.webkit.org/show_bug.cgi?id=191097
Source/WebCore:

Reviewed by Tim Horton.

Reveal is not currently testable.

The Reveal framework does the same job as Lookup and DataDectors.
In this patch we switch from using Lookup to determine what text
to select and define to using Reveal and RVItems. Since this
code needs to work on older systems, and Reveal is newer, we also need
to keep around the old code for old systems so that they can also
continue to work. Eventually we will remove this code and also likly switch
to passing RVItems across from the web process rather than making them
on each side.

* SourcesCocoa.txt:
* WebCore.xcodeproj/project.pbxproj:
* editing/mac/DictionaryLookup.h:
* editing/mac/DictionaryLookup.mm:

Create a delegate to respond to Reveal and help draw the string or highlight.

(-[WebRevealHighlight initWithHighlightRect:useDefaultHighlight:attributedString:]):
(-[WebRevealHighlight setClearTextIndicator:]):
(-[WebRevealHighlight revealContext:rectsForItem:]):
(-[WebRevealHighlight revealContext:drawRectsForItem:]):
(-[WebRevealHighlight revealContext:shouldUseDefaultHighlightForItem:]):
(-[WebRevealHighlight revealContext:stopHighlightingItem:]):
(WebCore::showPopupOrCreateAnimationController):

Unify the code paths and utalize the Reveal framework to create and/or display the popovers.

(WebCore::DictionaryLookup::showPopup):
(WebCore::DictionaryLookup::animationControllerForPopup):

Pipe the new callback through.

(WebCore::tokenRange): Deleted.

Only used with Lookup

(WebCore::selectionContainsPosition): Deleted.

Only used with Lookup.

* editing/mac/DictionaryLookupLegacy.mm: Copied from Source/WebCore/editing/mac/DictionaryLookup.mm.

Keep a copy of the previous implementation of DictionaryLookup, because Reveal not available on older
system.

(WebCore::tokenRange):
(WebCore::selectionContainsPosition):
(WebCore::expandSelectionByCharacters):
(WebCore::showPopupOrCreateAnimationController):
(WebCore::DictionaryLookup::showPopup):
(WebCore::DictionaryLookup::hidePopup):
(WebCore::DictionaryLookup::animationControllerForPopup):

Source/WebCore/PAL:

<rdar://problem/45924508>

Reviewed by Tim Horton.

Add in reveal SPI so WebKit will continue to build without the internal SDK.

* PAL.xcodeproj/project.pbxproj:
* pal/spi/mac/RevealSPI.h: Added.

Source/WebKit:

<rdar://problem/45924508>

Reviewed by Tim Horton.

Pass in what it needed to clear the textIndicators. This is better than
the current notification structure.

* UIProcess/Cocoa/WebViewImpl.mm:
(-[WKWindowVisibilityObserver dealloc]):
(-[WKWindowVisibilityObserver startObservingLookupDismissalIfNeeded]):
* UIProcess/mac/PageClientImplMac.mm:
(WebKit::PageClientImpl::didPerformDictionaryLookup):
* UIProcess/mac/WKImmediateActionController.mm:
(-[WKImmediateActionController _animationControllerForText]):
* WebProcess/Plugins/PDF/PDFPlugin.mm:
(WebKit::PDFPlugin::showDefinitionForAttributedString):

Generate and pass in the text indicator information, as this is needed now.

* WebProcess/WebPage/mac/WebPageMac.mm:
(WebKit::WebPage::dictionaryPopupInfoForSelectionInPDFPlugin):

Source/WebKitLegacy/mac:

<rdar://problem/45924508>

Reviewed by Tim Horton.

Pass in what it needed to clear the textIndicators. This is better than
the current notification structure.

* WebView/WebView.mm:
(-[WebView _animationControllerForDictionaryLookupPopupInfo:]):
(-[WebView _prepareForDictionaryLookup]):

LayoutTests:

Reviewed by Tim Horton.

Reveal selects spaces instead of adjacent words, no matter how interesting they are.
Update the tests to show this, and change the expections for previous platforms.

* editing/mac/selection/context-menu-select-editability-expected.txt:
* editing/mac/selection/context-menu-select-editability.html:
* platform/mac-highsierra/editing/mac/selection/context-menu-select-editability-expected.txt: Copied from LayoutTests/editing/mac/selection/context-menu-select-editability-expected.txt.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@238014 268f45cc-cd09-0410-ab3c-d52691b4dbfc

21 files changed:
LayoutTests/ChangeLog
LayoutTests/editing/mac/selection/context-menu-select-editability-expected.txt
LayoutTests/editing/mac/selection/context-menu-select-editability.html
LayoutTests/platform/mac-highsierra/editing/mac/selection/context-menu-select-editability-expected.txt [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/PAL/ChangeLog
Source/WebCore/PAL/PAL.xcodeproj/project.pbxproj
Source/WebCore/PAL/pal/spi/mac/RevealSPI.h [new file with mode: 0644]
Source/WebCore/SourcesCocoa.txt
Source/WebCore/WebCore.xcodeproj/project.pbxproj
Source/WebCore/editing/mac/DictionaryLookup.h
Source/WebCore/editing/mac/DictionaryLookup.mm
Source/WebCore/editing/mac/DictionaryLookupLegacy.mm [new file with mode: 0644]
Source/WebKit/ChangeLog
Source/WebKit/UIProcess/Cocoa/WebViewImpl.mm
Source/WebKit/UIProcess/mac/PageClientImplMac.mm
Source/WebKit/UIProcess/mac/WKImmediateActionController.mm
Source/WebKit/WebProcess/Plugins/PDF/PDFPlugin.mm
Source/WebKit/WebProcess/WebPage/mac/WebPageMac.mm
Source/WebKitLegacy/mac/ChangeLog
Source/WebKitLegacy/mac/WebView/WebView.mm

index 8833c15..20af5eb 100644 (file)
@@ -1,3 +1,17 @@
+2018-11-08  Megan Gardner  <megan_gardner@apple.com>
+
+        Adopt Reveal Framework to replace Lookup
+        https://bugs.webkit.org/show_bug.cgi?id=191097
+
+        Reviewed by Tim Horton.
+
+        Reveal selects spaces instead of adjacent words, no matter how interesting they are. 
+        Update the tests to show this, and change the expections for previous platforms.
+
+        * editing/mac/selection/context-menu-select-editability-expected.txt:
+        * editing/mac/selection/context-menu-select-editability.html:
+        * platform/mac-highsierra/editing/mac/selection/context-menu-select-editability-expected.txt: Copied from LayoutTests/editing/mac/selection/context-menu-select-editability-expected.txt.
+
 2018-11-08  Ryan Haddad  <ryanhaddad@apple.com>
 
         Clean up test expectations after r237942
index ea0072f..4acbb4c 100644 (file)
@@ -7,7 +7,7 @@ The crowd says: New York, New York    is a helluva town!
 
 
 PASS getSelectionForId('inputWhitespace') is ""
-PASS getSelectionForId('readOnlyWhitespace') is "New York, New York"
+PASS getSelectionForId('readOnlyWhitespace') is ""
 PASS successfullyParsed is true
 
 TEST COMPLETE
index 575c653..6baaa30 100644 (file)
@@ -31,7 +31,7 @@ function getSelectionForId(elementId)
 function performTest()
 {
     shouldBe("getSelectionForId('inputWhitespace')", '""');
-    shouldBe("getSelectionForId('readOnlyWhitespace')", '"New York, New York"');
+    shouldBe("getSelectionForId('readOnlyWhitespace')", '""');
 
     finishJSTest();
 }
diff --git a/LayoutTests/platform/mac-highsierra/editing/mac/selection/context-menu-select-editability-expected.txt b/LayoutTests/platform/mac-highsierra/editing/mac/selection/context-menu-select-editability-expected.txt
new file mode 100644 (file)
index 0000000..ab1a5b5
--- /dev/null
@@ -0,0 +1,15 @@
+This test checks that conext menu selection allows whitespace for non-editable fields. To test manually, right click on the blank text in the input box.
+
+The crowd says: New York, New York    is a helluva town!
+The crowd says: New York, New York    is a helluva town!
+
+
+
+
+PASS getSelectionForId('inputWhitespace') is ""
+FAIL getSelectionForId('readOnlyWhitespace') should be . Was New York, New York.
+PASS successfullyParsed is true
+Some tests failed.
+
+TEST COMPLETE
+
index ab05880..0ac0eb5 100644 (file)
@@ -1,3 +1,64 @@
+2018-11-08  Megan Gardner  <megan_gardner@apple.com>
+
+        Adopt Reveal Framework to replace Lookup
+        https://bugs.webkit.org/show_bug.cgi?id=191097
+
+        Reviewed by Tim Horton.
+
+        Reveal is not currently testable.
+
+        The Reveal framework does the same job as Lookup and DataDectors.
+        In this patch we switch from using Lookup to determine what text
+        to select and define to using Reveal and RVItems. Since this
+        code needs to work on older systems, and Reveal is newer, we also need
+        to keep around the old code for old systems so that they can also
+        continue to work. Eventually we will remove this code and also likly switch
+        to passing RVItems across from the web process rather than making them
+        on each side.
+
+        * SourcesCocoa.txt:
+        * WebCore.xcodeproj/project.pbxproj:
+        * editing/mac/DictionaryLookup.h:
+        * editing/mac/DictionaryLookup.mm:
+
+        Create a delegate to respond to Reveal and help draw the string or highlight.
+
+        (-[WebRevealHighlight initWithHighlightRect:useDefaultHighlight:attributedString:]):
+        (-[WebRevealHighlight setClearTextIndicator:]):
+        (-[WebRevealHighlight revealContext:rectsForItem:]):
+        (-[WebRevealHighlight revealContext:drawRectsForItem:]):
+        (-[WebRevealHighlight revealContext:shouldUseDefaultHighlightForItem:]):
+        (-[WebRevealHighlight revealContext:stopHighlightingItem:]):
+        (WebCore::showPopupOrCreateAnimationController):
+
+        Unify the code paths and utalize the Reveal framework to create and/or display the popovers.
+
+        (WebCore::DictionaryLookup::showPopup):
+        (WebCore::DictionaryLookup::animationControllerForPopup):
+
+        Pipe the new callback through.
+
+        (WebCore::tokenRange): Deleted.
+
+        Only used with Lookup
+
+        (WebCore::selectionContainsPosition): Deleted.
+
+        Only used with Lookup.
+
+        * editing/mac/DictionaryLookupLegacy.mm: Copied from Source/WebCore/editing/mac/DictionaryLookup.mm.
+
+        Keep a copy of the previous implementation of DictionaryLookup, because Reveal not available on older
+        system.
+
+        (WebCore::tokenRange):
+        (WebCore::selectionContainsPosition):
+        (WebCore::expandSelectionByCharacters):
+        (WebCore::showPopupOrCreateAnimationController):
+        (WebCore::DictionaryLookup::showPopup):
+        (WebCore::DictionaryLookup::hidePopup):
+        (WebCore::DictionaryLookup::animationControllerForPopup):
+
 2018-11-08  Keith Rollin  <krollin@apple.com>
 
         Create .xcfilelist files
index 3b0fef6..b4f407d 100644 (file)
@@ -1,3 +1,16 @@
+2018-11-08  Megan Gardner  <megan_gardner@apple.com>
+
+        Adopt Reveal Framework to replace Lookup
+        https://bugs.webkit.org/show_bug.cgi?id=191097
+        <rdar://problem/45924508>
+
+        Reviewed by Tim Horton.
+
+        Add in reveal SPI so WebKit will continue to build without the internal SDK.
+
+        * PAL.xcodeproj/project.pbxproj:
+        * pal/spi/mac/RevealSPI.h: Added.
+
 2018-11-06  Justin Fan  <justin_fan@apple.com>
 
         [WebGPU] Experimental prototype for WebGPURenderPipeline and WebGPUSwapChain
index 9d14456..21552df 100644 (file)
                2E1342CC215AA10A007199D2 /* UIKitSoftLink.h in Headers */ = {isa = PBXBuildFile; fileRef = 2E1342CA215AA10A007199D2 /* UIKitSoftLink.h */; };
                2E1342CD215AA10A007199D2 /* UIKitSoftLink.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2E1342CB215AA10A007199D2 /* UIKitSoftLink.mm */; };
                31308B1420A21705003FB929 /* SystemPreviewSPI.h in Headers */ = {isa = PBXBuildFile; fileRef = 31308B1320A21705003FB929 /* SystemPreviewSPI.h */; };
+               442956CD218A72DF0080DB54 /* RevealSPI.h in Headers */ = {isa = PBXBuildFile; fileRef = 442956CC218A72DE0080DB54 /* RevealSPI.h */; };
                570AB8F120AE2E8D00B8BE87 /* SecKeyProxySPI.h in Headers */ = {isa = PBXBuildFile; fileRef = 570AB8F020AE2E8D00B8BE87 /* SecKeyProxySPI.h */; };
                570AB8F920AF6E3D00B8BE87 /* NSXPCConnectionSPI.h in Headers */ = {isa = PBXBuildFile; fileRef = 570AB8F820AF6E3D00B8BE87 /* NSXPCConnectionSPI.h */; };
                7A1656441F97B2B900BA3CE4 /* NSKeyedArchiverSPI.h in Headers */ = {isa = PBXBuildFile; fileRef = 7A1656431F97B2B800BA3CE4 /* NSKeyedArchiverSPI.h */; };
                2E1342CB215AA10A007199D2 /* UIKitSoftLink.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = UIKitSoftLink.mm; path = ios/UIKitSoftLink.mm; sourceTree = "<group>"; };
                31308B1320A21705003FB929 /* SystemPreviewSPI.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SystemPreviewSPI.h; sourceTree = "<group>"; };
                37119A7820CCB5FF002C6DC9 /* WebKitTargetConditionals.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = WebKitTargetConditionals.xcconfig; sourceTree = "<group>"; };
+               442956CC218A72DE0080DB54 /* RevealSPI.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RevealSPI.h; sourceTree = "<group>"; };
                570AB8F020AE2E8D00B8BE87 /* SecKeyProxySPI.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecKeyProxySPI.h; sourceTree = "<group>"; };
                570AB8F820AF6E3D00B8BE87 /* NSXPCConnectionSPI.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = NSXPCConnectionSPI.h; sourceTree = "<group>"; };
                7A1656431F97B2B800BA3CE4 /* NSKeyedArchiverSPI.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NSKeyedArchiverSPI.h; sourceTree = "<group>"; };
                                0C7785861F45130F00F4EBB6 /* QTKitSPI.h */,
                                A102658A1F56748C00B4C844 /* QuickDrawSPI.h */,
                                0C7785871F45130F00F4EBB6 /* QuickLookMacSPI.h */,
+                               442956CC218A72DE0080DB54 /* RevealSPI.h */,
                                A1175B481F6AFF8E00C4B9F0 /* SpeechSynthesisSPI.h */,
                                0C7785881F45130F00F4EBB6 /* TUCallSPI.h */,
                        );
                                A102658B1F56748C00B4C844 /* QuickDrawSPI.h in Headers */,
                                0C7785A01F45130F00F4EBB6 /* QuickLookMacSPI.h in Headers */,
                                0C5AF9201F43A4C7002EAC02 /* QuickLookSPI.h in Headers */,
+                               442956CD218A72DF0080DB54 /* RevealSPI.h in Headers */,
                                570AB8F120AE2E8D00B8BE87 /* SecKeyProxySPI.h in Headers */,
                                0C2DA1581F3BEB4900DBC317 /* ServersSPI.h in Headers */,
                                A3C66CDD1F462D6A009E6EE9 /* SessionID.h in Headers */,
diff --git a/Source/WebCore/PAL/pal/spi/mac/RevealSPI.h b/Source/WebCore/PAL/pal/spi/mac/RevealSPI.h
new file mode 100644 (file)
index 0000000..d6b8da4
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2018 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. ``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
+ * 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 <objc/runtime.h>
+#import <pal/spi/mac/NSImmediateActionGestureRecognizerSPI.h>
+#import <wtf/SoftLinking.h>
+
+SOFT_LINK_PRIVATE_FRAMEWORK(Reveal)
+SOFT_LINK_PRIVATE_FRAMEWORK(RevealCore)
+SOFT_LINK_CLASS_OPTIONAL(Reveal, RVPresenter)
+SOFT_LINK_CLASS_OPTIONAL(Reveal, RVPresentingContext)
+SOFT_LINK_CLASS_OPTIONAL(RevealCore, RVItem)
+SOFT_LINK_CLASS_OPTIONAL(RevealCore, RVSelection)
+
+#if USE(APPLE_INTERNAL_SDK)
+
+#import <Reveal/RVPresenter.h>
+#import <Reveal/Reveal.h>
+#import <RevealCore/RVSelection.h>
+#import <RevealCore/RevealCore.h>
+
+
+#else
+
+@interface RVItem : NSObject <NSSecureCoding>
+- (instancetype)initWithText:(NSString *)text selectedRange:(NSRange)selectedRange NS_DESIGNATED_INITIALIZER;
+@end
+
+@interface RVSelection : NSObject
++ (NSRange)revealRangeAtIndex:(NSUInteger)clickIndex selectedRanges:(NSArray <NSValue *> *)selectedRanges shouldUpdateSelection:(BOOL *)shouldUpdateSelection;
+@end
+
+@interface RVPresenter : NSObject
+- (id<NSImmediateActionAnimationController>)animationControllerForItem:(RVItem *)item documentContext:(RVDocumentContext *)documentContext presentingContext:(RVPresentingContext *)presentingContext options:(NSDictionary *)options;
+- (BOOL)revealItem:(RVItem *)item documentContext:(RVDocumentContext *)documentContext presentingContext:(RVPresentingContext *)presentingContext options:(NSDictionary *)options;
+@end
+
+#endif // !USE(APPLE_INTERNAL_SDK)
index d9578c9..61ec2bc 100644 (file)
@@ -96,6 +96,7 @@ editing/ios/EditorIOS.mm
 
 editing/mac/AlternativeTextUIController.mm
 editing/mac/DictionaryLookup.mm
+editing/mac/DictionaryLookupLegacy.mm
 editing/mac/EditorMac.mm
 editing/mac/FrameSelectionMac.mm
 editing/mac/TextAlternativeWithRange.mm
index 487f485..15d6aa8 100644 (file)
                43F6FD9513BCD0B100224052 /* SVGAnimatedInteger.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SVGAnimatedInteger.cpp; sourceTree = "<group>"; };
                4415292C0E1AE8A000C4A2D0 /* HTMLPlugInImageElement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HTMLPlugInImageElement.h; sourceTree = "<group>"; };
                4415292D0E1AE8A000C4A2D0 /* HTMLPlugInImageElement.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = HTMLPlugInImageElement.cpp; sourceTree = "<group>"; };
+               442956CA218A6D300080DB54 /* DictionaryLookupLegacy.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = DictionaryLookupLegacy.mm; sourceTree = "<group>"; };
                443917FD1A91B2F8006E04F2 /* QuickLookSoftLink.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = QuickLookSoftLink.mm; sourceTree = "<group>"; };
                443917FE1A91B2F8006E04F2 /* QuickLookSoftLink.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = QuickLookSoftLink.h; sourceTree = "<group>"; };
                443F04260E75C8FB007E5407 /* NetworkStateNotifierIOS.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = NetworkStateNotifierIOS.mm; sourceTree = "<group>"; };
                                CE7B2DB01586ABAD0098B3FA /* AlternativeTextUIController.mm */,
                                937FF3D41A1012D6008EBA31 /* DictionaryLookup.h */,
                                937FF3D61A10131B008EBA31 /* DictionaryLookup.mm */,
+                               442956CA218A6D300080DB54 /* DictionaryLookupLegacy.mm */,
                                ED501DC50B249F2900AE18D9 /* EditorMac.mm */,
                                4A8C96EA0BE69032004EEFF0 /* FrameSelectionMac.mm */,
                                CE7B2DB11586ABAD0098B3FA /* TextAlternativeWithRange.h */,
index c461978..cb6d53e 100644 (file)
@@ -46,10 +46,10 @@ public:
 
     // FIXME: Should move/unify dictionaryPopupInfoForRange here too.
 
-    WEBCORE_EXPORT static void showPopup(const DictionaryPopupInfo&, NSView *, const WTF::Function<void(TextIndicator&)>& textIndicatorInstallationCallback, const WTF::Function<FloatRect(FloatRect)>& rootViewToViewConversionCallback = nullptr);
+    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);
     WEBCORE_EXPORT static void hidePopup();
 
-    WEBCORE_EXPORT static id <NSImmediateActionAnimationController> animationControllerForPopup(const DictionaryPopupInfo&, NSView *, const WTF::Function<void(TextIndicator&)>& textIndicatorInstallationCallback, const WTF::Function<FloatRect(FloatRect)>& rootViewToViewConversionCallback = nullptr);
+    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);
 };
 
 } // namespace WebCore
index 55062fb..4e4150c 100644 (file)
@@ -26,7 +26,7 @@
 #import "config.h"
 #import "DictionaryLookup.h"
 
-#if PLATFORM(MAC)
+#if PLATFORM(MAC) && ENABLE(REVEAL)
 
 #import "Document.h"
 #import "Editing.h"
 #import <PDFKit/PDFKit.h>
 #import <pal/spi/mac/LookupSPI.h>
 #import <pal/spi/mac/NSImmediateActionGestureRecognizerSPI.h>
+#import <pal/spi/mac/RevealSPI.h>
 #import <wtf/BlockObjCExceptions.h>
 #import <wtf/RefPtr.h>
 
-SOFT_LINK_CONSTANT_MAY_FAIL(Lookup, LUTermOptionDisableSearchTermIndicator, NSString *)
+@interface WebRevealHighlight <RVPresenterHighlightDelegate> : NSObject
 
-namespace WebCore {
+- (instancetype)initWithHighlightRect:(NSRect)highlightRect useDefaultHighlight:(BOOL)useDefaultHighlight attributedString:(NSAttributedString *) attributedString;
 
-static NSRange tokenRange(const String& string, NSRange range, NSDictionary **options)
-{
-    if (!getLULookupDefinitionModuleClass())
-        return NSMakeRange(NSNotFound, 0);
+@property (nonatomic, readonly) NSRect highlightRect;
+@property (nonatomic, readonly) BOOL useDefaultHighlight;
+@property (nonatomic, readonly) NSAttributedString *attributedString;
 
-    BEGIN_BLOCK_OBJC_EXCEPTIONS;
+- (void)setClearTextIndicator:(Function<void()>&&)clearTextIndicator;
 
-    return [classLULookupDefinitionModule tokenRangeForString:string range:range options:options];
+@end
 
-    END_BLOCK_OBJC_EXCEPTIONS;
+@implementation WebRevealHighlight {
+    Function<void()> _clearTextIndicator;
+}
 
-    return NSMakeRange(NSNotFound, 0);
+- (instancetype)initWithHighlightRect:(NSRect)highlightRect useDefaultHighlight:(BOOL)useDefaultHighlight attributedString:(NSAttributedString *) attributedString
+{
+    if (!(self = [super init]))
+        return nil;
+    
+    _highlightRect = highlightRect;
+    _useDefaultHighlight = useDefaultHighlight;
+    _attributedString = attributedString;
+    
+    return self;
 }
 
-static bool selectionContainsPosition(const VisiblePosition& position, const VisibleSelection& selection)
+- (void)setClearTextIndicator:(Function<void()>&&)clearTextIndicator
 {
-    if (!selection.isRange())
-        return false;
+    _clearTextIndicator = WTFMove(clearTextIndicator);
+}
 
-    RefPtr<Range> selectedRange = selection.toNormalizedRange();
-    if (!selectedRange)
-        return false;
+- (NSArray<NSValue *> *)revealContext:(RVPresentingContext *)context rectsForItem:(RVItem *)item
+{
+    UNUSED_PARAM(context);
+    UNUSED_PARAM(item);
+    return @[[NSValue valueWithRect:self.highlightRect]];
+}
 
-    return selectedRange->contains(position);
+- (void)revealContext:(RVPresentingContext *)context drawRectsForItem:(RVItem *)item
+{
+    UNUSED_PARAM(item);
+    
+    for (NSValue *rectVal in context.itemRectsInView) {
+        NSRect rect = rectVal.rectValue;
+
+        // Get current font attributes from the attributed string above, and add paragraph style attribute in order to center text.
+        RetainPtr<NSMutableDictionary> attributes = adoptNS([[NSMutableDictionary alloc] initWithDictionary:[self.attributedString fontAttributesInRange:NSMakeRange(0, [self.attributedString length])]]);
+        RetainPtr<NSMutableParagraphStyle> paragraph = adoptNS([[NSMutableParagraphStyle alloc] init]);
+        [paragraph setAlignment:NSTextAlignmentCenter];
+        [attributes setObject:paragraph.get() forKey:NSParagraphStyleAttributeName];
+    
+        RetainPtr<NSAttributedString> string = adoptNS([[NSAttributedString alloc] initWithString:[self.attributedString string] attributes:attributes.get()]);
+        [string drawInRect:rect];
+    }
 }
 
+- (BOOL)revealContext:(RVPresentingContext *)context shouldUseDefaultHighlightForItem:(RVItem *)item
+{
+    UNUSED_PARAM(context);
+    UNUSED_PARAM(item);
+    return self.useDefaultHighlight;
+}
+
+- (void)revealContext:(RVPresentingContext *)context stopHighlightingItem:(RVItem *)item
+{
+    UNUSED_PARAM(context);
+    UNUSED_PARAM(item);
+    auto block = WTFMove(_clearTextIndicator);
+    if (block)
+        block();
+}
+
+@end
+
+namespace WebCore {
+
 std::tuple<RefPtr<Range>, NSDictionary *> DictionaryLookup::rangeForSelection(const VisibleSelection& selection)
 {
+    BEGIN_BLOCK_OBJC_EXCEPTIONS;
+    
+    if (!getRVItemClass())
+        return { nullptr, nil };
+    
     auto selectedRange = selection.toNormalizedRange();
     if (!selectedRange)
         return { nullptr, nil };
@@ -95,15 +149,26 @@ std::tuple<RefPtr<Range>, NSDictionary *> DictionaryLookup::rangeForSelection(co
     int lengthToSelectionStart = TextIterator::rangeLength(makeRange(paragraphStart, selectionStart).get());
     int lengthToSelectionEnd = TextIterator::rangeLength(makeRange(paragraphStart, selectionEnd).get());
     NSRange rangeToPass = NSMakeRange(lengthToSelectionStart, lengthToSelectionEnd - lengthToSelectionStart);
-
-    NSDictionary *options = nil;
-    tokenRange(plainText(makeRange(paragraphStart, paragraphEnd).get()), rangeToPass, &options);
-
-    return { selectedRange, options };
+    
+    RefPtr<Range> fullCharacterRange = makeRange(paragraphStart, paragraphEnd);
+    String itemString = plainText(fullCharacterRange.get());
+    RetainPtr<RVItem> item = adoptNS([allocRVItemInstance() initWithText:itemString selectedRange:rangeToPass]);
+    NSRange highlightRange = item.get().highlightRange;
+    
+    return { TextIterator::subrange(*fullCharacterRange, highlightRange.location, highlightRange.length), nil };
+    
+    END_BLOCK_OBJC_EXCEPTIONS;
+    
+    return { nullptr, nil };
 }
 
 std::tuple<RefPtr<Range>, NSDictionary *> DictionaryLookup::rangeAtHitTestResult(const HitTestResult& hitTestResult)
 {
+    BEGIN_BLOCK_OBJC_EXCEPTIONS;
+    
+    if (!getRVItemClass())
+        return { nullptr, nil };
+    
     auto* node = hitTestResult.innerNonSharedNode();
     if (!node || !node->renderer())
         return { nullptr, nil };
@@ -121,30 +186,56 @@ std::tuple<RefPtr<Range>, NSDictionary *> DictionaryLookup::rangeAtHitTestResult
     if (position.isNull())
         position = firstPositionInOrBeforeNode(node);
 
-    // If we hit the selection, use that instead of letting Lookup decide the range.
     auto selection = frame->page()->focusController().focusedOrMainFrame().selection().selection();
-    if (selectionContainsPosition(position, selection))
-        return rangeForSelection(selection);
-
-    VisibleSelection selectionAccountingForLineRules { position };
-    selectionAccountingForLineRules.expandUsingGranularity(WordGranularity);
-    position = selectionAccountingForLineRules.start();
-
-    // As context, we are going to use 250 characters of text before and after the point.
-    auto fullCharacterRange = rangeExpandedAroundPositionByCharacters(position, 250);
-    if (!fullCharacterRange)
-        return { nullptr, nil };
-
-    NSRange rangeToPass = NSMakeRange(TextIterator::rangeLength(makeRange(fullCharacterRange->startPosition(), position).get()), 0);
-    NSDictionary *options = nil;
-    NSRange extractedRange = tokenRange(plainText(fullCharacterRange.get()), rangeToPass, &options);
+    NSRange selectionRange;
+    int hitIndex;
+    RefPtr<Range> fullCharacterRange;
+    
+    if (selection.selectionType() == VisibleSelection::RangeSelection) {
+        auto selectionStart = selection.visibleStart();
+        auto selectionEnd = selection.visibleEnd();
+        
+        // As context, we are going to use the surrounding paragraphs of text.
+        auto paragraphStart = startOfParagraph(selectionStart);
+        auto paragraphEnd = endOfParagraph(selectionEnd);
+        
+        auto rangeToSelectionStart = makeRange(paragraphStart, selectionStart);
+        auto rangeToSelectionEnd = makeRange(paragraphStart, selectionEnd);
+        
+        fullCharacterRange = makeRange(paragraphStart, paragraphEnd);
+        
+        selectionRange = NSMakeRange(TextIterator::rangeLength(rangeToSelectionStart.get()), TextIterator::rangeLength(makeRange(selectionStart, selectionEnd).get()));
+        
+        hitIndex = TextIterator::rangeLength(makeRange(paragraphStart, position).get());
+    } else {
+        VisibleSelection selectionAccountingForLineRules { position };
+        selectionAccountingForLineRules.expandUsingGranularity(WordGranularity);
+        position = selectionAccountingForLineRules.start();
+        // As context, we are going to use 250 characters of text before and after the point.
+        fullCharacterRange = rangeExpandedAroundPositionByCharacters(position, 250);
+        
+        if (!fullCharacterRange)
+            return { nullptr, nil };
+        
+        selectionRange = NSMakeRange(NSNotFound, 0);
+        hitIndex = TextIterator::rangeLength(makeRange(fullCharacterRange->startPosition(), position).get());
+    }
+    
+    NSRange selectedRange = [getRVSelectionClass() revealRangeAtIndex:hitIndex selectedRanges:@[[NSValue valueWithRange:selectionRange]] shouldUpdateSelection:nil];
+    
+    String itemString = plainText(fullCharacterRange.get());
+    RetainPtr<RVItem> item = adoptNS([allocRVItemInstance() initWithText:itemString selectedRange:selectedRange]);
+    NSRange highlightRange = item.get().highlightRange;
 
-    // tokenRange sometimes returns {NSNotFound, 0} if it was unable to determine a good string.
-    // FIXME (159063): We shouldn't need to check for zero length here.
-    if (extractedRange.location == NSNotFound || extractedRange.length == 0)
+    if (highlightRange.location == NSNotFound || !highlightRange.length)
         return { nullptr, nil };
-
-    return { TextIterator::subrange(*fullCharacterRange, extractedRange.location, extractedRange.length), options };
+    
+    return { TextIterator::subrange(*fullCharacterRange, highlightRange.location, highlightRange.length), nil };
+    
+    END_BLOCK_OBJC_EXCEPTIONS;
+    
+    return { nullptr, nil };
+    
 }
 
 static void expandSelectionByCharacters(PDFSelection *selection, NSInteger numberOfCharactersToExpand, NSInteger& charactersAddedBeforeStart, NSInteger& charactersAddedAfterEnd)
@@ -165,6 +256,9 @@ static void expandSelectionByCharacters(PDFSelection *selection, NSInteger numbe
 std::tuple<NSString *, NSDictionary *> DictionaryLookup::stringForPDFSelection(PDFSelection *selection)
 {
     BEGIN_BLOCK_OBJC_EXCEPTIONS;
+    
+    if (!getRVItemClass())
+        return { nullptr, nil };
 
     // Don't do anything if there is no character at the point.
     if (!selection || !selection.string.length)
@@ -181,12 +275,11 @@ std::tuple<NSString *, NSDictionary *> DictionaryLookup::stringForPDFSelection(P
     auto fullPlainTextString = [selectionForLookup string];
     auto rangeToPass = NSMakeRange(charactersAddedBeforeStart, 0);
 
-    NSDictionary *options = nil;
-    auto extractedRange = tokenRange(fullPlainTextString, rangeToPass, &options);
-
-    // This function sometimes returns {NSNotFound, 0} if it was unable to determine a good string.
+    RetainPtr<RVItem> item = adoptNS([allocRVItemInstance() initWithText:fullPlainTextString selectedRange:rangeToPass]);
+    NSRange extractedRange = item.get().highlightRange;
+    
     if (extractedRange.location == NSNotFound)
-        return { selection.string, options };
+        return { selection.string, nil };
 
     NSInteger lookupAddedBefore = rangeToPass.location - extractedRange.location;
     NSInteger lookupAddedAfter = (extractedRange.location + extractedRange.length) - (rangeToPass.location + originalLength);
@@ -195,18 +288,18 @@ std::tuple<NSString *, NSDictionary *> DictionaryLookup::stringForPDFSelection(P
     [selection extendSelectionAtEnd:lookupAddedAfter];
 
     ASSERT([selection.string isEqualToString:[fullPlainTextString substringWithRange:extractedRange]]);
-    return { selection.string, options };
+    return { selection.string, nil };
 
     END_BLOCK_OBJC_EXCEPTIONS;
 
     return { @"", nil };
 }
 
-static id <NSImmediateActionAnimationController> showPopupOrCreateAnimationController(bool createAnimationController, const DictionaryPopupInfo& dictionaryPopupInfo, NSView *view, const WTF::Function<void(TextIndicator&)>& textIndicatorInstallationCallback, const WTF::Function<FloatRect(FloatRect)>& rootViewToViewConversionCallback)
+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)
 {
     BEGIN_BLOCK_OBJC_EXCEPTIONS;
-
-    if (!getLULookupDefinitionModuleClass())
+    
+    if (!getRVItemClass())
         return nil;
 
     RetainPtr<NSMutableDictionary> mutableOptions = adoptNS([[NSMutableDictionary alloc] init]);
@@ -214,42 +307,57 @@ static id <NSImmediateActionAnimationController> showPopupOrCreateAnimationContr
         [mutableOptions addEntriesFromDictionary:options];
 
     auto textIndicator = TextIndicator::create(dictionaryPopupInfo.textIndicator);
-
-    if (canLoadLUTermOptionDisableSearchTermIndicator() && textIndicator.get().contentImage()) {
+    
+    RetainPtr<RVPresenter> presenter = adoptNS([allocRVPresenterInstance() init]);
+    
+    NSRect highlightRect;
+    NSPoint pointerLocation;
+    
+    if (textIndicator.get().contentImage()) {
         textIndicatorInstallationCallback(textIndicator.get());
-        [mutableOptions setObject:@YES forKey:getLUTermOptionDisableSearchTermIndicator()];
 
         FloatRect firstTextRectInViewCoordinates = textIndicator.get().textRectsInBoundingRectCoordinates()[0];
         FloatRect textBoundingRectInViewCoordinates = textIndicator.get().textBoundingRectInRootViewCoordinates();
-        if (rootViewToViewConversionCallback)
+        FloatRect selectionBoundingRectInViewCoordinates = textIndicator.get().selectionRectInRootViewCoordinates();
+        
+        if (rootViewToViewConversionCallback) {
             textBoundingRectInViewCoordinates = rootViewToViewConversionCallback(textBoundingRectInViewCoordinates);
+            selectionBoundingRectInViewCoordinates = rootViewToViewConversionCallback(selectionBoundingRectInViewCoordinates);
+        }
+        
         firstTextRectInViewCoordinates.moveBy(textBoundingRectInViewCoordinates.location());
-        if (createAnimationController)
-            return [getLULookupDefinitionModuleClass() lookupAnimationControllerForTerm:dictionaryPopupInfo.attributedString.get() relativeToRect:firstTextRectInViewCoordinates ofView:view options:mutableOptions.get()];
-
-        [getLULookupDefinitionModuleClass() showDefinitionForTerm:dictionaryPopupInfo.attributedString.get() relativeToRect:firstTextRectInViewCoordinates ofView:view options:mutableOptions.get()];
-        return nil;
+        highlightRect = selectionBoundingRectInViewCoordinates;
+        pointerLocation = firstTextRectInViewCoordinates.location();
+        
+    } else {
+        NSPoint textBaselineOrigin = dictionaryPopupInfo.origin;
+        
+        highlightRect = textIndicator->selectionRectInRootViewCoordinates();
+        pointerLocation = [view convertPoint:textBaselineOrigin toView:nil];
     }
-
-    NSPoint textBaselineOrigin = dictionaryPopupInfo.origin;
-
-    // Convert to screen coordinates.
-    textBaselineOrigin = [view convertPoint:textBaselineOrigin toView:nil];
-    textBaselineOrigin = [view.window convertRectToScreen:NSMakeRect(textBaselineOrigin.x, textBaselineOrigin.y, 0, 0)].origin;
-
+    
+    RetainPtr<WebRevealHighlight> webHighlight =  adoptNS([[WebRevealHighlight alloc] initWithHighlightRect: highlightRect useDefaultHighlight:!textIndicator.get().contentImage() attributedString:dictionaryPopupInfo.attributedString.get()]);
+    RetainPtr<RVPresentingContext> context = adoptNS([allocRVPresentingContextInstance() initWithPointerLocationInView:pointerLocation inView:view highlightDelegate:(id<RVPresenterHighlightDelegate>) webHighlight.get()]);
+    
+    RetainPtr<RVItem> item = adoptNS([allocRVItemInstance() initWithText:dictionaryPopupInfo.attributedString.get().string selectedRange:NSMakeRange(0, 0)]);
+    
+    [webHighlight setClearTextIndicator:[webHighlight = WTFMove(webHighlight), clearTextIndicator = WTFMove(clearTextIndicator)] {
+        if (clearTextIndicator)
+            clearTextIndicator();
+    }];
+    
     if (createAnimationController)
-        return [getLULookupDefinitionModuleClass() lookupAnimationControllerForTerm:dictionaryPopupInfo.attributedString.get() atLocation:textBaselineOrigin options:mutableOptions.get()];
-
-    [getLULookupDefinitionModuleClass() showDefinitionForTerm:dictionaryPopupInfo.attributedString.get() atLocation:textBaselineOrigin options:mutableOptions.get()];
+        return [presenter animationControllerForItem:item.get() documentContext:nil presentingContext:context.get() options:nil];
+    [presenter revealItem:item.get() documentContext:nil presentingContext:context.get() options:nil];
     return nil;
 
     END_BLOCK_OBJC_EXCEPTIONS;
     return nil;
 }
 
-void DictionaryLookup::showPopup(const DictionaryPopupInfo& dictionaryPopupInfo, NSView *view, const WTF::Function<void(TextIndicator&)>& textIndicatorInstallationCallback, const WTF::Function<FloatRect(FloatRect)>& rootViewToViewConversionCallback)
+void DictionaryLookup::showPopup(const DictionaryPopupInfo& dictionaryPopupInfo, NSView *view, const WTF::Function<void(TextIndicator&)>& textIndicatorInstallationCallback, const WTF::Function<FloatRect(FloatRect)>& rootViewToViewConversionCallback, WTF::Function<void()>&& clearTextIndicator)
 {
-    showPopupOrCreateAnimationController(false, dictionaryPopupInfo, view, textIndicatorInstallationCallback, rootViewToViewConversionCallback);
+    showPopupOrCreateAnimationController(false, dictionaryPopupInfo, view, textIndicatorInstallationCallback, rootViewToViewConversionCallback, WTFMove(clearTextIndicator));
 }
 
 void DictionaryLookup::hidePopup()
@@ -263,9 +371,9 @@ void DictionaryLookup::hidePopup()
     END_BLOCK_OBJC_EXCEPTIONS;
 }
 
-id <NSImmediateActionAnimationController> DictionaryLookup::animationControllerForPopup(const DictionaryPopupInfo& dictionaryPopupInfo, NSView *view, const WTF::Function<void(TextIndicator&)>& textIndicatorInstallationCallback, const WTF::Function<FloatRect(FloatRect)>& rootViewToViewConversionCallback)
+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)
 {
-    return showPopupOrCreateAnimationController(true, dictionaryPopupInfo, view, textIndicatorInstallationCallback, rootViewToViewConversionCallback);
+    return showPopupOrCreateAnimationController(true, dictionaryPopupInfo, view, textIndicatorInstallationCallback, rootViewToViewConversionCallback, WTFMove(clearTextIndicator));
 }
 
 } // namespace WebCore
diff --git a/Source/WebCore/editing/mac/DictionaryLookupLegacy.mm b/Source/WebCore/editing/mac/DictionaryLookupLegacy.mm
new file mode 100644 (file)
index 0000000..32551c1
--- /dev/null
@@ -0,0 +1,277 @@
+/*
+ * Copyright (C) 2014-2018 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"
+#import "DictionaryLookup.h"
+
+#if PLATFORM(MAC) && !ENABLE(REVEAL)
+
+#import "Document.h"
+#import "Editing.h"
+#import "FocusController.h"
+#import "Frame.h"
+#import "FrameSelection.h"
+#import "HTMLConverter.h"
+#import "HitTestResult.h"
+#import "Page.h"
+#import "Range.h"
+#import "RenderObject.h"
+#import "TextIterator.h"
+#import "VisiblePosition.h"
+#import "VisibleSelection.h"
+#import "VisibleUnits.h"
+#import <PDFKit/PDFKit.h>
+#import <pal/spi/mac/LookupSPI.h>
+#import <pal/spi/mac/NSImmediateActionGestureRecognizerSPI.h>
+#import <wtf/BlockObjCExceptions.h>
+#import <wtf/RefPtr.h>
+
+SOFT_LINK_CONSTANT_MAY_FAIL(Lookup, LUTermOptionDisableSearchTermIndicator, NSString *)
+
+namespace WebCore {
+
+static NSRange tokenRange(const String& string, NSRange range, NSDictionary **options)
+{
+    if (!getLULookupDefinitionModuleClass())
+        return NSMakeRange(NSNotFound, 0);
+
+    BEGIN_BLOCK_OBJC_EXCEPTIONS;
+
+    return [classLULookupDefinitionModule tokenRangeForString:string range:range options:options];
+
+    END_BLOCK_OBJC_EXCEPTIONS;
+
+    return NSMakeRange(NSNotFound, 0);
+}
+
+static bool selectionContainsPosition(const VisiblePosition& position, const VisibleSelection& selection)
+{
+    if (!selection.isRange())
+        return false;
+
+    RefPtr<Range> selectedRange = selection.toNormalizedRange();
+    if (!selectedRange)
+        return false;
+
+    return selectedRange->contains(position);
+}
+
+std::tuple<RefPtr<Range>, NSDictionary *> DictionaryLookup::rangeForSelection(const VisibleSelection& selection)
+{
+    auto selectedRange = selection.toNormalizedRange();
+    if (!selectedRange)
+        return { nullptr, nil };
+
+    // Since we already have the range we want, we just need to grab the returned options.
+    auto selectionStart = selection.visibleStart();
+    auto selectionEnd = selection.visibleEnd();
+
+    // As context, we are going to use the surrounding paragraphs of text.
+    auto paragraphStart = startOfParagraph(selectionStart);
+    auto paragraphEnd = endOfParagraph(selectionEnd);
+
+    int lengthToSelectionStart = TextIterator::rangeLength(makeRange(paragraphStart, selectionStart).get());
+    int lengthToSelectionEnd = TextIterator::rangeLength(makeRange(paragraphStart, selectionEnd).get());
+    NSRange rangeToPass = NSMakeRange(lengthToSelectionStart, lengthToSelectionEnd - lengthToSelectionStart);
+
+    NSDictionary *options = nil;
+    tokenRange(plainText(makeRange(paragraphStart, paragraphEnd).get()), rangeToPass, &options);
+
+    return { selectedRange, options };
+}
+
+std::tuple<RefPtr<Range>, NSDictionary *> DictionaryLookup::rangeAtHitTestResult(const HitTestResult& hitTestResult)
+{
+    auto* node = hitTestResult.innerNonSharedNode();
+    if (!node || !node->renderer())
+        return { nullptr, nil };
+
+    auto* frame = node->document().frame();
+    if (!frame)
+        return { nullptr, nil };
+
+    // Don't do anything if there is no character at the point.
+    auto framePoint = hitTestResult.roundedPointInInnerNodeFrame();
+    if (!frame->rangeForPoint(framePoint))
+        return { nullptr, nil };
+
+    auto position = frame->visiblePositionForPoint(framePoint);
+    if (position.isNull())
+        position = firstPositionInOrBeforeNode(node);
+
+    // If we hit the selection, use that instead of letting Lookup decide the range.
+    auto selection = frame->page()->focusController().focusedOrMainFrame().selection().selection();
+    if (selectionContainsPosition(position, selection))
+        return rangeForSelection(selection);
+
+    VisibleSelection selectionAccountingForLineRules { position };
+    selectionAccountingForLineRules.expandUsingGranularity(WordGranularity);
+    position = selectionAccountingForLineRules.start();
+
+    // As context, we are going to use 250 characters of text before and after the point.
+    auto fullCharacterRange = rangeExpandedAroundPositionByCharacters(position, 250);
+    if (!fullCharacterRange)
+        return { nullptr, nil };
+
+    NSRange rangeToPass = NSMakeRange(TextIterator::rangeLength(makeRange(fullCharacterRange->startPosition(), position).get()), 0);
+    NSDictionary *options = nil;
+    NSRange extractedRange = tokenRange(plainText(fullCharacterRange.get()), rangeToPass, &options);
+
+    // tokenRange sometimes returns {NSNotFound, 0} if it was unable to determine a good string.
+    // FIXME (159063): We shouldn't need to check for zero length here.
+    if (extractedRange.location == NSNotFound || !extractedRange.length)
+        return { nullptr, nil };
+
+    return { TextIterator::subrange(*fullCharacterRange, extractedRange.location, extractedRange.length), options };
+}
+
+static void expandSelectionByCharacters(PDFSelection *selection, NSInteger numberOfCharactersToExpand, NSInteger& charactersAddedBeforeStart, NSInteger& charactersAddedAfterEnd)
+{
+    BEGIN_BLOCK_OBJC_EXCEPTIONS;
+
+    size_t originalLength = selection.string.length;
+    [selection extendSelectionAtStart:numberOfCharactersToExpand];
+    
+    charactersAddedBeforeStart = selection.string.length - originalLength;
+    
+    [selection extendSelectionAtEnd:numberOfCharactersToExpand];
+    charactersAddedAfterEnd = selection.string.length - originalLength - charactersAddedBeforeStart;
+
+    END_BLOCK_OBJC_EXCEPTIONS;
+}
+
+std::tuple<NSString *, NSDictionary *> DictionaryLookup::stringForPDFSelection(PDFSelection *selection)
+{
+    BEGIN_BLOCK_OBJC_EXCEPTIONS;
+
+    // Don't do anything if there is no character at the point.
+    if (!selection || !selection.string.length)
+        return { @"", nil };
+
+    RetainPtr<PDFSelection> selectionForLookup = adoptNS([selection copy]);
+
+    // As context, we are going to use 250 characters of text before and after the point.
+    auto originalLength = [selectionForLookup string].length;
+    NSInteger charactersAddedBeforeStart = 0;
+    NSInteger charactersAddedAfterEnd = 0;
+    expandSelectionByCharacters(selectionForLookup.get(), 250, charactersAddedBeforeStart, charactersAddedAfterEnd);
+
+    auto fullPlainTextString = [selectionForLookup string];
+    auto rangeToPass = NSMakeRange(charactersAddedBeforeStart, 0);
+
+    NSDictionary *options = nil;
+    auto extractedRange = tokenRange(fullPlainTextString, rangeToPass, &options);
+
+    // This function sometimes returns {NSNotFound, 0} if it was unable to determine a good string.
+    if (extractedRange.location == NSNotFound)
+        return { selection.string, options };
+
+    NSInteger lookupAddedBefore = rangeToPass.location - extractedRange.location;
+    NSInteger lookupAddedAfter = (extractedRange.location + extractedRange.length) - (rangeToPass.location + originalLength);
+
+    [selection extendSelectionAtStart:lookupAddedBefore];
+    [selection extendSelectionAtEnd:lookupAddedAfter];
+
+    ASSERT([selection.string isEqualToString:[fullPlainTextString substringWithRange:extractedRange]]);
+    return { selection.string, options };
+
+    END_BLOCK_OBJC_EXCEPTIONS;
+
+    return { @"", nil };
+}
+
+static id <NSImmediateActionAnimationController> showPopupOrCreateAnimationController(bool createAnimationController, const DictionaryPopupInfo& dictionaryPopupInfo, NSView *view, const WTF::Function<void(TextIndicator&)>& textIndicatorInstallationCallback, const WTF::Function<FloatRect(FloatRect)>& rootViewToViewConversionCallback)
+{
+    BEGIN_BLOCK_OBJC_EXCEPTIONS;
+
+    if (!getLULookupDefinitionModuleClass())
+        return nil;
+
+    RetainPtr<NSMutableDictionary> mutableOptions = adoptNS([[NSMutableDictionary alloc] init]);
+    if (NSDictionary *options = dictionaryPopupInfo.options.get())
+        [mutableOptions addEntriesFromDictionary:options];
+
+    auto textIndicator = TextIndicator::create(dictionaryPopupInfo.textIndicator);
+
+    if (canLoadLUTermOptionDisableSearchTermIndicator() && textIndicator.get().contentImage()) {
+        textIndicatorInstallationCallback(textIndicator.get());
+        [mutableOptions setObject:@YES forKey:getLUTermOptionDisableSearchTermIndicator()];
+
+        FloatRect firstTextRectInViewCoordinates = textIndicator.get().textRectsInBoundingRectCoordinates()[0];
+        FloatRect textBoundingRectInViewCoordinates = textIndicator.get().textBoundingRectInRootViewCoordinates();
+        if (rootViewToViewConversionCallback)
+            textBoundingRectInViewCoordinates = rootViewToViewConversionCallback(textBoundingRectInViewCoordinates);
+        firstTextRectInViewCoordinates.moveBy(textBoundingRectInViewCoordinates.location());
+        if (createAnimationController)
+            return [getLULookupDefinitionModuleClass() lookupAnimationControllerForTerm:dictionaryPopupInfo.attributedString.get() relativeToRect:firstTextRectInViewCoordinates ofView:view options:mutableOptions.get()];
+
+        [getLULookupDefinitionModuleClass() showDefinitionForTerm:dictionaryPopupInfo.attributedString.get() relativeToRect:firstTextRectInViewCoordinates ofView:view options:mutableOptions.get()];
+        return nil;
+    }
+
+    NSPoint textBaselineOrigin = dictionaryPopupInfo.origin;
+
+    // Convert to screen coordinates.
+    textBaselineOrigin = [view convertPoint:textBaselineOrigin toView:nil];
+    textBaselineOrigin = [view.window convertRectToScreen:NSMakeRect(textBaselineOrigin.x, textBaselineOrigin.y, 0, 0)].origin;
+
+    if (createAnimationController)
+        return [getLULookupDefinitionModuleClass() lookupAnimationControllerForTerm:dictionaryPopupInfo.attributedString.get() atLocation:textBaselineOrigin options:mutableOptions.get()];
+
+    [getLULookupDefinitionModuleClass() showDefinitionForTerm:dictionaryPopupInfo.attributedString.get() atLocation:textBaselineOrigin options:mutableOptions.get()];
+    return nil;
+
+    END_BLOCK_OBJC_EXCEPTIONS;
+    return nil;
+}
+
+void DictionaryLookup::showPopup(const DictionaryPopupInfo& dictionaryPopupInfo, NSView *view, const WTF::Function<void(TextIndicator&)>& textIndicatorInstallationCallback, const WTF::Function<FloatRect(FloatRect)>& rootViewToViewConversionCallback, WTF::Function<void()>&& clearTextIndicator)
+{
+    UNUSED_PARAM(clearTextIndicator);
+    
+    showPopupOrCreateAnimationController(false, dictionaryPopupInfo, view, textIndicatorInstallationCallback, rootViewToViewConversionCallback);
+}
+
+void DictionaryLookup::hidePopup()
+{
+    BEGIN_BLOCK_OBJC_EXCEPTIONS;
+
+    if (!getLULookupDefinitionModuleClass())
+        return;
+    [getLULookupDefinitionModuleClass() hideDefinition];
+
+    END_BLOCK_OBJC_EXCEPTIONS;
+}
+
+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)
+{
+    UNUSED_PARAM(clearTextIndicator);
+    
+    return showPopupOrCreateAnimationController(true, dictionaryPopupInfo, view, textIndicatorInstallationCallback, rootViewToViewConversionCallback);
+}
+
+} // namespace WebCore
+
+#endif // PLATFORM(MAC) && !ENABLE(REVEAL)
index c60831f..a4329df 100644 (file)
@@ -1,3 +1,29 @@
+2018-11-08  Megan Gardner  <megan_gardner@apple.com>
+
+        Adopt Reveal Framework to replace Lookup
+        https://bugs.webkit.org/show_bug.cgi?id=191097
+        <rdar://problem/45924508>
+
+        Reviewed by Tim Horton.
+
+        Pass in what it needed to clear the textIndicators. This is better than
+        the current notification structure.
+
+        * UIProcess/Cocoa/WebViewImpl.mm:
+        (-[WKWindowVisibilityObserver dealloc]):
+        (-[WKWindowVisibilityObserver startObservingLookupDismissalIfNeeded]):
+        * UIProcess/mac/PageClientImplMac.mm:
+        (WebKit::PageClientImpl::didPerformDictionaryLookup):
+        * UIProcess/mac/WKImmediateActionController.mm:
+        (-[WKImmediateActionController _animationControllerForText]):
+        * WebProcess/Plugins/PDF/PDFPlugin.mm:
+        (WebKit::PDFPlugin::showDefinitionForAttributedString):
+
+        Generate and pass in the text indicator information, as this is needed now.
+
+        * WebProcess/WebPage/mac/WebPageMac.mm:
+        (WebKit::WebPage::dictionaryPopupInfoForSelectionInPDFPlugin):
+
 2018-11-08  Keith Rollin  <krollin@apple.com>
 
         Create .xcfilelist files
index 45cbf3b..80ba69c 100644 (file)
@@ -131,7 +131,9 @@ SOFT_LINK_CLASS(AVKit, AVFunctionBarScrubber)
 static NSString * const WKMediaExitFullScreenItem = @"WKMediaExitFullScreenItem";
 #endif // HAVE(TOUCH_BAR) && ENABLE(WEB_PLAYBACK_CONTROLS_MANAGER)
 
+#if PLATFORM(MAC) && !ENABLE(REVEAL)
 SOFT_LINK_CONSTANT_MAY_FAIL(Lookup, LUNotificationPopoverWillClose, NSString *)
+#endif // ENABLE(REVEAL)
 
 WTF_DECLARE_CF_TYPE_TRAIT(CGImage);
 
@@ -226,8 +228,10 @@ WTF_DECLARE_CF_TYPE_TRAIT(CGImage);
 
 - (void)dealloc
 {
+#if !ENABLE(REVEAL)
     if (_didRegisterForLookupPopoverCloseNotifications && canLoadLUNotificationPopoverWillClose())
         [[NSNotificationCenter defaultCenter] removeObserver:self name:getLUNotificationPopoverWillClose() object:nil];
+#endif // !ENABLE(REVEAL)
 
     NSNotificationCenter *workspaceNotificationCenter = [[NSWorkspace sharedWorkspace] notificationCenter];
     [workspaceNotificationCenter removeObserver:self name:NSWorkspaceActiveSpaceDidChangeNotification object:nil];
@@ -301,9 +305,10 @@ static void* keyValueObservingContext = &keyValueObservingContext;
         return;
 
     _didRegisterForLookupPopoverCloseNotifications = YES;
-
+#if !ENABLE(REVEAL)
     if (canLoadLUNotificationPopoverWillClose())
         [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_dictionaryLookupPopoverWillClose:) name:getLUNotificationPopoverWillClose() object:nil];
+#endif
 }
 
 - (void)_windowDidOrderOnScreen:(NSNotification *)notification
@@ -382,10 +387,12 @@ static void* keyValueObservingContext = &keyValueObservingContext;
         _impl->updateContentInsetsIfAutomatic();
 }
 
+#if !ENABLE(REVEAL)
 - (void)_dictionaryLookupPopoverWillClose:(NSNotification *)notification
 {
     _impl->clearTextIndicatorWithAnimation(WebCore::TextIndicatorWindowDismissalAnimation::None);
 }
+#endif
 
 - (void)_activeSpaceDidChange:(NSNotification *)notification
 {
index ff8b8ce..0d67201 100644 (file)
@@ -598,6 +598,8 @@ void PageClientImpl::didPerformDictionaryLookup(const DictionaryPopupInfo& dicti
 
     DictionaryLookup::showPopup(dictionaryPopupInfo, m_view, [this](TextIndicator& textIndicator) {
         m_impl->setTextIndicator(textIndicator, TextIndicatorWindowLifetime::Permanent);
+    }, nullptr, [this]() {
+        m_impl->clearTextIndicatorWithAnimation(WebCore::TextIndicatorWindowDismissalAnimation::None);
     });
 }
 
index f872070..9983907 100644 (file)
@@ -472,6 +472,8 @@ SOFT_LINK_CLASS(QuickLookUI, QLPreviewMenuItem)
 
     return WebCore::DictionaryLookup::animationControllerForPopup(dictionaryPopupInfo, _view, [self](WebCore::TextIndicator& textIndicator) {
         _viewImpl->setTextIndicator(textIndicator, WebCore::TextIndicatorWindowLifetime::Permanent);
+    }, nullptr, [self]() {
+        _viewImpl->clearTextIndicatorWithAnimation(WebCore::TextIndicatorWindowDismissalAnimation::None);
     });
 }
 
index d20760e..4dbec0e 100644 (file)
@@ -1872,7 +1872,24 @@ void PDFPlugin::showDefinitionForAttributedString(NSAttributedString *string, CG
     DictionaryPopupInfo dictionaryPopupInfo;
     dictionaryPopupInfo.origin = convertFromPDFViewToRootView(IntPoint(point));
     dictionaryPopupInfo.attributedString = string;
+    
+    
+    NSRect rangeRect;
+    rangeRect.origin = point;
+    CGFloat scaleFactor = PDFPlugin::scaleFactor();
+
+    rangeRect.size.height = string.size.height * scaleFactor;
+    rangeRect.size.width = string.size.width * scaleFactor;
 
+    rangeRect.origin.y -= rangeRect.size.height;
+
+    TextIndicatorData dataForSelection;
+    dataForSelection.selectionRectInRootViewCoordinates = rangeRect;
+    dataForSelection.textBoundingRectInRootViewCoordinates = rangeRect;
+    dataForSelection.contentImageScaleFactor = scaleFactor;
+    dataForSelection.presentationTransition = TextIndicatorPresentationTransition::FadeIn;
+    dictionaryPopupInfo.textIndicator = dataForSelection;
+    
     webFrame()->page()->send(Messages::WebPageProxy::DidPerformDictionaryLookup(dictionaryPopupInfo));
 }
 
index 14084ff..4733b1c 100644 (file)
@@ -520,13 +520,8 @@ DictionaryPopupInfo WebPage::dictionaryPopupInfoForSelectionInPDFPlugin(PDFSelec
         [scaledNSAttributedString addAttributes:scaledAttributes.get() range:range];
     }];
 
-    // Based on TextIndicator implementation:
-    // TODO(144307): Come up with a better way to share this information than duplicating these values.
-    CGFloat verticalMargin = 2.5;
-    CGFloat horizontalMargin = 0.5;
-
-    rangeRect.origin.y -= CGCeiling(rangeRect.size.height - maxAscender - std::abs(maxDescender) + verticalMargin * scaleFactor);
-    rangeRect.origin.x += CGFloor(horizontalMargin * scaleFactor);
+    rangeRect.size.height = nsAttributedString.size.height * scaleFactor;
+    rangeRect.size.width = nsAttributedString.size.width * scaleFactor;
     
     TextIndicatorData dataForSelection;
     dataForSelection.selectionRectInRootViewCoordinates = rangeRect;
index 35e2630..69a29e5 100644 (file)
@@ -1,3 +1,18 @@
+2018-11-08  Megan Gardner  <megan_gardner@apple.com>
+
+        Adopt Reveal Framework to replace Lookup
+        https://bugs.webkit.org/show_bug.cgi?id=191097
+        <rdar://problem/45924508>
+
+        Reviewed by Tim Horton.
+
+        Pass in what it needed to clear the textIndicators. This is better than
+        the current notification structure.
+
+        * WebView/WebView.mm:
+        (-[WebView _animationControllerForDictionaryLookupPopupInfo:]):
+        (-[WebView _prepareForDictionaryLookup]):
+
 2018-11-06  Justin Fan  <justin_fan@apple.com>
 
         [WebGPU] Experimental prototype for WebGPURenderPipeline and WebGPUSwapChain
index 4c59c7b..bcfcce2 100644 (file)
@@ -358,7 +358,7 @@ SOFT_LINK_CLASS(AVKit, AVFunctionBarScrubber)
 #endif // __MAC_OS_X_VERSION_MIN_REQUIRED >= 101300
 #endif // HAVE(TOUCH_BAR) && ENABLE(WEB_PLAYBACK_CONTROLS_MANAGER)
 
-#if PLATFORM(MAC)
+#if PLATFORM(MAC) && !ENABLE(REVEAL)
 SOFT_LINK_CONSTANT_MAY_FAIL(Lookup, LUNotificationPopoverWillClose, NSString *)
 #endif
 
@@ -9531,6 +9531,8 @@ bool LayerFlushController::flushLayers()
         [self _setTextIndicator:textIndicator withLifetime:TextIndicatorWindowLifetime::Permanent];
     }, [self](FloatRect rectInRootViewCoordinates) {
         return [self _convertRectFromRootView:rectInRootViewCoordinates];
+    }, [self]() {
+        [self _clearTextIndicatorWithAnimation:TextIndicatorWindowDismissalAnimation::FadeOut];
     });
 }
 
@@ -9578,9 +9580,12 @@ bool LayerFlushController::flushLayers()
         return;
 
     _private->hasInitializedLookupObserver = YES;
-
+    
+#if !ENABLE(REVEAL)
     if (canLoadLUNotificationPopoverWillClose())
         [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_dictionaryLookupPopoverWillClose:) name:getLUNotificationPopoverWillClose() object:nil];
+#endif // !ENABLE(REVEAL)
+    
 }
 
 - (void)_showDictionaryLookupPopup:(const DictionaryPopupInfo&)dictionaryPopupInfo
@@ -9597,10 +9602,12 @@ bool LayerFlushController::flushLayers()
     });
 }
 
+#if !ENABLE(REVEAL)
 - (void)_dictionaryLookupPopoverWillClose:(NSNotification *)notification
 {
     [self _clearTextIndicatorWithAnimation:TextIndicatorWindowDismissalAnimation::FadeOut];
 }
+#endif // ENABLE(REVEAL)
 
 #endif // PLATFORM(MAC)