PDFPlugin: Make scrolling between pages in non-continuous modes work
authortimothy_horton@apple.com <timothy_horton@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 11 Mar 2013 23:47:20 +0000 (23:47 +0000)
committertimothy_horton@apple.com <timothy_horton@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 11 Mar 2013 23:47:20 +0000 (23:47 +0000)
https://bugs.webkit.org/show_bug.cgi?id=111415
<rdar://problem/12555320>

Reviewed by Alexey Proskuryakov.

* WebProcess/Plugins/PDF/PDFLayerControllerDetails.h:
Add some more PDFLayerController SPI.

* WebProcess/Plugins/PDF/PDFPlugin.h:
(PDFPlugin): Override handleWheelEvent.

* WebProcess/Plugins/PDF/PDFPlugin.mm:
(WebKit::PDFPlugin::handleWheelEvent):
If PDFLayerController is in non-continuous mode, allow scrolling between
pages by intercepting scroll events, and checking whether we're at the
top or bottom of a page. If we are, and a single event exceeds the threshold
of 20px (0px for legacy scroll wheels), we jump to the next or previous
page and scroll to the right place. Do not allow momentum scrolling to
switch pages.

* WebCore.exp.in: Export ScrollableArea::scrollToOffsetWithoutAnimation.

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

Source/WebCore/ChangeLog
Source/WebCore/WebCore.exp.in
Source/WebKit2/ChangeLog
Source/WebKit2/WebProcess/Plugins/PDF/PDFLayerControllerDetails.h
Source/WebKit2/WebProcess/Plugins/PDF/PDFPlugin.h
Source/WebKit2/WebProcess/Plugins/PDF/PDFPlugin.mm

index d5f02ab..03f21d3 100644 (file)
@@ -1,3 +1,13 @@
+2013-03-11  Tim Horton  <timothy_horton@apple.com>
+
+        PDFPlugin: Make scrolling between pages in non-continuous modes work
+        https://bugs.webkit.org/show_bug.cgi?id=111415
+        <rdar://problem/12555320>
+
+        Reviewed by Alexey Proskuryakov.
+
+        * WebCore.exp.in: Export ScrollableArea::scrollToOffsetWithoutAnimation.
+
 2013-03-11  Mark Lam  <mark.lam@apple.com>
 
         Remove the use of the quotaMap cache in DatabaseTracker.
index a1140c0..c7b44ad 100644 (file)
@@ -362,6 +362,7 @@ __ZN7WebCore14ScrollableArea27willRemoveVerticalScrollbarEPNS_9ScrollbarE
 __ZN7WebCore14ScrollableArea27notifyScrollPositionChangedERKNS_8IntPointE
 __ZN7WebCore14ScrollableArea28setScrollOffsetFromInternalsERKNS_8IntPointE
 __ZN7WebCore14ScrollableArea29willRemoveHorizontalScrollbarEPNS_9ScrollbarE
+__ZN7WebCore14ScrollableArea30scrollToOffsetWithoutAnimationERKNS_10FloatPointE
 __ZN7WebCore14ScrollableArea6scrollENS_15ScrollDirectionENS_17ScrollGranularityEf
 __ZN7WebCore14ScrollableAreaC2Ev
 __ZN7WebCore14ScrollableAreaD2Ev
index 8e6341b..0df8d31 100644 (file)
@@ -1,3 +1,26 @@
+2013-03-11  Tim Horton  <timothy_horton@apple.com>
+
+        PDFPlugin: Make scrolling between pages in non-continuous modes work
+        https://bugs.webkit.org/show_bug.cgi?id=111415
+        <rdar://problem/12555320>
+
+        Reviewed by Alexey Proskuryakov.
+
+        * WebProcess/Plugins/PDF/PDFLayerControllerDetails.h:
+        Add some more PDFLayerController SPI.
+
+        * WebProcess/Plugins/PDF/PDFPlugin.h:
+        (PDFPlugin): Override handleWheelEvent.
+
+        * WebProcess/Plugins/PDF/PDFPlugin.mm:
+        (WebKit::PDFPlugin::handleWheelEvent):
+        If PDFLayerController is in non-continuous mode, allow scrolling between
+        pages by intercepting scroll events, and checking whether we're at the
+        top or bottom of a page. If we are, and a single event exceeds the threshold
+        of 20px (0px for legacy scroll wheels), we jump to the next or previous
+        page and scroll to the right place. Do not allow momentum scrolling to
+        switch pages.
+
 2013-03-11  Mark Lam  <mark.lam@apple.com>
 
         Fix some WebDatabaseManagerProxy methods to only send to one WebProcsess
