Source/WebCore: Reviewed by Simon Fraser.
authorjonlee@apple.com <jonlee@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 16 May 2011 17:25:02 +0000 (17:25 +0000)
committerjonlee@apple.com <jonlee@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 16 May 2011 17:25:02 +0000 (17:25 +0000)
       Can't horizontally scroll iframes and overflow because wheel events are always accepted
       https://bugs.webkit.org/show_bug.cgi?id=60779

       * dom/Document.cpp:
       (WebCore::Document::Document): Initialize wheel event handler count
       (WebCore::Document::didAddWheelEventHandler): Increment count, and tell the main frame
       to recalculate the total number of wheel event handlers in all of its frames' documents
       (WebCore::Document::didRemoveWheelEventHandler): Reverse of previous method
       * dom/Document.h:
       (WebCore::Document::wheelEventHandlerCount): Access the count
       * dom/Node.cpp:
       (WebCore::tryAddEventListener): If the event listener is a mouse wheel event, then
       tell the document to increment its count
       (WebCore::tryRemoveEventListener): Reverse of previous method

       * page/ChromeClient.h: Two new methods:
 numWheelEventHandlersChanged: WebProcess tells UIProcess to update its cached
   count of total wheel event handlers, which in this case only include horizontal
   scrollbars and mouse wheel JS handlers
 shouldRubberBandInDirection: allow the UIProcess to provide some control over
   whether rubber banding is allowed when scrolling in a particular direction
       * loader/EmptyClients.h:
       (WebCore::EmptyChromeClient::numWheelEventHandlersChanged): Default empty impl
       (WebCore::EmptyChromeClient::shouldRubberBandInDirection): Default empty impl
       * page/EventHandler.cpp:
       (WebCore::EventHandler::handleWheelEvent): Remove a redundant pointer check
       * page/Frame.cpp:
       (WebCore::Frame::setDocument): When the frame's document changes, calculate that
       document's total wheel event handlers, and notify the UIProcess
       (WebCore::Frame::notifyChromeClientWheelEventHandlerCountChanged): Performs a crawl
       of the frame tree to aggregate the count
       * page/Frame.h:

       * platform/ScrollableArea.h: Virtualize didAddHorizontalScrollbar and
       willRemoveHorizontalScrollbar for overriding in RenderLayer and FrameView
       (WebCore::ScrollableArea::isHorizontalScrollerPinnedToMinimumPosition): Returns true if there is
       no scrollbar or the scroller position is in the minimum scroll position.
       (WebCore::ScrollableArea::isHorizontalScrollerPinnedToMaximumPosition): Converse of the above.
       (WebCore::ScrollableArea::shouldRubberBandInDirection): Default impl
       * page/FrameView.cpp:
       (WebCore::FrameView::didAddHorizontalScrollbar): Updates the frame's document's count
       (WebCore::FrameView::willRemoveHorizontalScrollbar): Updates the frame's document's
       count
       (WebCore::FrameView::shouldRubberBandInDirection): Connective glue
       * page/FrameView.h: Adding overriding methods from ScrollableArea
       * rendering/RenderLayer.cpp: Similar functionality to FrameView
       (WebCore::RenderLayer::didAddHorizontalScrollbar):
       (WebCore::RenderLayer::willRemoveHorizontalScrollbar):
       * rendering/RenderLayer.h:

       * platform/mac/ScrollAnimatorMac.h: Fix typo of "momentum"
       * platform/mac/ScrollAnimatorMac.mm:
       (WebCore::ScrollAnimatorMac::ScrollAnimatorMac): Fix typo of "momentum"
       (WebCore::ScrollAnimatorMac::smoothScrollWithEvent): Fix typo of "coalesced"
       (WebCore::ScrollAnimatorMac::beginScrollGesture): Fix typo of "coalesced"
       (WebCore::ScrollAnimatorMac::snapRubberBand): Fix typo of "momentum"

       (WebCore::ScrollAnimatorMac::handleWheelEvent): New logic for determining whether
       to allow rubber-banding based on the area's scroll position and the wheel event.
       Could prevent accepting the wheel event. Also, fix typo of "momentum"
       (WebCore::isScrollingLeftAndShouldNotRubberBand): Inline helper function for logic
       (WebCore::isScrollingRightAndShouldNotRubberBand): Inline helper function for logic

Source/WebKit/chromium: Can't horizontally scroll iframes and overflow because wheel events are always accepted
https://bugs.webkit.org/show_bug.cgi?id=60779

Reviewed by Simon Fraser.

* src/ChromeClientImpl.h:
(WebKit::ChromeClientImpl::shouldRubberBandInDirection): Default impl of new ChromeClient method
(WebKit::ChromeClientImpl::numWheelEventHandlersChanged): Default impl of new ChromeClient method

Source/WebKit/efl: Can't horizontally scroll iframes and overflow because wheel events are always accepted
https://bugs.webkit.org/show_bug.cgi?id=60779

Reviewed by Simon Fraser.

* WebCoreSupport/ChromeClientEfl.h:
(WebCore::ChromeClientEfl::shouldRubberBandInDirection): Default impl of new ChromeClient method
(WebCore::ChromeClientEfl::numWheelEventHandlersChanged): Default impl of new ChromeClient method

Source/WebKit/gtk: Can't horizontally scroll iframes and overflow because wheel events are always accepted
https://bugs.webkit.org/show_bug.cgi?id=60779

Reviewed by Simon Fraser.

* WebCoreSupport/ChromeClientGtk.h:
(WebKit::ChromeClient::shouldRubberBandInDirection): Default impl of new ChromeClient method
(WebKit::ChromeClient::numWheelEventHandlersChanged): Default impl of new ChromeClient method

Source/WebKit/haiku: Can't horizontally scroll iframes and overflow because wheel events are always accepted
https://bugs.webkit.org/show_bug.cgi?id=60779

Reviewed by Simon Fraser.

* WebCoreSupport/ChromeClientHaiku.h:
(WebCore::ChromeClientHaiku::shouldRubberBandInDirection): Default impl of new ChromeClient method
(WebCore::ChromeClientHaiku::numWheelEventHandlersChanged): Default impl of new ChromeClient method

Source/WebKit/mac: Can't horizontally scroll iframes and overflow because wheel events are always accepted
https://bugs.webkit.org/show_bug.cgi?id=60779

Reviewed by Simon Fraser.

* WebCoreSupport/WebChromeClient.h:
(WebChromeClient::numWheelEventHandlersChanged): Default impl of new ChromeClient method
(WebChromeClient::shouldRubberBandInDirection): Default impl of new ChromeClient method

Source/WebKit/qt: Can't horizontally scroll iframes and overflow because wheel events are always accepted
https://bugs.webkit.org/show_bug.cgi?id=60779

Reviewed by Simon Fraser.

* WebCoreSupport/ChromeClientQt.h:
(WebCore::ChromeClientQt::shouldRubberBandInDirection): Default impl of new ChromeClient method
(WebCore::ChromeClientQt::numWheelEventHandlersChanged): Default impl of new ChromeClient method

Source/WebKit/win: Can't horizontally scroll iframes and overflow because wheel events are always accepted
https://bugs.webkit.org/show_bug.cgi?id=60779

Reviewed by Simon Fraser.

* WebCoreSupport/WebChromeClient.h:
(WebChromeClient::shouldRubberBandInDirection): Default impl of new ChromeClient method
(WebChromeClient::numWheelEventHandlersChanged): Default impl of new ChromeClient method

Source/WebKit/wince: Can't horizontally scroll iframes and overflow because wheel events are always accepted
https://bugs.webkit.org/show_bug.cgi?id=60779

Reviewed by Simon Fraser.

* WebCoreSupport/ChromeClientWinCE.h:
(WebKit::ChromeClientWinCE::shouldRubberBandInDirection): Default impl of new ChromeClient method
(WebKit::ChromeClientWinCE::numWheelEventHandlersChanged): Default impl of new ChromeClient method

Source/WebKit/wx: Can't horizontally scroll iframes and overflow because wheel events are always accepted
https://bugs.webkit.org/show_bug.cgi?id=60779

Reviewed by Simon Fraser.

* WebKitSupport/ChromeClientWx.h:
(WebCore::ChromeClientWx::shouldRubberBandInDirection): Default impl of new ChromeClient method
(WebCore::ChromeClientWx::numWheelEventHandlersChanged): Default impl of new ChromeClient method

Source/WebKit2: Can't horizontally scroll iframes and overflow because wheel events are always accepted
https://bugs.webkit.org/show_bug.cgi?id=60779

Reviewed by Simon Fraser.

We keep track of the number of horizontal scrollbars and mouse wheel event handlers in the
UI process as a means of determining whether horizontal scroll events will be handled
by the web process.

