Title: [154535] trunk/Source/WebCore
Revision
154535
Author
[email protected]
Date
2013-08-23 17:30:00 -0700 (Fri, 23 Aug 2013)

Log Message

Improve scrolling behavior in iTunes
https://bugs.webkit.org/show_bug.cgi?id=120241
<rdar://problem/14825344>

Reviewed by Sam Weinig.

When vertically scrolling a page with horizontally scrollable overflow areas,
vertical scroll gestures would be interrupted when wheel events with non-zero
X deltas were intercepted by the overflow areas.

Fix by storing a small history of wheel events deltas and using
it to determine of the scroll gesture is primarily vertical or horizontal.
When this is detected, avoid dispatching scroll events on the on the
non-dominant axis.

Currently this behavior is conditionalized to only apply in iTunes.

* page/EventHandler.cpp:
(WebCore::EventHandler::EventHandler):
(WebCore::EventHandler::recordWheelEventDelta):
(WebCore::deltaIsPredominantlyVertical):
(WebCore::EventHandler::dominantScrollGestureDirection):
(WebCore::EventHandler::handleWheelEvent):
(WebCore::EventHandler::defaultWheelEventHandler):
* page/EventHandler.h:
* platform/RuntimeApplicationChecks.cpp:
(WebCore::applicationIsITunes):
* platform/RuntimeApplicationChecks.h:

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (154534 => 154535)


--- trunk/Source/WebCore/ChangeLog	2013-08-24 00:28:19 UTC (rev 154534)
+++ trunk/Source/WebCore/ChangeLog	2013-08-24 00:30:00 UTC (rev 154535)
@@ -1,3 +1,34 @@
+2013-08-23  Simon Fraser  <[email protected]>
+
+        Improve scrolling behavior in iTunes
+        https://bugs.webkit.org/show_bug.cgi?id=120241
+        <rdar://problem/14825344>
+
+        Reviewed by Sam Weinig.
+
+        When vertically scrolling a page with horizontally scrollable overflow areas,
+        vertical scroll gestures would be interrupted when wheel events with non-zero
+        X deltas were intercepted by the overflow areas.
+        
+        Fix by storing a small history of wheel events deltas and using
+        it to determine of the scroll gesture is primarily vertical or horizontal.
+        When this is detected, avoid dispatching scroll events on the on the
+        non-dominant axis.
+        
+        Currently this behavior is conditionalized to only apply in iTunes.
+
+        * page/EventHandler.cpp:
+        (WebCore::EventHandler::EventHandler):
+        (WebCore::EventHandler::recordWheelEventDelta):
+        (WebCore::deltaIsPredominantlyVertical):
+        (WebCore::EventHandler::dominantScrollGestureDirection):
+        (WebCore::EventHandler::handleWheelEvent):
+        (WebCore::EventHandler::defaultWheelEventHandler):
+        * page/EventHandler.h:
+        * platform/RuntimeApplicationChecks.cpp:
+        (WebCore::applicationIsITunes):
+        * platform/RuntimeApplicationChecks.h:
+
 2013-08-23  Pratik Solanki  <[email protected]>
 
         MediaQuery::expressions() should return a reference

Modified: trunk/Source/WebCore/page/EventHandler.cpp (154534 => 154535)


--- trunk/Source/WebCore/page/EventHandler.cpp	2013-08-24 00:28:19 UTC (rev 154534)
+++ trunk/Source/WebCore/page/EventHandler.cpp	2013-08-24 00:30:00 UTC (rev 154535)
@@ -75,6 +75,7 @@
 #include "RenderTextControlSingleLine.h"
 #include "RenderView.h"
 #include "RenderWidget.h"
+#include "RuntimeApplicationChecks.h"
 #include "ScrollAnimator.h"
 #include "Scrollbar.h"
 #include "Settings.h"
@@ -332,6 +333,7 @@
     , m_clickCount(0)
     , m_mousePositionIsUnknown(true)
     , m_mouseDownTimestamp(0)
+    , m_inTrackingScrollGesturePhase(false)
     , m_widgetIsLatched(false)
 #if PLATFORM(MAC)
     , m_mouseDownView(nil)
@@ -2435,6 +2437,41 @@
 }
 #endif
 
