Changeset 175595 in webkit


Ignore:
Timestamp:
Nov 4, 2014 5:24:20 PM (9 years ago)
Author:
aestes@apple.com
Message:

[iOS] Add long press support for links in WKPDFView
https://bugs.webkit.org/show_bug.cgi?id=138357

Reviewed by Dan Bernstein.

Use WKActionSheetAssistant to show a link action sheet in response to long-pressing on a link. Have WKPDFView
conform to WKActionSheetAssistantDelegate in order to respond to the open and copy actions as well as to
provide the link's URL and position information to WKActionSheetAssistant. The long-pressed link is highlighted
for .75 seconds before the sheet is displayed in order to match UIWebPDFView.

  • UIProcess/ios/WKActionSheetAssistant.h: Made protocol methods that WKPDFView doesn't implement optional.
  • UIProcess/ios/WKActionSheetAssistant.mm:

(-[WKActionSheetAssistant updatePositionInformation]): Checked if delegate responds to
updatePositionInformationForActionSheetAssistant: before calling.
(-[WKActionSheetAssistant _createSheetWithElementActions:showLinkTitle:]): Checked if delegate responds to
actionSheetAssistant:willStartInteractionWithElement: before calling.
(-[WKActionSheetAssistant cleanupSheet]): Checked if delegate responds to actionSheetAssistantDidStopInteraction:
before calling.

  • UIProcess/ios/WKPDFView.h: Conformed to WKActionSheetAssistantDelegate.
  • UIProcess/ios/WKPDFView.mm:

(-[WKPDFView web_initWithFrame:webView:]): Instantiated a WKActionSheetAssistant and set self as its delegate.
(-[WKPDFView _highlightLinkAnnotation:forDuration:completionHandler:]): Moved highlight drawing to here from
annotation:wasTouchedAtPoint:controller: in order to be reused for long-press.
(-[WKPDFView _URLForLinkAnnotation:]): Moved URL creation to here from annotation:wasTouchedAtPoint:controller:
in order to be reused for long-press. Generated an absolute URL since this URL might go into the pasteboard.
(-[WKPDFView annotation:wasTouchedAtPoint:controller:]): Changed to call
_highlightLinkAnnotation:forDuration:completionHandler: and _URLForLinkAnnotation:.
(-[WKPDFView annotation:isBeingPressedAtPoint:controller:]): Set values on _positionInformation and called
-[WKActionSheetAssistant showLinkSheet] after showing a highlight for .75 seconds.
(-[WKPDFView positionInformation]): Returned _positionInformation.
(-[WKPDFView performAction:]): Added a UTF-8 text and URL representation of the pressed URL to the pasteboard.
(-[WKPDFView openElementAtLocation:]): Called WebPage::navigateToURLWithSimulatedClick().
(-[WKPDFView actionsForElement:defaultActions:]): Returned actions from UIClient::actionsForElement().
(-[WKPDFView _createHighlightViewWithFrame:]): Deleted.