* UIProcess/WebPageProxy.cpp:
(WebKit::WebPageProxy::willHandleHorizontalScrollEvents): Return true if there is at least
one wheel event handler
* UIProcess/WebPageProxy.h: Add new variable to cache the count
(WebKit::WebPageProxy::numWheelEventHandlersChanged): Sets the count

The rest just provides all the connections.
* UIProcess/API/C/WKPage.cpp:
(WKPageWillHandleHorizontalScrollEvents):
* UIProcess/API/C/WKPage.h:
* UIProcess/WebPageProxy.messages.in:
* WebProcess/InjectedBundle/API/c/WKBundlePage.h:
* WebProcess/InjectedBundle/InjectedBundlePageUIClient.cpp:
(WebKit::InjectedBundlePageUIClient::shouldRubberBandInDirection):
* WebProcess/InjectedBundle/InjectedBundlePageUIClient.h:
* WebProcess/WebCoreSupport/WebChromeClient.cpp:
(WebKit::WebChromeClient::shouldRubberBandInDirection): Forward to injected bundle UI client
(WebKit::WebChromeClient::updateCountWheelEventHandlers): Updates the web page proxy
* WebProcess/WebCoreSupport/WebChromeClient.h:

Tools: Can't horizontally scroll iframes and overflow because wheel events are always accepted
https://bugs.webkit.org/show_bug.cgi?id=60779

Reviewed by Simon Fraser.

* WebKitTestRunner/InjectedBundle/InjectedBundlePage.cpp:
(WTR::InjectedBundlePage::InjectedBundlePage): Set new default method to nil.

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

47 files changed:
Source/WebCore/ChangeLog
Source/WebCore/dom/Document.cpp
Source/WebCore/dom/Document.h
Source/WebCore/dom/Node.cpp
Source/WebCore/loader/EmptyClients.h
Source/WebCore/page/ChromeClient.h
Source/WebCore/page/EventHandler.cpp
Source/WebCore/page/Frame.cpp
Source/WebCore/page/Frame.h
Source/WebCore/page/FrameView.cpp
Source/WebCore/page/FrameView.h
Source/WebCore/platform/ScrollableArea.h
Source/WebCore/platform/mac/ScrollAnimatorMac.h
Source/WebCore/platform/mac/ScrollAnimatorMac.mm
Source/WebCore/rendering/RenderLayer.cpp
Source/WebCore/rendering/RenderLayer.h
Source/WebKit/chromium/ChangeLog
Source/WebKit/chromium/src/ChromeClientImpl.h
Source/WebKit/efl/ChangeLog
Source/WebKit/efl/WebCoreSupport/ChromeClientEfl.h
Source/WebKit/gtk/ChangeLog
Source/WebKit/gtk/WebCoreSupport/ChromeClientGtk.h
Source/WebKit/haiku/ChangeLog
Source/WebKit/haiku/WebCoreSupport/ChromeClientHaiku.h
Source/WebKit/mac/ChangeLog
Source/WebKit/mac/WebCoreSupport/WebChromeClient.h
Source/WebKit/qt/ChangeLog
Source/WebKit/qt/WebCoreSupport/ChromeClientQt.h
Source/WebKit/win/ChangeLog
Source/WebKit/win/WebCoreSupport/WebChromeClient.h
Source/WebKit/wince/ChangeLog
Source/WebKit/wince/WebCoreSupport/ChromeClientWinCE.h
Source/WebKit/wx/ChangeLog
Source/WebKit/wx/WebKitSupport/ChromeClientWx.h
Source/WebKit2/ChangeLog
Source/WebKit2/UIProcess/API/C/WKPage.cpp
Source/WebKit2/UIProcess/API/C/WKPage.h
Source/WebKit2/UIProcess/WebPageProxy.cpp
Source/WebKit2/UIProcess/WebPageProxy.h
Source/WebKit2/UIProcess/WebPageProxy.messages.in
Source/WebKit2/WebProcess/InjectedBundle/API/c/WKBundlePage.h
Source/WebKit2/WebProcess/InjectedBundle/InjectedBundlePageUIClient.cpp
Source/WebKit2/WebProcess/InjectedBundle/InjectedBundlePageUIClient.h
Source/WebKit2/WebProcess/WebCoreSupport/WebChromeClient.cpp
Source/WebKit2/WebProcess/WebCoreSupport/WebChromeClient.h
Tools/ChangeLog
Tools/WebKitTestRunner/InjectedBundle/InjectedBundlePage.cpp

index 733297e26f1eabfb5924bb5a338dfa955660faec..b00c5a4786d5b26d64a6a04ed22ab0081fe0ee36 100644 (file)
@@ -1,3 +1,70 @@
+2011-05-16  Jon Lee  <jonlee@apple.com>
+
+       Reviewed by Simon Fraser.
+
+       Can't horizontally scroll iframes and overflow because wheel events are always accepted
+       https://bugs.webkit.org/show_bug.cgi?id=60779
+
+       * dom/Document.cpp:
+       (WebCore::Document::Document): Initialize wheel event handler count
+       (WebCore::Document::didAddWheelEventHandler): Increment count, and tell the main frame
+       to recalculate the total number of wheel event handlers in all of its frames' documents
+       (WebCore::Document::didRemoveWheelEventHandler): Reverse of previous method
+       * dom/Document.h:
+       (WebCore::Document::wheelEventHandlerCount): Access the count
+       * dom/Node.cpp:
+       (WebCore::tryAddEventListener): If the event listener is a mouse wheel event, then
+       tell the document to increment its count
+       (WebCore::tryRemoveEventListener): Reverse of previous method
+
+       * page/ChromeClient.h: Two new methods:
+         numWheelEventHandlersChanged: WebProcess tells UIProcess to update its cached
+           count of total wheel event handlers, which in this case only include horizontal
+           scrollbars and mouse wheel JS handlers
+         shouldRubberBandInDirection: allow the UIProcess to provide some control over
+           whether rubber banding is allowed when scrolling in a particular direction
+       * loader/EmptyClients.h:
+       (WebCore::EmptyChromeClient::numWheelEventHandlersChanged): Default empty impl
+       (WebCore::EmptyChromeClient::shouldRubberBandInDirection): Default empty impl
+       * page/EventHandler.cpp:
+       (WebCore::EventHandler::handleWheelEvent): Remove a redundant pointer check
+       * page/Frame.cpp:
+       (WebCore::Frame::setDocument): When the frame's document changes, calculate that
+       document's total wheel event handlers, and notify the UIProcess
+       (WebCore::Frame::notifyChromeClientWheelEventHandlerCountChanged): Performs a crawl
+       of the frame tree to aggregate the count
+       * page/Frame.h:
+
+       * platform/ScrollableArea.h: Virtualize didAddHorizontalScrollbar and
+       willRemoveHorizontalScrollbar for overriding in RenderLayer and FrameView
+       (WebCore::ScrollableArea::isHorizontalScrollerPinnedToMinimumPosition): Returns true if there is
+       no scrollbar or the scroller position is in the minimum scroll position.
+       (WebCore::ScrollableArea::isHorizontalScrollerPinnedToMaximumPosition): Converse of the above.
+       (WebCore::ScrollableArea::shouldRubberBandInDirection): Default impl
+       * page/FrameView.cpp:
+       (WebCore::FrameView::didAddHorizontalScrollbar): Updates the frame's document's count
+       (WebCore::FrameView::willRemoveHorizontalScrollbar): Updates the frame's document's
+       count
+       (WebCore::FrameView::shouldRubberBandInDirection): Connective glue
+       * page/FrameView.h: Adding overriding methods from ScrollableArea
+       * rendering/RenderLayer.cpp: Similar functionality to FrameView
+       (WebCore::RenderLayer::didAddHorizontalScrollbar):
+       (WebCore::RenderLayer::willRemoveHorizontalScrollbar):
+       * rendering/RenderLayer.h:
+       
+       * platform/mac/ScrollAnimatorMac.h: Fix typo of "momentum"
+       * platform/mac/ScrollAnimatorMac.mm:
+       (WebCore::ScrollAnimatorMac::ScrollAnimatorMac): Fix typo of "momentum"
+       (WebCore::ScrollAnimatorMac::smoothScrollWithEvent): Fix typo of "coalesced"
+       (WebCore::ScrollAnimatorMac::beginScrollGesture): Fix typo of "coalesced"
+       (WebCore::ScrollAnimatorMac::snapRubberBand): Fix typo of "momentum"
+       
+       (WebCore::ScrollAnimatorMac::handleWheelEvent): New logic for determining whether
+       to allow rubber-banding based on the area's scroll position and the wheel event.
+       Could prevent accepting the wheel event. Also, fix typo of "momentum"
+       (WebCore::isScrollingLeftAndShouldNotRubberBand): Inline helper function for logic
+       (WebCore::isScrollingRightAndShouldNotRubberBand): Inline helper function for logic
+
 2011-05-16  Leandro Gracia Gil  <leandrogracia@chromium.org>
 
         Reviewed by Tony Gentilcore.
