Make it possible to test overlay scrollbar interactions
authorsimon.fraser@apple.com <simon.fraser@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sun, 3 May 2020 03:49:16 +0000 (03:49 +0000)
committersimon.fraser@apple.com <simon.fraser@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sun, 3 May 2020 03:49:16 +0000 (03:49 +0000)
https://bugs.webkit.org/show_bug.cgi?id=211342

Reviewed by Daniel Bates.

Source/WebCore:

Add internals.horizontalScrollbarState() and internals.verticalScrollbarState() and hook them
up via ScrollableArea to ScrollAnimatorMac. They dump state based on the NSScrollerImp state.

Make internals.setUsesOverlayScrollbars(true) actually trigger real overlay scrollbars by notifying
the ScrollbarTheme about the scrollbar style change.

Tests: fast/scrolling/mac/scrollbars/overlay-scrollbar-hovered.html
       fast/scrolling/mac/scrollbars/overlay-scrollbar-reveal.html
       fast/scrolling/mac/scrollbars/overlay-scrollbar-state.html
       fast/scrolling/mac/scrollbars/scrollbar-state.html

* platform/ScrollAnimator.h:
(WebCore::ScrollAnimator::ScrollAnimator::horizontalScrollbarStateForTesting const):
(WebCore::ScrollAnimator::ScrollAnimator::verticalScrollbarStateForTesting const):
* platform/ScrollableArea.cpp:
(WebCore::ScrollableArea::horizontalScrollbarStateForTesting const):
(WebCore::ScrollableArea::verticalScrollbarStateForTesting const):
* platform/ScrollableArea.h:
* platform/mac/NSScrollerImpDetails.h:
* platform/mac/ScrollAnimatorMac.h:
* platform/mac/ScrollAnimatorMac.mm:
(WebCore::scrollbarState):
(WebCore::ScrollAnimatorMac::horizontalScrollbarStateForTesting const):
(WebCore::ScrollAnimatorMac::verticalScrollbarStateForTesting const):
* testing/Internals.cpp:
(WebCore:: const):
(WebCore::Internals::scrollbarOverlayStyle const):
(WebCore::Internals::scrollbarUsingDarkAppearance const):
(WebCore::Internals::horizontalScrollbarState const):
(WebCore::Internals::verticalScrollbarState const):
(WebCore::Internals::setUsesOverlayScrollbars):
* testing/Internals.h:
* testing/Internals.idl:

LayoutTests:

New tests, and some helper functions in UIHelper.

* fast/scrolling/mac/scrollbars/overlay-scrollbar-hovered-expected.txt: Added.
* fast/scrolling/mac/scrollbars/overlay-scrollbar-hovered.html: Added.
* fast/scrolling/mac/scrollbars/overlay-scrollbar-reveal-expected.txt: Added.
* fast/scrolling/mac/scrollbars/overlay-scrollbar-reveal.html: Added.
* fast/scrolling/mac/scrollbars/overlay-scrollbar-state-expected.txt: Added.
* fast/scrolling/mac/scrollbars/overlay-scrollbar-state.html: Added.
* fast/scrolling/mac/scrollbars/scrollbar-state-expected.txt: Added.
* fast/scrolling/mac/scrollbars/scrollbar-state.html: Added.
* resources/ui-helper.js:
(window.UIHelper.async mouseWheelMayBeginAt):
(window.UIHelper.async mouseWheelCancelAt):
(window.UIHelper.async waitForCondition):

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

