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 733297e..b00c5a4 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 7a41c99..878eda3 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 302e02f..4b86835 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 2a3f97c..d717c85 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 aa2fc9c..f3204dd 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 8941845..9a0fdeb 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 d415ee0..146222a 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 fcc5d5e..d5b79f0 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 dec22d7..44fe46e 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 c4cbaeb..30885b6 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 49a6d9a..5b73950 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 4bbed3e..7b0f5ba 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 bfef95b..ff05e25 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 99383da..605baf7 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 4515f77..c937604 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 326a14d..78cdc2e 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 4e08c19..9b569b0 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 1fd545b..c206917 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 fbe5af6..4d48832 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 aa17974..e0a20b6 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 5a8a734..e0f5b8f 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 d420a2e..5d5b136 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 ae890be..76c7171 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 8a097a0..322d0b2 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 1b13e77..129cf28 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 0ecb9f2..3d1b308 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 6552c36..75c8bcc 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 8176167..c861ba6 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 00efe8f..3442790 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 4a3cf3b..1529e1c 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 383389a..f216961 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 95709ae..13c9ec0 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 eea6f6d..67bc455 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 0d8149c..820c8ab 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 fefe0c5..a8fda2f 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 941d2c7..3c3d213 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 d01c838..1d434bd 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 4ba04a7..c61582d 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 314970a..7316bf0 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 9a9c135..1cedbe7 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 6e12954..097f239 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 532d058..4880039 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 47a5ca8..fbbb90c 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 fd5ee55..4b4eb61 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 9038eaf..d0017bf 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 76cf1ab..bb9edf0 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 2a1f85d..b79be4d 100644 (file)
@@ -225,6 +225,7 @@ InjectedBundlePage::InjectedBundlePage(WKBundlePageRef page)
         0, /*paintCustomOverhangArea*/
         0, /*shouldGenerateFileForUpload*/
         0, /*generateFileForUpload*/
+        0, /*shouldRubberBandInDirection*/
     };
     WKBundlePageSetUIClient(m_page, &uiClient);