+void EventHandler::recordWheelEventDelta(const PlatformWheelEvent& event)
+{
+    const size_t recentEventCount = 3;
+    
+    m_recentWheelEventDeltas.append(FloatSize(event.deltaX(), event.deltaY()));
+    if (m_recentWheelEventDeltas.size() > recentEventCount)
+        m_recentWheelEventDeltas.removeFirst();
+}
+
+static bool deltaIsPredominantlyVertical(const FloatSize& delta)
+{
+    return fabs(delta.height()) > fabs(delta.width());
+}
+
+EventHandler::DominantScrollGestureDirection EventHandler::dominantScrollGestureDirection() const
+{
+    bool allVertical = m_recentWheelEventDeltas.size();
+    bool allHorizontal = m_recentWheelEventDeltas.size();
+
+    Deque<FloatSize>::const_iterator end = m_recentWheelEventDeltas.end();
+    for (Deque<FloatSize>::const_iterator it = m_recentWheelEventDeltas.begin(); it != end; ++it) {
+        bool isVertical = deltaIsPredominantlyVertical(*it);
+        allVertical &= isVertical;
+        allHorizontal &= !isVertical;
+    }
+    
+    if (allVertical)
+        return DominantScrollDirectionVertical;
+
+    if (allHorizontal)
+        return DominantScrollDirectionHorizontal;
+    
+    return DominantScrollDirectionNone;
+}
+
 bool EventHandler::handleWheelEvent(const PlatformWheelEvent& e)
 {
     Document* doc = m_frame->document();
@@ -2490,6 +2527,22 @@
     if (m_baseEventType == PlatformEvent::NoType && shouldTurnVerticalTicksIntoHorizontal(result, e))
         event = event.copyTurningVerticalTicksIntoHorizontalTicks();
 
+#if PLATFORM(MAC)
+    switch (event.phase()) {
+    case PlatformWheelEventPhaseBegan:
+        m_recentWheelEventDeltas.clear();
+        m_inTrackingScrollGesturePhase = true;
+        break;
+    case PlatformWheelEventPhaseEnded:
+        m_inTrackingScrollGesturePhase = false;
+        break;
+    default:
+        break;
+    }
+#endif
+
+    recordWheelEventDelta(event);
+
     if (node) {
         // Figure out which view to send the event to.
         RenderObject* target = node->renderer();
@@ -2524,12 +2577,17 @@
     Node* stopNode = m_previousWheelScrolledNode.get();
     ScrollGranularity granularity = wheelGranularityToScrollGranularity(wheelEvent->deltaMode());
     
+    DominantScrollGestureDirection dominantDirection = DominantScrollDirectionNone;
+    // Workaround for scrolling issues in iTunes (<rdar://problem/14758615>).
+    if (m_inTrackingScrollGesturePhase && applicationIsITunes())
+        dominantDirection = dominantScrollGestureDirection();
+    
     // Break up into two scrolls if we need to.  Diagonal movement on 
     // a MacBook pro is an example of a 2-dimensional mouse wheel event (where both deltaX and deltaY can be set).
-    if (scrollNode(wheelEvent->rawDeltaX(), granularity, ScrollLeft, ScrollRight, startNode, &stopNode))
+    if (dominantDirection != DominantScrollDirectionVertical && scrollNode(wheelEvent->rawDeltaX(), granularity, ScrollLeft, ScrollRight, startNode, &stopNode))
         wheelEvent->setDefaultHandled();
     
-    if (scrollNode(wheelEvent->rawDeltaY(), granularity, ScrollUp, ScrollDown, startNode, &stopNode))
+    if (dominantDirection != DominantScrollDirectionHorizontal && scrollNode(wheelEvent->rawDeltaY(), granularity, ScrollUp, ScrollDown, startNode, &stopNode))
         wheelEvent->setDefaultHandled();
     
     if (!m_latchedWheelEventNode)

Modified: trunk/Source/WebCore/page/EventHandler.h (154534 => 154535)


--- trunk/Source/WebCore/page/EventHandler.h	2013-08-24 00:28:19 UTC (rev 154534)
+++ trunk/Source/WebCore/page/EventHandler.h	2013-08-24 00:30:00 UTC (rev 154535)
@@ -37,6 +37,7 @@
 #include "TextEventInputType.h"
 #include "TextGranularity.h"
 #include "Timer.h"
+#include <wtf/Deque.h>
 #include <wtf/Forward.h>
 #include <wtf/OwnPtr.h>
 #include <wtf/RefPtr.h>
@@ -292,6 +293,14 @@
     bool logicalScrollOverflow(ScrollLogicalDirection, ScrollGranularity, Node* startingNode = 0);
     
     bool shouldTurnVerticalTicksIntoHorizontal(const HitTestResult&, const PlatformWheelEvent&) const;
+    void recordWheelEventDelta(const PlatformWheelEvent&);
+    enum DominantScrollGestureDirection {
+        DominantScrollDirectionNone,
+        DominantScrollDirectionVertical,
+        DominantScrollDirectionHorizontal
+    };
+    DominantScrollGestureDirection dominantScrollGestureDirection() const;
+    
     bool mouseDownMayStartSelect() const { return m_mouseDownMayStartSelect; }
 
     static bool isKeyboardOptionTab(KeyboardEvent*);
@@ -466,7 +475,9 @@
     double m_mouseDownTimestamp;
     PlatformMouseEvent m_mouseDown;
 
+    Deque<FloatSize> m_recentWheelEventDeltas;
     RefPtr<Node> m_latchedWheelEventNode;
+    bool m_inTrackingScrollGesturePhase;
     bool m_widgetIsLatched;
 
     RefPtr<Node> m_previousWheelScrolledNode;

Modified: trunk/Source/WebCore/platform/RuntimeApplicationChecks.cpp (154534 => 154535)


--- trunk/Source/WebCore/platform/RuntimeApplicationChecks.cpp	2013-08-24 00:28:19 UTC (rev 154534)
+++ trunk/Source/WebCore/platform/RuntimeApplicationChecks.cpp	2013-08-24 00:30:00 UTC (rev 154535)
@@ -66,6 +66,12 @@
     return isAppleMail;
 }
 
+bool applicationIsITunes()
+{
+    static bool isITunes = mainBundleIsEqualTo("com.apple.iTunes");
+    return isITunes;
+}
+
 bool applicationIsMicrosoftMessenger()
 {
     static bool isMicrosoftMessenger = mainBundleIsEqualTo("com.microsoft.Messenger");

Modified: trunk/Source/WebCore/platform/RuntimeApplicationChecks.h (154534 => 154535)


--- trunk/Source/WebCore/platform/RuntimeApplicationChecks.h	2013-08-24 00:28:19 UTC (rev 154534)
+++ trunk/Source/WebCore/platform/RuntimeApplicationChecks.h	2013-08-24 00:30:00 UTC (rev 154535)
@@ -32,6 +32,7 @@
 bool applicationIsAdobeInstaller();
 bool applicationIsAperture();
 bool applicationIsAppleMail();
+bool applicationIsITunes();
 bool applicationIsMicrosoftMessenger();
 bool applicationIsMicrosoftMyDay();
 bool applicationIsMicrosoftOutlook();
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to