20 files changed:
LayoutTests/ChangeLog
LayoutTests/fast/scrolling/mac/scrollbars/overlay-scrollbar-hovered-expected.txt [new file with mode: 0644]
LayoutTests/fast/scrolling/mac/scrollbars/overlay-scrollbar-hovered.html [new file with mode: 0644]
LayoutTests/fast/scrolling/mac/scrollbars/overlay-scrollbar-reveal-expected.txt [new file with mode: 0644]
LayoutTests/fast/scrolling/mac/scrollbars/overlay-scrollbar-reveal.html [new file with mode: 0644]
LayoutTests/fast/scrolling/mac/scrollbars/overlay-scrollbar-state-expected.txt [new file with mode: 0644]
LayoutTests/fast/scrolling/mac/scrollbars/overlay-scrollbar-state.html [new file with mode: 0644]
LayoutTests/fast/scrolling/mac/scrollbars/scrollbar-state-expected.txt [new file with mode: 0644]
LayoutTests/fast/scrolling/mac/scrollbars/scrollbar-state.html [new file with mode: 0644]
LayoutTests/resources/ui-helper.js
Source/WebCore/ChangeLog
Source/WebCore/platform/ScrollAnimator.h
Source/WebCore/platform/ScrollableArea.cpp
Source/WebCore/platform/ScrollableArea.h
Source/WebCore/platform/mac/NSScrollerImpDetails.h
Source/WebCore/platform/mac/ScrollAnimatorMac.h
Source/WebCore/platform/mac/ScrollAnimatorMac.mm
Source/WebCore/testing/Internals.cpp
Source/WebCore/testing/Internals.h
Source/WebCore/testing/Internals.idl

index 9e40d01..1917c1a 100644 (file)
@@ -1,3 +1,25 @@
+2020-05-02  Simon Fraser  <simon.fraser@apple.com>
+
+        Make it possible to test overlay scrollbar interactions
+        https://bugs.webkit.org/show_bug.cgi?id=211342
+
+        Reviewed by Daniel Bates.
+
+        New tests, and some helper functions in UIHelper.
+
+        * fast/scrolling/mac/scrollbars/overlay-scrollbar-hovered-expected.txt: Added.
+        * fast/scrolling/mac/scrollbars/overlay-scrollbar-hovered.html: Added.
+        * fast/scrolling/mac/scrollbars/overlay-scrollbar-reveal-expected.txt: Added.
+        * fast/scrolling/mac/scrollbars/overlay-scrollbar-reveal.html: Added.
+        * fast/scrolling/mac/scrollbars/overlay-scrollbar-state-expected.txt: Added.
+        * fast/scrolling/mac/scrollbars/overlay-scrollbar-state.html: Added.
+        * fast/scrolling/mac/scrollbars/scrollbar-state-expected.txt: Added.
+        * fast/scrolling/mac/scrollbars/scrollbar-state.html: Added.
+        * resources/ui-helper.js:
+        (window.UIHelper.async mouseWheelMayBeginAt):
+        (window.UIHelper.async mouseWheelCancelAt):
+        (window.UIHelper.async waitForCondition):
+
 2020-05-02  Diego Pino Garcia  <dpino@igalia.com>
 
         [GTK][WPE] Gardening, several WebGL tests are failing after r261023
