Title: [177300] trunk/Source/WebKit/mac
Revision
177300
Author
[email protected]
Date
2014-12-15 11:49:24 -0800 (Mon, 15 Dec 2014)

Log Message

Implement Data Detectors immediate actions for Legacy WebKit
https://bugs.webkit.org/show_bug.cgi?id=139619
<rdar://problem/19198539>

Reviewed by Eric Carlson.

* WebView/WebHTMLView.mm:
(-[WebHTMLView mouseDown:mouseDown:]):
Send mouseDown along to the WebImmediateActionController too.

* WebView/WebImmediateActionController.h:
* WebView/WebImmediateActionController.mm:
(-[WebImmediateActionController webViewClosed]):
(-[WebImmediateActionController webView:willHandleMouseDown:]):
(-[WebImmediateActionController _cancelImmediateAction]):
(-[WebImmediateActionController _clearImmediateActionState]):
(-[WebImmediateActionController immediateActionRecognizerWillPrepare:]):
(-[WebImmediateActionController _defaultAnimationController]):
(-[WebImmediateActionController _updateImmediateActionItem]):
(-[WebImmediateActionController _menuItemForDataDetectedText]):
(-[WebImmediateActionController _showTextIndicator]):
(-[WebImmediateActionController _hideTextIndicator]):
Copy most of the DataDetectors implementation into WebImmediateActionController.

* WebView/WebUIDelegatePrivate.h:
Add a new type.

* WebView/WebView.mm:
(-[WebView _commonInitializationWithFrameName:groupName:]):
Temporarily disable action menus.

(-[WebView _immediateActionController]):
* WebView/WebViewInternal.h:

Modified Paths

Diff

Modified: trunk/Source/WebKit/mac/ChangeLog (177299 => 177300)


--- trunk/Source/WebKit/mac/ChangeLog	2014-12-15 19:46:34 UTC (rev 177299)
+++ trunk/Source/WebKit/mac/ChangeLog	2014-12-15 19:49:24 UTC (rev 177300)
@@ -1,3 +1,39 @@
+2014-12-15  Timothy Horton  <[email protected]>
+
+        Implement Data Detectors immediate actions for Legacy WebKit
+        https://bugs.webkit.org/show_bug.cgi?id=139619
+        <rdar://problem/19198539>
+
+        Reviewed by Eric Carlson.
+
+        * WebView/WebHTMLView.mm:
+        (-[WebHTMLView mouseDown:mouseDown:]):
+        Send mouseDown along to the WebImmediateActionController too.
+
+        * WebView/WebImmediateActionController.h:
+        * WebView/WebImmediateActionController.mm:
+        (-[WebImmediateActionController webViewClosed]):
+        (-[WebImmediateActionController webView:willHandleMouseDown:]):
+        (-[WebImmediateActionController _cancelImmediateAction]):
+        (-[WebImmediateActionController _clearImmediateActionState]):
+        (-[WebImmediateActionController immediateActionRecognizerWillPrepare:]):
+        (-[WebImmediateActionController _defaultAnimationController]):
+        (-[WebImmediateActionController _updateImmediateActionItem]):
+        (-[WebImmediateActionController _menuItemForDataDetectedText]):
+        (-[WebImmediateActionController _showTextIndicator]):
+        (-[WebImmediateActionController _hideTextIndicator]):
+        Copy most of the DataDetectors implementation into WebImmediateActionController.
+
+        * WebView/WebUIDelegatePrivate.h:
+        Add a new type.
+
+        * WebView/WebView.mm:
+        (-[WebView _commonInitializationWithFrameName:groupName:]):
+        Temporarily disable action menus.
+
+        (-[WebView _immediateActionController]):
+        * WebView/WebViewInternal.h:
+
 2014-12-15  Myles C. Maxfield  <[email protected]>
 
         Delete Notation because we don't use it

Modified: trunk/Source/WebKit/mac/WebView/WebHTMLView.mm (177299 => 177300)


--- trunk/Source/WebKit/mac/WebView/WebHTMLView.mm	2014-12-15 19:46:34 UTC (rev 177299)
+++ trunk/Source/WebKit/mac/WebView/WebHTMLView.mm	2014-12-15 19:49:24 UTC (rev 177300)
@@ -3822,6 +3822,7 @@
 
 #if PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101000
     [[[self _webView] _actionMenuController] webView:[self _webView] willHandleMouseDown:event];
+    [[[self _webView] _immediateActionController] webView:[self _webView] willHandleMouseDown:event];
 #endif
 
 #if PLATFORM(IOS)

Modified: trunk/Source/WebKit/mac/WebView/WebImmediateActionController.h (177299 => 177300)