index 7a41c9938dbfad394559c8a9f3a564b9b5ae25de..878eda3c2d672449d3f4f96597d2fca19605f44c 100644 (file)
@@ -422,6 +422,7 @@ Document::Document(Frame* frame, const KURL& url, bool isXHTML, bool isHTML)
     , m_writingModeSetOnDocumentElement(false)
     , m_writeRecursionIsTooDeep(false)
     , m_writeRecursionDepth(0)
+    , m_wheelEventHandlerCount(0)
 {
     m_document = this;
 
@@ -5079,4 +5080,21 @@ PassRefPtr<TouchList> Document::createTouchList(ExceptionCode&) const
 }
 #endif
 
+void Document::didAddWheelEventHandler()
+{
+    ++m_wheelEventHandlerCount;
+    Frame* mainFrame = page() ? page()->mainFrame() : 0;
+    if (mainFrame)
+        mainFrame->notifyChromeClientWheelEventHandlerCountChanged();
+}
+
+void Document::didRemoveWheelEventHandler()
+{
+    ASSERT(m_wheelEventHandlerCount > 0);
+    --m_wheelEventHandlerCount;
+    Frame* mainFrame = page() ? page()->mainFrame() : 0;
+    if (mainFrame)
+        mainFrame->notifyChromeClientWheelEventHandlerCountChanged();
+}
+
 } // namespace WebCore
index 302e02ff802d3136861b07b2693249555e78fee4..4b8683585a70ecc52b86766a88c2233e3a897c44 100644 (file)
@@ -1100,6 +1100,11 @@ public:
 
     ContentSecurityPolicy* contentSecurityPolicy() { return m_contentSecurityPolicy.get(); }
 
+    // Used to keep track of horizontal scrollbars and onmousewheel event handlers only.
+    unsigned wheelEventHandlerCount() const { return m_wheelEventHandlerCount; }
+    void didAddWheelEventHandler();
+    void didRemoveWheelEventHandler();
+    
 protected:
     Document(Frame*, const KURL&, bool isXHTML, bool isHTML);
 
@@ -1397,6 +1402,8 @@ private:
     RefPtr<MediaQueryMatcher> m_mediaQueryMatcher;
     bool m_writeRecursionIsTooDeep;
     unsigned m_writeRecursionDepth;
+    
+    unsigned m_wheelEventHandlerCount;
 
 #if ENABLE(REQUEST_ANIMATION_FRAME)
     OwnPtr<ScriptedAnimationController> m_scriptedAnimationController;
index 2a3f97c691415a70b6bf735d8a783d55fbc6b141..d717c85254254d7f83003860fe3831c278a49afa 100644 (file)
@@ -28,6 +28,8 @@
 #include "AXObjectCache.h"
 #include "Attr.h"
 #include "Attribute.h"
+#include "Chrome.h"
+#include "ChromeClient.h"
 #include "CSSParser.h"
 #include "CSSRule.h"
 #include "CSSRuleList.h"
@@ -2668,9 +2670,12 @@ static inline bool tryAddEventListener(Node* targetNode, const AtomicString& eve
     if (!targetNode->EventTarget::addEventListener(eventType, listener, useCapture))
         return false;
 
-    if (Document* document = targetNode->document())
+    if (Document* document = targetNode->document()) {
         document->addListenerTypeIfNeeded(eventType);
-
+        if (eventType == eventNames().mousewheelEvent)
+            document->didAddWheelEventHandler();
+    }
+        
     return true;
 }
 
@@ -2715,7 +2720,11 @@ static inline bool tryRemoveEventListener(Node* targetNode, const AtomicString&
 
     // FIXME: Notify Document that the listener has vanished. We need to keep track of a number of
     // listeners for each type, not just a bool - see https://bugs.webkit.org/show_bug.cgi?id=33861
-
+    if (Document* document = targetNode->document()) {
+        if (eventType == eventNames().mousewheelEvent)
+            document->didRemoveWheelEventHandler();
+    }
+    
     return true;
 }
 
index aa2fc9cd5455deca4301cf58ffd62231f475e996..f3204ddce85cb2ec29f575d1e4c6749740e7e7fa 100644 (file)
@@ -223,6 +223,10 @@ public:
 #if ENABLE(TOUCH_EVENTS)
     virtual void needTouchEvents(bool) { }
 #endif
+    
+    virtual void numWheelEventHandlersChanged(unsigned) { }
+    
+    virtual bool shouldRubberBandInDirection(WebCore::ScrollDirection) const { return false; }
 };
 
 class EmptyFrameLoaderClient : public FrameLoaderClient {
index 8941845a774867284f2ac639639bac325d6e182b..9a0fdebeb8d0b979602e18717580c5a6d814d624 100644 (file)
@@ -170,6 +170,7 @@ namespace WebCore {
         virtual void setToolTip(const String&, TextDirection) = 0;
 
         virtual void print(Frame*) = 0;
+        virtual bool shouldRubberBandInDirection(ScrollDirection) const = 0;
 
 #if ENABLE(DATABASE)
         virtual void exceededDatabaseQuota(Frame*, const String& databaseName) = 0;
@@ -320,6 +321,8 @@ namespace WebCore {
         };
         virtual void willRunModalDialogDuringPageDismissal(const DialogType&) const { }
 
+        virtual void numWheelEventHandlersChanged(unsigned) = 0;
+        
     protected:
         virtual ~ChromeClient() { }
     };
index d415ee06df3255c906e7b5e3365347d86fc3dd01..146222acd47ab0fd16f39329c800d9f298afe91b 100644 (file)
@@ -2136,10 +2136,11 @@ bool EventHandler::handleWheelEvent(PlatformWheelEvent& e)
     if (e.isAccepted())
         return true;
 
+    // We do another check on the frame view because the event handler can run JS which results in the frame getting destroyed.
     view = m_frame->view();
     if (!view)
         return false;
-
+    
     view->wheelEvent(e);
     return e.isAccepted();
 }
index fcc5d5e82358ed47e37828e84433bb894e64adb8..d5b79f0900c1e62cdd8992c446e47fdf9dc83426 100644 (file)
@@ -307,8 +307,11 @@ void Frame::setDocument(PassRefPtr<Document> newDoc)
     // Update the cached 'document' property, which is now stale.
     m_script.updateDocument();
 
-    if (m_page)
+    if (m_page) {
         m_page->updateViewportArguments();
+        if (m_page->mainFrame() == this)
+            notifyChromeClientWheelEventHandlerCountChanged();
+    }
 }
 
 #if ENABLE(ORIENTATION_EVENTS)
@@ -1114,4 +1117,18 @@ void Frame::scalePage(float scale, const IntPoint& origin)
     }
 }
 
+void Frame::notifyChromeClientWheelEventHandlerCountChanged() const
+{
+    // Ensure that this method is being called on the main frame of the page.
+    ASSERT(m_page && m_page->mainFrame() == this);
+    
+    unsigned count = 0;
+    for (const Frame* frame = this; frame; frame = frame->tree()->traverseNext()) {
+        if (frame->document())
+            count += frame->document()->wheelEventHandlerCount();
+    }
+    
+    m_page->chrome()->client()->numWheelEventHandlersChanged(count);
+}
+
 } // namespace WebCore
index dec22d74ab1f5b28dfd70df8b248c1edd0b10aeb..44fe46ee668a0cf182149b9ee04d647109c14698 100644 (file)
@@ -206,6 +206,9 @@ namespace WebCore {
 #if ENABLE(MEDIA_STREAM)
         MediaStreamFrameController* mediaStreamFrameController() const { return m_mediaStreamFrameController.get(); }
 #endif
+        
+        // Should only be called on the main frame of a page.
+        void notifyChromeClientWheelEventHandlerCountChanged() const;
 
     // ========
 
index c4cbaebeec5e178cf49e28c1acdb59bbb63fbdfa..30885b6a5af9a2fca06404047e4a1de72d73274a 100644 (file)
@@ -28,6 +28,7 @@
 #include "FrameView.h"
 
 #include "AXObjectCache.h"
+#include "BackForwardController.h"
 #include "CSSStyleSelector.h"
 #include "CachedResourceLoader.h"
 #include "Chrome.h"
@@ -306,6 +307,21 @@ void FrameView::detachCustomScrollbars()
     }
 }
 
+void FrameView::didAddHorizontalScrollbar(Scrollbar* scrollbar)
+{
+    if (m_frame->document())
+        m_frame->document()->didAddWheelEventHandler();
+    ScrollView::didAddHorizontalScrollbar(scrollbar);
+}
+
+void FrameView::willRemoveHorizontalScrollbar(Scrollbar* scrollbar)
+{
+    ScrollView::willRemoveHorizontalScrollbar(scrollbar);
+    // FIXME: maybe need a separate ScrollableArea::didRemoveHorizontalScrollbar callback?
+    if (m_frame->document())
+        m_frame->document()->didRemoveWheelEventHandler();
+}
+
 ScrollbarOverlayStyle FrameView::recommendedScrollbarOverlayStyle() const
 {
     Color bgColor = m_frame->getDocumentBackgroundColor();
@@ -1490,6 +1506,14 @@ void FrameView::repaintFixedElementsAfterScrolling()
     }
 }
 