diff --git a/LayoutTests/fast/scrolling/mac/scrollbars/overlay-scrollbar-hovered-expected.txt b/LayoutTests/fast/scrolling/mac/scrollbars/overlay-scrollbar-hovered-expected.txt
new file mode 100644 (file)
index 0000000..d76bce2
--- /dev/null
@@ -0,0 +1,15 @@
+Test hover over overlay scrollbar
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+Document
+enabled
+Hovering vertical scrollbar should show expanded scrollbar
+PASS Scrollbar state: enabled,expanded,visible_track,visible_thumb
+Unhovering vertical scrollbar should hide it
+PASS Thumb and track hidden
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/fast/scrolling/mac/scrollbars/overlay-scrollbar-hovered.html b/LayoutTests/fast/scrolling/mac/scrollbars/overlay-scrollbar-hovered.html
new file mode 100644 (file)
index 0000000..eb6f0bc
--- /dev/null
@@ -0,0 +1,66 @@
+<!DOCTYPE html> <!-- webkit-test-runner [ internal:useMockScrollbars=false ] -->
+<html>
+<head>
+    <style>
+        body {
+            height: 1000px;
+        }
+    </style>
+    <script src="../../../../resources/js-test-pre.js"></script>
+    <script src="../../../../resources/ui-helper.js"></script>
+    
+    <script>
+        jsTestIsAsync = true;
+        
+        window.internals.setUsesOverlayScrollbars(true);
+
+        async function doTest()
+        {
+            description('Test hover over overlay scrollbar');
+            if (!window.internals)
+                return;
+            
+            debug('Document');
+            debug(internals.verticalScrollbarState());
+            
+            let windowWidth = window.innerWidth;
+
+            debug('Hovering vertical scrollbar should show expanded scrollbar');
+            await UIHelper.mouseWheelScrollAt(windowWidth - 8, 10);
+            await UIHelper.waitForCondition(() => {
+                let state = internals.verticalScrollbarState();
+                let expanded = state.indexOf('expanded') != -1;
+                if (expanded)
+                    testPassed('Scrollbar state: ' + state);
+                return expanded;
+            });
+
+            debug('Unhovering vertical scrollbar should hide it');
+            await UIHelper.moveMouseAndWaitForFrame(windowWidth - 20, 10);
+            await UIHelper.waitForCondition(() => {
+                let state = internals.verticalScrollbarState();
+                let thumbHidden = state.indexOf('visible_thumb') == -1;
+                let trackHidden = state.indexOf('visible_track') == -1;
+                if (thumbHidden && trackHidden)
+                    testPassed('Thumb and track hidden');
+                return thumbHidden && trackHidden;
+            });
+
+            finishJSTest();
+        }
+
+        window.addEventListener('load', () => {
+            doTest();
+        }, false);
+    </script>
+</head>
+<body>
+    <div class="auto scroller">
+        <div class="contents"></div>
+    </div>
+    <div class="scroll scroller">
+        <div class="contents"></div>
+    </div>
+    <script src="../../../../resources/js-test-post.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/fast/scrolling/mac/scrollbars/overlay-scrollbar-reveal-expected.txt b/LayoutTests/fast/scrolling/mac/scrollbars/overlay-scrollbar-reveal-expected.txt
new file mode 100644 (file)
index 0000000..7fef5af
--- /dev/null
@@ -0,0 +1,15 @@
+Test maybegin and cancelled
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+Document
+enabled
+MayBegin should show the scrollbar
+PASS Scrollbar state: enabled,visible_thumb
+Cancelled should hide the scrollbar
+PASS Scrollbar state: enabled
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/fast/scrolling/mac/scrollbars/overlay-scrollbar-reveal.html b/LayoutTests/fast/scrolling/mac/scrollbars/overlay-scrollbar-reveal.html
new file mode 100644 (file)
index 0000000..a0ee919
--- /dev/null
@@ -0,0 +1,66 @@
+<!DOCTYPE html> <!-- webkit-test-runner [ internal:useMockScrollbars=false ] -->
+<html>
+<head>
+    <style>
+        body {
+            height: 1000px;
+        }
+    </style>
+    <script src="../../../../resources/js-test-pre.js"></script>
+    <script src="../../../../resources/ui-helper.js"></script>
+    
+    <script>
+        jsTestIsAsync = true;
+        
+        window.internals.setUsesOverlayScrollbars(true);
+
+        async function doTest()
+        {
+            description('Test maybegin and cancelled');
+            if (!window.internals)
+                return;
+            
+            debug('Document');
+            debug(internals.verticalScrollbarState());
+            
+            let windowWidth = window.innerWidth;
+
+            debug('MayBegin should show the scrollbar');
+            await UIHelper.mouseWheelMayBeginAt(100, 100);
+            await UIHelper.waitForCondition(() => {
+                let state = internals.verticalScrollbarState();
+                let visible = state.indexOf('visible_thumb') != -1;
+                if (visible)
+                    testPassed('Scrollbar state: ' + state);
+                return visible;
+            });
+
+            debug('Cancelled should hide the scrollbar');
+            await UIHelper.mouseWheelCancelAt(100, 100);
+
+            await UIHelper.waitForCondition(() => {
+                let state = internals.verticalScrollbarState();
+                let hidden = state.indexOf('visible_thumb') == -1;
+                if (hidden)
+                    testPassed('Scrollbar state: ' + state);
+                return hidden;
+            });
+
+            finishJSTest();
+        }
+
+        window.addEventListener('load', () => {
+            doTest();
+        }, false);
+    </script>
+</head>
+<body>
+    <div class="auto scroller">
+        <div class="contents"></div>
+    </div>
+    <div class="scroll scroller">
+        <div class="contents"></div>
+    </div>
+    <script src="../../../../resources/js-test-post.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/fast/scrolling/mac/scrollbars/overlay-scrollbar-state-expected.txt b/LayoutTests/fast/scrolling/mac/scrollbars/overlay-scrollbar-state-expected.txt
new file mode 100644 (file)
index 0000000..b37bd5d
--- /dev/null
@@ -0,0 +1,18 @@
+Test scrollbar state internals
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+Document
+enabled
+none
+overflow:auto
+PASS internals.verticalScrollbarState(autoScroller) is "enabled"
+PASS internals.horizontalScrollbarState(autoScroller) is "none"
+overflow:scroll
+PASS internals.verticalScrollbarState(scrollScroller) is "enabled"
+PASS internals.horizontalScrollbarState(scrollScroller) is "none"
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/fast/scrolling/mac/scrollbars/overlay-scrollbar-state.html b/LayoutTests/fast/scrolling/mac/scrollbars/overlay-scrollbar-state.html
new file mode 100644 (file)
index 0000000..2afc3a1
--- /dev/null
@@ -0,0 +1,66 @@
+<!DOCTYPE html> <!-- webkit-test-runner [ internal:useMockScrollbars=false ] -->
+<html>
+<head>
+    <style>
+        body {
+            height: 1000px;
+        }
+        .scroller {
+            margin: 10px;
+            width: 100px;
+            height: 100px;
+        }
+        .contents {
+            width: 100%;
+            height: 200%;
+        }
+        .auto {
+            overflow: auto;
+        }
+        .scroll {
+            overflow: scroll;
+        }
+    </style>
+    <script src="../../../../resources/js-test-pre.js"></script>
+    <script>
+        jsTestIsAsync = true;
+        
+        let autoScroller;
+        let scrollScroller;
+        
+        window.internals.setUsesOverlayScrollbars(true);
+
+        window.addEventListener('load', () => {
+            description('Test scrollbar state internals');
+            if (!window.internals)
+                return;
+            
+            debug('Document');
+            debug(internals.verticalScrollbarState());
+            debug(internals.horizontalScrollbarState());
+
+            autoScroller = document.querySelector('.auto.scroller')
+            scrollScroller = document.querySelector('.scroll.scroller')
+
+            debug('overflow:auto');
+            shouldBeEqualToString('internals.verticalScrollbarState(autoScroller)', 'enabled');
+            shouldBeEqualToString('internals.horizontalScrollbarState(autoScroller)', 'none');
+
+            debug('overflow:scroll');
+            shouldBeEqualToString('internals.verticalScrollbarState(scrollScroller)', 'enabled');
+            shouldBeEqualToString('internals.horizontalScrollbarState(scrollScroller)', 'none');
+
+            finishJSTest();
+        }, false);
+    </script>
+</head>
+<body>
+    <div class="auto scroller">
+        <div class="contents"></div>
+    </div>
+    <div class="scroll scroller">
+        <div class="contents"></div>
+    </div>
+    <script src="../../../../resources/js-test-post.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/fast/scrolling/mac/scrollbars/scrollbar-state-expected.txt b/LayoutTests/fast/scrolling/mac/scrollbars/scrollbar-state-expected.txt
new file mode 100644 (file)
index 0000000..9c9af08
--- /dev/null
@@ -0,0 +1,18 @@
+Test scrollbar state internals
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+Document
+PASS internals.verticalScrollbarState() is "enabled"
+PASS internals.horizontalScrollbarState() is "none"
+overflow:auto
+PASS internals.verticalScrollbarState(autoScroller) is "enabled"
+PASS internals.horizontalScrollbarState(autoScroller) is "none"
+overflow:scroll
+PASS internals.verticalScrollbarState(scrollScroller) is "enabled"
+PASS internals.horizontalScrollbarState(scrollScroller) is "disabled"
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/fast/scrolling/mac/scrollbars/scrollbar-state.html b/LayoutTests/fast/scrolling/mac/scrollbars/scrollbar-state.html
new file mode 100644 (file)
index 0000000..5ad6c66
--- /dev/null
@@ -0,0 +1,64 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <style>
+        body {
+            height: 1000px;
+        }
+        .scroller {
+            margin: 10px;
+            width: 100px;
+            height: 100px;
+        }
+        .contents {
+            width: 100%;
+            height: 200%;
+        }
+        .auto {
+            overflow: auto;
+        }
+        .scroll {
+            overflow: scroll;
+        }
+    </style>
+    <script src="../../../../resources/js-test-pre.js"></script>
+    <script>
+        jsTestIsAsync = true;
+        
+        let autoScroller;
+        let scrollScroller;
+
+        window.addEventListener('load', () => {
+            description('Test scrollbar state internals');
+            if (!window.internals)
+                return;
+            
+            debug('Document');
+            shouldBeEqualToString('internals.verticalScrollbarState()', 'enabled');
+            shouldBeEqualToString('internals.horizontalScrollbarState()', 'none');
+
+            autoScroller = document.querySelector('.auto.scroller')
+            scrollScroller = document.querySelector('.scroll.scroller')
+
+            debug('overflow:auto');
+            shouldBeEqualToString('internals.verticalScrollbarState(autoScroller)', 'enabled');
+            shouldBeEqualToString('internals.horizontalScrollbarState(autoScroller)', 'none');
+
+            debug('overflow:scroll');
+            shouldBeEqualToString('internals.verticalScrollbarState(scrollScroller)', 'enabled');
+            shouldBeEqualToString('internals.horizontalScrollbarState(scrollScroller)', 'disabled');
+
+            finishJSTest();
+        }, false);
+    </script>
+</head>
+<body>
+    <div class="auto scroller">
+        <div class="contents"></div>
+    </div>
+    <div class="scroll scroller">
+        <div class="contents"></div>
+    </div>
+    <script src="../../../../resources/js-test-post.js"></script>
+</body>
+</html>
index 2d1def2..d37e19d 100644 (file)
@@ -59,6 +59,20 @@ window.UIHelper = class UIHelper {
         });
     }
 