--- trunk/Source/WebKit/mac/WebView/WebImmediateActionController.h	2014-12-15 19:46:34 UTC (rev 177299)
+++ trunk/Source/WebKit/mac/WebView/WebImmediateActionController.h	2014-12-15 19:49:24 UTC (rev 177300)
@@ -30,19 +30,33 @@
 #import <WebCore/NSImmediateActionGestureRecognizerSPI.h>
 #import <wtf/RetainPtr.h>
 
+@class DDActionContext;
 @class WebView;
 
+namespace WebCore {
+class Range;
+class TextIndicator;
+}
+
 @interface WebImmediateActionController : NSObject <NSImmediateActionGestureRecognizerDelegate> {
 @private
     WebView *_webView;
     WebImmediateActionType _type;
     WebCore::HitTestResult _hitTestResult;
     NSImmediateActionGestureRecognizer *_immediateActionRecognizer;
+
+    RetainPtr<DDActionContext> _currentActionContext;
+    RefPtr<WebCore::Range> _currentDetectedDataRange;
+    RefPtr<WebCore::TextIndicator> _currentDetectedDataTextIndicator;
+    BOOL _isShowingTextIndicator;
+    BOOL _hasActivatedActionContext;
 }
 
 - (instancetype)initWithWebView:(WebView *)webView recognizer:(NSImmediateActionGestureRecognizer *)immediateActionRecognizer;
 - (void)webViewClosed;
 
+- (void)webView:(WebView *)webView willHandleMouseDown:(NSEvent *)event;
+
 @end
 
 #endif // PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101000

Modified: trunk/Source/WebKit/mac/WebView/WebImmediateActionController.mm (177299 => 177300)


--- trunk/Source/WebKit/mac/WebView/WebImmediateActionController.mm	2014-12-15 19:46:34 UTC (rev 177299)
+++ trunk/Source/WebKit/mac/WebView/WebImmediateActionController.mm	2014-12-15 19:49:24 UTC (rev 177300)
@@ -27,16 +27,22 @@
 
 #if PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101000
 
+#import "DOMElementInternal.h"
+#import "DOMNodeInternal.h"
+#import "DOMRangeInternal.h"
 #import "WebElementDictionary.h"
 #import "WebFrameInternal.h"
 #import "WebHTMLView.h"
 #import "WebHTMLViewInternal.h"
 #import "WebUIDelegatePrivate.h"
 #import "WebViewInternal.h"
+#import <WebCore/DataDetection.h>
+#import <WebCore/DataDetectorsSPI.h>
 #import <WebCore/EventHandler.h>
 #import <WebCore/Frame.h>
 #import <WebCore/NSMenuSPI.h>
 #import <WebCore/SoftLinking.h>
+#import <WebCore/TextIndicator.h>
 #import <objc/objc-class.h>
 #import <objc/objc.h>
 
@@ -66,11 +72,28 @@
 {
     _webView = nil;
     _immediateActionRecognizer = nil;
+    _currentActionContext = nil;
 }
 
+- (void)webView:(WebView *)webView willHandleMouseDown:(NSEvent *)event
+{
+    [self _clearImmediateActionState];
+}
+
+- (void)_cancelImmediateAction
+{
+    // Reset the recognizer by turning it off and on again.
+    _immediateActionRecognizer.enabled = NO;
+    _immediateActionRecognizer.enabled = YES;
+
+    [self _clearImmediateActionState];
+}
+
 - (void)_clearImmediateActionState
 {
     _type = WebImmediateActionNone;
+    _currentActionContext = nil;
+    _immediateActionRecognizer.animationController = nil;
 }
 
 - (void)performHitTestAtPoint:(NSPoint)viewPoint
@@ -95,6 +118,17 @@
     NSPoint locationInDocumentView = [immediateActionRecognizer locationInView:documentView];
     [self performHitTestAtPoint:locationInDocumentView];
     [self _updateImmediateActionItem];
+
+    if (!_immediateActionRecognizer.animationController) {
+        [self _cancelImmediateAction];
+        return;
+    }
+
+    if (_currentActionContext) {
+        _hasActivatedActionContext = YES;
+        if (![getDDActionsManagerClass() shouldUseActionsWithContext:_currentActionContext.get()])
+            [self _cancelImmediateAction];
+    }
 }
 
 - (void)immediateActionRecognizerWillBeginAnimation:(NSImmediateActionGestureRecognizer *)immediateActionRecognizer
@@ -123,12 +157,8 @@
 
 #pragma mark Immediate actions
 