+bool FrameView::shouldRubberBandInDirection(ScrollDirection direction) const
+{
+    Page* page = frame() ? frame()->page() : 0;
+    if (!page)
+        return ScrollView::shouldRubberBandInDirection(direction);
+    return page->chrome()->client()->shouldRubberBandInDirection(direction);
+}
+
 HostWindow* FrameView::hostWindow() const
 {
     Page* page = frame() ? frame()->page() : 0;
index 49a6d9a57a2760e92b0273999116d472fce5783e..5b73950b5d6176ad7e12f5feea128162cfff6ba3 100644 (file)
@@ -82,6 +82,8 @@ public:
     virtual PassRefPtr<Scrollbar> createScrollbar(ScrollbarOrientation);
 
     virtual bool avoidScrollbarCreation() const;
+    virtual void didAddHorizontalScrollbar(Scrollbar*);
+    virtual void willRemoveHorizontalScrollbar(Scrollbar*);
 
     virtual void setContentsSize(const IntSize&);
 
@@ -160,6 +162,7 @@ public:
     void setScrollPosition(const IntPoint&);
     void scrollPositionChangedViaPlatformWidget();
     virtual void repaintFixedElementsAfterScrolling();
+    virtual bool shouldRubberBandInDirection(ScrollDirection) const;
 
     String mediaType() const;
     void setMediaType(const String&);
index 4bbed3e5acd574686243c156e0c9270fab861265..7b0f5ba06eaa233bee3d708ab245345d6e313a00 100644 (file)
@@ -73,8 +73,8 @@ public:
 
     void didAddVerticalScrollbar(Scrollbar*);
     void willRemoveVerticalScrollbar(Scrollbar*);
-    void didAddHorizontalScrollbar(Scrollbar*);
-    void willRemoveHorizontalScrollbar(Scrollbar*);
+    virtual void didAddHorizontalScrollbar(Scrollbar*);
+    virtual void willRemoveHorizontalScrollbar(Scrollbar*);
 
     bool hasOverlayScrollbars() const;
     virtual ScrollbarOverlayStyle recommendedScrollbarOverlayStyle() const { return ScrollbarOverlayStyleDefault; }
@@ -131,6 +131,11 @@ public:
     virtual bool shouldSuspendScrollAnimations() const { return true; }
     virtual void scrollbarStyleChanged() { }
     virtual void setVisibleScrollerThumbRect(const IntRect&) { }
+    
+    bool isHorizontalScrollerPinnedToMinimumPosition() const { return !horizontalScrollbar() || scrollPosition(horizontalScrollbar()) <= minimumScrollPosition().x(); }
+    bool isHorizontalScrollerPinnedToMaximumPosition() const { return !horizontalScrollbar() || scrollPosition(horizontalScrollbar()) >= maximumScrollPosition().x(); }
+    
+    virtual bool shouldRubberBandInDirection(ScrollDirection) const { return true; }
 
     virtual void disconnectFromPage() { }
 
index bfef95bc3b8f6c520a0a899159fcb43054616972..ff05e25ca6ef6f1735893f237debb773df12dff7 100644 (file)
@@ -144,8 +144,12 @@ private:
     bool m_inScrollGesture;
     bool m_momentumScrollInProgress;
     bool m_ignoreMomentumScrolls;
+    bool m_scrollerInitiallyPinnedOnLeft;
+    bool m_scrollerInitiallyPinnedOnRight;
+    int m_cumulativeHorizontalScroll;
+    bool m_didCumulativeHorizontalScrollEverSwitchToOppositeDirectionOfPin;
     
-    CFTimeInterval m_lastMomemtumScrollTimestamp;
+    CFTimeInterval m_lastMomentumScrollTimestamp;
     FloatSize m_overflowScrollDelta;
     FloatSize m_stretchScrollForce;
     FloatSize m_momentumVelocity;
index 99383da3da965c6f267d2eef963be9ff102cd2c9..605baf7f89488655759e73b8dd75dd2c14228f6c 100644 (file)
@@ -459,7 +459,7 @@ ScrollAnimatorMac::ScrollAnimatorMac(ScrollableArea* scrollableArea)
     , m_inScrollGesture(false)
     , m_momentumScrollInProgress(false)
     , m_ignoreMomentumScrolls(false)
-    , m_lastMomemtumScrollTimestamp(0)
+    , m_lastMomentumScrollTimestamp(0)
     , m_startTime(0)
     , m_snapRubberBandTimer(this, &ScrollAnimatorMac::snapRubberBandTimerFired)
 #endif
@@ -764,6 +764,16 @@ static float scrollWheelMultiplier()
     return multiplier;
 }
 
+static inline bool isScrollingLeftAndShouldNotRubberBand(PlatformWheelEvent& wheelEvent, ScrollableArea* scrollableArea)
+{
+    return wheelEvent.deltaX() > 0 && !scrollableArea->shouldRubberBandInDirection(ScrollLeft);
+}
+
+static inline bool isScrollingRightAndShouldNotRubberBand(PlatformWheelEvent& wheelEvent, ScrollableArea* scrollableArea)
+{
+    return wheelEvent.deltaX() < 0 && !scrollableArea->shouldRubberBandInDirection(ScrollRight);
+}
+
 void ScrollAnimatorMac::handleWheelEvent(PlatformWheelEvent& wheelEvent)
 {
     m_haveScrolledSincePageLoad = true;
@@ -787,17 +797,47 @@ void ScrollAnimatorMac::handleWheelEvent(PlatformWheelEvent& wheelEvent)
             ScrollAnimator::handleWheelEvent(wheelEvent);
             return;
         }
-    }
+        
+        if (m_scrollableArea->horizontalScrollbar()) {
+            // If there is a scrollbar, we aggregate the wheel events to get an
+            // overall trend of the scroll. If the direction of the scroll is ever
+            // in the opposite direction of the pin location, then we switch the
+            // boolean, and rubber band. That is, if we were pinned to the left,
+            // and we ended up scrolling to the right, we rubber band.
+            m_cumulativeHorizontalScroll += wheelEvent.deltaX();
+            if (m_scrollerInitiallyPinnedOnLeft && m_cumulativeHorizontalScroll < 0)
+                m_didCumulativeHorizontalScrollEverSwitchToOppositeDirectionOfPin = true;
+            if (m_scrollerInitiallyPinnedOnRight && m_cumulativeHorizontalScroll > 0)
+                m_didCumulativeHorizontalScrollEverSwitchToOppositeDirectionOfPin = true;
+        }
 
-    wheelEvent.accept();
+        // After a gesture begins, we go through:
+        // 1+ PlatformWheelEventPhaseNone
+        // 0+ PlatformWheelEventPhaseChanged
+        // 1 PlatformWheelEventPhaseEnded if there was at least one changed event
+        if (wheelEvent.momentumPhase() == PlatformWheelEventPhaseNone && !m_didCumulativeHorizontalScrollEverSwitchToOppositeDirectionOfPin) {
+            if ((isScrollingLeftAndShouldNotRubberBand(wheelEvent, m_scrollableArea) &&
+                m_scrollerInitiallyPinnedOnLeft &&
+                m_scrollableArea->isHorizontalScrollerPinnedToMinimumPosition()) ||
+                (isScrollingRightAndShouldNotRubberBand(wheelEvent, m_scrollableArea) &&
+                m_scrollerInitiallyPinnedOnRight &&
+                m_scrollableArea->isHorizontalScrollerPinnedToMaximumPosition())) {
+                ScrollAnimator::handleWheelEvent(wheelEvent);
+                return;
+            }
+        }
+    }
 
-    bool isMometumScrollEvent = (wheelEvent.momentumPhase() != PlatformWheelEventPhaseNone);
-    if (m_ignoreMomentumScrolls && (isMometumScrollEvent || m_snapRubberBandTimer.isActive())) {
-        if (wheelEvent.momentumPhase() == PlatformWheelEventPhaseEnded)
+    bool isMomentumScrollEvent = (wheelEvent.momentumPhase() != PlatformWheelEventPhaseNone);
+    if (m_ignoreMomentumScrolls && (isMomentumScrollEvent || m_snapRubberBandTimer.isActive())) {
+        if (wheelEvent.momentumPhase() == PlatformWheelEventPhaseEnded) {
             m_ignoreMomentumScrolls = false;
+            wheelEvent.accept();
+        }
         return;
     }
 
+    wheelEvent.accept();
     smoothScrollWithEvent(wheelEvent);
 }
 
