- 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