Changeset 154535 in webkit


Ignore:
Timestamp:
Aug 23, 2013, 5:30:00 PM (12 years ago)
Author:
Simon Fraser
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:
Location:
trunk/Source/WebCore
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r154533 r154535  
     12013-08-23  Simon Fraser  <simon.fraser@apple.com>
     2
     3        Improve scrolling behavior in iTunes
     4        https://bugs.webkit.org/show_bug.cgi?id=120241
     5        <rdar://problem/14825344>
     6
     7        Reviewed by Sam Weinig.
     8
     9        When vertically scrolling a page with horizontally scrollable overflow areas,
     10        vertical scroll gestures would be interrupted when wheel events with non-zero
     11        X deltas were intercepted by the overflow areas.
     12       
     13        Fix by storing a small history of wheel events deltas and using
     14        it to determine of the scroll gesture is primarily vertical or horizontal.
     15        When this is detected, avoid dispatching scroll events on the on the
     16        non-dominant axis.
     17       
     18        Currently this behavior is conditionalized to only apply in iTunes.
     19
     20        * page/EventHandler.cpp:
     21        (WebCore::EventHandler::EventHandler):
     22        (WebCore::EventHandler::recordWheelEventDelta):
     23        (WebCore::deltaIsPredominantlyVertical):
     24        (WebCore::EventHandler::dominantScrollGestureDirection):
     25        (WebCore::EventHandler::handleWheelEvent):
     26        (WebCore::EventHandler::defaultWheelEventHandler):
     27        * page/EventHandler.h:
     28        * platform/RuntimeApplicationChecks.cpp:
     29        (WebCore::applicationIsITunes):
     30        * platform/RuntimeApplicationChecks.h:
     31
    1322013-08-23  Pratik Solanki  <psolanki@apple.com>
    233
  • trunk/Source/WebCore/page/EventHandler.cpp

    r154286 r154535  
    7676#include "RenderView.h"
    7777#include "RenderWidget.h"
     78#include "RuntimeApplicationChecks.h"
    7879#include "ScrollAnimator.h"
    7980#include "Scrollbar.h"
     
    333334    , m_mousePositionIsUnknown(true)
    334335    , m_mouseDownTimestamp(0)
     336    , m_inTrackingScrollGesturePhase(false)
    335337    , m_widgetIsLatched(false)
    336338#if PLATFORM(MAC)
     
    24362438#endif
    24372439
     2440void EventHandler::recordWheelEventDelta(const PlatformWheelEvent& event)
     2441{
     2442    const size_t recentEventCount = 3;
     2443   
     2444    m_recentWheelEventDeltas.append(FloatSize(event.deltaX(), event.deltaY()));
     2445    if (m_recentWheelEventDeltas.size() > recentEventCount)
     2446        m_recentWheelEventDeltas.removeFirst();
     2447}
     2448
     2449static bool deltaIsPredominantlyVertical(const FloatSize& delta)
     2450{
     2451    return fabs(delta.height()) > fabs(delta.width());
     2452}
     2453
     2454EventHandler::DominantScrollGestureDirection EventHandler::dominantScrollGestureDirection() const
     2455{
     2456    bool allVertical = m_recentWheelEventDeltas.size();
     2457    bool allHorizontal = m_recentWheelEventDeltas.size();
     2458
     2459    Deque<FloatSize>::const_iterator end = m_recentWheelEventDeltas.end();
     2460    for (Deque<FloatSize>::const_iterator it = m_recentWheelEventDeltas.begin(); it != end; ++it) {
     2461        bool isVertical = deltaIsPredominantlyVertical(*it);
     2462        allVertical &= isVertical;
     2463        allHorizontal &= !isVertical;
     2464    }
     2465   
     2466    if (allVertical)
     2467        return DominantScrollDirectionVertical;
     2468
     2469    if (allHorizontal)
     2470        return DominantScrollDirectionHorizontal;
     2471   
     2472    return DominantScrollDirectionNone;
     2473}
     2474
    24382475bool EventHandler::handleWheelEvent(const PlatformWheelEvent& e)
    24392476{
     
    24902527    if (m_baseEventType == PlatformEvent::NoType && shouldTurnVerticalTicksIntoHorizontal(result, e))
    24912528        event = event.copyTurningVerticalTicksIntoHorizontalTicks();
     2529
     2530#if PLATFORM(MAC)
     2531    switch (event.phase()) {
     2532    case PlatformWheelEventPhaseBegan:
     2533        m_recentWheelEventDeltas.clear();
     2534        m_inTrackingScrollGesturePhase = true;
     2535        break;
     2536    case PlatformWheelEventPhaseEnded:
     2537        m_inTrackingScrollGesturePhase = false;
     2538        break;
     2539    default:
     2540        break;
     2541    }
     2542#endif
     2543
     2544    recordWheelEventDelta(event);
    24922545
    24932546    if (node) {
     
    25252578    ScrollGranularity granularity = wheelGranularityToScrollGranularity(wheelEvent->deltaMode());
    25262579   
     2580    DominantScrollGestureDirection dominantDirection = DominantScrollDirectionNone;
     2581    // Workaround for scrolling issues in iTunes (<rdar://problem/14758615>).
     2582    if (m_inTrackingScrollGesturePhase && applicationIsITunes())
     2583        dominantDirection = dominantScrollGestureDirection();
     2584   
    25272585    // Break up into two scrolls if we need to.  Diagonal movement on
    25282586    // a MacBook pro is an example of a 2-dimensional mouse wheel event (where both deltaX and deltaY can be set).
    2529     if (scrollNode(wheelEvent->rawDeltaX(), granularity, ScrollLeft, ScrollRight, startNode, &stopNode))
     2587    if (dominantDirection != DominantScrollDirectionVertical && scrollNode(wheelEvent->rawDeltaX(), granularity, ScrollLeft, ScrollRight, startNode, &stopNode))
    25302588        wheelEvent->setDefaultHandled();
    25312589   
    2532     if (scrollNode(wheelEvent->rawDeltaY(), granularity, ScrollUp, ScrollDown, startNode, &stopNode))
     2590    if (dominantDirection != DominantScrollDirectionHorizontal && scrollNode(wheelEvent->rawDeltaY(), granularity, ScrollUp, ScrollDown, startNode, &stopNode))
    25332591        wheelEvent->setDefaultHandled();
    25342592   
  • trunk/Source/WebCore/page/EventHandler.h

    r153907 r154535  
    3838#include "TextGranularity.h"
    3939#include "Timer.h"
     40#include <wtf/Deque.h>
    4041#include <wtf/Forward.h>
    4142#include <wtf/OwnPtr.h>
     
    293294   
    294295    bool shouldTurnVerticalTicksIntoHorizontal(const HitTestResult&, const PlatformWheelEvent&) const;
     296    void recordWheelEventDelta(const PlatformWheelEvent&);
     297    enum DominantScrollGestureDirection {
     298        DominantScrollDirectionNone,
     299        DominantScrollDirectionVertical,
     300        DominantScrollDirectionHorizontal
     301    };
     302    DominantScrollGestureDirection dominantScrollGestureDirection() const;
     303   
    295304    bool mouseDownMayStartSelect() const { return m_mouseDownMayStartSelect; }
    296305
     
    467476    PlatformMouseEvent m_mouseDown;
    468477
     478    Deque<FloatSize> m_recentWheelEventDeltas;
    469479    RefPtr<Node> m_latchedWheelEventNode;
     480    bool m_inTrackingScrollGesturePhase;
    470481    bool m_widgetIsLatched;
    471482
  • trunk/Source/WebCore/platform/RuntimeApplicationChecks.cpp

    r152348 r154535  
    6767}
    6868
     69bool applicationIsITunes()
     70{
     71    static bool isITunes = mainBundleIsEqualTo("com.apple.iTunes");
     72    return isITunes;
     73}
     74
    6975bool applicationIsMicrosoftMessenger()
    7076{
  • trunk/Source/WebCore/platform/RuntimeApplicationChecks.h

    r152348 r154535  
    3333bool applicationIsAperture();
    3434bool applicationIsAppleMail();
     35bool applicationIsITunes();
    3536bool applicationIsMicrosoftMessenger();
    3637bool applicationIsMicrosoftMyDay();
Note: See TracChangeset for help on using the changeset viewer.