- a/Source/WebCore/ChangeLog +15 lines
Lines 1-3 a/Source/WebCore/ChangeLog_sec1
1
2015-03-02  Commit Queue  <commit-queue@webkit.org>
2
3
        Unreviewed, rolling out r180902.
4
        https://bugs.webkit.org/show_bug.cgi?id=142205
5
6
        It broke scrolling in some cases. See bug 142202 for details.
7
        (Requested by bdash on #webkit).
8
9
        Reverted changeset:
10
11
        "Move scroll animating functions from ScrollAnimator to
12
        ScrollController"
13
        https://bugs.webkit.org/show_bug.cgi?id=142102
14
        http://trac.webkit.org/changeset/180902
15
1
2015-03-02  Yoav Weiss  <yoav@yoav.ws>
16
2015-03-02  Yoav Weiss  <yoav@yoav.ws>
2
17
3
        Add a microtask abstraction
18
        Add a microtask abstraction
- a/Source/WebCore/WebCore.xcodeproj/project.pbxproj -8 / +8 lines
Lines 786-791 a/Source/WebCore/WebCore.xcodeproj/project.pbxproj_sec1
786
		1A927FD31416A15B003A83C8 /* npruntime.h in Headers */ = {isa = PBXBuildFile; fileRef = 1A927FD01416A15B003A83C8 /* npruntime.h */; settings = {ATTRIBUTES = (Private, ); }; };
786
		1A927FD31416A15B003A83C8 /* npruntime.h in Headers */ = {isa = PBXBuildFile; fileRef = 1A927FD01416A15B003A83C8 /* npruntime.h */; settings = {ATTRIBUTES = (Private, ); }; };
787
		1A927FD41416A15B003A83C8 /* nptypes.h in Headers */ = {isa = PBXBuildFile; fileRef = 1A927FD11416A15B003A83C8 /* nptypes.h */; settings = {ATTRIBUTES = (Private, ); }; };
787
		1A927FD41416A15B003A83C8 /* nptypes.h in Headers */ = {isa = PBXBuildFile; fileRef = 1A927FD11416A15B003A83C8 /* nptypes.h */; settings = {ATTRIBUTES = (Private, ); }; };
788
		1A98956B0AA78F80005EF5EF /* URLCF.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A98956A0AA78F80005EF5EF /* URLCF.cpp */; };
788
		1A98956B0AA78F80005EF5EF /* URLCF.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A98956A0AA78F80005EF5EF /* URLCF.cpp */; };
789
		1AA84F04143BA7BD0051D153 /* ScrollController.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1AA84F02143BA7BD0051D153 /* ScrollController.mm */; };
790
		1AA84F05143BA7BD0051D153 /* ScrollController.h in Headers */ = {isa = PBXBuildFile; fileRef = 1AA84F03143BA7BD0051D153 /* ScrollController.h */; settings = {ATTRIBUTES = (Private, ); }; };
789
		1AA8799011CBE846003C664F /* PluginStrategy.h in Headers */ = {isa = PBXBuildFile; fileRef = 1AA8798F11CBE846003C664F /* PluginStrategy.h */; settings = {ATTRIBUTES = (Private, ); }; };
791
		1AA8799011CBE846003C664F /* PluginStrategy.h in Headers */ = {isa = PBXBuildFile; fileRef = 1AA8798F11CBE846003C664F /* PluginStrategy.h */; settings = {ATTRIBUTES = (Private, ); }; };
790
		1AAADDA314DB409F00AF64B3 /* ScrollingTree.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AAADDA114DB409F00AF64B3 /* ScrollingTree.cpp */; };
792
		1AAADDA314DB409F00AF64B3 /* ScrollingTree.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AAADDA114DB409F00AF64B3 /* ScrollingTree.cpp */; };
791
		1AAADDA414DB409F00AF64B3 /* ScrollingTree.h in Headers */ = {isa = PBXBuildFile; fileRef = 1AAADDA214DB409F00AF64B3 /* ScrollingTree.h */; settings = {ATTRIBUTES = (Private, ); }; };
793
		1AAADDA414DB409F00AF64B3 /* ScrollingTree.h in Headers */ = {isa = PBXBuildFile; fileRef = 1AAADDA214DB409F00AF64B3 /* ScrollingTree.h */; settings = {ATTRIBUTES = (Private, ); }; };
Lines 2444-2451 a/Source/WebCore/WebCore.xcodeproj/project.pbxproj_sec2
2444
		7A74ECBD101839DA00BF939E /* JSInspectorFrontendHostCustom.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7A74ECBC101839DA00BF939E /* JSInspectorFrontendHostCustom.cpp */; };
2446
		7A74ECBD101839DA00BF939E /* JSInspectorFrontendHostCustom.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7A74ECBC101839DA00BF939E /* JSInspectorFrontendHostCustom.cpp */; };
2445
		7A93868518DCC14500B8263D /* VTTScanner.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7A93868218DCC14500B8263D /* VTTScanner.cpp */; };
2447
		7A93868518DCC14500B8263D /* VTTScanner.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7A93868218DCC14500B8263D /* VTTScanner.cpp */; };
2446
		7A93868618DCC14500B8263D /* VTTScanner.h in Headers */ = {isa = PBXBuildFile; fileRef = 7A93868318DCC14500B8263D /* VTTScanner.h */; };
2448
		7A93868618DCC14500B8263D /* VTTScanner.h in Headers */ = {isa = PBXBuildFile; fileRef = 7A93868318DCC14500B8263D /* VTTScanner.h */; };
2447
		7A9ADFF31AA1163800D2733C /* ScrollController.h in Headers */ = {isa = PBXBuildFile; fileRef = 7AFFA4111AA1039D00F0125B /* ScrollController.h */; settings = {ATTRIBUTES = (Private, ); }; };
2448
		7A9ADFF41AA1163B00D2733C /* ScrollController.mm in Sources */ = {isa = PBXBuildFile; fileRef = 7AFFA4121AA1039D00F0125B /* ScrollController.mm */; };
2449
		7AA3A699194A64E7001CBD24 /* TileController.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7AA3A695194A64E7001CBD24 /* TileController.cpp */; };
2449
		7AA3A699194A64E7001CBD24 /* TileController.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7AA3A695194A64E7001CBD24 /* TileController.cpp */; };
2450
		7AA3A69A194A64E7001CBD24 /* TileController.h in Headers */ = {isa = PBXBuildFile; fileRef = 7AA3A696194A64E7001CBD24 /* TileController.h */; settings = {ATTRIBUTES = (Private, ); }; };
2450
		7AA3A69A194A64E7001CBD24 /* TileController.h in Headers */ = {isa = PBXBuildFile; fileRef = 7AA3A696194A64E7001CBD24 /* TileController.h */; settings = {ATTRIBUTES = (Private, ); }; };
2451
		7AA3A69B194A64E7001CBD24 /* TileGrid.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7AA3A697194A64E7001CBD24 /* TileGrid.cpp */; };
2451
		7AA3A69B194A64E7001CBD24 /* TileGrid.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7AA3A697194A64E7001CBD24 /* TileGrid.cpp */; };
Lines 7813-7818 a/Source/WebCore/WebCore.xcodeproj/project.pbxproj_sec3
7813
		1A927FD01416A15B003A83C8 /* npruntime.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = npruntime.h; sourceTree = "<group>"; };
7813
		1A927FD01416A15B003A83C8 /* npruntime.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = npruntime.h; sourceTree = "<group>"; };
7814
		1A927FD11416A15B003A83C8 /* nptypes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = nptypes.h; sourceTree = "<group>"; };
7814
		1A927FD11416A15B003A83C8 /* nptypes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = nptypes.h; sourceTree = "<group>"; };
7815
		1A98956A0AA78F80005EF5EF /* URLCF.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = URLCF.cpp; sourceTree = "<group>"; };
7815
		1A98956A0AA78F80005EF5EF /* URLCF.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = URLCF.cpp; sourceTree = "<group>"; };
7816
		1AA84F02143BA7BD0051D153 /* ScrollController.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ScrollController.mm; sourceTree = "<group>"; };
7817
		1AA84F03143BA7BD0051D153 /* ScrollController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ScrollController.h; sourceTree = "<group>"; };
7816
		1AA8798F11CBE846003C664F /* PluginStrategy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PluginStrategy.h; sourceTree = "<group>"; };
7818
		1AA8798F11CBE846003C664F /* PluginStrategy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PluginStrategy.h; sourceTree = "<group>"; };
7817
		1AAADDA114DB409F00AF64B3 /* ScrollingTree.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ScrollingTree.cpp; sourceTree = "<group>"; };
7819
		1AAADDA114DB409F00AF64B3 /* ScrollingTree.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ScrollingTree.cpp; sourceTree = "<group>"; };
7818
		1AAADDA214DB409F00AF64B3 /* ScrollingTree.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ScrollingTree.h; sourceTree = "<group>"; };
7820
		1AAADDA214DB409F00AF64B3 /* ScrollingTree.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ScrollingTree.h; sourceTree = "<group>"; };
Lines 9670-9677 a/Source/WebCore/WebCore.xcodeproj/project.pbxproj_sec4
9670
		7AF9B20918CFB5F200C64BEF /* JSVTTRegion.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSVTTRegion.h; sourceTree = "<group>"; };
9672
		7AF9B20918CFB5F200C64BEF /* JSVTTRegion.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSVTTRegion.h; sourceTree = "<group>"; };
9671
		7AF9B20A18CFB5F300C64BEF /* JSVTTRegionList.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSVTTRegionList.cpp; sourceTree = "<group>"; };
9673
		7AF9B20A18CFB5F300C64BEF /* JSVTTRegionList.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSVTTRegionList.cpp; sourceTree = "<group>"; };
9672
		7AF9B20B18CFB5F300C64BEF /* JSVTTRegionList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSVTTRegionList.h; sourceTree = "<group>"; };
9674
		7AF9B20B18CFB5F300C64BEF /* JSVTTRegionList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSVTTRegionList.h; sourceTree = "<group>"; };
9673
		7AFFA4111AA1039D00F0125B /* ScrollController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ScrollController.h; sourceTree = "<group>"; };
9674
		7AFFA4121AA1039D00F0125B /* ScrollController.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ScrollController.mm; sourceTree = "<group>"; };
9675
		7C2BDD3B17C7F98B0038FF15 /* JSDOMGlobalObjectTask.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSDOMGlobalObjectTask.cpp; sourceTree = "<group>"; };
9675
		7C2BDD3B17C7F98B0038FF15 /* JSDOMGlobalObjectTask.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSDOMGlobalObjectTask.cpp; sourceTree = "<group>"; };
9676
		7C2BDD3C17C7F98B0038FF15 /* JSDOMGlobalObjectTask.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSDOMGlobalObjectTask.h; sourceTree = "<group>"; };
9676
		7C2BDD3C17C7F98B0038FF15 /* JSDOMGlobalObjectTask.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSDOMGlobalObjectTask.h; sourceTree = "<group>"; };
9677
		7C3B796F1908757B00B47A2D /* UserMessageHandler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = UserMessageHandler.cpp; sourceTree = "<group>"; };
9677
		7C3B796F1908757B00B47A2D /* UserMessageHandler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = UserMessageHandler.cpp; sourceTree = "<group>"; };
Lines 16597-16602 a/Source/WebCore/WebCore.xcodeproj/project.pbxproj_sec5
16597
				BC51156D12B1749C00C96754 /* ScrollAnimatorMac.mm */,
16597
				BC51156D12B1749C00C96754 /* ScrollAnimatorMac.mm */,
16598
				BC8B853C0E7C7F1100AB6984 /* ScrollbarThemeMac.h */,
16598
				BC8B853C0E7C7F1100AB6984 /* ScrollbarThemeMac.h */,
16599
				BCEF869E0E844E9D00A85CD5 /* ScrollbarThemeMac.mm */,
16599
				BCEF869E0E844E9D00A85CD5 /* ScrollbarThemeMac.mm */,
16600
				1AA84F03143BA7BD0051D153 /* ScrollController.h */,
16601
				1AA84F02143BA7BD0051D153 /* ScrollController.mm */,
16600
				9353676A09AED88B00D35CD6 /* ScrollViewMac.mm */,
16602
				9353676A09AED88B00D35CD6 /* ScrollViewMac.mm */,
16601
				077AF14118F4B1BB0001ED61 /* SerializedPlatformRepresentationMac.h */,
16603
				077AF14118F4B1BB0001ED61 /* SerializedPlatformRepresentationMac.h */,
16602
				077AF14218F4B1BB0001ED61 /* SerializedPlatformRepresentationMac.mm */,
16604
				077AF14218F4B1BB0001ED61 /* SerializedPlatformRepresentationMac.mm */,
Lines 18706-18713 a/Source/WebCore/WebCore.xcodeproj/project.pbxproj_sec6
18706
				1A0409F21A43675C009E47F3 /* MachSendRight.cpp */,
18708
				1A0409F21A43675C009E47F3 /* MachSendRight.cpp */,