index 85e909e..097701e 100644 (file)
@@ -53,7 +53,8 @@
 
 - (void)setFrameSize:(CGSize)size;
 
-- (void)setDisplayMode:(int)mode;
+- (PDFDisplayMode)displayMode;
+- (void)setDisplayMode:(PDFDisplayMode)mode;
 - (void)setDisplaysPageBreaks:(BOOL)pageBreaks;
 
 - (CGFloat)contentScaleFactor;
 - (void)gotoSelection:(PDFSelection *)selection;
 - (PDFSelection *)getSelectionForWordAtPoint:(CGPoint)point;
 
+- (NSUInteger)lastPageIndex;
+- (NSUInteger)currentPageIndex;
+- (void)gotoNextPage;
+- (void)gotoPreviousPage;
+
 - (void)copySelection;
 - (void)selectAll;
 
index 2259ebd..92b95cb 100644 (file)
@@ -114,6 +114,8 @@ private:
     virtual bool performDictionaryLookupAtLocation(const WebCore::FloatPoint&) OVERRIDE;
     virtual String getSelectionString() const OVERRIDE;
 
+    virtual bool handleWheelEvent(const WebWheelEvent& event) OVERRIDE;
+
     // ScrollableArea functions.
     virtual void setScrollOffset(const WebCore::IntPoint&) OVERRIDE;
     virtual void invalidateScrollbarRect(WebCore::Scrollbar*, const WebCore::IntRect&) OVERRIDE;
index 5173c2f..480ffa7 100644 (file)
@@ -85,6 +85,10 @@ static const char* annotationStyle =
 "    resize: none; "
 "}";
 
+// In non-continuous modes, a single scroll event with a magnitude of >= 20px
+// will jump to the next or previous page, to match PDFKit behavior.
+static const int defaultScrollMagnitudeThresholdForPageFlip = 20;
+
 @interface WKPDFPluginScrollbarLayer : CALayer
 {
     WebKit::PDFPlugin* _pdfPlugin;
@@ -303,7 +307,7 @@ void PDFPlugin::pdfDocumentDidLoad()
     m_pdfLayerController.get().document = document.get();
 
     updatePageAndDeviceScaleFactors();
-    
+
     if (handlesPageScaleFactor())
         pluginView()->setPageScaleFactor([m_pdfLayerController.get() contentScaleFactor], IntPoint());
 
@@ -980,6 +984,45 @@ void PDFPlugin::performWebSearch(NSString *string)
     webFrame()->page()->send(Messages::WebPageProxy::SearchTheWeb(string));
 }
 
+bool PDFPlugin::handleWheelEvent(const WebWheelEvent& event)
+{
+    PDFDisplayMode displayMode = [m_pdfLayerController.get() displayMode];
+
+    if (displayMode == kPDFDisplaySinglePageContinuous || displayMode == kPDFDisplayTwoUpContinuous)
+        return SimplePDFPlugin::handleWheelEvent(event);
+
+    NSUInteger currentPageIndex = [m_pdfLayerController.get() currentPageIndex];
+    bool inFirstPage = currentPageIndex == 0;
+    bool inLastPage = [m_pdfLayerController.get() lastPageIndex] == currentPageIndex;
+
+    bool atScrollTop = scrollPosition().y() == 0;
+    bool atScrollBottom = scrollPosition().y() == maximumScrollPosition().y();
+
+    bool inMomentumScroll = event.momentumPhase() != WebWheelEvent::PhaseNone;
+
+    int scrollMagnitudeThresholdForPageFlip = defaultScrollMagnitudeThresholdForPageFlip;
+
+    // Imprecise input devices should have a lower threshold so that "clicky" scroll wheels can flip pages.
+    if (!event.hasPreciseScrollingDeltas())
+        scrollMagnitudeThresholdForPageFlip = 0;
+
+    if (atScrollBottom && !inLastPage && event.delta().height() < 0) {
+        if (event.delta().height() <= -scrollMagnitudeThresholdForPageFlip && !inMomentumScroll)
+            [m_pdfLayerController.get() gotoNextPage];
+        return true;
+    } else if (atScrollTop && !inFirstPage && event.delta().height() > 0) {
+        if (event.delta().height() >= scrollMagnitudeThresholdForPageFlip && !inMomentumScroll) {
+            [CATransaction begin];
+            [m_pdfLayerController.get() gotoPreviousPage];
+            scrollToOffsetWithoutAnimation(maximumScrollPosition());
+            [CATransaction commit];
+        }
+        return true;
+    }
+
+    return SimplePDFPlugin::handleWheelEvent(event);
+}
+
 } // namespace WebKit
 
 #endif // ENABLE(PDFKIT_PLUGIN)