@@ -881,11 +921,11 @@ void ScrollAnimatorMac::smoothScrollWithEvent(PlatformWheelEvent& wheelEvent)
     // Reset overflow values because we may decide to remove delta at various points and put it into overflow.
     m_overflowScrollDelta = FloatSize();
 
-    float eventCoallescedDeltaX = -wheelEvent.deltaX();
-    float eventCoallescedDeltaY = -wheelEvent.deltaY();
+    float eventCoalescedDeltaX = -wheelEvent.deltaX();
+    float eventCoalescedDeltaY = -wheelEvent.deltaY();
 
-    deltaX += eventCoallescedDeltaX;
-    deltaY += eventCoallescedDeltaY;
+    deltaX += eventCoalescedDeltaX;
+    deltaY += eventCoalescedDeltaY;
 
     // Slightly prefer scrolling vertically by applying the = case to deltaY
     if (fabsf(deltaY) >= fabsf(deltaX))
@@ -908,14 +948,14 @@ void ScrollAnimatorMac::smoothScrollWithEvent(PlatformWheelEvent& wheelEvent)
     if (!m_momentumScrollInProgress && (phase == PlatformWheelEventPhaseBegan || phase == PlatformWheelEventPhaseChanged))
         m_momentumScrollInProgress = true;
 