-- (void)_updateImmediateActionItem
+- (id <NSImmediateActionAnimationController>)_defaultAnimationController
 {
-    _type = WebImmediateActionNone;
-    _immediateActionRecognizer.animationController = nil;
-    id <NSImmediateActionAnimationController> defaultAnimationController = nil;
-
     NSURL *url = ""
     NSString *absoluteURLString = [url absoluteString];
     if (url && WebCore::protocolIsInHTTPFamily(absoluteURLString)) {
@@ -137,9 +167,26 @@
         RetainPtr<QLPreviewMenuItem> qlPreviewLinkItem = [NSMenuItem standardQuickLookMenuItem];
         [qlPreviewLinkItem setPreviewStyle:QLPreviewStylePopover];
         [qlPreviewLinkItem setDelegate:self];
-        defaultAnimationController = (id <NSImmediateActionAnimationController>)qlPreviewLinkItem.get();
+        return (id <NSImmediateActionAnimationController>)qlPreviewLinkItem.get();
     }
 
+    Node* node = _hitTestResult.innerNode();
+    if ((node && node->isTextNode()) || _hitTestResult.isOverTextInsideFormControlElement()) {
+        if (NSMenuItem *immediateActionItem = [self _menuItemForDataDetectedText]) {
+            _type = WebImmediateActionDataDetectedItem;
+            return (id<NSImmediateActionAnimationController>)immediateActionItem;
+        }
+    }
+
+    return nil;
+}
+
+- (void)_updateImmediateActionItem
+{
+    _type = WebImmediateActionNone;
+
+    id <NSImmediateActionAnimationController> defaultAnimationController = [self _defaultAnimationController];
+
     // Allow clients the opportunity to override the default immediate action.
     id customClientAnimationController = nil;
     if ([[_webView UIDelegate] respondsToSelector:@selector(_webView:immediateActionAnimationControllerForHitTestResult:withType:)]) {
@@ -147,8 +194,10 @@
         customClientAnimationController = [[_webView UIDelegate] _webView:_webView immediateActionAnimationControllerForHitTestResult:webHitTestResult.get() withType:_type];
     }
 
-    if (customClientAnimationController == [NSNull null])
+    if (customClientAnimationController == [NSNull null]) {
+        [self _cancelImmediateAction];
         return;
+    }
     if (customClientAnimationController && [customClientAnimationController conformsToProtocol:@protocol(NSImmediateActionAnimationController)])
         _immediateActionRecognizer.animationController = (id <NSImmediateActionAnimationController>)customClientAnimationController;
     else
@@ -175,6 +224,80 @@
     return NSMaxYEdge;
 }
 
+#pragma mark Data Detectors actions
+
+- (NSMenuItem *)_menuItemForDataDetectedText
+{
+    RefPtr<Range> detectedDataRange;
+    FloatRect detectedDataBoundingBox;
+    RetainPtr<DDActionContext> actionContext;
+
+    if ([[_webView UIDelegate] respondsToSelector:@selector(_webView:actionContextForHitTestResult:range:)]) {
+        RetainPtr<WebElementDictionary> hitTestDictionary = adoptNS([[WebElementDictionary alloc] initWithHitTestResult:_hitTestResult]);
+
+        DOMRange *customDataDetectorsRange;
+        actionContext = [[_webView UIDelegate] _webView:_webView actionContextForHitTestResult:hitTestDictionary.get() range:&customDataDetectorsRange];
+
+        if (actionContext && customDataDetectorsRange)
+            detectedDataRange = core(customDataDetectorsRange);
+    }
+
+    // If the client didn't give us an action context, try to scan around the hit point.
+    if (!actionContext || !detectedDataRange)
+        actionContext = DataDetection::detectItemAroundHitTestResult(_hitTestResult, detectedDataBoundingBox, detectedDataRange);
+
+    if (!actionContext || !detectedDataRange)
+        return nil;
+
+    [actionContext setAltMode:YES];
+    if ([[getDDActionsManagerClass() sharedManager] respondsToSelector:@selector(hasActionsForResult:actionContext:)]) {
+        if (![[getDDActionsManagerClass() sharedManager] hasActionsForResult:[actionContext mainResult] actionContext:actionContext.get()])
+            return nil;
+    }
+
+    _currentDetectedDataTextIndicator = TextIndicator::createWithRange(*detectedDataRange, TextIndicatorPresentationTransition::BounceAndCrossfade);
+
+    _currentActionContext = [actionContext contextForView:_webView altMode:YES interactionStartedHandler:^() {
+    } interactionChangedHandler:^() {
+        [self _showTextIndicator];
+    } interactionStoppedHandler:^() {
+        [self _hideTextIndicator];
+    }];
+    _currentDetectedDataRange = detectedDataRange;
+
+    [_currentActionContext setHighlightFrame:[_webView.window convertRectToScreen:detectedDataBoundingBox]];
+
+    NSArray *menuItems = [[getDDActionsManagerClass() sharedManager] menuItemsForResult:[_currentActionContext mainResult] actionContext:_currentActionContext.get()];
+    if (menuItems.count != 1)
+        return nil;
+
+    if (_currentDetectedDataTextIndicator)
+        _currentDetectedDataTextIndicator->setPresentationTransition(TextIndicatorPresentationTransition::Bounce);
+    return menuItems.lastObject;
+}
+
+#pragma mark Text Indicator
+
+- (void)_showTextIndicator
+{
+    if (_isShowingTextIndicator)
+        return;
+
+    if (_type == WebImmediateActionDataDetectedItem && _currentDetectedDataTextIndicator) {
+        [_webView _setTextIndicator:_currentDetectedDataTextIndicator.get() fadeOut:NO animationCompletionHandler:^ { }];
+        _isShowingTextIndicator = YES;
+    }
+}
+
+- (void)_hideTextIndicator
+{
+    if (!_isShowingTextIndicator)
+        return;
+
+    [_webView _clearTextIndicator];
+    _isShowingTextIndicator = NO;
+}
+
 @end
 
 #endif // PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101000