18707
				1A0409DB1A4360B5009E47F3 /* MachSendRight.h */,
18709
				1A0409DB1A4360B5009E47F3 /* MachSendRight.h */,
18708
				ADB6B29718FB90240081963E /* MemoryPressureHandlerCocoa.mm */,
18710
				ADB6B29718FB90240081963E /* MemoryPressureHandlerCocoa.mm */,
18709
				7AFFA4111AA1039D00F0125B /* ScrollController.h */,
18710
				7AFFA4121AA1039D00F0125B /* ScrollController.mm */,
18711
				5D5975B119635F1100D00878 /* SystemVersion.h */,
18711
				5D5975B119635F1100D00878 /* SystemVersion.h */,
18712
				5D5975B219635F1100D00878 /* SystemVersion.mm */,
18712
				5D5975B219635F1100D00878 /* SystemVersion.mm */,
18713
				7CC564B918BAC720001B9652 /* TelephoneNumberDetectorCocoa.cpp */,
18713
				7CC564B918BAC720001B9652 /* TelephoneNumberDetectorCocoa.cpp */,
Lines 24661-24667 a/Source/WebCore/WebCore.xcodeproj/project.pbxproj_sec7
24661
				A8EA7CB50A192B9C00A8EF5F /* HTMLParagraphElement.h in Headers */,
24661
				A8EA7CB50A192B9C00A8EF5F /* HTMLParagraphElement.h in Headers */,
24662
				A871D4580A127CBC00B12A68 /* HTMLParamElement.h in Headers */,
24662
				A871D4580A127CBC00B12A68 /* HTMLParamElement.h in Headers */,
24663
				93E2A307123E9DC0009FE12A /* HTMLParserIdioms.h in Headers */,
24663
				93E2A307123E9DC0009FE12A /* HTMLParserIdioms.h in Headers */,
24664
				7A9ADFF31AA1163800D2733C /* ScrollController.h in Headers */,
24665
				973F418A169B95FF0006BF60 /* HTMLParserOptions.h in Headers */,
24664
				973F418A169B95FF0006BF60 /* HTMLParserOptions.h in Headers */,
24666
				977B3871122883E900B81FF8 /* HTMLParserScheduler.h in Headers */,
24665
				977B3871122883E900B81FF8 /* HTMLParserScheduler.h in Headers */,
24667
				A871D4560A127CBC00B12A68 /* HTMLPlugInElement.h in Headers */,
24666
				A871D4560A127CBC00B12A68 /* HTMLPlugInElement.h in Headers */,
Lines 26116-26121 a/Source/WebCore/WebCore.xcodeproj/project.pbxproj_sec8
26116
				BC8B853E0E7C7F1100AB6984 /* ScrollbarThemeMac.h in Headers */,
26115
				BC8B853E0E7C7F1100AB6984 /* ScrollbarThemeMac.h in Headers */,
26117
				0FE71406142170B800DB33BA /* ScrollbarThemeMock.h in Headers */,
26116
				0FE71406142170B800DB33BA /* ScrollbarThemeMock.h in Headers */,
26118
				5D925B680F64D4DD00B847F0 /* ScrollBehavior.h in Headers */,
26117
				5D925B680F64D4DD00B847F0 /* ScrollBehavior.h in Headers */,
26118
				1AA84F05143BA7BD0051D153 /* ScrollController.h in Headers */,
26119
				0F605AED15F94848004DF0C0 /* ScrollingConstraints.h in Headers */,
26119
				0F605AED15F94848004DF0C0 /* ScrollingConstraints.h in Headers */,
26120
				1AF62EE814DA22A70041556C /* ScrollingCoordinator.h in Headers */,
26120
				1AF62EE814DA22A70041556C /* ScrollingCoordinator.h in Headers */,
26121
				0FC4E40D187F82E10045882C /* ScrollingCoordinatorIOS.h in Headers */,
26121
				0FC4E40D187F82E10045882C /* ScrollingCoordinatorIOS.h in Headers */,
Lines 27511-27517 a/Source/WebCore/WebCore.xcodeproj/project.pbxproj_sec9
27511
				E19AC3F41824DC7900349426 /* CryptoAlgorithmSHA512.cpp in Sources */,
27511
				E19AC3F41824DC7900349426 /* CryptoAlgorithmSHA512.cpp in Sources */,
27512
				E1FE13641834351100892F13 /* CryptoDigestMac.cpp in Sources */,
27512
				E1FE13641834351100892F13 /* CryptoDigestMac.cpp in Sources */,
27513
				E157A8E418173A3A009F821D /* CryptoKey.cpp in Sources */,
27513
				E157A8E418173A3A009F821D /* CryptoKey.cpp in Sources */,
27514
				7A9ADFF41AA1163B00D2733C /* ScrollController.mm in Sources */,
27515
				E125F84D1824289D00D84CD9 /* CryptoKeyAES.cpp in Sources */,
27514
				E125F84D1824289D00D84CD9 /* CryptoKeyAES.cpp in Sources */,
27516
				E125F863182C303A00D84CD9 /* CryptoKeyDataOctetSequence.cpp in Sources */,
27515
				E125F863182C303A00D84CD9 /* CryptoKeyDataOctetSequence.cpp in Sources */,
27517
				E1C266DE18319F31003F8B33 /* CryptoKeyDataRSAComponents.cpp in Sources */,
27516
				E1C266DE18319F31003F8B33 /* CryptoKeyDataRSAComponents.cpp in Sources */,
Lines 29524-29529 a/Source/WebCore/WebCore.xcodeproj/project.pbxproj_sec10
29524
				BCEF869F0E844E9D00A85CD5 /* ScrollbarThemeMac.mm in Sources */,
29523
				BCEF869F0E844E9D00A85CD5 /* ScrollbarThemeMac.mm in Sources */,
29525
				0FE71405142170B800DB33BA /* ScrollbarThemeMock.cpp in Sources */,
29524
				0FE71405142170B800DB33BA /* ScrollbarThemeMock.cpp in Sources */,
29526
				5D925B670F64D4DD00B847F0 /* ScrollBehavior.cpp in Sources */,
29525
				5D925B670F64D4DD00B847F0 /* ScrollBehavior.cpp in Sources */,
29526
				1AA84F04143BA7BD0051D153 /* ScrollController.mm in Sources */,
29527
				0F605AEC15F94848004DF0C0 /* ScrollingConstraints.cpp in Sources */,
29527
				0F605AEC15F94848004DF0C0 /* ScrollingConstraints.cpp in Sources */,
29528
				1AF62EE714DA22A70041556C /* ScrollingCoordinator.cpp in Sources */,
29528
				1AF62EE714DA22A70041556C /* ScrollingCoordinator.cpp in Sources */,
29529
				0FC4E40E187F82E10045882C /* ScrollingCoordinatorIOS.mm in Sources */,
29529
				0FC4E40E187F82E10045882C /* ScrollingCoordinatorIOS.mm in Sources */,
- a/Source/WebCore/page/mac/EventHandlerMac.mm -6 lines
Lines 961-972 bool EventHandler::platformCompleteWheelEvent(const PlatformWheelEvent& wheelEve a/Source/WebCore/page/mac/EventHandlerMac.mm_sec1
961
    
961
    
962
    bool didHandleEvent = view ? view->wheelEvent(wheelEvent) : false;
962
    bool didHandleEvent = view ? view->wheelEvent(wheelEvent) : false;
963
    m_isHandlingWheelEvent = false;
963
    m_isHandlingWheelEvent = false;
964
    
965
#if ENABLE(CSS_SCROLL_SNAP)
966
    if (scrollableArea)
967
        platformNotifySnapIfNecessary(wheelEvent, *scrollableArea);
968
#endif
969
970
    return didHandleEvent;
964
    return didHandleEvent;
971
}
965
}
972
966
- a/Source/WebCore/page/scrolling/mac/ScrollingTreeFrameScrollingNodeMac.h -5 / +3 lines
Lines 61-66 private: a/Source/WebCore/page/scrolling/mac/ScrollingTreeFrameScrollingNodeMac.h_sec1
61
    virtual IntPoint absoluteScrollPosition() override;
61
    virtual IntPoint absoluteScrollPosition() override;
62
    virtual void immediateScrollBy(const FloatSize&) override;
62
    virtual void immediateScrollBy(const FloatSize&) override;
63
    virtual void immediateScrollByWithoutContentEdgeConstraints(const FloatSize&) override;
63
    virtual void immediateScrollByWithoutContentEdgeConstraints(const FloatSize&) override;
64
    virtual void startSnapRubberbandTimer() override;
65
    virtual void stopSnapRubberbandTimer() override;
64
    virtual void adjustScrollPositionToBoundsIfNecessary() override;
66
    virtual void adjustScrollPositionToBoundsIfNecessary() override;
65
67
66
    virtual FloatPoint scrollPosition() const override;
68
    virtual FloatPoint scrollPosition() const override;
Lines 78-91 private: a/Source/WebCore/page/scrolling/mac/ScrollingTreeFrameScrollingNodeMac.h_sec2
78
80
79
    bool isAlreadyPinnedInDirectionOfGesture(const PlatformWheelEvent&, ScrollEventAxis);
81
    bool isAlreadyPinnedInDirectionOfGesture(const PlatformWheelEvent&, ScrollEventAxis);
80
82
81
#if ENABLE(CSS_SCROLL_SNAP) && PLATFORM(MAC)
82
    LayoutUnit scrollOffsetOnAxis(ScrollEventAxis) override;
83
    void immediateScrollOnAxis(ScrollEventAxis, float delta) override;
84
#endif
85
86
    void logExposedUnfilledArea();
83
    void logExposedUnfilledArea();
87
84
88
    ScrollController m_scrollController;
85
    ScrollController m_scrollController;
86
    RetainPtr<CFRunLoopTimerRef> m_snapRubberbandTimer;
89
87
90
    RetainPtr<CALayer> m_scrollLayer;
88
    RetainPtr<CALayer> m_scrollLayer;
91
    RetainPtr<CALayer> m_scrolledContentsLayer;
89
    RetainPtr<CALayer> m_scrolledContentsLayer;