Location:
trunk/Source/WebKit2
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebKit2/ChangeLog

    r175591 r175595  
     12014-11-04  Andy Estes  <aestes@apple.com>
     2
     3        [iOS] Add long press support for links in WKPDFView
     4        https://bugs.webkit.org/show_bug.cgi?id=138357
     5
     6        Reviewed by Dan Bernstein.
     7
     8        Use WKActionSheetAssistant to show a link action sheet in response to long-pressing on a link. Have WKPDFView
     9        conform to WKActionSheetAssistantDelegate in order to respond to the open and copy actions as well as to
     10        provide the link's URL and position information to WKActionSheetAssistant. The long-pressed link is highlighted
     11        for .75 seconds before the sheet is displayed in order to match UIWebPDFView.
     12
     13        * UIProcess/ios/WKActionSheetAssistant.h: Made protocol methods that WKPDFView doesn't implement optional.
     14        * UIProcess/ios/WKActionSheetAssistant.mm:
     15        (-[WKActionSheetAssistant updatePositionInformation]): Checked if delegate responds to
     16        updatePositionInformationForActionSheetAssistant: before calling.
     17        (-[WKActionSheetAssistant _createSheetWithElementActions:showLinkTitle:]): Checked if delegate responds to
     18        actionSheetAssistant:willStartInteractionWithElement: before calling.
     19        (-[WKActionSheetAssistant cleanupSheet]): Checked if delegate responds to actionSheetAssistantDidStopInteraction:
     20        before calling.
     21        * UIProcess/ios/WKPDFView.h: Conformed to WKActionSheetAssistantDelegate.
     22        * UIProcess/ios/WKPDFView.mm:
     23        (-[WKPDFView web_initWithFrame:webView:]): Instantiated a WKActionSheetAssistant and set self as its delegate.
     24        (-[WKPDFView _highlightLinkAnnotation:forDuration:completionHandler:]): Moved highlight drawing to here from
     25        annotation:wasTouchedAtPoint:controller: in order to be reused for long-press.
     26        (-[WKPDFView _URLForLinkAnnotation:]): Moved URL creation to here from annotation:wasTouchedAtPoint:controller:
     27        in order to be reused for long-press. Generated an absolute URL since this URL might go into the pasteboard.
     28        (-[WKPDFView annotation:wasTouchedAtPoint:controller:]): Changed to call
     29        _highlightLinkAnnotation:forDuration:completionHandler: and _URLForLinkAnnotation:.
     30        (-[WKPDFView annotation:isBeingPressedAtPoint:controller:]): Set values on _positionInformation and called
     31        -[WKActionSheetAssistant showLinkSheet] after showing a highlight for .75 seconds.
     32        (-[WKPDFView positionInformation]): Returned _positionInformation.
     33        (-[WKPDFView performAction:]): Added a UTF-8 text and URL representation of the pressed URL to the pasteboard.
     34        (-[WKPDFView openElementAtLocation:]): Called WebPage::navigateToURLWithSimulatedClick().
     35        (-[WKPDFView actionsForElement:defaultActions:]): Returned actions from UIClient::actionsForElement().
     36        (-[WKPDFView _createHighlightViewWithFrame:]): Deleted.
     37
    1382014-11-04  Anders Carlsson  <andersca@apple.com>
    239
  • trunk/Source/WebKit2/UIProcess/ios/WKActionSheetAssistant.h

    r175577 r175595  
    4141@protocol WKActionSheetDelegate;
    4242
    43 @protocol WKActionSheetAssistantDelegate
     43@protocol WKActionSheetAssistantDelegate <NSObject>
    4444@required
    4545- (const WebKit::InteractionInformationAtPosition&)positionInformationForActionSheetAssistant:(WKActionSheetAssistant *)assistant;
    46 - (void)updatePositionInformationForActionSheetAssistant:(WKActionSheetAssistant *)assistant;
    4746- (void)actionSheetAssistant:(WKActionSheetAssistant *)assistant performAction:(WebKit::SheetAction)action;
    4847- (void)actionSheetAssistant:(WKActionSheetAssistant *)assistant openElementAtLocation:(CGPoint)location;
    4948- (RetainPtr<NSArray>)actionSheetAssistant:(WKActionSheetAssistant *)assistant decideActionsForElement:(_WKActivatedElementInfo *)element defaultActions:(RetainPtr<NSArray>)defaultActions;
     49
     50@optional
     51- (void)updatePositionInformationForActionSheetAssistant:(WKActionSheetAssistant *)assistant;
    5052- (void)actionSheetAssistant:(WKActionSheetAssistant *)assistant willStartInteractionWithElement:(_WKActivatedElementInfo *)element;
    5153- (void)actionSheetAssistantDidStopInteraction:(WKActionSheetAssistant *)assistant;
     54
    5255@end
    5356
  • trunk/Source/WebKit2/UIProcess/ios/WKActionSheetAssistant.mm

    r175577 r175595  
    164164- (void)updatePositionInformation
    165165{
    166     [_delegate.get() updatePositionInformationForActionSheetAssistant:self];
     166    auto delegate = _delegate.get();
     167    if ([delegate respondsToSelector:@selector(updatePositionInformationForActionSheetAssistant:)])
     168        [delegate updatePositionInformationForActionSheetAssistant:self];
    167169}
    168170
     
    237239                                                            [self cleanupSheet];
    238240                                                        }]];
    239     [delegate actionSheetAssistant:self willStartInteractionWithElement:_elementInfo.get()];
     241
     242    if ([delegate respondsToSelector:@selector(actionSheetAssistant:willStartInteractionWithElement:)])
     243        [delegate actionSheetAssistant:self willStartInteractionWithElement:_elementInfo.get()];
    240244}
    241245
     
    366370- (void)cleanupSheet
    367371{
    368     [_delegate.get() actionSheetAssistantDidStopInteraction:self];
     372    auto delegate = _delegate.get();
     373    if ([delegate respondsToSelector:@selector(actionSheetAssistantDidStopInteraction:)])
     374        [delegate actionSheetAssistantDidStopInteraction:self];
    369375
    370376    [_interactionSheet doneWithSheet];
  • trunk/Source/WebKit2/UIProcess/ios/WKPDFView.h

    r174072 r175595  
    2626#if PLATFORM(IOS)
    2727
     28#import "WKActionSheetAssistant.h"
    2829#import "WKWebViewContentProvider.h"
    2930#import <CorePDF/UIPDFAnnotationController.h>
     
    3132#import <UIKit/UIView.h>
    3233
    33 @interface WKPDFView : UIView <WKWebViewContentProvider, UIPDFPageViewDelegate, UIPDFAnnotationControllerDelegate>
     34@interface WKPDFView : UIView <WKWebViewContentProvider, UIPDFPageViewDelegate, UIPDFAnnotationControllerDelegate, WKActionSheetAssistantDelegate>
    3435
    3536@property (nonatomic, readonly) NSString *suggestedFilename;
  • trunk/Source/WebKit2/UIProcess/ios/WKPDFView.mm

    r174286 r175595  
    2929#if PLATFORM(IOS)
    3030
     31#import "APIUIClient.h"
    3132#import "SessionState.h"
     33#import "WKNSURLExtras.h"
    3234#import "WKPDFPageNumberIndicator.h"
    3335#import "WKWebViewInternal.h"
     
    3739#import <CorePDF/UIPDFPage.h>
    3840#import <CorePDF/UIPDFPageView.h>
     41#import <MobileCoreServices/UTCoreTypes.h>
    3942#import <UIKit/UIScrollView_Private.h>
    4043#import <WebCore/FloatRect.h>
    4144#import <WebCore/_UIHighlightViewSPI.h>
    42 #import <chrono>
    4345#import <wtf/RetainPtr.h>
    4446#import <wtf/Vector.h>
     
    8082    BOOL _isStartingZoom;
    8183    BOOL _isPerformingSameDocumentNavigation;
     84
     85    RetainPtr<WKActionSheetAssistant> _actionSheetAssistant;
     86    WebKit::InteractionInformationAtPosition _positionInformation;
    8287}
    8388
     
    95100    [_scrollView setMaximumZoomScale:pdfMaximumZoomScale];
    96101    [_scrollView setBackgroundColor:[UIColor grayColor]];
     102
     103    _actionSheetAssistant = adoptNS([[WKActionSheetAssistant alloc] initWithView:self]);
     104    [_actionSheetAssistant setDelegate:self];
    97105
    98106    return self;
     
    320328}
    321329
    322 - (RetainPtr<_UIHighlightView>)_createHighlightViewWithFrame:(CGRect)frame
     330- (void)_highlightLinkAnnotation:(UIPDFLinkAnnotation *)linkAnnotation forDuration:(NSTimeInterval)duration completionHandler:(void (^)())completionHandler
    323331{
    324332    static const CGFloat highlightBorderRadius = 3;
     
    326334    static UIColor *highlightColor = [[UIColor alloc] initWithRed:highlightColorComponent green:highlightColorComponent blue:highlightColorComponent alpha:0.3];
    327335
    328     RetainPtr<_UIHighlightView> highlightView = adoptNS([[_UIHighlightView alloc] initWithFrame:CGRectInset(frame, -highlightBorderRadius, -highlightBorderRadius)]);
     336    UIPDFPageView *pageView = linkAnnotation.annotationController.pageView;
     337    CGRect highlightViewFrame = [self convertRect:[pageView convertRectFromPDFPageSpace:linkAnnotation.Rect] fromView:pageView];
     338    RetainPtr<_UIHighlightView> highlightView = adoptNS([[_UIHighlightView alloc] initWithFrame:CGRectInset(highlightViewFrame, -highlightBorderRadius, -highlightBorderRadius)]);
    329339    [highlightView setOpaque:NO];
    330340    [highlightView setCornerRadius:highlightBorderRadius];
    331341    [highlightView setColor:highlightColor];
    332     return highlightView;
     342
     343    ASSERT(isMainThread());
     344    [self addSubview:highlightView.get()];
     345    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, duration * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
     346        [highlightView removeFromSuperview];
     347        completionHandler();
     348    });
     349}
     350
     351- (NSURL *)_URLForLinkAnnotation:(UIPDFLinkAnnotation *)linkAnnotation
     352{
     353    NSURL *documentURL = _webView.URL;
     354
     355    if (NSURL *url = linkAnnotation.url)
     356        return [NSURL URLWithString:url.relativeString relativeToURL:documentURL];
     357
     358    if (NSUInteger pageNumber = linkAnnotation.pageNumber) {
     359        String anchorString = ASCIILiteral("#page");
     360        anchorString.append(String::number(pageNumber));
     361        return [NSURL _web_URLWithWTFString:anchorString relativeToURL:documentURL];
     362    }
     363
     364    return nil;
    333365}
    334366
     
    361393- (void)annotation:(UIPDFAnnotation *)annotation wasTouchedAtPoint:(CGPoint)point controller:(UIPDFAnnotationController *)controller
    362394{
    363     ASSERT(isMainThread());
    364 
    365395    if (![annotation isKindOfClass:[UIPDFLinkAnnotation class]])
    366396        return;
    367397
    368398    UIPDFLinkAnnotation *linkAnnotation = (UIPDFLinkAnnotation *)annotation;
    369     String urlString;
    370     if (NSURL *url = linkAnnotation.url)
    371         urlString = url.absoluteString;
    372     else if (NSUInteger pageNumber = linkAnnotation.pageNumber) {
    373         urlString = ASCIILiteral("#page");
    374         urlString.append(String::number(pageNumber));
    375     }
    376 
    377     if (urlString.isEmpty())
     399    RetainPtr<NSURL> url = [self _URLForLinkAnnotation:linkAnnotation];
     400    if (!url)
    378401        return;
    379402
    380403    CGPoint documentPoint = [controller.pageView convertPoint:point toView:self];
    381404    CGPoint screenPoint = [self.window convertPoint:[self convertPoint:documentPoint toView:nil] toWindow:nil];
    382     static const int64_t dispatchOffset = std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::milliseconds(200)).count();
    383405    RetainPtr<WKWebView> retainedWebView = _webView;
    384406
    385     CGRect highlightViewFrame = [self convertRect:[controller.pageView convertRectFromPDFPageSpace:annotation.Rect] fromView:controller.pageView];
    386     RetainPtr<_UIHighlightView> highlightView = [self _createHighlightViewWithFrame:highlightViewFrame];
    387     [self addSubview:highlightView.get()];
    388     dispatch_after(dispatch_time(DISPATCH_TIME_NOW, dispatchOffset), dispatch_get_main_queue(), ^ {
    389         retainedWebView->_page->navigateToURLWithSimulatedClick(urlString, roundedIntPoint(documentPoint), roundedIntPoint(screenPoint));
    390         [highlightView removeFromSuperview];
    391     });
     407    [self _highlightLinkAnnotation:linkAnnotation forDuration:.2 completionHandler:^{
     408        retainedWebView->_page->navigateToURLWithSimulatedClick([url absoluteString], roundedIntPoint(documentPoint), roundedIntPoint(screenPoint));
     409    }];
     410}
     411
     412- (void)annotation:(UIPDFAnnotation *)annotation isBeingPressedAtPoint:(CGPoint)point controller:(UIPDFAnnotationController *)controller
     413{
     414    if (![annotation isKindOfClass:[UIPDFLinkAnnotation class]])
     415        return;
     416
     417    UIPDFLinkAnnotation *linkAnnotation = (UIPDFLinkAnnotation *)annotation;
     418    NSURL *url = [self _URLForLinkAnnotation:linkAnnotation];
     419    if (!url)
     420        return;
     421
     422    _positionInformation.url = url.absoluteString;
     423    _positionInformation.point = roundedIntPoint([controller.pageView convertPoint:point toView:self]);
     424    _positionInformation.bounds = roundedIntRect([self convertRect:[controller.pageView convertRectFromPDFPageSpace:annotation.Rect] fromView:controller.pageView]);
     425
     426    [self _highlightLinkAnnotation:linkAnnotation forDuration:.75 completionHandler:^{
     427        [_actionSheetAssistant showLinkSheet];
     428    }];
     429}
     430
     431#pragma mark WKActionSheetAssistantDelegate
     432
     433- (const WebKit::InteractionInformationAtPosition&)positionInformationForActionSheetAssistant:(WKActionSheetAssistant *)assistant
     434{
     435    return _positionInformation;
     436}
     437
     438- (void)actionSheetAssistant:(WKActionSheetAssistant *)assistant performAction:(WebKit::SheetAction)action
     439{
     440    if (action != WebKit::SheetAction::Copy)
     441        return;
     442
     443    NSDictionary *representations = @{
     444        (NSString *)kUTTypeUTF8PlainText : _positionInformation.url,
     445        (NSString *)kUTTypeURL : [NSURL URLWithString:_positionInformation.url]
     446    };
     447
     448    [UIPasteboard generalPasteboard].items = @[ representations ];
     449}
     450
     451- (void)actionSheetAssistant:(WKActionSheetAssistant *)assistant openElementAtLocation:(CGPoint)location
     452{
     453    CGPoint screenPoint = [self.window convertPoint:[self convertPoint:location toView:nil] toWindow:nil];
     454    _webView->_page->navigateToURLWithSimulatedClick(_positionInformation.url, roundedIntPoint(location), roundedIntPoint(screenPoint));
     455}
     456
     457- (RetainPtr<NSArray>)actionSheetAssistant:(WKActionSheetAssistant *)assistant decideActionsForElement:(_WKActivatedElementInfo *)element defaultActions:(RetainPtr<NSArray>)defaultActions
     458{
     459    return _webView->_page->uiClient().actionsForElement(element, WTF::move(defaultActions));
    392460}
    393461
Note: See TracChangeset for help on using the changeset viewer.