Modified: trunk/Source/WebKit/mac/WebView/WebUIDelegatePrivate.h (177299 => 177300)


--- trunk/Source/WebKit/mac/WebView/WebUIDelegatePrivate.h	2014-12-15 19:46:34 UTC (rev 177299)
+++ trunk/Source/WebKit/mac/WebView/WebUIDelegatePrivate.h	2014-12-15 19:49:24 UTC (rev 177300)
@@ -146,7 +146,8 @@
 
 typedef enum {
     WebImmediateActionNone = 0,
-    WebImmediateActionLinkPreview
+    WebImmediateActionLinkPreview,
+    WebImmediateActionDataDetectedItem
 } WebImmediateActionType;
 
 // Message Sources.

Modified: trunk/Source/WebKit/mac/WebView/WebView.mm (177299 => 177300)


--- trunk/Source/WebKit/mac/WebView/WebView.mm	2014-12-15 19:46:34 UTC (rev 177299)
+++ trunk/Source/WebKit/mac/WebView/WebView.mm	2014-12-15 19:49:24 UTC (rev 177300)
@@ -886,12 +886,13 @@
     [frameView release];
 
 #if PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101000
-    if ([self respondsToSelector:@selector(setActionMenu:)]) {
+    // FIXME: Temporarily disable action menu installation.
+    /*if ([self respondsToSelector:@selector(setActionMenu:)]) {
         RetainPtr<NSMenu> actionMenu = adoptNS([[NSMenu alloc] init]);
         self.actionMenu = actionMenu.get();
         _private->actionMenuController = [[WebActionMenuController alloc] initWithWebView:self];
         self.actionMenu.autoenablesItems = NO;
-    }
+    }*/
 
     if (Class gestureClass = NSClassFromString(@"NSImmediateActionGestureRecognizer")) {
         RetainPtr<NSImmediateActionGestureRecognizer> recognizer = adoptNS([(NSImmediateActionGestureRecognizer *)[gestureClass alloc] initWithTarget:nil action:NULL]);
@@ -8605,6 +8606,11 @@
 {
     return _private->actionMenuController;
 }
+
+- (WebImmediateActionController *)_immediateActionController
+{
+    return _private->immediateActionController;
+}
 #endif // __MAC_OS_X_VERSION_MIN_REQUIRED >= 101000
 
 - (void)_setTextIndicator:(TextIndicator *)textIndicator fadeOut:(BOOL)fadeOut animationCompletionHandler:(std::function<void ()>)completionHandler

Modified: trunk/Source/WebKit/mac/WebView/WebViewInternal.h (177299 => 177300)


--- trunk/Source/WebKit/mac/WebView/WebViewInternal.h	2014-12-15 19:46:34 UTC (rev 177299)
+++ trunk/Source/WebKit/mac/WebView/WebViewInternal.h	2014-12-15 19:49:24 UTC (rev 177300)
@@ -66,6 +66,7 @@
 @class WebActionMenuController;
 @class WebBasePluginPackage;
 @class WebDownload;
+@class WebImmediateActionController;
 @class WebNodeHighlight;
 
 #ifdef __cplusplus
@@ -263,6 +264,7 @@
 - (void)_showDictionaryLookupPopup:(const DictionaryPopupInfo&)dictionaryPopupInfo;
 #if __MAC_OS_X_VERSION_MIN_REQUIRED >= 101000
 - (WebActionMenuController *)_actionMenuController;
+- (WebImmediateActionController *)_immediateActionController;
 #endif
 #endif
 
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to