- a/Source/WebCore/page/scrolling/mac/ScrollingTreeFrameScrollingNodeMac.mm -13 / +28 lines
Lines 66-71 ScrollingTreeFrameScrollingNodeMac::ScrollingTreeFrameScrollingNodeMac(Scrolling a/Source/WebCore/page/scrolling/mac/ScrollingTreeFrameScrollingNodeMac.mm_sec1
66
66
67
ScrollingTreeFrameScrollingNodeMac::~ScrollingTreeFrameScrollingNodeMac()
67
ScrollingTreeFrameScrollingNodeMac::~ScrollingTreeFrameScrollingNodeMac()
68
{
68
{
69
    if (m_snapRubberbandTimer)
70
        CFRunLoopTimerInvalidate(m_snapRubberbandTimer.get());
69
}
71
}
70
72
71
void ScrollingTreeFrameScrollingNodeMac::updateBeforeChildren(const ScrollingStateNode& stateNode)
73
void ScrollingTreeFrameScrollingNodeMac::updateBeforeChildren(const ScrollingStateNode& stateNode)
Lines 294-299 void ScrollingTreeFrameScrollingNodeMac::immediateScrollByWithoutContentEdgeCons a/Source/WebCore/page/scrolling/mac/ScrollingTreeFrameScrollingNodeMac.mm_sec2
294
    scrollByWithoutContentEdgeConstraints(offset);
296
    scrollByWithoutContentEdgeConstraints(offset);
295
}
297
}
296
298
299
void ScrollingTreeFrameScrollingNodeMac::startSnapRubberbandTimer()
300
{
301
    ASSERT(!m_snapRubberbandTimer);
302
303
    CFTimeInterval timerInterval = 1.0 / 60.0;
304
305
    m_snapRubberbandTimer = adoptCF(CFRunLoopTimerCreateWithHandler(kCFAllocatorDefault, CFAbsoluteTimeGetCurrent() + timerInterval, timerInterval, 0, 0, ^(CFRunLoopTimerRef) {
306
        m_scrollController.snapRubberBandTimerFired();
307
    }));
308
    CFRunLoopAddTimer(CFRunLoopGetCurrent(), m_snapRubberbandTimer.get(), kCFRunLoopDefaultMode);
309
}
310
311
void ScrollingTreeFrameScrollingNodeMac::stopSnapRubberbandTimer()
312
{
313
    if (!m_snapRubberbandTimer)
314
        return;
315
316
    scrollingTree().setMainFrameIsRubberBanding(false);
317
318
    // Since the rubberband timer has stopped, totalContentsSizeForRubberBand can be synchronized with totalContentsSize.
319
    setTotalContentsSizeForRubberBand(totalContentsSize());
320
321
    CFRunLoopTimerInvalidate(m_snapRubberbandTimer.get());
322
    m_snapRubberbandTimer = nullptr;
323
}
324
297
void ScrollingTreeFrameScrollingNodeMac::adjustScrollPositionToBoundsIfNecessary()
325
void ScrollingTreeFrameScrollingNodeMac::adjustScrollPositionToBoundsIfNecessary()
298
{
326
{
299
    FloatPoint currentScrollPosition = absoluteScrollPosition();
327
    FloatPoint currentScrollPosition = absoluteScrollPosition();
Lines 512-530 void logWheelEventHandlerCountChanged(unsigned count) a/Source/WebCore/page/scrolling/mac/ScrollingTreeFrameScrollingNodeMac.mm_sec3
512
    WTFLogAlways("SCROLLING: Wheel event handler count changed. Time: %f Count: %u\n", WTF::monotonicallyIncreasingTime(), count);
540
    WTFLogAlways("SCROLLING: Wheel event handler count changed. Time: %f Count: %u\n", WTF::monotonicallyIncreasingTime(), count);
513
}
541
}
514
542
515
#if ENABLE(CSS_SCROLL_SNAP) && PLATFORM(MAC)
516
LayoutUnit ScrollingTreeFrameScrollingNodeMac::scrollOffsetOnAxis(ScrollEventAxis)
517
{
518
    // Temporary stub until http://webkit.org/b/141973.
519
    return 0;
520
}
521
522
void ScrollingTreeFrameScrollingNodeMac::immediateScrollOnAxis(ScrollEventAxis, float)
523
{
524
    // Temporary stub until http://webkit.org/b/141973.
525
}
526
#endif
527
528
} // namespace WebCore
543
} // namespace WebCore
529
544
530
#endif // ENABLE(ASYNC_SCROLLING) && PLATFORM(MAC)
545
#endif // ENABLE(ASYNC_SCROLLING) && PLATFORM(MAC)
- a/Source/WebCore/platform/ScrollAnimator.cpp -10 / +58 lines
Lines 49-57 std::unique_ptr<ScrollAnimator> ScrollAnimator::create(ScrollableArea& scrollabl a/Source/WebCore/platform/ScrollAnimator.cpp_sec1
49
49
50
ScrollAnimator::ScrollAnimator(ScrollableArea& scrollableArea)
50
ScrollAnimator::ScrollAnimator(ScrollableArea& scrollableArea)
51
    : m_scrollableArea(scrollableArea)
51
    : m_scrollableArea(scrollableArea)
52
#if (ENABLE(CSS_SCROLL_SNAP) || ENABLE(RUBBER_BANDING)) && PLATFORM(MAC)
53
    , m_scrollController(this)
54
#endif
55
    , m_currentPosX(0)
52
    , m_currentPosX(0)
56
    , m_currentPosY(0)
53
    , m_currentPosY(0)
57
{
54
{
Lines 84-99 void ScrollAnimator::scrollToOffsetWithoutAnimation(const FloatPoint& offset) a/Source/WebCore/platform/ScrollAnimator.cpp_sec2
84
}
81
}
85
82
86
#if ENABLE(CSS_SCROLL_SNAP) && PLATFORM(MAC)
83
#if ENABLE(CSS_SCROLL_SNAP) && PLATFORM(MAC)
87
bool ScrollAnimator::processWheelEventForScrollSnap(const PlatformWheelEvent& wheelEvent)
84
void ScrollAnimator::processWheelEventForScrollSnap(const PlatformWheelEvent& wheelEvent)
88
{
85
{
89
    return m_scrollController.processWheelEventForScrollSnap(wheelEvent);
86
    if (m_verticalScrollSnapAnimator)
87
        m_verticalScrollSnapAnimator->handleWheelEvent(wheelEvent);
88
    if (m_horizontalScrollSnapAnimator)
89
        m_horizontalScrollSnapAnimator->handleWheelEvent(wheelEvent);
90
}
90
}
91
#endif
91
#endif
92
92
93
bool ScrollAnimator::handleWheelEvent(const PlatformWheelEvent& e)
93
bool ScrollAnimator::handleWheelEvent(const PlatformWheelEvent& e)
94
{
94
{
95
#if ENABLE(CSS_SCROLL_SNAP) && PLATFORM(MAC)
95
#if ENABLE(CSS_SCROLL_SNAP) && PLATFORM(MAC)
96
    m_scrollController.processWheelEventForScrollSnap(e);
96
    if (m_verticalScrollSnapAnimator) {
97
        m_verticalScrollSnapAnimator->handleWheelEvent(e);
98
        if (m_verticalScrollSnapAnimator->shouldOverrideWheelEvent(e))
99
            return false;
100
    }
101
    if (m_horizontalScrollSnapAnimator) {
102
        m_horizontalScrollSnapAnimator->handleWheelEvent(e);
103
        if (m_horizontalScrollSnapAnimator->shouldOverrideWheelEvent(e))
104
            return false;
105
    }
97
#endif
106
#endif
98
#if PLATFORM(COCOA)
107
#if PLATFORM(COCOA)
99
    // Events in the PlatformWheelEventPhaseMayBegin phase have no deltas, and therefore never passes through the scroll handling logic below.
108
    // Events in the PlatformWheelEventPhaseMayBegin phase have no deltas, and therefore never passes through the scroll handling logic below.
Lines 174-188 void ScrollAnimator::notifyPositionChanged(const FloatSize& delta) a/Source/WebCore/platform/ScrollAnimator.cpp_sec3
174
#if ENABLE(CSS_SCROLL_SNAP) && PLATFORM(MAC)
183
#if ENABLE(CSS_SCROLL_SNAP) && PLATFORM(MAC)
175
void ScrollAnimator::updateScrollAnimatorsAndTimers()
184
void ScrollAnimator::updateScrollAnimatorsAndTimers()
176
{
185
{
177
    m_scrollController.updateScrollAnimatorsAndTimers(m_scrollableArea);
186
    // FIXME: Currently, scroll snap animators are recreated even though the snap offsets alone can be updated.
187
    if (m_scrollableArea.horizontalSnapOffsets()) {
188
        m_horizontalScrollSnapAnimator = std::make_unique<AxisScrollSnapAnimator>(this, m_scrollableArea.horizontalSnapOffsets(), ScrollEventAxis::Horizontal);
189
        m_horizontalScrollSnapTimer = std::make_unique<Timer>(*this, &ScrollAnimator::horizontalScrollSnapTimerFired);
190
    } else if (m_horizontalScrollSnapAnimator) {
191
        m_horizontalScrollSnapAnimator = nullptr;
192
        m_horizontalScrollSnapTimer = nullptr;
193
    }
194
    if (m_scrollableArea.verticalSnapOffsets()) {
195
        m_verticalScrollSnapAnimator = std::make_unique<AxisScrollSnapAnimator>(this, m_scrollableArea.verticalSnapOffsets(), ScrollEventAxis::Vertical);
196
        m_verticalScrollSnapTimer = std::make_unique<Timer>(*this, &ScrollAnimator::verticalScrollSnapTimerFired);
197
    } else if (m_verticalScrollSnapAnimator) {
198
        m_verticalScrollSnapAnimator = nullptr;
199
        m_verticalScrollSnapTimer = nullptr;
200
    }
178
}
201
}
179
202
180
LayoutUnit ScrollAnimator::scrollOffsetOnAxis(ScrollEventAxis axis)
203
LayoutUnit ScrollAnimator::scrollOffsetInAxis(ScrollEventAxis axis)
181
{
204
{
182
    return axis == ScrollEventAxis::Horizontal ? m_currentPosX : m_currentPosY;
205
    FloatPoint currentPosition = this->currentPosition();
206
    return axis == ScrollEventAxis::Horizontal ? currentPosition.x() : currentPosition.y();
183
}
207
}
184
208
185
void ScrollAnimator::immediateScrollOnAxis(ScrollEventAxis axis, float delta)
209
void ScrollAnimator::immediateScrollInAxis(ScrollEventAxis axis, float delta)
186
{
210
{
187
    FloatPoint currentPosition = this->currentPosition();
211
    FloatPoint currentPosition = this->currentPosition();
188
    if (axis == ScrollEventAxis::Horizontal)
212
    if (axis == ScrollEventAxis::Horizontal)
Lines 190-195 void ScrollAnimator::immediateScrollOnAxis(ScrollEventAxis axis, float delta) a/Source/WebCore/platform/ScrollAnimator.cpp_sec4
190
    else
214
    else
191
        scrollToOffsetWithoutAnimation(FloatPoint(currentPosition.x(), currentPosition.y() + delta));
215
        scrollToOffsetWithoutAnimation(FloatPoint(currentPosition.x(), currentPosition.y() + delta));
192
}
216
}
217
218
void ScrollAnimator::startScrollSnapTimer(ScrollEventAxis axis)
219
{
220
    Timer* scrollSnapTimer = axis == ScrollEventAxis::Horizontal ? m_horizontalScrollSnapTimer.get() : m_verticalScrollSnapTimer.get();
221
    if (!scrollSnapTimer->isActive())
222
        scrollSnapTimer->startRepeating(1.0 / 60.0);
223
}
224
225
void ScrollAnimator::stopScrollSnapTimer(ScrollEventAxis axis)
226
{
227
    Timer* scrollSnapTimer = axis == ScrollEventAxis::Horizontal ? m_horizontalScrollSnapTimer.get() : m_verticalScrollSnapTimer.get();
228
    if (scrollSnapTimer->isActive())
229
        scrollSnapTimer->stop();
230
}
231
232
void ScrollAnimator::horizontalScrollSnapTimerFired()
233
{
234
    m_horizontalScrollSnapAnimator->scrollSnapAnimationUpdate();
235
}
236
237
void ScrollAnimator::verticalScrollSnapTimerFired()
238
{
239
    m_verticalScrollSnapAnimator->scrollSnapAnimationUpdate();
240
}
193
#endif
241
#endif
194
242
195
} // namespace WebCore
243
} // namespace WebCore
- a/Source/WebCore/platform/ScrollAnimator.h -12 / +23 lines
Lines 33-46 a/Source/WebCore/platform/ScrollAnimator.h_sec1
33
#define ScrollAnimator_h
33
#define ScrollAnimator_h
34
34
35
#include "FloatSize.h"
35
#include "FloatSize.h"
36
#include "LayoutUnit.h"
37
#include "PlatformWheelEvent.h"
36
#include "PlatformWheelEvent.h"
38
#include "ScrollTypes.h"
37
#include "ScrollTypes.h"
39
#include <wtf/FastMalloc.h>
38
#include <wtf/FastMalloc.h>
40
#include <wtf/Forward.h>
39
#include <wtf/Forward.h>
41
40
42
#if (ENABLE(RUBBER_BANDING) || ENABLE(CSS_SCROLL_SNAP)) && PLATFORM(MAC)
41
#if ENABLE(CSS_SCROLL_SNAP) && PLATFORM(MAC)
43
#include "ScrollController.h"
42
#include "AxisScrollSnapAnimator.h"
43
#include "Timer.h"
44
#endif
44
#endif
45
45
46
namespace WebCore {
46
namespace WebCore {
Lines 50-57 class PlatformTouchEvent; a/Source/WebCore/platform/ScrollAnimator.h_sec2
50
class ScrollableArea;
50
class ScrollableArea;
51
class Scrollbar;
51
class Scrollbar;
52
52
53
#if (ENABLE(CSS_SCROLL_SNAP) || ENABLE(RUBBER_BANDING)) && PLATFORM(MAC)
53
#if ENABLE(CSS_SCROLL_SNAP) && PLATFORM(MAC)
54
class ScrollAnimator : private ScrollControllerClient {
54
class ScrollAnimator : public AxisScrollSnapAnimatorClient {
55
#else
55
#else
56
class ScrollAnimator {
56
class ScrollAnimator {
57
#endif
57
#endif
Lines 118-139 public: a/Source/WebCore/platform/ScrollAnimator.h_sec3
118
    virtual bool isRubberBandInProgress() const { return false; }
118
    virtual bool isRubberBandInProgress() const { return false; }
119
119
120
#if ENABLE(CSS_SCROLL_SNAP) && PLATFORM(MAC)
120
#if ENABLE(CSS_SCROLL_SNAP) && PLATFORM(MAC)
121
    bool processWheelEventForScrollSnap(const PlatformWheelEvent&);
121
    void processWheelEventForScrollSnap(const PlatformWheelEvent&);
122
123
    void updateScrollAnimatorsAndTimers();
122
    void updateScrollAnimatorsAndTimers();
124
    LayoutUnit scrollOffsetOnAxis(ScrollEventAxis) override;
123
    virtual LayoutUnit scrollOffsetInAxis(ScrollEventAxis) override;
125
    void immediateScrollOnAxis(ScrollEventAxis, float delta) override;
124
    virtual void immediateScrollInAxis(ScrollEventAxis, float delta) override;
125
    virtual void startScrollSnapTimer(ScrollEventAxis) override;
126
    virtual void stopScrollSnapTimer(ScrollEventAxis) override;
126
#endif
127
#endif
127
128
128
protected:
129
protected:
129
    virtual void notifyPositionChanged(const FloatSize& delta);
130
    virtual void notifyPositionChanged(const FloatSize& delta);
130
131
131
    ScrollableArea& m_scrollableArea;
132
#if ENABLE(CSS_SCROLL_SNAP) && PLATFORM(MAC)
132
#if (ENABLE(CSS_SCROLL_SNAP) || ENABLE(RUBBER_BANDING)) && PLATFORM(MAC)
133
    // Trivial wrappers around the actual update loop in AxisScrollSnapAnimator, since WebCore Timer requires a Timer argument.
133
    ScrollController m_scrollController;
134
    void horizontalScrollSnapTimerFired();
135
    void verticalScrollSnapTimerFired();
134
#endif
136
#endif
137
138
    ScrollableArea& m_scrollableArea;
135
    float m_currentPosX; // We avoid using a FloatPoint in order to reduce
139
    float m_currentPosX; // We avoid using a FloatPoint in order to reduce
136
    float m_currentPosY; // subclass code complexity.
140
    float m_currentPosY; // subclass code complexity.
141
#if ENABLE(CSS_SCROLL_SNAP) && PLATFORM(MAC)
142
    std::unique_ptr<AxisScrollSnapAnimator> m_horizontalScrollSnapAnimator;
143
    std::unique_ptr<Timer> m_horizontalScrollSnapTimer;
144
    // FIXME: Find a way to consolidate both timers into one variable.
145
    std::unique_ptr<AxisScrollSnapAnimator> m_verticalScrollSnapAnimator;
146
    std::unique_ptr<Timer> m_verticalScrollSnapTimer;
147
#endif
137
};
148
};
138
149
139
} // namespace WebCore
150
} // namespace WebCore
- a/Source/WebCore/platform/cocoa/ScrollController.h -144 lines
Lines 1-144 a/Source/WebCore/platform/cocoa/ScrollController.h_sec1
1
/*
2
 * Copyright (C) 2011, 2014-2015 Apple Inc. All rights reserved.
3
 *
4
 * Redistribution and use in source and binary forms, with or without
5
 * modification, are permitted provided that the following conditions
6
 * are met:
7
 * 1. Redistributions of source code must retain the above copyright
8
 *    notice, this list of conditions and the following disclaimer.
9
 * 2. Redistributions in binary form must reproduce the above copyright
10
 *    notice, this list of conditions and the following disclaimer in the
11
 *    documentation and/or other materials provided with the distribution.
12
 *
13
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23
 * THE POSSIBILITY OF SUCH DAMAGE.
24
 */
25
26
#ifndef ScrollController_h
27
#define ScrollController_h
28
29
#if ENABLE(RUBBER_BANDING)
30
31
#include "FloatPoint.h"
32
#include "FloatSize.h"
33
#include "ScrollTypes.h"
34
#include <wtf/Noncopyable.h>
35
#include <wtf/RunLoop.h>
36
37
#if ENABLE(CSS_SCROLL_SNAP)
38
#include "AxisScrollSnapAnimator.h"
39
#endif
40
41
namespace WebCore {
42
43
class PlatformWheelEvent;
44
class ScrollableArea;
45
46
class ScrollControllerClient {
47
protected:
48
    virtual ~ScrollControllerClient() { }
49
50
public:
51
    virtual bool allowsHorizontalStretching(const PlatformWheelEvent&) = 0;
52
    virtual bool allowsVerticalStretching(const PlatformWheelEvent&) = 0;
53
    virtual IntSize stretchAmount() = 0;
54
    virtual bool pinnedInDirection(const FloatSize&) = 0;
55
    virtual bool canScrollHorizontally() = 0;
56
    virtual bool canScrollVertically() = 0;
57
    virtual bool shouldRubberBandInDirection(ScrollDirection) = 0;
58
59
    // Return the absolute scroll position, not relative to the scroll origin.
60
    virtual WebCore::IntPoint absoluteScrollPosition() = 0;
61
62
    virtual void immediateScrollBy(const FloatSize&) = 0;
63
    virtual void immediateScrollByWithoutContentEdgeConstraints(const FloatSize&) = 0;
64
65
    // If the current scroll position is within the overhang area, this function will cause
66
    // the page to scroll to the nearest boundary point.
67
    virtual void adjustScrollPositionToBoundsIfNecessary() = 0;
68
69
#if ENABLE(CSS_SCROLL_SNAP) && PLATFORM(MAC)
70
    virtual LayoutUnit scrollOffsetOnAxis(ScrollEventAxis) = 0;
71
    virtual void immediateScrollOnAxis(ScrollEventAxis, float delta) = 0;
72
#endif
73
};
74
75
#if ENABLE(CSS_SCROLL_SNAP) && PLATFORM(MAC)
76
class ScrollController : public AxisScrollSnapAnimatorClient {
77
#else
78
class ScrollController {
79
#endif
80
    WTF_MAKE_NONCOPYABLE(ScrollController);
81
82
public:
83
    explicit ScrollController(ScrollControllerClient*);
84
85
    bool handleWheelEvent(const PlatformWheelEvent&);
86
87
    bool isRubberBandInProgress() const;
88
89
#if ENABLE(CSS_SCROLL_SNAP) && PLATFORM(MAC)
90
    bool processWheelEventForScrollSnap(const PlatformWheelEvent&);
91
    void updateScrollAnimatorsAndTimers(const ScrollableArea&);
92
#endif
93
94
private:
95
    void startSnapRubberbandTimer();
96
    void stopSnapRubberbandTimer();
97
    void snapRubberBand();
98
    void snapRubberBandTimerFired();
99
100
    bool shouldRubberBandInHorizontalDirection(const PlatformWheelEvent&);
101
102
#if ENABLE(CSS_SCROLL_SNAP) && PLATFORM(MAC)
103
    void horizontalScrollSnapTimerFired();
104
    void verticalScrollSnapTimerFired();
105
    void startScrollSnapTimer(ScrollEventAxis);
106
    void stopScrollSnapTimer(ScrollEventAxis);
107
108
    LayoutUnit scrollOffsetOnAxis(ScrollEventAxis) override;
109
    void immediateScrollOnAxis(ScrollEventAxis, float delta) override;
110
#endif
111
112
    ScrollControllerClient* m_client;
113
    
114
    CFTimeInterval m_lastMomentumScrollTimestamp;
115
    FloatSize m_overflowScrollDelta;
116
    FloatSize m_stretchScrollForce;
117
    FloatSize m_momentumVelocity;
118
119
    // Rubber band state.
120
    CFTimeInterval m_startTime;
121
    FloatSize m_startStretch;
122
    FloatPoint m_origOrigin;
123
    FloatSize m_origVelocity;
124
    RunLoop::Timer<ScrollController> m_snapRubberbandTimer;
125
    
126
#if ENABLE(CSS_SCROLL_SNAP) && PLATFORM(MAC)
127
    // FIXME: Find a way to consolidate both timers into one variable.
128
    std::unique_ptr<AxisScrollSnapAnimator> m_horizontalScrollSnapAnimator;
129
    std::unique_ptr<AxisScrollSnapAnimator> m_verticalScrollSnapAnimator;
130
    RunLoop::Timer<ScrollController> m_horizontalScrollSnapTimer;
131
    RunLoop::Timer<ScrollController> m_verticalScrollSnapTimer;
132
#endif
133
134
    bool m_inScrollGesture;
135
    bool m_momentumScrollInProgress;
136
    bool m_ignoreMomentumScrolls;
137
    bool m_snapRubberbandTimerIsActive;
138
};
139
140
} // namespace WebCore
141
142
#endif // ENABLE(RUBBER_BANDING)
143
144
#endif // ScrollController_h
- a/Source/WebCore/platform/cocoa/ScrollController.mm -492 lines
Lines 1-492 a/Source/WebCore/platform/cocoa/ScrollController.mm_sec1
1
/*
2
 * Copyright (C) 2011, 2014-2015 Apple Inc. All rights reserved.
3
 *
4
 * Redistribution and use in source and binary forms, with or without
5
 * modification, are permitted provided that the following conditions
6
 * are met:
7
 * 1. Redistributions of source code must retain the above copyright
8
 *    notice, this list of conditions and the following disclaimer.
9
 * 2. Redistributions in binary form must reproduce the above copyright
10
 *    notice, this list of conditions and the following disclaimer in the
11
 *    documentation and/or other materials provided with the distribution.
12
 *
13
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23
 * THE POSSIBILITY OF SUCH DAMAGE.
24
 */
25
26
#include "config.h"
27
#include "ScrollController.h"
28
29
#include "PlatformWheelEvent.h"
30
#include "WebCoreSystemInterface.h"
31
#include <sys/sysctl.h>
32
#include <sys/time.h>
33
34
#if ENABLE(CSS_SCROLL_SNAP)
35
#include "AxisScrollSnapAnimator.h"
36
#include "ScrollableArea.h"
37
#endif
38
39
#if ENABLE(RUBBER_BANDING)
40
41
static NSTimeInterval systemUptime()
42
{
43
    if ([[NSProcessInfo processInfo] respondsToSelector:@selector(systemUptime)])
44
        return [[NSProcessInfo processInfo] systemUptime];
45
46
    // Get how long system has been up. Found by looking getting "boottime" from the kernel.
47
    static struct timeval boottime = {0, 0};
48
    if (!boottime.tv_sec) {
49
        int mib[2] = {CTL_KERN, KERN_BOOTTIME};
50
        size_t size = sizeof(boottime);
51
        if (-1 == sysctl(mib, 2, &boottime, &size, 0, 0))
52
            boottime.tv_sec = 0;
53
    }
54
    struct timeval now;
55
    if (boottime.tv_sec && -1 != gettimeofday(&now, 0)) {
56
        struct timeval uptime;
57
        timersub(&now, &boottime, &uptime);
58
        NSTimeInterval result = uptime.tv_sec + (uptime.tv_usec / 1E+6);
59
        return result;
60
    }
61
    return 0;
62
}
63
64
65
namespace WebCore {
66
67
static const float scrollVelocityZeroingTimeout = 0.10f;
68
static const float rubberbandDirectionLockStretchRatio = 1;
69
static const float rubberbandMinimumRequiredDeltaBeforeStretch = 10;
70
71
static float elasticDeltaForTimeDelta(float initialPosition, float initialVelocity, float elapsedTime)
72
{
73
    return wkNSElasticDeltaForTimeDelta(initialPosition, initialVelocity, elapsedTime);
74
}
75
76
static float elasticDeltaForReboundDelta(float delta)
77
{
78
    return wkNSElasticDeltaForReboundDelta(delta);
79
}
80
81
static float reboundDeltaForElasticDelta(float delta)
82
{
83
    return wkNSReboundDeltaForElasticDelta(delta);
84
}
85
86
static float scrollWheelMultiplier()
87
{
88
    static float multiplier = -1;
89
    if (multiplier < 0) {
90
        multiplier = [[NSUserDefaults standardUserDefaults] floatForKey:@"NSScrollWheelMultiplier"];
91
        if (multiplier <= 0)
92
            multiplier = 1;
93
    }
94
    return multiplier;
95
}
96
97
ScrollController::ScrollController(ScrollControllerClient* client)
98
    : m_client(client)
99
    , m_lastMomentumScrollTimestamp(0)
100
    , m_startTime(0)
101
    , m_snapRubberbandTimer(RunLoop::current(), this, &ScrollController::snapRubberBandTimerFired)
102
#if ENABLE(CSS_SCROLL_SNAP) && PLATFORM(MAC)
103
    , m_horizontalScrollSnapTimer(RunLoop::current(), this, &ScrollController::horizontalScrollSnapTimerFired)
104
    , m_verticalScrollSnapTimer(RunLoop::current(), this, &ScrollController::verticalScrollSnapTimerFired)
105
#endif
106
    , m_inScrollGesture(false)
107
    , m_momentumScrollInProgress(false)
108
    , m_ignoreMomentumScrolls(false)
109
    , m_snapRubberbandTimerIsActive(false)
110
{
111
}
112
113
bool ScrollController::handleWheelEvent(const PlatformWheelEvent& wheelEvent)
114
{
115
#if ENABLE(CSS_SCROLL_SNAP) && PLATFORM(MAC)
116
    if (!processWheelEventForScrollSnap(wheelEvent))
117
        return false;
118
#endif
119
    if (wheelEvent.phase() == PlatformWheelEventPhaseBegan) {
120
        // First, check if we should rubber-band at all.
121
        if (m_client->pinnedInDirection(FloatSize(-wheelEvent.deltaX(), 0))
122
            && !shouldRubberBandInHorizontalDirection(wheelEvent))
123
            return false;
124
125
        m_inScrollGesture = true;
126
        m_momentumScrollInProgress = false;
127
        m_ignoreMomentumScrolls = false;
128
        m_lastMomentumScrollTimestamp = 0;
129
        m_momentumVelocity = FloatSize();
130
131
        IntSize stretchAmount = m_client->stretchAmount();
132
        m_stretchScrollForce.setWidth(reboundDeltaForElasticDelta(stretchAmount.width()));
133
        m_stretchScrollForce.setHeight(reboundDeltaForElasticDelta(stretchAmount.height()));
134
        m_overflowScrollDelta = FloatSize();
135
136
        stopSnapRubberbandTimer();
137
138
        return true;
139
    }
140
141
    if (wheelEvent.phase() == PlatformWheelEventPhaseEnded) {
142
        snapRubberBand();
143
        return true;
144
    }
145
146
    bool isMomentumScrollEvent = (wheelEvent.momentumPhase() != PlatformWheelEventPhaseNone);
147
    if (m_ignoreMomentumScrolls && (isMomentumScrollEvent || m_snapRubberbandTimerIsActive)) {
148
        if (wheelEvent.momentumPhase() == PlatformWheelEventPhaseEnded) {
149
            m_ignoreMomentumScrolls = false;
150
            return true;
151
        }
152
        return false;
153
    }
154
155
    float deltaX = m_overflowScrollDelta.width();
156
    float deltaY = m_overflowScrollDelta.height();
157
158
    // Reset overflow values because we may decide to remove delta at various points and put it into overflow.
159
    m_overflowScrollDelta = FloatSize();
160
161
    IntSize stretchAmount = m_client->stretchAmount();
162
    bool isVerticallyStretched = stretchAmount.height();
163
    bool isHorizontallyStretched = stretchAmount.width();
164
165
    float eventCoalescedDeltaX;
166
    float eventCoalescedDeltaY;
167
168
    if (isVerticallyStretched || isHorizontallyStretched) {
169
        eventCoalescedDeltaX = -wheelEvent.unacceleratedScrollingDeltaX();
170
        eventCoalescedDeltaY = -wheelEvent.unacceleratedScrollingDeltaY();
171
    } else {
172
        eventCoalescedDeltaX = -wheelEvent.deltaX();
173
        eventCoalescedDeltaY = -wheelEvent.deltaY();
174
    }
175
176
    deltaX += eventCoalescedDeltaX;
177
    deltaY += eventCoalescedDeltaY;
178
179
    // Slightly prefer scrolling vertically by applying the = case to deltaY
180
    if (fabsf(deltaY) >= fabsf(deltaX))
181
        deltaX = 0;
182
    else
183
        deltaY = 0;
184
185
    bool shouldStretch = false;
186
187
    PlatformWheelEventPhase momentumPhase = wheelEvent.momentumPhase();
188
189
    // If we are starting momentum scrolling then do some setup.
190
    if (!m_momentumScrollInProgress && (momentumPhase == PlatformWheelEventPhaseBegan || momentumPhase == PlatformWheelEventPhaseChanged))
191
        m_momentumScrollInProgress = true;
192
193
    CFTimeInterval timeDelta = wheelEvent.timestamp() - m_lastMomentumScrollTimestamp;
194
    if (m_inScrollGesture || m_momentumScrollInProgress) {
195
        if (m_lastMomentumScrollTimestamp && timeDelta > 0 && timeDelta < scrollVelocityZeroingTimeout) {
196
            m_momentumVelocity.setWidth(eventCoalescedDeltaX / (float)timeDelta);
197
            m_momentumVelocity.setHeight(eventCoalescedDeltaY / (float)timeDelta);
198
            m_lastMomentumScrollTimestamp = wheelEvent.timestamp();
199
        } else {
200
            m_lastMomentumScrollTimestamp = wheelEvent.timestamp();
201
            m_momentumVelocity = FloatSize();
202
        }
203
204
        if (isVerticallyStretched) {
205
            if (!isHorizontallyStretched && m_client->pinnedInDirection(FloatSize(deltaX, 0))) {
206
                // Stretching only in the vertical.
207
                if (deltaY && (fabsf(deltaX / deltaY) < rubberbandDirectionLockStretchRatio))
208
                    deltaX = 0;
209
                else if (fabsf(deltaX) < rubberbandMinimumRequiredDeltaBeforeStretch) {
210
                    m_overflowScrollDelta.setWidth(m_overflowScrollDelta.width() + deltaX);
211
                    deltaX = 0;
212
                } else
213
                    m_overflowScrollDelta.setWidth(m_overflowScrollDelta.width() + deltaX);
214
            }
215
        } else if (isHorizontallyStretched) {
216
            // Stretching only in the horizontal.
217
            if (m_client->pinnedInDirection(FloatSize(0, deltaY))) {
218
                if (deltaX && (fabsf(deltaY / deltaX) < rubberbandDirectionLockStretchRatio))
219
                    deltaY = 0;
220
                else if (fabsf(deltaY) < rubberbandMinimumRequiredDeltaBeforeStretch) {
221
                    m_overflowScrollDelta.setHeight(m_overflowScrollDelta.height() + deltaY);
222
                    deltaY = 0;
223
                } else
224
                    m_overflowScrollDelta.setHeight(m_overflowScrollDelta.height() + deltaY);
225
            }
226
        } else {
227
            // Not stretching at all yet.
228
            if (m_client->pinnedInDirection(FloatSize(deltaX, deltaY))) {
229
                if (fabsf(deltaY) >= fabsf(deltaX)) {
230
                    if (fabsf(deltaX) < rubberbandMinimumRequiredDeltaBeforeStretch) {
231
                        m_overflowScrollDelta.setWidth(m_overflowScrollDelta.width() + deltaX);
232
                        deltaX = 0;
233
                    } else
234
                        m_overflowScrollDelta.setWidth(m_overflowScrollDelta.width() + deltaX);
235
                }
236
                shouldStretch = true;
237
            }
238
        }
239
    }
240
241
    if (deltaX || deltaY) {
242
        if (!(shouldStretch || isVerticallyStretched || isHorizontallyStretched)) {
243
            if (deltaY) {
244
                deltaY *= scrollWheelMultiplier();
245
                m_client->immediateScrollBy(FloatSize(0, deltaY));
246
            }
247
            if (deltaX) {
248
                deltaX *= scrollWheelMultiplier();
249
                m_client->immediateScrollBy(FloatSize(deltaX, 0));
250
            }
251
        } else {
252
            if (!m_client->allowsHorizontalStretching(wheelEvent)) {
253
                deltaX = 0;
254
                eventCoalescedDeltaX = 0;
255
            } else if (deltaX && !isHorizontallyStretched && !m_client->pinnedInDirection(FloatSize(deltaX, 0))) {
256
                deltaX *= scrollWheelMultiplier();
257
258
                m_client->immediateScrollByWithoutContentEdgeConstraints(FloatSize(deltaX, 0));
259
                deltaX = 0;
260
            }
261
262
            if (!m_client->allowsVerticalStretching(wheelEvent)) {
263
                deltaY = 0;
264
                eventCoalescedDeltaY = 0;
265
            } else if (deltaY && !isVerticallyStretched && !m_client->pinnedInDirection(FloatSize(0, deltaY))) {
266
                deltaY *= scrollWheelMultiplier();
267
268
                m_client->immediateScrollByWithoutContentEdgeConstraints(FloatSize(0, deltaY));
269
                deltaY = 0;
270
            }
271
272
            IntSize stretchAmount = m_client->stretchAmount();
273
274
            if (m_momentumScrollInProgress) {
275
                if ((m_client->pinnedInDirection(FloatSize(eventCoalescedDeltaX, eventCoalescedDeltaY)) || (fabsf(eventCoalescedDeltaX) + fabsf(eventCoalescedDeltaY) <= 0)) && m_lastMomentumScrollTimestamp) {
276
                    m_ignoreMomentumScrolls = true;
277
                    m_momentumScrollInProgress = false;
278
                    snapRubberBand();
279
                }
280
            }
281
282
            m_stretchScrollForce.setWidth(m_stretchScrollForce.width() + deltaX);
283
            m_stretchScrollForce.setHeight(m_stretchScrollForce.height() + deltaY);
284
285
            FloatSize dampedDelta(ceilf(elasticDeltaForReboundDelta(m_stretchScrollForce.width())), ceilf(elasticDeltaForReboundDelta(m_stretchScrollForce.height())));
286
287
            m_client->immediateScrollByWithoutContentEdgeConstraints(dampedDelta - stretchAmount);
288
        }
289
    }
290
291
    if (m_momentumScrollInProgress && momentumPhase == PlatformWheelEventPhaseEnded) {
292
        m_momentumScrollInProgress = false;
293
        m_ignoreMomentumScrolls = false;
294
        m_lastMomentumScrollTimestamp = 0;
295
    }
296
297
    return true;
298
}
299
300
static inline float roundTowardZero(float num)
301
{
302
    return num > 0 ? ceilf(num - 0.5f) : floorf(num + 0.5f);
303
}
304
305
static inline float roundToDevicePixelTowardZero(float num)
306
{
307
    float roundedNum = roundf(num);
308
    if (fabs(num - roundedNum) < 0.125)
309
        num = roundedNum;
310
311
    return roundTowardZero(num);
312
}
313
314
void ScrollController::snapRubberBandTimerFired()
315
{
316
    if (!m_momentumScrollInProgress || m_ignoreMomentumScrolls) {
317
        CFTimeInterval timeDelta = [NSDate timeIntervalSinceReferenceDate] - m_startTime;
318
319
        if (m_startStretch == FloatSize()) {
320
            m_startStretch = m_client->stretchAmount();
321
            if (m_startStretch == FloatSize()) {
322
                stopSnapRubberbandTimer();
323
324
                m_stretchScrollForce = FloatSize();
325
                m_startTime = 0;
326
                m_startStretch = FloatSize();
327
                m_origOrigin = FloatPoint();
328
                m_origVelocity = FloatSize();
329
                return;
330
            }
331
332
            m_origOrigin = m_client->absoluteScrollPosition() - m_startStretch;
333
            m_origVelocity = m_momentumVelocity;
334
335
            // Just like normal scrolling, prefer vertical rubberbanding
336
            if (fabsf(m_origVelocity.height()) >= fabsf(m_origVelocity.width()))
337
                m_origVelocity.setWidth(0);
338
339
            // Don't rubber-band horizontally if it's not possible to scroll horizontally
340
            if (!m_client->canScrollHorizontally())
341
                m_origVelocity.setWidth(0);
342
343
            // Don't rubber-band vertically if it's not possible to scroll vertically
344
            if (!m_client->canScrollVertically())
345
                m_origVelocity.setHeight(0);
346
        }
347
348
        FloatPoint delta(roundToDevicePixelTowardZero(elasticDeltaForTimeDelta(m_startStretch.width(), -m_origVelocity.width(), (float)timeDelta)),
349
            roundToDevicePixelTowardZero(elasticDeltaForTimeDelta(m_startStretch.height(), -m_origVelocity.height(), (float)timeDelta)));
350
351
        if (fabs(delta.x()) >= 1 || fabs(delta.y()) >= 1) {
352
            m_client->immediateScrollByWithoutContentEdgeConstraints(FloatSize(delta.x(), delta.y()) - m_client->stretchAmount());
353
354
            FloatSize newStretch = m_client->stretchAmount();
355
356
            m_stretchScrollForce.setWidth(reboundDeltaForElasticDelta(newStretch.width()));
357
            m_stretchScrollForce.setHeight(reboundDeltaForElasticDelta(newStretch.height()));
358
        } else {
359
            m_client->adjustScrollPositionToBoundsIfNecessary();
360
361
            stopSnapRubberbandTimer();
362
            m_stretchScrollForce = FloatSize();
363
            m_startTime = 0;
364
            m_startStretch = FloatSize();
365
            m_origOrigin = FloatPoint();
366
            m_origVelocity = FloatSize();
367
        }
368
    } else {
369
        m_startTime = [NSDate timeIntervalSinceReferenceDate];
370
        m_startStretch = FloatSize();
371
    }
372
}
373
374
bool ScrollController::isRubberBandInProgress() const
375
{
376
    if (!m_inScrollGesture && !m_momentumScrollInProgress && !m_snapRubberbandTimerIsActive)
377
        return false;
378
379
    return !m_client->stretchAmount().isZero();
380
}
381
382
void ScrollController::startSnapRubberbandTimer()
383
{
384
    m_snapRubberbandTimer.startRepeating(1.0 / 60.0);
385
}
386
387
void ScrollController::stopSnapRubberbandTimer()
388
{
389
    m_snapRubberbandTimer.stop();
390
    m_snapRubberbandTimerIsActive = false;
391
}
392
393
void ScrollController::snapRubberBand()
394
{
395
    CFTimeInterval timeDelta = systemUptime() - m_lastMomentumScrollTimestamp;
396
    if (m_lastMomentumScrollTimestamp && timeDelta >= scrollVelocityZeroingTimeout)
397
        m_momentumVelocity = FloatSize();
398
399
    m_inScrollGesture = false;
400
401
    if (m_snapRubberbandTimerIsActive)
402
        return;
403
404
    m_startTime = [NSDate timeIntervalSinceReferenceDate];
405
    m_startStretch = FloatSize();
406
    m_origOrigin = FloatPoint();
407
    m_origVelocity = FloatSize();
408
409
    startSnapRubberbandTimer();
410
    m_snapRubberbandTimerIsActive = true;
411
}
412
413
bool ScrollController::shouldRubberBandInHorizontalDirection(const PlatformWheelEvent& wheelEvent)
414
{
415
    if (wheelEvent.deltaX() > 0)
416
        return m_client->shouldRubberBandInDirection(ScrollLeft);
417
    if (wheelEvent.deltaX() < 0)
418
        return m_client->shouldRubberBandInDirection(ScrollRight);
419
420
    return true;
421
}
422
423
#if ENABLE(CSS_SCROLL_SNAP) && PLATFORM(MAC)
424
bool ScrollController::processWheelEventForScrollSnap(const PlatformWheelEvent& wheelEvent)
425
{
426
    if (m_verticalScrollSnapAnimator) {
427
        m_verticalScrollSnapAnimator->handleWheelEvent(wheelEvent);
428
        if (m_verticalScrollSnapAnimator->shouldOverrideWheelEvent(wheelEvent))
429
            return false;
430
    }
431
    if (m_horizontalScrollSnapAnimator) {
432
        m_horizontalScrollSnapAnimator->handleWheelEvent(wheelEvent);
433
        if (m_horizontalScrollSnapAnimator->shouldOverrideWheelEvent(wheelEvent))
434
            return false;
435
    }
436
437
    return true;
438
}
439
    
440
void ScrollController::updateScrollAnimatorsAndTimers(const ScrollableArea& scrollableArea)
441
{
442
    // FIXME: Currently, scroll snap animators are recreated even though the snap offsets alone can be updated.
443
    if (scrollableArea.horizontalSnapOffsets())
444
        m_horizontalScrollSnapAnimator = std::make_unique<AxisScrollSnapAnimator>(this, scrollableArea.horizontalSnapOffsets(), ScrollEventAxis::Horizontal);
445
    else if (m_horizontalScrollSnapAnimator)
446
        m_horizontalScrollSnapAnimator = nullptr;
447
448
    if (scrollableArea.verticalSnapOffsets())
449
        m_verticalScrollSnapAnimator = std::make_unique<AxisScrollSnapAnimator>(this, scrollableArea.verticalSnapOffsets(), ScrollEventAxis::Vertical);
450
    else if (m_verticalScrollSnapAnimator)
451
        m_verticalScrollSnapAnimator = nullptr;
452
}
453
454
void ScrollController::startScrollSnapTimer(ScrollEventAxis axis)
455
{
456
    RunLoop::Timer<ScrollController>& scrollSnapTimer = axis == ScrollEventAxis::Horizontal ? m_horizontalScrollSnapTimer : m_verticalScrollSnapTimer;
457
    if (!scrollSnapTimer.isActive())
458
        scrollSnapTimer.startRepeating(1.0 / 60.0);
459
}
460
461
void ScrollController::stopScrollSnapTimer(ScrollEventAxis axis)
462
{
463
    RunLoop::Timer<ScrollController>& scrollSnapTimer = axis == ScrollEventAxis::Horizontal ? m_horizontalScrollSnapTimer : m_verticalScrollSnapTimer;
464
    scrollSnapTimer.stop();
465
}
466
    
467
void ScrollController::horizontalScrollSnapTimerFired()
468
{
469
    if (m_horizontalScrollSnapAnimator)
470
        m_horizontalScrollSnapAnimator->scrollSnapAnimationUpdate();
471
}
472
473
void ScrollController::verticalScrollSnapTimerFired()
474
{
475
    if (m_verticalScrollSnapAnimator)
476
        m_verticalScrollSnapAnimator->scrollSnapAnimationUpdate();
477
}
478
479
LayoutUnit ScrollController::scrollOffsetOnAxis(ScrollEventAxis axis)
480
{
481
    return m_client->scrollOffsetOnAxis(axis);
482
}
483
484
void ScrollController::immediateScrollOnAxis(ScrollEventAxis axis, float delta)
485
{
486
    m_client->immediateScrollOnAxis(axis, delta);
487
}
488
#endif
489
490
} // namespace WebCore
491
492
#endif // ENABLE(RUBBER_BANDING)
- a/Source/WebCore/platform/mac/AxisScrollSnapAnimator.h -2 / +2 lines
Lines 57-64 protected: a/Source/WebCore/platform/mac/AxisScrollSnapAnimator.h_sec1
57
    virtual ~AxisScrollSnapAnimatorClient() { }
57
    virtual ~AxisScrollSnapAnimatorClient() { }
58
58
59
public:
59
public:
60
    virtual LayoutUnit scrollOffsetOnAxis(ScrollEventAxis) = 0;
60
    virtual LayoutUnit scrollOffsetInAxis(ScrollEventAxis) = 0;
61
    virtual void immediateScrollOnAxis(ScrollEventAxis, float velocity) = 0;
61
    virtual void immediateScrollInAxis(ScrollEventAxis, float velocity) = 0;
62
    virtual void startScrollSnapTimer(ScrollEventAxis) = 0;
62
    virtual void startScrollSnapTimer(ScrollEventAxis) = 0;
63
    virtual void stopScrollSnapTimer(ScrollEventAxis) = 0;
63
    virtual void stopScrollSnapTimer(ScrollEventAxis) = 0;
64
};
64
};
- a/Source/WebCore/platform/mac/AxisScrollSnapAnimator.mm -5 / +5 lines
Lines 117-123 void AxisScrollSnapAnimator::handleWheelEvent(const PlatformWheelEvent& event) a/Source/WebCore/platform/mac/AxisScrollSnapAnimator.mm_sec1
117
        // Begin tracking wheel deltas for glide prediction.
117
        // Begin tracking wheel deltas for glide prediction.
118
        endScrollSnapAnimation(ScrollSnapState::UserInteraction);
118
        endScrollSnapAnimation(ScrollSnapState::UserInteraction);
119
        pushInitialWheelDelta(wheelDelta);
119
        pushInitialWheelDelta(wheelDelta);
120
        m_beginTrackingWheelDeltaOffset = m_client->scrollOffsetOnAxis(m_axis);
120
        m_beginTrackingWheelDeltaOffset = m_client->scrollOffsetInAxis(m_axis);
121
        break;
121
        break;
122
122
123
    case WheelEventStatus::InertialScrolling:
123
    case WheelEventStatus::InertialScrolling:
Lines 153-159 void AxisScrollSnapAnimator::scrollSnapAnimationUpdate() a/Source/WebCore/platform/mac/AxisScrollSnapAnimator.mm_sec2
153
    ASSERT(m_currentState == ScrollSnapState::Gliding || m_currentState == ScrollSnapState::Snapping);
153
    ASSERT(m_currentState == ScrollSnapState::Gliding || m_currentState == ScrollSnapState::Snapping);
154
    float delta = m_currentState == ScrollSnapState::Snapping ? computeSnapDelta() : computeGlideDelta();
154
    float delta = m_currentState == ScrollSnapState::Snapping ? computeSnapDelta() : computeGlideDelta();
155
    if (delta)
155
    if (delta)
156
        m_client->immediateScrollOnAxis(m_axis, delta);
156
        m_client->immediateScrollInAxis(m_axis, delta);
157
    else
157
    else
158
        endScrollSnapAnimation(ScrollSnapState::DestinationReached);
158
        endScrollSnapAnimation(ScrollSnapState::DestinationReached);
159
}
159
}
Lines 161-167 void AxisScrollSnapAnimator::scrollSnapAnimationUpdate() a/Source/WebCore/platform/mac/AxisScrollSnapAnimator.mm_sec3
161
void AxisScrollSnapAnimator::beginScrollSnapAnimation(ScrollSnapState newState)
161
void AxisScrollSnapAnimator::beginScrollSnapAnimation(ScrollSnapState newState)
162
{
162
{
163
    ASSERT(newState == ScrollSnapState::Gliding || newState == ScrollSnapState::Snapping);
163
    ASSERT(newState == ScrollSnapState::Gliding || newState == ScrollSnapState::Snapping);
164
    LayoutUnit offset = m_client->scrollOffsetOnAxis(m_axis);
164
    LayoutUnit offset = m_client->scrollOffsetInAxis(m_axis);
165
    float initialWheelDelta = newState == ScrollSnapState::Gliding ? averageInitialWheelDelta() : 0;
165
    float initialWheelDelta = newState == ScrollSnapState::Gliding ? averageInitialWheelDelta() : 0;
166
    LayoutUnit projectedScrollDestination = newState == ScrollSnapState::Gliding ? m_beginTrackingWheelDeltaOffset + LayoutUnit(projectedInertialScrollDistance(initialWheelDelta)) : offset;
166
    LayoutUnit projectedScrollDestination = newState == ScrollSnapState::Gliding ? m_beginTrackingWheelDeltaOffset + LayoutUnit(projectedInertialScrollDistance(initialWheelDelta)) : offset;
167
    projectedScrollDestination = std::min(std::max(projectedScrollDestination, m_snapOffsets->first()), m_snapOffsets->last());
167
    projectedScrollDestination = std::min(std::max(projectedScrollDestination, m_snapOffsets->first()), m_snapOffsets->last());
Lines 203-209 void AxisScrollSnapAnimator::endScrollSnapAnimation(ScrollSnapState newState) a/Source/WebCore/platform/mac/AxisScrollSnapAnimator.mm_sec4
203
// relationship of the distance traveled, clamped by arbitrary min and max values.
203
// relationship of the distance traveled, clamped by arbitrary min and max values.
204
float AxisScrollSnapAnimator::computeSnapDelta() const
204
float AxisScrollSnapAnimator::computeSnapDelta() const
205
{
205
{
206
    LayoutUnit offset = m_client->scrollOffsetOnAxis(m_axis);
206
    LayoutUnit offset = m_client->scrollOffsetInAxis(m_axis);
207
    bool canComputeSnap =  (m_initialOffset <= offset && offset < m_targetOffset) || (m_targetOffset < offset && offset <= m_initialOffset);
207
    bool canComputeSnap =  (m_initialOffset <= offset && offset < m_targetOffset) || (m_targetOffset < offset && offset <= m_initialOffset);
208
    if (m_currentState != ScrollSnapState::Snapping || !canComputeSnap)
208
    if (m_currentState != ScrollSnapState::Snapping || !canComputeSnap)
209
        return 0;
209
        return 0;
Lines 237-243 float AxisScrollSnapAnimator::computeSnapDelta() const a/Source/WebCore/platform/mac/AxisScrollSnapAnimator.mm_sec5
237
// and VF. Thus, we can express our gliding equation all in terms of V0, VF and t.
237
// and VF. Thus, we can express our gliding equation all in terms of V0, VF and t.
238
float AxisScrollSnapAnimator::computeGlideDelta() const
238
float AxisScrollSnapAnimator::computeGlideDelta() const
239
{
239
{
240
    LayoutUnit offset = m_client->scrollOffsetOnAxis(m_axis);
240
    LayoutUnit offset = m_client->scrollOffsetInAxis(m_axis);
241
    bool canComputeGlide = (m_initialOffset <= offset && offset < m_targetOffset) || (m_targetOffset < offset && offset <= m_initialOffset);
241
    bool canComputeGlide = (m_initialOffset <= offset && offset < m_targetOffset) || (m_targetOffset < offset && offset <= m_initialOffset);
242
    if (m_currentState != ScrollSnapState::Gliding || !canComputeGlide)
242
    if (m_currentState != ScrollSnapState::Gliding || !canComputeGlide)
243
        return 0;
243
        return 0;
- a/Source/WebCore/platform/mac/ScrollAnimatorMac.h -1 / +12 lines
Lines 32-37 a/Source/WebCore/platform/mac/ScrollAnimatorMac.h_sec1
32
#include "FloatPoint.h"
32
#include "FloatPoint.h"
33
#include "FloatSize.h"
33
#include "FloatSize.h"
34
#include "ScrollAnimator.h"
34
#include "ScrollAnimator.h"
35
#include "ScrollController.h"
35
#include "Timer.h"
36
#include "Timer.h"
36
#include <wtf/RetainPtr.h>
37
#include <wtf/RetainPtr.h>
37
38
Lines 41-51 OBJC_CLASS WebScrollbarPainterDelegate; a/Source/WebCore/platform/mac/ScrollAnimatorMac.h_sec2
41
42
42
typedef id ScrollbarPainterController;
43
typedef id ScrollbarPainterController;
43
44
45
#if !ENABLE(RUBBER_BANDING)
46
class ScrollControllerClient { };
47
#endif
48
44
namespace WebCore {
49
namespace WebCore {
45
50
46
class Scrollbar;
51
class Scrollbar;
47
52
48
class ScrollAnimatorMac : public ScrollAnimator {
53
class ScrollAnimatorMac : public ScrollAnimator, private ScrollControllerClient {
49
54
50
public:
55
public:
51
    ScrollAnimatorMac(ScrollableArea&);
56
    ScrollAnimatorMac(ScrollableArea&);
Lines 145-155 private: a/Source/WebCore/platform/mac/ScrollAnimatorMac.h_sec3
145
    virtual WebCore::IntPoint absoluteScrollPosition() override;
150
    virtual WebCore::IntPoint absoluteScrollPosition() override;
146
    virtual void immediateScrollByWithoutContentEdgeConstraints(const FloatSize&) override;
151
    virtual void immediateScrollByWithoutContentEdgeConstraints(const FloatSize&) override;
147
    virtual void immediateScrollBy(const FloatSize&) override;
152
    virtual void immediateScrollBy(const FloatSize&) override;
153
    virtual void startSnapRubberbandTimer() override;
154
    virtual void stopSnapRubberbandTimer() override;
148
    virtual void adjustScrollPositionToBoundsIfNecessary() override;
155
    virtual void adjustScrollPositionToBoundsIfNecessary() override;
149
156
150
    bool pinnedInDirection(float deltaX, float deltaY);
157
    bool pinnedInDirection(float deltaX, float deltaY);
158
    void snapRubberBandTimerFired();
151
159
152
    bool isAlreadyPinnedInDirectionOfGesture(const PlatformWheelEvent&, ScrollEventAxis);
160
    bool isAlreadyPinnedInDirectionOfGesture(const PlatformWheelEvent&, ScrollEventAxis);
161
162
    ScrollController m_scrollController;
163
    Timer m_snapRubberBandTimer;
153
#endif
164
#endif
154
165
155
    bool m_haveScrolledSincePageLoad;
166
    bool m_haveScrolledSincePageLoad;
- a/Source/WebCore/platform/mac/ScrollAnimatorMac.mm +19 lines
Lines 643-648 ScrollAnimatorMac::ScrollAnimatorMac(ScrollableArea& scrollableArea) a/Source/WebCore/platform/mac/ScrollAnimatorMac.mm_sec1
643
    : ScrollAnimator(scrollableArea)
643
    : ScrollAnimator(scrollableArea)
644
    , m_initialScrollbarPaintTimer(*this, &ScrollAnimatorMac::initialScrollbarPaintTimerFired)
644
    , m_initialScrollbarPaintTimer(*this, &ScrollAnimatorMac::initialScrollbarPaintTimerFired)
645
    , m_sendContentAreaScrolledTimer(*this, &ScrollAnimatorMac::sendContentAreaScrolledTimerFired)
645
    , m_sendContentAreaScrolledTimer(*this, &ScrollAnimatorMac::sendContentAreaScrolledTimerFired)
646
#if ENABLE(RUBBER_BANDING)
647
    , m_scrollController(this)
648
    , m_snapRubberBandTimer(*this, &ScrollAnimatorMac::snapRubberBandTimerFired)
649
#endif
646
    , m_haveScrolledSincePageLoad(false)
650
    , m_haveScrolledSincePageLoad(false)
647
    , m_needsScrollerStyleUpdate(false)
651
    , m_needsScrollerStyleUpdate(false)
648
{
652
{
Lines 1266-1271 void ScrollAnimatorMac::immediateScrollBy(const FloatSize& delta) a/Source/WebCore/platform/mac/ScrollAnimatorMac.mm_sec2
1266
    m_currentPosY = newPos.y();
1270
    m_currentPosY = newPos.y();
1267
    notifyPositionChanged(adjustedDelta);
1271
    notifyPositionChanged(adjustedDelta);
1268
}
1272
}
1273
1274
void ScrollAnimatorMac::startSnapRubberbandTimer()
1275
{
1276
    m_snapRubberBandTimer.startRepeating(1.0 / 60.0);
1277
}
1278
1279
void ScrollAnimatorMac::stopSnapRubberbandTimer()
1280
{
1281
    m_snapRubberBandTimer.stop();
1282
}
1283
1284
void ScrollAnimatorMac::snapRubberBandTimerFired()
1285
{
1286
    m_scrollController.snapRubberBandTimerFired();
1287
}
1269
#endif
1288
#endif
1270
1289
1271
void ScrollAnimatorMac::updateScrollerStyle()
1290
void ScrollAnimatorMac::updateScrollerStyle()
- a/Source/WebCore/platform/mac/ScrollController.h +107 lines
Line 0 a/Source/WebCore/platform/mac/ScrollController.h_sec1
1
/*
2
 * Copyright (C) 2011 Apple Inc. All rights reserved.
3
 *
4
 * Redistribution and use in source and binary forms, with or without
5
 * modification, are permitted provided that the following conditions
6
 * are met:
7
 * 1. Redistributions of source code must retain the above copyright
8
 *    notice, this list of conditions and the following disclaimer.
9
 * 2. Redistributions in binary form must reproduce the above copyright
10
 *    notice, this list of conditions and the following disclaimer in the
11
 *    documentation and/or other materials provided with the distribution.
12
 *
13
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23
 * THE POSSIBILITY OF SUCH DAMAGE.
24
 */
25
26
#ifndef ScrollController_h
27
#define ScrollController_h
28
29
#if ENABLE(RUBBER_BANDING)
30
31
#include "FloatPoint.h"
32
#include "FloatSize.h"
33
#include "ScrollTypes.h"
34
#include <wtf/Noncopyable.h>
35
36
namespace WebCore {
37
38
class PlatformWheelEvent;
39
40
class ScrollControllerClient {
41
protected:
42
    virtual ~ScrollControllerClient() { }
43
44
public:
45
    virtual bool allowsHorizontalStretching(const PlatformWheelEvent&) = 0;
46
    virtual bool allowsVerticalStretching(const PlatformWheelEvent&) = 0;
47
    virtual IntSize stretchAmount() = 0;
48
    virtual bool pinnedInDirection(const FloatSize&) = 0;
49
    virtual bool canScrollHorizontally() = 0;
50
    virtual bool canScrollVertically() = 0;
51
    virtual bool shouldRubberBandInDirection(ScrollDirection) = 0;
52
53
    // Return the absolute scroll position, not relative to the scroll origin.
54
    virtual WebCore::IntPoint absoluteScrollPosition() = 0;
55
56
    virtual void immediateScrollBy(const FloatSize&) = 0;
57
    virtual void immediateScrollByWithoutContentEdgeConstraints(const FloatSize&) = 0;
58
    virtual void startSnapRubberbandTimer() = 0;
59
    virtual void stopSnapRubberbandTimer() = 0;
60
61
    // If the current scroll position is within the overhang area, this function will cause
62
    // the page to scroll to the nearest boundary point.
63
    virtual void adjustScrollPositionToBoundsIfNecessary() = 0;
64
};
65
66
class ScrollController {
67
    WTF_MAKE_NONCOPYABLE(ScrollController);
68
69
public:
70
    explicit ScrollController(ScrollControllerClient*);
71
72
    bool handleWheelEvent(const PlatformWheelEvent&);
73
    void snapRubberBandTimerFired();
74
75
    bool isRubberBandInProgress() const;
76
77
private:
78
    void stopSnapRubberbandTimer();
79
    void snapRubberBand();
80
81
    bool shouldRubberBandInHorizontalDirection(const PlatformWheelEvent&);
82
83
    ScrollControllerClient* m_client;
84
85
    bool m_inScrollGesture;
86
    bool m_momentumScrollInProgress;
87
    bool m_ignoreMomentumScrolls;
88
    
89
    CFTimeInterval m_lastMomentumScrollTimestamp;
90
    FloatSize m_overflowScrollDelta;
91
    FloatSize m_stretchScrollForce;
92
    FloatSize m_momentumVelocity;
93
94
    // Rubber band state.
95
    CFTimeInterval m_startTime;
96
    FloatSize m_startStretch;
97
    FloatPoint m_origOrigin;
98
    FloatSize m_origVelocity;
99
100
    bool m_snapRubberbandTimerIsActive;
101
};
102
103
} // namespace WebCore
104
105
#endif // ENABLE(RUBBER_BANDING)
106
107
#endif // ScrollController_h
- a/Source/WebCore/platform/mac/ScrollController.mm +406 lines
Line 0 a/Source/WebCore/platform/mac/ScrollController.mm_sec1
1
/*
2
 * Copyright (C) 2011, 2014-2015 Apple Inc. All rights reserved.
3
 *
4
 * Redistribution and use in source and binary forms, with or without
5
 * modification, are permitted provided that the following conditions
6
 * are met:
7
 * 1. Redistributions of source code must retain the above copyright
8
 *    notice, this list of conditions and the following disclaimer.
9
 * 2. Redistributions in binary form must reproduce the above copyright
10
 *    notice, this list of conditions and the following disclaimer in the
11
 *    documentation and/or other materials provided with the distribution.
12
 *
13
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23
 * THE POSSIBILITY OF SUCH DAMAGE.
24
 */
25
26
#include "config.h"
27
#include "ScrollController.h"
28
29
#include "PlatformWheelEvent.h"
30
#include "WebCoreSystemInterface.h"
31
#include <sys/sysctl.h>
32
#include <sys/time.h>
33
34
#if ENABLE(RUBBER_BANDING)
35
36
static NSTimeInterval systemUptime()
37
{
38
    if ([[NSProcessInfo processInfo] respondsToSelector:@selector(systemUptime)])
39
        return [[NSProcessInfo processInfo] systemUptime];
40
41
    // Get how long system has been up. Found by looking getting "boottime" from the kernel.
42
    static struct timeval boottime = {0, 0};
43
    if (!boottime.tv_sec) {
44
        int mib[2] = {CTL_KERN, KERN_BOOTTIME};
45
        size_t size = sizeof(boottime);
46
        if (-1 == sysctl(mib, 2, &boottime, &size, 0, 0))
47
            boottime.tv_sec = 0;
48
    }
49
    struct timeval now;
50
    if (boottime.tv_sec && -1 != gettimeofday(&now, 0)) {
51
        struct timeval uptime;
52
        timersub(&now, &boottime, &uptime);
53
        NSTimeInterval result = uptime.tv_sec + (uptime.tv_usec / 1E+6);
54
        return result;
55
    }
56
    return 0;
57
}
58
59
60
namespace WebCore {
61
62
static const float scrollVelocityZeroingTimeout = 0.10f;
63
static const float rubberbandDirectionLockStretchRatio = 1;
64
static const float rubberbandMinimumRequiredDeltaBeforeStretch = 10;
65
66
static float elasticDeltaForTimeDelta(float initialPosition, float initialVelocity, float elapsedTime)
67
{
68
    return wkNSElasticDeltaForTimeDelta(initialPosition, initialVelocity, elapsedTime);
69
}
70
71
static float elasticDeltaForReboundDelta(float delta)
72
{
73
    return wkNSElasticDeltaForReboundDelta(delta);
74
}
75
76
static float reboundDeltaForElasticDelta(float delta)
77
{
78
    return wkNSReboundDeltaForElasticDelta(delta);
79
}
80
81
static float scrollWheelMultiplier()
82
{
83
    static float multiplier = -1;
84
    if (multiplier < 0) {
85
        multiplier = [[NSUserDefaults standardUserDefaults] floatForKey:@"NSScrollWheelMultiplier"];
86
        if (multiplier <= 0)
87
            multiplier = 1;
88
    }
89
    return multiplier;
90
}
91
92
ScrollController::ScrollController(ScrollControllerClient* client)
93
    : m_client(client)
94
    , m_inScrollGesture(false)
95
    , m_momentumScrollInProgress(false)
96
    , m_ignoreMomentumScrolls(false)
97
    , m_lastMomentumScrollTimestamp(0)
98
    , m_startTime(0)
99
    , m_snapRubberbandTimerIsActive(false)
100
{
101
}
102
103
bool ScrollController::handleWheelEvent(const PlatformWheelEvent& wheelEvent)
104
{
105
    if (wheelEvent.phase() == PlatformWheelEventPhaseBegan) {
106
        // First, check if we should rubber-band at all.
107
        if (m_client->pinnedInDirection(FloatSize(-wheelEvent.deltaX(), 0))
108
            && !shouldRubberBandInHorizontalDirection(wheelEvent))
109
            return false;
110
111
        m_inScrollGesture = true;
112
        m_momentumScrollInProgress = false;
113
        m_ignoreMomentumScrolls = false;
114
        m_lastMomentumScrollTimestamp = 0;
115
        m_momentumVelocity = FloatSize();
116
117
        IntSize stretchAmount = m_client->stretchAmount();
118
        m_stretchScrollForce.setWidth(reboundDeltaForElasticDelta(stretchAmount.width()));
119
        m_stretchScrollForce.setHeight(reboundDeltaForElasticDelta(stretchAmount.height()));
120
        m_overflowScrollDelta = FloatSize();
121
122
        stopSnapRubberbandTimer();
123
124
        return true;
125
    }
126
127
    if (wheelEvent.phase() == PlatformWheelEventPhaseEnded) {
128
        snapRubberBand();
129
        return true;
130
    }
131
132
    bool isMomentumScrollEvent = (wheelEvent.momentumPhase() != PlatformWheelEventPhaseNone);
133
    if (m_ignoreMomentumScrolls && (isMomentumScrollEvent || m_snapRubberbandTimerIsActive)) {
134
        if (wheelEvent.momentumPhase() == PlatformWheelEventPhaseEnded) {
135
            m_ignoreMomentumScrolls = false;
136
            return true;
137
        }
138
        return false;
139
    }
140
141
    float deltaX = m_overflowScrollDelta.width();
142
    float deltaY = m_overflowScrollDelta.height();
143
144
    // Reset overflow values because we may decide to remove delta at various points and put it into overflow.
145
    m_overflowScrollDelta = FloatSize();
146
147
    IntSize stretchAmount = m_client->stretchAmount();
148
    bool isVerticallyStretched = stretchAmount.height();
149
    bool isHorizontallyStretched = stretchAmount.width();
150
151
    float eventCoalescedDeltaX;
152
    float eventCoalescedDeltaY;
153
154
    if (isVerticallyStretched || isHorizontallyStretched) {
155
        eventCoalescedDeltaX = -wheelEvent.unacceleratedScrollingDeltaX();
156
        eventCoalescedDeltaY = -wheelEvent.unacceleratedScrollingDeltaY();
157
    } else {
158
        eventCoalescedDeltaX = -wheelEvent.deltaX();
159
        eventCoalescedDeltaY = -wheelEvent.deltaY();
160
    }
161
162
    deltaX += eventCoalescedDeltaX;
163
    deltaY += eventCoalescedDeltaY;
164
165
    // Slightly prefer scrolling vertically by applying the = case to deltaY
166
    if (fabsf(deltaY) >= fabsf(deltaX))
167
        deltaX = 0;
168
    else
169
        deltaY = 0;
170
171
    bool shouldStretch = false;
172
173
    PlatformWheelEventPhase momentumPhase = wheelEvent.momentumPhase();
174
175
    // If we are starting momentum scrolling then do some setup.
176
    if (!m_momentumScrollInProgress && (momentumPhase == PlatformWheelEventPhaseBegan || momentumPhase == PlatformWheelEventPhaseChanged))
177
        m_momentumScrollInProgress = true;
178
179
    CFTimeInterval timeDelta = wheelEvent.timestamp() - m_lastMomentumScrollTimestamp;
180
    if (m_inScrollGesture || m_momentumScrollInProgress) {
181
        if (m_lastMomentumScrollTimestamp && timeDelta > 0 && timeDelta < scrollVelocityZeroingTimeout) {
182
            m_momentumVelocity.setWidth(eventCoalescedDeltaX / (float)timeDelta);
183
            m_momentumVelocity.setHeight(eventCoalescedDeltaY / (float)timeDelta);
184
            m_lastMomentumScrollTimestamp = wheelEvent.timestamp();
185
        } else {
186
            m_lastMomentumScrollTimestamp = wheelEvent.timestamp();
187
            m_momentumVelocity = FloatSize();
188
        }
189
190
        if (isVerticallyStretched) {
191
            if (!isHorizontallyStretched && m_client->pinnedInDirection(FloatSize(deltaX, 0))) {
192
                // Stretching only in the vertical.
193
                if (deltaY && (fabsf(deltaX / deltaY) < rubberbandDirectionLockStretchRatio))
194
                    deltaX = 0;
195
                else if (fabsf(deltaX) < rubberbandMinimumRequiredDeltaBeforeStretch) {
196
                    m_overflowScrollDelta.setWidth(m_overflowScrollDelta.width() + deltaX);
197
                    deltaX = 0;
198
                } else
199
                    m_overflowScrollDelta.setWidth(m_overflowScrollDelta.width() + deltaX);
200
            }
201
        } else if (isHorizontallyStretched) {
202
            // Stretching only in the horizontal.
203
            if (m_client->pinnedInDirection(FloatSize(0, deltaY))) {
204
                if (deltaX && (fabsf(deltaY / deltaX) < rubberbandDirectionLockStretchRatio))
205
                    deltaY = 0;
206
                else if (fabsf(deltaY) < rubberbandMinimumRequiredDeltaBeforeStretch) {
207
                    m_overflowScrollDelta.setHeight(m_overflowScrollDelta.height() + deltaY);
208
                    deltaY = 0;
209
                } else
210
                    m_overflowScrollDelta.setHeight(m_overflowScrollDelta.height() + deltaY);
211
            }
212
        } else {
213
            // Not stretching at all yet.
214
            if (m_client->pinnedInDirection(FloatSize(deltaX, deltaY))) {
215
                if (fabsf(deltaY) >= fabsf(deltaX)) {
216
                    if (fabsf(deltaX) < rubberbandMinimumRequiredDeltaBeforeStretch) {
217
                        m_overflowScrollDelta.setWidth(m_overflowScrollDelta.width() + deltaX);
218
                        deltaX = 0;
219
                    } else
220
                        m_overflowScrollDelta.setWidth(m_overflowScrollDelta.width() + deltaX);
221
                }
222
                shouldStretch = true;
223
            }
224
        }
225
    }
226
227
    if (deltaX || deltaY) {
228
        if (!(shouldStretch || isVerticallyStretched || isHorizontallyStretched)) {
229
            if (deltaY) {
230
                deltaY *= scrollWheelMultiplier();
231
                m_client->immediateScrollBy(FloatSize(0, deltaY));
232
            }
233
            if (deltaX) {
234
                deltaX *= scrollWheelMultiplier();
235
                m_client->immediateScrollBy(FloatSize(deltaX, 0));
236
            }
237
        } else {
238
            if (!m_client->allowsHorizontalStretching(wheelEvent)) {
239
                deltaX = 0;
240
                eventCoalescedDeltaX = 0;
241
            } else if (deltaX && !isHorizontallyStretched && !m_client->pinnedInDirection(FloatSize(deltaX, 0))) {
242
                deltaX *= scrollWheelMultiplier();
243
244
                m_client->immediateScrollByWithoutContentEdgeConstraints(FloatSize(deltaX, 0));
245
                deltaX = 0;
246
            }
247
248
            if (!m_client->allowsVerticalStretching(wheelEvent)) {
249
                deltaY = 0;
250
                eventCoalescedDeltaY = 0;
251
            } else if (deltaY && !isVerticallyStretched && !m_client->pinnedInDirection(FloatSize(0, deltaY))) {
252
                deltaY *= scrollWheelMultiplier();
253
254
                m_client->immediateScrollByWithoutContentEdgeConstraints(FloatSize(0, deltaY));
255
                deltaY = 0;
256
            }
257
258
            IntSize stretchAmount = m_client->stretchAmount();
259
260
            if (m_momentumScrollInProgress) {
261
                if ((m_client->pinnedInDirection(FloatSize(eventCoalescedDeltaX, eventCoalescedDeltaY)) || (fabsf(eventCoalescedDeltaX) + fabsf(eventCoalescedDeltaY) <= 0)) && m_lastMomentumScrollTimestamp) {
262
                    m_ignoreMomentumScrolls = true;
263
                    m_momentumScrollInProgress = false;
264
                    snapRubberBand();
265
                }
266
            }
267
268
            m_stretchScrollForce.setWidth(m_stretchScrollForce.width() + deltaX);
269
            m_stretchScrollForce.setHeight(m_stretchScrollForce.height() + deltaY);
270
271
            FloatSize dampedDelta(ceilf(elasticDeltaForReboundDelta(m_stretchScrollForce.width())), ceilf(elasticDeltaForReboundDelta(m_stretchScrollForce.height())));
272
273
            m_client->immediateScrollByWithoutContentEdgeConstraints(dampedDelta - stretchAmount);
274
        }
275
    }
276
277
    if (m_momentumScrollInProgress && momentumPhase == PlatformWheelEventPhaseEnded) {
278
        m_momentumScrollInProgress = false;
279
        m_ignoreMomentumScrolls = false;
280
        m_lastMomentumScrollTimestamp = 0;
281
    }
282
283
    return true;
284
}
285
286
static inline float roundTowardZero(float num)
287
{
288
    return num > 0 ? ceilf(num - 0.5f) : floorf(num + 0.5f);
289
}
290
291
static inline float roundToDevicePixelTowardZero(float num)
292
{
293
    float roundedNum = roundf(num);
294
    if (fabs(num - roundedNum) < 0.125)
295
        num = roundedNum;
296
297
    return roundTowardZero(num);
298
}
299
300
void ScrollController::snapRubberBandTimerFired()
301
{
302
    if (!m_momentumScrollInProgress || m_ignoreMomentumScrolls) {
303
        CFTimeInterval timeDelta = [NSDate timeIntervalSinceReferenceDate] - m_startTime;
304
305
        if (m_startStretch == FloatSize()) {
306
            m_startStretch = m_client->stretchAmount();
307
            if (m_startStretch == FloatSize()) {
308
                stopSnapRubberbandTimer();
309
310
                m_stretchScrollForce = FloatSize();
311
                m_startTime = 0;
312
                m_startStretch = FloatSize();
313
                m_origOrigin = FloatPoint();
314
                m_origVelocity = FloatSize();
315
                return;
316
            }
317
318
            m_origOrigin = m_client->absoluteScrollPosition() - m_startStretch;
319
            m_origVelocity = m_momentumVelocity;
320
321
            // Just like normal scrolling, prefer vertical rubberbanding
322
            if (fabsf(m_origVelocity.height()) >= fabsf(m_origVelocity.width()))
323
                m_origVelocity.setWidth(0);
324
325
            // Don't rubber-band horizontally if it's not possible to scroll horizontally
326
            if (!m_client->canScrollHorizontally())
327
                m_origVelocity.setWidth(0);
328
329
            // Don't rubber-band vertically if it's not possible to scroll vertically
330
            if (!m_client->canScrollVertically())
331
                m_origVelocity.setHeight(0);
332
        }
333
334
        FloatPoint delta(roundToDevicePixelTowardZero(elasticDeltaForTimeDelta(m_startStretch.width(), -m_origVelocity.width(), (float)timeDelta)),
335
            roundToDevicePixelTowardZero(elasticDeltaForTimeDelta(m_startStretch.height(), -m_origVelocity.height(), (float)timeDelta)));
336
337
        if (fabs(delta.x()) >= 1 || fabs(delta.y()) >= 1) {
338
            m_client->immediateScrollByWithoutContentEdgeConstraints(FloatSize(delta.x(), delta.y()) - m_client->stretchAmount());
339
340
            FloatSize newStretch = m_client->stretchAmount();
341
342
            m_stretchScrollForce.setWidth(reboundDeltaForElasticDelta(newStretch.width()));
343
            m_stretchScrollForce.setHeight(reboundDeltaForElasticDelta(newStretch.height()));
344
        } else {
345
            m_client->adjustScrollPositionToBoundsIfNecessary();
346
347
            stopSnapRubberbandTimer();
348
            m_stretchScrollForce = FloatSize();
349
            m_startTime = 0;
350
            m_startStretch = FloatSize();
351
            m_origOrigin = FloatPoint();
352
            m_origVelocity = FloatSize();
353
        }
354
    } else {
355
        m_startTime = [NSDate timeIntervalSinceReferenceDate];
356
        m_startStretch = FloatSize();
357
    }
358
}
359
360
bool ScrollController::isRubberBandInProgress() const
361
{
362
    if (!m_inScrollGesture && !m_momentumScrollInProgress && !m_snapRubberbandTimerIsActive)
363
        return false;
364
365
    return !m_client->stretchAmount().isZero();
366
}
367
368
void ScrollController::stopSnapRubberbandTimer()
369
{
370
    m_client->stopSnapRubberbandTimer();
371
    m_snapRubberbandTimerIsActive = false;
372
}
373
374
void ScrollController::snapRubberBand()
375
{
376
    CFTimeInterval timeDelta = systemUptime() - m_lastMomentumScrollTimestamp;
377
    if (m_lastMomentumScrollTimestamp && timeDelta >= scrollVelocityZeroingTimeout)
378
        m_momentumVelocity = FloatSize();
379
380
    m_inScrollGesture = false;
381
382
    if (m_snapRubberbandTimerIsActive)
383
        return;
384
385
    m_startTime = [NSDate timeIntervalSinceReferenceDate];
386
    m_startStretch = FloatSize();
387
    m_origOrigin = FloatPoint();
388
    m_origVelocity = FloatSize();
389
390
    m_client->startSnapRubberbandTimer();
391
    m_snapRubberbandTimerIsActive = true;
392
}
393
394
bool ScrollController::shouldRubberBandInHorizontalDirection(const PlatformWheelEvent& wheelEvent)
395
{
396
    if (wheelEvent.deltaX() > 0)
397
        return m_client->shouldRubberBandInDirection(ScrollLeft);
398
    if (wheelEvent.deltaX() < 0)
399
        return m_client->shouldRubberBandInDirection(ScrollRight);
400
401
    return true;
402
}
403
404
} // namespace WebCore
405
406
#endif // ENABLE(RUBBER_BANDING)

Return to Bug 142205