+    static async mouseWheelMayBeginAt(x, y)
+    {
+        eventSender.mouseMoveTo(x, y);
+        eventSender.mouseScrollByWithWheelAndMomentumPhases(x, y, "maybegin", "none");
+        await UIHelper.animationFrame();
+    }
+
+    static async mouseWheelCancelAt(x, y)
+    {
+        eventSender.mouseMoveTo(x, y);
+        eventSender.mouseScrollByWithWheelAndMomentumPhases(x, y, "cancelled", "none");
+        await UIHelper.animationFrame();
+    }
+
     static async waitForScrollCompletion()
     {
         return new Promise(resolve => {
@@ -73,6 +87,13 @@ window.UIHelper = class UIHelper {
         return new Promise(requestAnimationFrame);
     }
 
+    static async waitForCondition(conditionFunc)
+    {
+        while (!conditionFunc()) {
+            await UIHelper.animationFrame();
+        }
+    }
+
     static sendEventStream(eventStream)
     {
         const eventStreamAsString = JSON.stringify(eventStream);
index 6ff0222..44b7ff5 100644 (file)
@@ -1,3 +1,44 @@
+2020-05-02  Simon Fraser  <simon.fraser@apple.com>
+
+        Make it possible to test overlay scrollbar interactions
+        https://bugs.webkit.org/show_bug.cgi?id=211342
+
+        Reviewed by Daniel Bates.
+
+        Add internals.horizontalScrollbarState() and internals.verticalScrollbarState() and hook them
+        up via ScrollableArea to ScrollAnimatorMac. They dump state based on the NSScrollerImp state.
+
+        Make internals.setUsesOverlayScrollbars(true) actually trigger real overlay scrollbars by notifying
+        the ScrollbarTheme about the scrollbar style change.
+
+        Tests: fast/scrolling/mac/scrollbars/overlay-scrollbar-hovered.html
+               fast/scrolling/mac/scrollbars/overlay-scrollbar-reveal.html
+               fast/scrolling/mac/scrollbars/overlay-scrollbar-state.html
+               fast/scrolling/mac/scrollbars/scrollbar-state.html
+
+        * platform/ScrollAnimator.h:
+        (WebCore::ScrollAnimator::ScrollAnimator::horizontalScrollbarStateForTesting const):
+        (WebCore::ScrollAnimator::ScrollAnimator::verticalScrollbarStateForTesting const):
+        * platform/ScrollableArea.cpp:
+        (WebCore::ScrollableArea::horizontalScrollbarStateForTesting const):
+        (WebCore::ScrollableArea::verticalScrollbarStateForTesting const):
+        * platform/ScrollableArea.h:
+        * platform/mac/NSScrollerImpDetails.h:
+        * platform/mac/ScrollAnimatorMac.h:
+        * platform/mac/ScrollAnimatorMac.mm:
+        (WebCore::scrollbarState):
+        (WebCore::ScrollAnimatorMac::horizontalScrollbarStateForTesting const):
+        (WebCore::ScrollAnimatorMac::verticalScrollbarStateForTesting const):
+        * testing/Internals.cpp:
+        (WebCore:: const):
+        (WebCore::Internals::scrollbarOverlayStyle const):
+        (WebCore::Internals::scrollbarUsingDarkAppearance const):
+        (WebCore::Internals::horizontalScrollbarState const):
+        (WebCore::Internals::verticalScrollbarState const):
+        (WebCore::Internals::setUsesOverlayScrollbars):
+        * testing/Internals.h:
+        * testing/Internals.idl:
+
 2020-05-02  Daniel Bates  <dabates@apple.com>
 
         Page::editableElementsInRect() should return root editable elements
index 9b7c09b..661187a 100644 (file)
@@ -123,6 +123,9 @@ public:
     virtual bool isRubberBandInProgress() const { return false; }
     virtual bool isScrollSnapInProgress() const { return false; }
 
+    virtual String horizontalScrollbarStateForTesting() const { return emptyString(); }
+    virtual String verticalScrollbarStateForTesting() const { return emptyString(); }
+
     void setWheelEventTestMonitor(RefPtr<WheelEventTestMonitor>&& testMonitor) { m_wheelEventTestMonitor = testMonitor; }
 
 #if (ENABLE(CSS_SCROLL_SNAP) || ENABLE(RUBBER_BANDING)) && PLATFORM(MAC)
index cdad360..13a4bd9 100644 (file)
@@ -438,6 +438,16 @@ bool ScrollableArea::hasLayerForScrollCorner() const
     return layerForScrollCorner();
 }
 
+String ScrollableArea::horizontalScrollbarStateForTesting() const
+{
+    return scrollAnimator().horizontalScrollbarStateForTesting();
+}
+
+String ScrollableArea::verticalScrollbarStateForTesting() const
+{
+    return scrollAnimator().verticalScrollbarStateForTesting();
+}
+
 #if ENABLE(CSS_SCROLL_SNAP)
 ScrollSnapOffsetsInfo<LayoutUnit>& ScrollableArea::ensureSnapOffsetsInfo()
 {
index f004d3b..892d8de 100644 (file)
@@ -136,6 +136,9 @@ public:
     virtual bool horizontalScrollbarHiddenByStyle() const { return false; }
     virtual bool verticalScrollbarHiddenByStyle() const { return false; }
 
+    WEBCORE_EXPORT String horizontalScrollbarStateForTesting() const;
+    WEBCORE_EXPORT String verticalScrollbarStateForTesting() const;
+
     bool inLiveResize() const { return m_inLiveResize; }
     WEBCORE_EXPORT virtual void willStartLiveResize();
     WEBCORE_EXPORT virtual void willEndLiveResize();
index 1ad3e31..c14e183 100644 (file)
@@ -29,6 +29,8 @@
 
 #include <wtf/Optional.h>
 
+enum NSScrollerStyle : long;
+
 namespace WebCore {
 
 class WEBCORE_EXPORT ScrollerStyle {
index 8795cf8..ef6eea0 100644 (file)
@@ -138,6 +138,9 @@ private:
     bool isRubberBandInProgress() const override;
     bool isScrollSnapInProgress() const override;
 
+    String horizontalScrollbarStateForTesting() const final;
+    String verticalScrollbarStateForTesting() const final;
+
 #if ENABLE(RUBBER_BANDING)
     /// ScrollControllerClient member functions.
     IntSize stretchAmount() const override;
index 8a1e08d..6186034 100644 (file)
@@ -853,6 +853,43 @@ bool ScrollAnimatorMac::isScrollSnapInProgress() const
 #endif
 }
 
+static String scrollbarState(Scrollbar* scrollbar)
+{
+    if (!scrollbar)
+        return "none"_s;
+
+    StringBuilder result;
+    result.append(scrollbar->enabled() ? "enabled"_s : "disabled"_s);
+
+    if (!scrollbar->isOverlayScrollbar())
+        return result.toString();
+
+    NSScrollerImp *scrollerImp = scrollerImpForScrollbar(*scrollbar);
+    if (!scrollerImp)
+        return result.toString();
+
+    if (scrollerImp.expanded)
+        result.append(",expanded"_s);
+
+    if (scrollerImp.trackAlpha > 0)
+        result.append(",visible_track"_s);
+
+    if (scrollerImp.knobAlpha > 0)
+        result.append(",visible_thumb"_s);
+
+    return result.toString();
+}
+
+String ScrollAnimatorMac::horizontalScrollbarStateForTesting() const
+{
+    return scrollbarState(m_scrollableArea.horizontalScrollbar());
+}
+
+String ScrollAnimatorMac::verticalScrollbarStateForTesting() const
+{
+    return scrollbarState(m_scrollableArea.verticalScrollbar());
+}
+
 void ScrollAnimatorMac::immediateScrollToPositionForScrollAnimation(const FloatPoint& newPosition)
 {
     ASSERT(m_scrollAnimationHelper);
index e6c704e..99c6500 100644 (file)
 
 #if PLATFORM(MAC)
 #include "GraphicsContextGLOpenGLManager.h"
+#include "NSScrollerImpDetails.h"
+#include "ScrollbarThemeMac.h"
 #endif
 
 #if PLATFORM(COCOA)
@@ -2746,7 +2748,7 @@ ExceptionOr<String> Internals::repaintRectsAsText() const
     return document->frame()->trackedRepaintRectsAsText();
 }
 
-ExceptionOr<String> Internals::scrollbarOverlayStyle(Node* node) const
+ExceptionOr<ScrollableArea*> Internals::scrollableAreaForNode(Node* node) const
 {
     if (!node)
         node = contextDocument();
@@ -2754,17 +2756,18 @@ ExceptionOr<String> Internals::scrollbarOverlayStyle(Node* node) const
     if (!node)
         return Exception { InvalidAccessError };
 
-    node->document().updateLayoutIgnorePendingStylesheets();
+    auto nodeRef = makeRef(*node);
+    nodeRef->document().updateLayoutIgnorePendingStylesheets();
 
     ScrollableArea* scrollableArea = nullptr;
-    if (is<Document>(*node)) {
-        auto* frameView = downcast<Document>(node)->view();
+    if (is<Document>(nodeRef)) {
+        auto* frameView = downcast<Document>(nodeRef.get()).view();
         if (!frameView)
             return Exception { InvalidAccessError };
 
         scrollableArea = frameView;
-    } else if (is<Element>(*node)) {
-        auto& element = *downcast<Element>(node);
+    } else if (is<Element>(nodeRef)) {
+        auto& element = downcast<Element>(nodeRef.get());
         if (!element.renderBox())
             return Exception { InvalidAccessError };
 
@@ -2775,6 +2778,16 @@ ExceptionOr<String> Internals::scrollbarOverlayStyle(Node* node) const
     if (!scrollableArea)
         return Exception { InvalidNodeTypeError };
 
+    return scrollableArea;
+}
+
+ExceptionOr<String> Internals::scrollbarOverlayStyle(Node* node) const
+{
+    auto areaOrException = scrollableAreaForNode(node);
+    if (areaOrException.hasException())
+        return areaOrException.releaseException();
+
+    auto* scrollableArea = areaOrException.releaseReturnValue();
     switch (scrollableArea->scrollbarOverlayStyle()) {
     case ScrollbarOverlayStyleDefault:
         return "default"_str;
@@ -2790,34 +2803,32 @@ ExceptionOr<String> Internals::scrollbarOverlayStyle(Node* node) const
 
 ExceptionOr<bool> Internals::scrollbarUsingDarkAppearance(Node* node) const
 {
-    if (!node)
-        node = contextDocument();
+    auto areaOrException = scrollableAreaForNode(node);
+    if (areaOrException.hasException())
+        return areaOrException.releaseException();
 
-    if (!node)
-        return Exception { InvalidAccessError };
-
-    node->document().updateLayoutIgnorePendingStylesheets();
-
-    ScrollableArea* scrollableArea = nullptr;
-    if (is<Document>(*node)) {
-        auto* frameView = downcast<Document>(node)->view();
-        if (!frameView)
-            return Exception { InvalidAccessError };
+    auto* scrollableArea = areaOrException.releaseReturnValue();
+    return scrollableArea->useDarkAppearance();
+}
 
-        scrollableArea = frameView;
-    } else if (is<Element>(*node)) {
-        auto& element = *downcast<Element>(node);
-        if (!element.renderBox())
-            return Exception { InvalidAccessError };
+ExceptionOr<String> Internals::horizontalScrollbarState(Node* node) const
+{
+    auto areaOrException = scrollableAreaForNode(node);
+    if (areaOrException.hasException())
+        return areaOrException.releaseException();
 
-        scrollableArea = element.renderBox()->layer();
-    } else
-        return Exception { InvalidNodeTypeError };
+    auto* scrollableArea = areaOrException.releaseReturnValue();
+    return scrollableArea->horizontalScrollbarStateForTesting();
+}
 
-    if (!scrollableArea)
-        return Exception { InvalidNodeTypeError };
+ExceptionOr<String> Internals::verticalScrollbarState(Node* node) const
+{
+    auto areaOrException = scrollableAreaForNode(node);
+    if (areaOrException.hasException())
+        return areaOrException.releaseException();
 
-    return scrollableArea->useDarkAppearance();
+    auto* scrollableArea = areaOrException.releaseReturnValue();
+    return scrollableArea->verticalScrollbarStateForTesting();
 }
 
 ExceptionOr<String> Internals::scrollingStateTreeAsText() const
@@ -3575,6 +3586,14 @@ JSC::JSValue Internals::evaluateInWorldIgnoringException(const String& name, con
 void Internals::setUsesOverlayScrollbars(bool enabled)
 {
     WebCore::DeprecatedGlobalSettings::setUsesOverlayScrollbars(enabled);
+#if PLATFORM(MAC)
+    ScrollerStyle::setUseOverlayScrollbars(enabled);
+    ScrollbarTheme& theme = ScrollbarTheme::theme();
+    if (theme.isMockTheme())
+        return;
+
+    static_cast<ScrollbarThemeMac&>(theme).preferencesChanged();
+#endif
 }
 
 void Internals::setUsesMockScrollAnimator(bool enabled)
index 23c4fc0..c42b6c7 100644 (file)
@@ -96,6 +96,7 @@ class RTCPeerConnection;
 class Range;
 class RenderedDocumentMarker;
 class SVGSVGElement;
+class ScrollableArea;
 class SerializedScriptValue;
 class SourceBuffer;
 class StringCallback;
@@ -397,6 +398,9 @@ public:
     ExceptionOr<String> scrollbarOverlayStyle(Node*) const;
     ExceptionOr<bool> scrollbarUsingDarkAppearance(Node*) const;
 
+    ExceptionOr<String> horizontalScrollbarState(Node*) const;
+    ExceptionOr<String> verticalScrollbarState(Node*) const;
+
     ExceptionOr<String> scrollingStateTreeAsText() const;
     ExceptionOr<String> scrollingTreeAsText() const;
     ExceptionOr<String> mainThreadScrollingReasons() const;
@@ -1014,6 +1018,7 @@ private:
     Frame* frame() const;
 
     ExceptionOr<RenderedDocumentMarker*> markerAt(Node&, const String& markerType, unsigned index);
+    ExceptionOr<ScrollableArea*> scrollableAreaForNode(Node*) const;
 
 #if ENABLE(MEDIA_STREAM)
     // RealtimeMediaSource::Observer API
index c150ecb..93168f7 100644 (file)
@@ -459,6 +459,8 @@ enum CompositingPolicy {
 
     [MayThrowException] DOMString scrollbarOverlayStyle(optional Node? node = null);
     [MayThrowException] boolean scrollbarUsingDarkAppearance(optional Node? node = null);
+    [MayThrowException] DOMString horizontalScrollbarState(optional Node? node = null);
+    [MayThrowException] DOMString verticalScrollbarState(optional Node? node = null);
 
     [MayThrowException] DOMString scrollingStateTreeAsText();
     [MayThrowException] DOMString scrollingTreeAsText();