-    CFTimeInterval timeDelta = wheelEvent.timestamp() - m_lastMomemtumScrollTimestamp;
+    CFTimeInterval timeDelta = wheelEvent.timestamp() - m_lastMomentumScrollTimestamp;
     if (m_inScrollGesture || m_momentumScrollInProgress) {
-        if (m_lastMomemtumScrollTimestamp && timeDelta > 0 && timeDelta < scrollVelocityZeroingTimeout) {
-            m_momentumVelocity.setWidth(eventCoallescedDeltaX / (float)timeDelta);
-            m_momentumVelocity.setHeight(eventCoallescedDeltaY / (float)timeDelta);
-            m_lastMomemtumScrollTimestamp = wheelEvent.timestamp();
+        if (m_lastMomentumScrollTimestamp && timeDelta > 0 && timeDelta < scrollVelocityZeroingTimeout) {
+            m_momentumVelocity.setWidth(eventCoalescedDeltaX / (float)timeDelta);
+            m_momentumVelocity.setHeight(eventCoalescedDeltaY / (float)timeDelta);
+            m_lastMomentumScrollTimestamp = wheelEvent.timestamp();
         } else {
-            m_lastMomemtumScrollTimestamp = wheelEvent.timestamp();
+            m_lastMomentumScrollTimestamp = wheelEvent.timestamp();
             m_momentumVelocity = FloatSize();
         }
 
@@ -969,7 +1009,7 @@ void ScrollAnimatorMac::smoothScrollWithEvent(PlatformWheelEvent& wheelEvent)
         } else {
             if (!allowsHorizontalStretching()) {
                 deltaX = 0;
-                eventCoallescedDeltaX = 0;
+                eventCoalescedDeltaX = 0;
             } else if ((deltaX != 0) && !isHorizontallyStretched && !pinnedInDirection(deltaX, 0)) {
                 deltaX *= scrollWheelMultiplier();
 
@@ -982,7 +1022,7 @@ void ScrollAnimatorMac::smoothScrollWithEvent(PlatformWheelEvent& wheelEvent)
             
             if (!allowsVerticalStretching()) {
                 deltaY = 0;
-                eventCoallescedDeltaY = 0;
+                eventCoalescedDeltaY = 0;
             } else if ((deltaY != 0) && !isVerticallyStretched && !pinnedInDirection(0, deltaY)) {
                 deltaY *= scrollWheelMultiplier();
 
@@ -996,7 +1036,7 @@ void ScrollAnimatorMac::smoothScrollWithEvent(PlatformWheelEvent& wheelEvent)
             IntSize stretchAmount = m_scrollableArea->overhangAmount();
         
             if (m_momentumScrollInProgress) {
-                if ((pinnedInDirection(eventCoallescedDeltaX, eventCoallescedDeltaY) || (fabsf(eventCoallescedDeltaX) + fabsf(eventCoallescedDeltaY) <= 0)) && m_lastMomemtumScrollTimestamp) {
+                if ((pinnedInDirection(eventCoalescedDeltaX, eventCoalescedDeltaY) || (fabsf(eventCoalescedDeltaX) + fabsf(eventCoalescedDeltaY) <= 0)) && m_lastMomentumScrollTimestamp) {
                     m_ignoreMomentumScrolls = true;
                     m_momentumScrollInProgress = false;
                     snapRubberBand();
@@ -1021,7 +1061,7 @@ void ScrollAnimatorMac::smoothScrollWithEvent(PlatformWheelEvent& wheelEvent)
     if (m_momentumScrollInProgress && phase == PlatformWheelEventPhaseEnded) {
         m_momentumScrollInProgress = false;
         m_ignoreMomentumScrolls = false;
-        m_lastMomemtumScrollTimestamp = 0;
+        m_lastMomentumScrollTimestamp = 0;
     }
 }
 
@@ -1033,9 +1073,13 @@ void ScrollAnimatorMac::beginScrollGesture()
     m_inScrollGesture = true;
     m_momentumScrollInProgress = false;
     m_ignoreMomentumScrolls = false;
-    m_lastMomemtumScrollTimestamp = 0;
+    m_lastMomentumScrollTimestamp = 0;
     m_momentumVelocity = FloatSize();
-
+    m_scrollerInitiallyPinnedOnLeft = m_scrollableArea->isHorizontalScrollerPinnedToMinimumPosition();
+    m_scrollerInitiallyPinnedOnRight = m_scrollableArea->isHorizontalScrollerPinnedToMaximumPosition();
+    m_cumulativeHorizontalScroll = 0;
+    m_didCumulativeHorizontalScrollEverSwitchToOppositeDirectionOfPin = false;
+    
     IntSize stretchAmount = m_scrollableArea->overhangAmount();
     m_stretchScrollForce.setWidth(reboundDeltaForElasticDelta(stretchAmount.width()));
     m_stretchScrollForce.setHeight(reboundDeltaForElasticDelta(stretchAmount.height()));
@@ -1055,8 +1099,8 @@ void ScrollAnimatorMac::endScrollGesture()
 
 void ScrollAnimatorMac::snapRubberBand()
 {
-    CFTimeInterval timeDelta = [[NSProcessInfo processInfo] systemUptime] - m_lastMomemtumScrollTimestamp;
-    if (m_lastMomemtumScrollTimestamp && timeDelta >= scrollVelocityZeroingTimeout)
+    CFTimeInterval timeDelta = [[NSProcessInfo processInfo] systemUptime] - m_lastMomentumScrollTimestamp;
+    if (m_lastMomentumScrollTimestamp && timeDelta >= scrollVelocityZeroingTimeout)
         m_momentumVelocity = FloatSize();
 
     m_inScrollGesture = false;
index 4515f771de5706bbfd8cb67223d14a9035ea5d12..c937604623e1900b88d9262259fb79fc42d7a326 100644 (file)
@@ -1930,6 +1930,19 @@ bool RenderLayer::scrollsOverflow() const
     return toRenderBox(renderer())->scrollsOverflow();
 }
 
+void RenderLayer::didAddHorizontalScrollbar(Scrollbar* scrollbar)
+{
+    m_renderer->document()->didAddWheelEventHandler();
+    ScrollableArea::didAddHorizontalScrollbar(scrollbar);
+}
+
+void RenderLayer::willRemoveHorizontalScrollbar(Scrollbar* scrollbar)
+{
+    ScrollableArea::willRemoveHorizontalScrollbar(scrollbar);
+    // FIXME: maybe need a separate ScrollableArea::didRemoveHorizontalScrollbar callback?
+    m_renderer->document()->didRemoveWheelEventHandler();
+}
+
 void RenderLayer::setHasHorizontalScrollbar(bool hasScrollbar)
 {
     if (hasScrollbar == (m_hBar != 0))
index 326a14dd1a8bbaef198c95894f586d0482bc04c1..78cdc2e9fbe78db61e32c6cf67eaf90707c3a3e6 100644 (file)
@@ -247,6 +247,8 @@ public:
     IntRect getRectToExpose(const IntRect& visibleRect, const IntRect& exposeRect, const ScrollAlignment& alignX, const ScrollAlignment& alignY);
 
     bool scrollsOverflow() const;
+    virtual void didAddHorizontalScrollbar(Scrollbar*);
+    virtual void willRemoveHorizontalScrollbar(Scrollbar*);
     void setHasHorizontalScrollbar(bool);
     void setHasVerticalScrollbar(bool);
 
index 4e08c19add2e9f1ad3a2daf3dea797d47eb77eb3..9b569b0ec27de48c949f22439add454857534ee0 100644 (file)
@@ -1,3 +1,14 @@
+2011-05-13  Jon Lee  <jonlee@apple.com>
+
+        Reviewed by Simon Fraser.
+
+        Can't horizontally scroll iframes and overflow because wheel events are always accepted
+        https://bugs.webkit.org/show_bug.cgi?id=60779
+
+        * src/ChromeClientImpl.h:
+        (WebKit::ChromeClientImpl::shouldRubberBandInDirection): Default impl of new ChromeClient method
+        (WebKit::ChromeClientImpl::numWheelEventHandlersChanged): Default impl of new ChromeClient method
+
 2011-05-13  Tao Bai  <michaelbai@chromium.org>
 
         Reviewed by Darin Fisher.
index 1fd545bc3b126a6ad24f1b990ac561c196208917..c206917f144234e9182c6bf746c0f87d954f3b32 100644 (file)
@@ -196,6 +196,9 @@ public:
 
     virtual void willRunModalDialogDuringPageDismissal(const DialogType&) const;
 
+    virtual bool shouldRubberBandInDirection(WebCore::ScrollDirection) const { return true; }
+    virtual void numWheelEventHandlersChanged(unsigned) { }
+
 private:
     void getPopupMenuInfo(WebCore::PopupContainer*, WebPopupMenuInfo*);
     void setCursor(const WebCursorInfo&);
index fbe5af621cc245e4803dc6cda466ee5509551c2b..4d4883281e59bbd601a5198254b3f37e033fe941 100755 (executable)
@@ -1,3 +1,14 @@
+2011-05-16  Jon Lee  <jonlee@apple.com>
+
+        Reviewed by Simon Fraser.
+
+        Can't horizontally scroll iframes and overflow because wheel events are always accepted
+        https://bugs.webkit.org/show_bug.cgi?id=60779
+
+        * WebCoreSupport/ChromeClientEfl.h:
+        (WebCore::ChromeClientEfl::shouldRubberBandInDirection): Default impl of new ChromeClient method
+        (WebCore::ChromeClientEfl::numWheelEventHandlersChanged): Default impl of new ChromeClient method
+
 2011-05-16  Grzegorz Czajkowski  <g.czajkowski@samsung.com>
 
         Reviewed by Antonio Gomes.
index aa1797491e2d062e9aaa312872b4b7b9332d4da8..e0a20b607d4522860af995d58669d3ae186bbf63 100644 (file)
@@ -152,6 +152,9 @@ public:
     virtual PassRefPtr<PopupMenu> createPopupMenu(PopupMenuClient*) const;
     virtual PassRefPtr<SearchPopupMenu> createSearchPopupMenu(PopupMenuClient*) const;
 
+    virtual bool shouldRubberBandInDirection(WebCore::ScrollDirection) const { return true; }
+    virtual void numWheelEventHandlersChanged(unsigned) { }
+
     Evas_Object* m_view;
     KURL m_hoveredLinkURL;
 };
index 5a8a7346c405a455270473d2eb8782dea1cfabfa..e0f5b8f7e5b067c853ab63fd58eac5094f55e64c 100644 (file)
@@ -1,3 +1,14 @@
+2011-05-13  Jon Lee  <jonlee@apple.com>
+
+        Reviewed by Simon Fraser.
+
+        Can't horizontally scroll iframes and overflow because wheel events are always accepted
+        https://bugs.webkit.org/show_bug.cgi?id=60779
+
+        * WebCoreSupport/ChromeClientGtk.h:
+        (WebKit::ChromeClient::shouldRubberBandInDirection): Default impl of new ChromeClient method
+        (WebKit::ChromeClient::numWheelEventHandlersChanged): Default impl of new ChromeClient method
+
 2011-05-13  Sam Weinig  <sam@webkit.org>
 
         Reviewed by Anders Carlsson.
index d420a2e35c761fc65cc83d22bcff47697ea576ca..5d5b136d18bfb5f0a8b7b9a5adbb9d8e099e6147 100644 (file)
@@ -152,6 +152,9 @@ namespace WebKit {
         virtual void exitFullScreenForElement(WebCore::Element*);
 #endif
 
+        virtual bool shouldRubberBandInDirection(WebCore::ScrollDirection) const { return true; }
+        virtual void numWheelEventHandlersChanged(unsigned) { }
+
     private:
         WebKitWebView* m_webView;
         GtkAdjustmentWatcher m_adjustmentWatcher;
index ae890be91b7e0ce6d345edcd6637304fa0deb9c3..76c717185b36b3a9aa455d5855ae8d5db0a63a7f 100644 (file)
@@ -1,3 +1,14 @@
+2011-05-13  Jon Lee  <jonlee@apple.com>
+
+        Reviewed by Simon Fraser.
+
+        Can't horizontally scroll iframes and overflow because wheel events are always accepted
+        https://bugs.webkit.org/show_bug.cgi?id=60779
+
+        * WebCoreSupport/ChromeClientHaiku.h:
+        (WebCore::ChromeClientHaiku::shouldRubberBandInDirection): Default impl of new ChromeClient method
+        (WebCore::ChromeClientHaiku::numWheelEventHandlersChanged): Default impl of new ChromeClient method
+
 2011-05-05  Ryosuke Niwa  <rniwa@webkit.org>
 
         Reviewed by Eric Seidel.
index 8a097a0467d8a7e5e6a3e48eaa417ddf962230ed..322d0b22458016197e26eab52bebb10306da5440 100644 (file)
@@ -159,6 +159,9 @@ namespace WebCore {
         // Notification that the given form element has changed. This function
         // will be called frequently, so handling should be very fast.
         virtual void formStateDidChange(const Node*);
+
+        virtual bool shouldRubberBandInDirection(WebCore::ScrollDirection) const { return true; }
+        virtual void numWheelEventHandlersChanged(unsigned) { }
     };
 
 } // namespace WebCore
index 1b13e77ee19e09d8d4912538888a0a7d79070091..129cf28ed568eb60094e7d61c605add33fa3a7d9 100644 (file)
@@ -1,3 +1,14 @@
+2011-05-13  Jon Lee  <jonlee@apple.com>
+
+        Reviewed by Simon Fraser.
+
+        Can't horizontally scroll iframes and overflow because wheel events are always accepted
+        https://bugs.webkit.org/show_bug.cgi?id=60779
+
+        * WebCoreSupport/WebChromeClient.h:
+        (WebChromeClient::numWheelEventHandlersChanged): Default impl of new ChromeClient method
+        (WebChromeClient::shouldRubberBandInDirection): Default impl of new ChromeClient method
+
 2011-05-13  Sam Weinig  <sam@webkit.org>
 
         Reviewed by Anders Carlsson.
index 0ecb9f24de3e98619060836503a34d5b888eed60..3d1b3086dc1b5100fdb3f76ac12dd7f05343d9cb 100644 (file)
@@ -182,6 +182,10 @@ public:
 #if ENABLE(CONTEXT_MENUS)
     virtual void showContextMenu();
 #endif
+    
+    virtual void numWheelEventHandlersChanged(unsigned) { }
+    
+    virtual bool shouldRubberBandInDirection(WebCore::ScrollDirection) const { return false; }
 private:
     WebView *m_webView;
 };
index 6552c36b0e32e030c63dd26e3ae1ab8796f4887e..75c8bcceeac52de46d60105ae0766fcbda5625c3 100644 (file)
@@ -1,3 +1,14 @@
+2011-05-16  Jon Lee  <jonlee@apple.com>
+
+        Reviewed by Simon Fraser.
+
+        Can't horizontally scroll iframes and overflow because wheel events are always accepted
+        https://bugs.webkit.org/show_bug.cgi?id=60779
+
+        * WebCoreSupport/ChromeClientQt.h:
+        (WebCore::ChromeClientQt::shouldRubberBandInDirection): Default impl of new ChromeClient method
+        (WebCore::ChromeClientQt::numWheelEventHandlersChanged): Default impl of new ChromeClient method
+
 2011-05-16  Andreas Kling  <kling@webkit.org>
 
         Reviewed by Kenneth Rohde Christiansen.
index 8176167dee385d5db1b848e7927323200c927649..c861ba61bea33fb47b06969669135a3f7665458b 100644 (file)
@@ -194,6 +194,9 @@ public:
 
     virtual void dispatchViewportDataDidChange(const ViewportArguments&) const;
 
+    virtual bool shouldRubberBandInDirection(WebCore::ScrollDirection) const { return true; }
+    virtual void numWheelEventHandlersChanged(unsigned) { }
+
     QWebPage* m_webPage;
     KURL lastHoverURL;
     String lastHoverTitle;
index 00efe8fd9e0e9c93b37b4539bf61200e95796a08..34427901f01e2b49dfda3851ff6d0c01e657f7f6 100644 (file)
@@ -1,3 +1,14 @@
+2011-05-13  Jon Lee  <jonlee@apple.com>
+
+        Reviewed by Simon Fraser.
+
+        Can't horizontally scroll iframes and overflow because wheel events are always accepted
+        https://bugs.webkit.org/show_bug.cgi?id=60779
+
+        * WebCoreSupport/WebChromeClient.h:
+        (WebChromeClient::shouldRubberBandInDirection): Default impl of new ChromeClient method
+        (WebChromeClient::numWheelEventHandlersChanged): Default impl of new ChromeClient method
+
 2011-05-13  Sam Weinig  <sam@webkit.org>
 
         Reviewed by Anders Carlsson.
index 4a3cf3b9005794dd2ff0c35a517342cd74ea4a48..1529e1c4c9c958c52f89dac43cc3a956a109def9 100644 (file)
@@ -182,6 +182,9 @@ public:
     virtual void exitFullScreenForElement(WebCore::Element*);
 #endif
 
+    virtual bool shouldRubberBandInDirection(WebCore::ScrollDirection) const { return true; }
+    virtual void numWheelEventHandlersChanged(unsigned) { }
+
 private:
     COMPtr<IWebUIDelegate> uiDelegate();
 
index 383389a66b00c8650a75d774276de1c59d47b4fa..f2169617e367211c4c99887ed70cb6d375a4d41a 100644 (file)
@@ -1,3 +1,14 @@
+2011-05-13  Jon Lee  <jonlee@apple.com>
+
+        Reviewed by Simon Fraser.
+
+        Can't horizontally scroll iframes and overflow because wheel events are always accepted
+        https://bugs.webkit.org/show_bug.cgi?id=60779
+
+        * WebCoreSupport/ChromeClientWinCE.h:
+        (WebKit::ChromeClientWinCE::shouldRubberBandInDirection): Default impl of new ChromeClient method
+        (WebKit::ChromeClientWinCE::numWheelEventHandlersChanged): Default impl of new ChromeClient method
+
 2011-05-05  Ryosuke Niwa  <rniwa@webkit.org>
 
         Reviewed by Eric Seidel.
index 95709ae250a8a64e2a52dc513273b79ae4f0e37b..13c9ec0a1035f8966f2f6405c99956b1eebe8e93 100644 (file)
@@ -177,6 +177,9 @@ public:
     virtual PassRefPtr<WebCore::PopupMenu> createPopupMenu(WebCore::PopupMenuClient*) const;
     virtual PassRefPtr<WebCore::SearchPopupMenu> createSearchPopupMenu(WebCore::PopupMenuClient*) const;
 
+    virtual bool shouldRubberBandInDirection(WebCore::ScrollDirection) const { return true; }
+    virtual void numWheelEventHandlersChanged(unsigned) { }
+
 private:
     WebView* m_webView;
 };
index eea6f6da49c3f27ed4bad4614ed2d6b7728ff3a3..67bc455e8e2a300da7840da90e49df0503526736 100644 (file)
@@ -1,3 +1,14 @@
+2011-05-13  Jon Lee  <jonlee@apple.com>
+
+        Reviewed by Simon Fraser.
+
+        Can't horizontally scroll iframes and overflow because wheel events are always accepted
+        https://bugs.webkit.org/show_bug.cgi?id=60779
+
+        * WebKitSupport/ChromeClientWx.h:
+        (WebCore::ChromeClientWx::shouldRubberBandInDirection): Default impl of new ChromeClient method
+        (WebCore::ChromeClientWx::numWheelEventHandlersChanged): Default impl of new ChromeClient method
+
 2011-05-09  Robin Dunn  <robin@alldunn.com>
 
         Reviewed by Kevin Ollivier.
index 0d8149c0c8256e6e4b84b501997ffad72bfa9304..820c8abe9b8987ec681c43e3682b4f74e6f4f34f 100644 (file)
@@ -152,6 +152,9 @@ public:
     virtual PassRefPtr<PopupMenu> createPopupMenu(PopupMenuClient*) const;
     virtual PassRefPtr<SearchPopupMenu> createSearchPopupMenu(PopupMenuClient*) const;
 
+    virtual bool shouldRubberBandInDirection(WebCore::ScrollDirection) const { return true; }
+    virtual void numWheelEventHandlersChanged(unsigned) { }
+
 private:
     wxWebView* m_webView;
 };
index fefe0c589efb0c48fbee24434b99541340ed4302..a8fda2f9d368e689a1c83da80b9ee167d1fbc1ff 100644 (file)
@@ -1,3 +1,34 @@
+2011-05-16  Jon Lee  <jonlee@apple.com>
+
+        Reviewed by Simon Fraser.
+
+        Can't horizontally scroll iframes and overflow because wheel events are always accepted
+        https://bugs.webkit.org/show_bug.cgi?id=60779
+
+        We keep track of the number of horizontal scrollbars and mouse wheel event handlers in the
+        UI process as a means of determining whether horizontal scroll events will be handled
+        by the web process.
+
+        * UIProcess/WebPageProxy.cpp:
+        (WebKit::WebPageProxy::willHandleHorizontalScrollEvents): Return true if there is at least
+        one wheel event handler
+        * UIProcess/WebPageProxy.h: Add new variable to cache the count
+        (WebKit::WebPageProxy::numWheelEventHandlersChanged): Sets the count
+
+        The rest just provides all the connections.
+        * UIProcess/API/C/WKPage.cpp:
+        (WKPageWillHandleHorizontalScrollEvents):
+        * UIProcess/API/C/WKPage.h:
+        * UIProcess/WebPageProxy.messages.in:
+        * WebProcess/InjectedBundle/API/c/WKBundlePage.h:
+        * WebProcess/InjectedBundle/InjectedBundlePageUIClient.cpp:
+        (WebKit::InjectedBundlePageUIClient::shouldRubberBandInDirection):
+        * WebProcess/InjectedBundle/InjectedBundlePageUIClient.h:
+        * WebProcess/WebCoreSupport/WebChromeClient.cpp:
+        (WebKit::WebChromeClient::shouldRubberBandInDirection): Forward to injected bundle UI client
+        (WebKit::WebChromeClient::updateCountWheelEventHandlers): Updates the web page proxy
+        * WebProcess/WebCoreSupport/WebChromeClient.h:
+
 2011-05-16  Anders Carlsson  <andersca@apple.com>
 
         Reviewed by Oliver Hunt.
index 941d2c7a31b33e24ca63ff519d7897858f1e6197..3c3d21350e4e324d95b9e5da6ccaea87a82b716f 100644 (file)
@@ -146,6 +146,11 @@ WKBackForwardListRef WKPageGetBackForwardList(WKPageRef pageRef)
     return toAPI(toImpl(pageRef)->backForwardList());
 }
 
+bool WKPageWillHandleHorizontalScrollEvents(WKPageRef pageRef)
+{
+    return toImpl(pageRef)->willHandleHorizontalScrollEvents();
+}
+
 WKStringRef WKPageCopyTitle(WKPageRef pageRef)
 {
     return toCopiedAPI(toImpl(pageRef)->pageTitle());
index d01c83895962a697375346ef5aeebd7d264c321a..1d434bd3c57500a062d10b4158c6179844917d79 100644 (file)
@@ -288,7 +288,8 @@ WK_EXPORT bool WKPageCanGoBack(WKPageRef page);
 WK_EXPORT void WKPageGoToBackForwardListItem(WKPageRef page, WKBackForwardListItemRef item);
 WK_EXPORT void WKPageTryRestoreScrollPosition(WKPageRef page);
 WK_EXPORT WKBackForwardListRef WKPageGetBackForwardList(WKPageRef page);
-
+WK_EXPORT bool WKPageWillHandleHorizontalScrollEvents(WKPageRef page);
+    
 WK_EXPORT WKStringRef WKPageCopyTitle(WKPageRef page);
 
 WK_EXPORT WKURLRef WKPageCopyPendingAPIRequestURL(WKPageRef page);
index 4ba04a7b3eac9c549db0d0ae728cf06e46a40064..c61582d20cd6e31c46258d0dfba6bc5791df7208 100644 (file)
@@ -3060,6 +3060,11 @@ void WebPageProxy::didFailToInitializePlugin(const String& mimeType)
     m_loaderClient.didFailToInitializePlugin(this, mimeType);
 }
 
+bool WebPageProxy::willHandleHorizontalScrollEvents() const
+{
+    return m_wheelEventHandlerCount > 0;
+}
+
 void WebPageProxy::didFinishLoadingDataForCustomRepresentation(const String& suggestedFilename, const CoreIPC::DataReference& dataReference)
 {
     m_pageClient->didFinishLoadingDataForCustomRepresentation(suggestedFilename, dataReference);
index 314970a0d2788e20d0a17dfde2e9c6869cd927c6..7316bf062ea96b3fd1279d2e959e9759844961e9 100644 (file)
@@ -226,6 +226,8 @@ public:
     void didChangeBackForwardList(WebBackForwardListItem* addedItem, Vector<RefPtr<APIObject> >* removedItems);
     void shouldGoToBackForwardListItem(uint64_t itemID, bool& shouldGoToBackForwardListItem);
 
+    bool willHandleHorizontalScrollEvents() const;
+
     bool canShowMIMEType(const String& mimeType) const;
 
     bool drawsBackground() const { return m_drawsBackground; }
@@ -611,6 +613,7 @@ private:
     void didChangeScrollbarsForMainFrame(bool hasHorizontalScrollbar, bool hasVerticalScrollbar);
     void didChangeScrollOffsetPinningForMainFrame(bool pinnedToLeftSide, bool pinnedToRightSide);
     void didFailToInitializePlugin(const String& mimeType);
+    void numWheelEventHandlersChanged(unsigned count) { m_wheelEventHandlerCount = count; }
 
     void reattachToWebProcess();
     void reattachToWebProcessWithItem(WebBackForwardListItem*);
@@ -866,6 +869,9 @@ private:
 
     bool m_mainFrameHasHorizontalScrollbar;
     bool m_mainFrameHasVerticalScrollbar;
+    // This aggregated count of wheel handlers only includes horizontal scrollbars
+    // and JS wheel event handlers.
+    int m_wheelEventHandlerCount;
 
     bool m_mainFrameIsPinnedToLeftSide;
     bool m_mainFrameIsPinnedToRightSide;
index 9a9c135949307215d3f0c81ec7c675b6e5a0e846..1cedbe7f0dd053d6e8f91e3d6cc5cbdf106e86b5 100644 (file)
@@ -62,6 +62,7 @@ messages -> WebPageProxy {
     DidChangeScrollbarsForMainFrame(bool hasHorizontalScrollbar, bool hasVerticalScrollbar)
     DidChangeScrollOffsetPinningForMainFrame(bool hasHorizontalScrollbar, bool hasVerticalScrollbar)
     DidFailToInitializePlugin(WTF::String mimeType)
+    NumWheelEventHandlersChanged(unsigned count)
 
 #if ENABLE(TILED_BACKING_STORE)
     PageDidRequestScroll(WebCore::IntPoint point)
index 6e12954a1613b9a91cf4a327639cfd9412b02ed6..097f2392d3d815d5336fc57b11b76c7e6ddaf220 100644 (file)
@@ -72,6 +72,12 @@ enum {
 };
 typedef uint32_t WKFullScreenKeyboardRequestType;
 
+enum {
+    WKScrollDirectionLeft,
+    WKScrollDirectionRight
+};
+typedef uint32_t WKScrollDirection;
+
 // Loader Client
 typedef void (*WKBundlePageDidStartProvisionalLoadForFrameCallback)(WKBundlePageRef page, WKBundleFrameRef frame, WKTypeRef* userData, const void *clientInfo);
 typedef void (*WKBundlePageDidReceiveServerRedirectForProvisionalLoadForFrameCallback)(WKBundlePageRef page, WKBundleFrameRef frame, WKTypeRef* userData, const void *clientInfo);
@@ -175,7 +181,8 @@ typedef void (*WKBundlePageMouseDidMoveOverElementCallback)(WKBundlePageRef page
 typedef void (*WKBundlePageDidScrollCallback)(WKBundlePageRef page, const void *clientInfo);
 typedef void (*WKBundlePagePaintCustomOverhangAreaCallback)(WKBundlePageRef page, WKGraphicsContextRef graphicsContext, WKRect horizontalOverhang, WKRect verticalOverhang, WKRect dirtyRect, const void* clientInfo);
 typedef WKStringRef (*WKBundlePageGenerateFileForUploadCallback)(WKBundlePageRef page, WKStringRef originalFilePath, const void* clientInfo);
-
+typedef bool (*WKBundlePageShouldRubberBandInDirectionCallback)(WKBundlePageRef page, WKScrollDirection scrollDirection, const void* clientInfo);
+    
 struct WKBundlePageUIClient {
     int                                                                 version;
     const void *                                                        clientInfo;
@@ -189,6 +196,7 @@ struct WKBundlePageUIClient {
     WKBundlePagePaintCustomOverhangAreaCallback                         paintCustomOverhangArea;
     WKBundlePageGenerateFileForUploadCallback                           shouldGenerateFileForUpload;
     WKBundlePageGenerateFileForUploadCallback                           generateFileForUpload;
+    WKBundlePageShouldRubberBandInDirectionCallback                     shouldRubberBandInDirection;
 };
 typedef struct WKBundlePageUIClient WKBundlePageUIClient;
 
index 532d0587911b813127bffa71fa27e212855474dd..48800399c31d0e7575cbafc134b8700c4c351276 100644 (file)
@@ -115,4 +115,9 @@ String InjectedBundlePageUIClient::generateFileForUpload(WebPage* page, const St
     return generatedFilePath ? generatedFilePath->string() : String();
 }
 
+bool InjectedBundlePageUIClient::shouldRubberBandInDirection(WebPage* page, WKScrollDirection direction) const
+{
+    return m_client.shouldRubberBandInDirection(toAPI(page), direction, m_client.clientInfo);
+}
+
 } // namespace WebKit
index 47a5ca852b59ceaad5f6c4409334eafc423c1d7f..fbbb90cff8a4a13608c8832edcee989c498853c7 100644 (file)
@@ -58,6 +58,8 @@ public:
 
     String shouldGenerateFileForUpload(WebPage*, const String& originalFilePath);
     String generateFileForUpload(WebPage*, const String& originalFilePath);
+    
+    bool shouldRubberBandInDirection(WebPage*, WKScrollDirection) const;
 };
 
 } // namespace WebKit
index fd5ee5590f2585f4bc8684eb2f4d6f423bb0675a..4b4eb613da02d7455f59afbd7e162fb30d42b222 100644 (file)
@@ -759,4 +759,22 @@ void WebChromeClient::notifyScrollerThumbIsVisibleInRect(const IntRect& scroller
     m_page->send(Messages::WebPageProxy::NotifyScrollerThumbIsVisibleInRect(scrollerThumb));
 }
 
+bool WebChromeClient::shouldRubberBandInDirection(WebCore::ScrollDirection direction) const
+{
+    ASSERT(direction != WebCore::ScrollUp && direction != WebCore::ScrollDown);
+    
+    if (direction == WebCore::ScrollLeft)
+        return m_page->injectedBundleUIClient().shouldRubberBandInDirection(m_page, WKScrollDirectionLeft);
+    if (direction == WebCore::ScrollRight)
+        return m_page->injectedBundleUIClient().shouldRubberBandInDirection(m_page, WKScrollDirectionRight);
+
+    ASSERT_NOT_REACHED();
+    return true;
+}
+
+void WebChromeClient::numWheelEventHandlersChanged(unsigned count)
+{
+    m_page->send(Messages::WebPageProxy::NumWheelEventHandlersChanged(count));
+}
+
 } // namespace WebKit
index 9038eaf2a00ee05b114b438540aece5d5f15f7e8..d0017bfdd9310329501dcf043b5ce4caad1dd6d0 100644 (file)
@@ -218,6 +218,9 @@ private:
 
     virtual void didCompleteRubberBandForMainFrame(const WebCore::IntSize&) const;
     virtual void notifyScrollerThumbIsVisibleInRect(const WebCore::IntRect&);
+    virtual bool shouldRubberBandInDirection(WebCore::ScrollDirection) const;
+    
+    virtual void numWheelEventHandlersChanged(unsigned);
 
     String m_cachedToolTip;
     mutable RefPtr<WebFrame> m_cachedFrameSetLargestFrame;
index 76cf1ab6fef4d10d8b690f2d240a30a4ffa98320..bb9edf0d969d4f8fb4448bc3f365f48f8679de32 100644 (file)
@@ -1,3 +1,13 @@
+2011-05-16  Jon Lee  <jonlee@apple.com>
+
+        Reviewed by Simon Fraser.
+
+        Can't horizontally scroll iframes and overflow because wheel events are always accepted
+        https://bugs.webkit.org/show_bug.cgi?id=60779
+
+        * WebKitTestRunner/InjectedBundle/InjectedBundlePage.cpp:
+        (WTR::InjectedBundlePage::InjectedBundlePage): Set new default method to nil.
+
 2011-05-16  Ademar de Souza Reis Jr.  <ademar.reis@openbossa.org>
 
         Reviewed by Csaba Osztrogon√°c.
index 2a1f85d3a6befdf97898e30f150aa6314194bedc..b79be4d0d18013bfd060cd4f3303fdfd79e01935 100644 (file)
@@ -225,6 +225,7 @@ InjectedBundlePage::InjectedBundlePage(WKBundlePageRef page)
         0, /*paintCustomOverhangArea*/
         0, /*shouldGenerateFileForUpload*/
         0, /*generateFileForUpload*/
+        0, /*shouldRubberBandInDirection*/
     };
     WKBundlePageSetUIClient(m_page, &uiClient);