Diff
Modified: trunk/LayoutTests/ChangeLog (190329 => 190330)
--- trunk/LayoutTests/ChangeLog 2015-09-29 21:25:11 UTC (rev 190329)
+++ trunk/LayoutTests/ChangeLog 2015-09-29 22:56:20 UTC (rev 190330)
@@ -1,3 +1,18 @@
+2015-09-29 Wenson Hsieh <wenson_hs...@apple.com>
+
+ Snap offsets should update when style is programmatically changed
+ https://bugs.webkit.org/show_bug.cgi?id=135964
+ <rdar://problem/18162411>
+
+ Reviewed by Darin Adler.
+
+ Tests style updates in both cases where -points and -coordinates are used to position snap points.
+
+ * css3/scroll-snap/scroll-snap-style-changed-coordinates-expected.txt: Added.
+ * css3/scroll-snap/scroll-snap-style-changed-coordinates.html: Added.
+ * css3/scroll-snap/scroll-snap-style-changed-repeat-expected.txt: Added.
+ * css3/scroll-snap/scroll-snap-style-changed-repeat.html: Added.
+
2015-09-29 Commit Queue <commit-qu...@webkit.org>
Unreviewed, rolling out r190289.
Added: trunk/LayoutTests/css3/scroll-snap/scroll-snap-style-changed-coordinates-expected.txt (0 => 190330)
--- trunk/LayoutTests/css3/scroll-snap/scroll-snap-style-changed-coordinates-expected.txt (rev 0)
+++ trunk/LayoutTests/css3/scroll-snap/scroll-snap-style-changed-coordinates-expected.txt 2015-09-29 22:56:20 UTC (rev 190330)
@@ -0,0 +1,9 @@
+PASS successfullyParsed is true
+
+TEST COMPLETE
+Original snap offsets: vertical = { 0, 500, 1000, 1500, 2000, 2500 }
+Updated child coordinates to 0px 250px: vertical = { 0, 250, 750, 1250, 1750, 2250, 2500 }
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
Added: trunk/LayoutTests/css3/scroll-snap/scroll-snap-style-changed-coordinates.html (0 => 190330)
--- trunk/LayoutTests/css3/scroll-snap/scroll-snap-style-changed-coordinates.html (rev 0)
+++ trunk/LayoutTests/css3/scroll-snap/scroll-snap-style-changed-coordinates.html 2015-09-29 22:56:20 UTC (rev 190330)
@@ -0,0 +1,74 @@
+<html>
+
+ <head>
+ <style>
+ #gallery {
+ width: 515px;
+ height: 500px;
+ -webkit-scroll-snap-type: mandatory;
+ -webkit-overflow-scrolling: touch;
+ overflow-y: scroll;
+ position: absolute;
+ }
+
+ .vertical {
+ width: 500px;
+ height: 500px;
+ -webkit-scroll-snap-coordinate: 0% 0%;
+ position: absolute;
+ }
+
+ #child00 { background-color: #DD0000; left: 0; top: 0px; }
+ #child01 { background-color: #FF6666; left: 0; top: 500px; }
+ #child02 { background-color: #00DD00; left: 0; top: 1000px; }
+ #child03 { background-color: #66FF66; left: 0; top: 1500px; }
+ #child04 { background-color: #0000DD; left: 0; top: 2000px; }
+ #child05 { background-color: #6666FF; left: 0; top: 2500px; }
+ </style>
+ <script src=""
+ <script>
+ function setup() {
+ var gallery = document.getElementById("gallery");
+ var coordinateChildElements = document.getElementsByClassName("vertical");
+
+ function snapOffsets() {
+ return window.internals.scrollSnapOffsets(gallery);
+ }
+
+ function dumpGalleryAndUpdateCoordinates() {
+ debug("Original snap offsets: " + snapOffsets());
+ for (var index = 0; index < coordinateChildElements.length; ++index)
+ coordinateChildElements[index].style.webkitScrollSnapCoordinate = "0px 250px";
+
+ setTimeout(dumpGalleryAndFinishTest, 0);
+ }
+
+ function dumpGalleryAndFinishTest() {
+ debug("Updated child coordinates to 0px 250px: " + snapOffsets());
+ finishJSTest();
+ testRunner.notifyDone();
+ }
+
+ if (window.testRunner) {
+ window.jsTestIsAsync = true;
+ testRunner.dumpAsText();
+ testRunner.waitUntilDone();
+ setTimeout(dumpGalleryAndUpdateCoordinates, 0);
+ }
+ }
+ </script>
+ </head>
+
+ <body _onload_="setup()">
+ <div id="gallery">
+ <div class="vertical" id="child00"></div>
+ <div class="vertical" id="child01"></div>
+ <div class="vertical" id="child02"></div>
+ <div class="vertical" id="child03"></div>
+ <div class="vertical" id="child04"></div>
+ <div class="vertical" id="child05"></div>
+ </div>
+ <script src=""
+ </body>
+
+</html>
Added: trunk/LayoutTests/css3/scroll-snap/scroll-snap-style-changed-repeat-expected.txt (0 => 190330)
--- trunk/LayoutTests/css3/scroll-snap/scroll-snap-style-changed-repeat-expected.txt (rev 0)
+++ trunk/LayoutTests/css3/scroll-snap/scroll-snap-style-changed-repeat-expected.txt 2015-09-29 22:56:20 UTC (rev 190330)
@@ -0,0 +1,11 @@
+PASS successfullyParsed is true
+
+TEST COMPLETE
+Original snap offsets: vertical = { 0, 500, 1000, 1500, 2000, 2500 }
+Updated points-y to repeat(1000px): vertical = { 0, 1000, 2000, 2500 }
+Updated destination to 0px 250px: vertical = { 0, 750, 1750, 2500 }
+Updated type to none:
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
Added: trunk/LayoutTests/css3/scroll-snap/scroll-snap-style-changed-repeat.html (0 => 190330)
--- trunk/LayoutTests/css3/scroll-snap/scroll-snap-style-changed-repeat.html (rev 0)
+++ trunk/LayoutTests/css3/scroll-snap/scroll-snap-style-changed-repeat.html 2015-09-29 22:56:20 UTC (rev 190330)
@@ -0,0 +1,83 @@
+<html>
+
+ <head>
+ <style>
+ #gallery {
+ width: 515px;
+ height: 500px;
+ -webkit-scroll-snap-type: mandatory;
+ -webkit-overflow-scrolling: touch;
+ -webkit-scroll-snap-points-y: repeat(500px);
+ overflow-y: scroll;
+ position: absolute;
+ }
+
+ .vertical {
+ width: 500px;
+ height: 500px;
+ }
+
+ #child00 { background-color: #DD0000; }
+ #child01 { background-color: #FF6666; }
+ #child02 { background-color: #00DD00; }
+ #child03 { background-color: #66FF66; }
+ #child04 { background-color: #0000DD; }
+ #child05 { background-color: #6666FF; }
+ </style>
+ <script src=""
+ <script>
+ function setup() {
+ var gallery = document.getElementById("gallery");
+
+ function snapOffsets() {
+ return window.internals.scrollSnapOffsets(gallery);
+ }
+
+ // Test starts here. Each function call triggers the next.
+ function dumpSnapOffsetsAndUpdatePointsY() {
+ debug("Original snap offsets: " + snapOffsets());
+ gallery.style.webkitScrollSnapPointsY = "repeat(1000px)";
+ setTimeout(dumpSnapOffsetsAndUpdateDestination, 0);
+ }
+
+ function dumpSnapOffsetsAndUpdateDestination() {
+ debug("Updated points-y to repeat(1000px): " + snapOffsets());
+ gallery.style.webkitScrollSnapDestination = "0px 250px";
+ setTimeout(dumpSnapOffsetsAndUpdateType, 0);
+ }
+
+ function dumpSnapOffsetsAndUpdateType() {
+ debug("Updated destination to 0px 250px: " + snapOffsets());
+ gallery.style.webkitScrollSnapType = "none";
+ setTimeout(dumpSnapOffsetsAndFinishTest, 0);
+ }
+
+ function dumpSnapOffsetsAndFinishTest() {
+ debug("Updated type to none:" + snapOffsets());
+ finishJSTest();
+ testRunner.notifyDone();
+ }
+
+ if (window.testRunner) {
+ window.jsTestIsAsync = true;
+ testRunner.dumpAsText();
+ testRunner.waitUntilDone();
+ setTimeout(dumpSnapOffsetsAndUpdatePointsY, 0);
+ }
+ }
+ </script>
+ </head>
+
+ <body _onload_="setup()">
+ <div id="gallery">
+ <div class="vertical" id="child00"></div>
+ <div class="vertical" id="child01"></div>
+ <div class="vertical" id="child02"></div>
+ <div class="vertical" id="child03"></div>
+ <div class="vertical" id="child04"></div>
+ <div class="vertical" id="child05"></div>
+ </div>
+ <script src=""
+ </body>
+
+</html>
Modified: trunk/Source/WebCore/ChangeLog (190329 => 190330)
--- trunk/Source/WebCore/ChangeLog 2015-09-29 21:25:11 UTC (rev 190329)
+++ trunk/Source/WebCore/ChangeLog 2015-09-29 22:56:20 UTC (rev 190330)
@@ -1,3 +1,40 @@
+2015-09-29 Wenson Hsieh <wenson_hs...@apple.com>
+
+ Snap offsets should update when style is programmatically changed
+ https://bugs.webkit.org/show_bug.cgi?id=135964
+ <rdar://problem/18162411>
+
+ Reviewed by Darin Adler.
+
+ Tests: css3/scroll-snap/scroll-snap-style-changed-coordinates.html
+ css3/scroll-snap/scroll-snap-style-changed-repeat.html
+
+ Updating scroll snap style properties now programmatically updates the scroll snap container. Does not yet
+ handle the case of reparented elements with scroll snap coordinates. Adds some plumbing the FrameView and
+ RenderLayerCompositor to immediately update the scrolling coordinator when updating the FrameView due to
+ style changes.
+
+ * page/FrameView.cpp:
+ (WebCore::FrameView::updateScrollingCoordinatorScrollSnapProperties): Calls on the compositor to reupdate scroll snap
+ properties on the FrameView.
+ * page/FrameView.h:
+ * page/scrolling/AsyncScrollingCoordinator.cpp: Sets snap offsets to an empty vector when appropriate.
+ (WebCore::setStateScrollingNodeSnapOffsetsAsFloat): Ditto.
+ (WebCore::AsyncScrollingCoordinator::frameViewLayoutUpdated): Ditto.
+ (WebCore::AsyncScrollingCoordinator::updateOverflowScrollingNode): Ditto.
+ (WebCore::AsyncScrollingCoordinator::updateScrollSnapPropertiesWithFrameView): Updates scroll snap properties
+ from a given FrameView.
+ * page/scrolling/AsyncScrollingCoordinator.h:
+ * page/scrolling/ScrollingCoordinator.h:
+ (WebCore::ScrollingCoordinator::updateScrollSnapPropertiesWithFrameView):
+ * rendering/RenderLayerCompositor.cpp:
+ (WebCore::RenderLayerCompositor::updateScrollSnapPropertiesWithFrameView): Updates the scrolling coordinator's
+ scroll snap properties.
+ * rendering/RenderLayerCompositor.h: Plumb scroll snap property updating to the FrameView.
+ * rendering/RenderLayerModelObject.cpp: Checks for style changes and updates snap offsets when appropriate.
+ (WebCore::scrollSnapContainerRequiresUpdateForStyleUpdate): Ditto.
+ (WebCore::RenderLayerModelObject::styleDidChange): Ditto.
+
2015-09-29 Jer Noble <jer.no...@apple.com>
REGRESSION: WebAudio user-gesture restriction is no longer lifted by touchstart event
Modified: trunk/Source/WebCore/page/FrameView.cpp (190329 => 190330)
--- trunk/Source/WebCore/page/FrameView.cpp 2015-09-29 21:25:11 UTC (rev 190329)
+++ trunk/Source/WebCore/page/FrameView.cpp 2015-09-29 22:56:20 UTC (rev 190330)
@@ -1007,6 +1007,11 @@
return false;
}
+
+void FrameView::updateScrollingCoordinatorScrollSnapProperties() const
+{
+ renderView()->compositor().updateScrollSnapPropertiesWithFrameView(*this);
+}
#endif
bool FrameView::flushCompositingStateForThisFrame(const Frame& rootFrameForFlush)
Modified: trunk/Source/WebCore/page/FrameView.h (190329 => 190330)
--- trunk/Source/WebCore/page/FrameView.h 2015-09-29 21:25:11 UTC (rev 190329)
+++ trunk/Source/WebCore/page/FrameView.h 2015-09-29 22:56:20 UTC (rev 190330)
@@ -544,6 +544,7 @@
#if ENABLE(CSS_SCROLL_SNAP)
void updateSnapOffsets() override;
bool isScrollSnapInProgress() const override;
+ void updateScrollingCoordinatorScrollSnapProperties() const;
#endif
virtual float adjustScrollStepForFixedContent(float step, ScrollbarOrientation, ScrollGranularity) override;
Modified: trunk/Source/WebCore/page/scrolling/AsyncScrollingCoordinator.cpp (190329 => 190330)
--- trunk/Source/WebCore/page/scrolling/AsyncScrollingCoordinator.cpp 2015-09-29 21:25:11 UTC (rev 190329)
+++ trunk/Source/WebCore/page/scrolling/AsyncScrollingCoordinator.cpp 2015-09-29 22:56:20 UTC (rev 190330)
@@ -62,14 +62,15 @@
scheduleTreeStateCommit();
}
-static inline void setStateScrollingNodeSnapOffsetsAsFloat(ScrollingStateScrollingNode& node, ScrollEventAxis axis, const Vector<LayoutUnit>& snapOffsets, float deviceScaleFactor)
+static inline void setStateScrollingNodeSnapOffsetsAsFloat(ScrollingStateScrollingNode& node, ScrollEventAxis axis, const Vector<LayoutUnit>* snapOffsets, float deviceScaleFactor)
{
// FIXME: Incorporate current page scale factor in snapping to device pixel. Perhaps we should just convert to float here and let UI process do the pixel snapping?
Vector<float> snapOffsetsAsFloat;
- snapOffsetsAsFloat.reserveInitialCapacity(snapOffsets.size());
- for (auto& offset : snapOffsets)
- snapOffsetsAsFloat.append(roundToDevicePixel(offset, deviceScaleFactor, false));
-
+ if (snapOffsets) {
+ snapOffsetsAsFloat.reserveInitialCapacity(snapOffsets->size());
+ for (auto& offset : *snapOffsets)
+ snapOffsetsAsFloat.uncheckedAppend(roundToDevicePixel(offset, deviceScaleFactor, false));
+ }
if (axis == ScrollEventAxis::Horizontal)
node.setHorizontalSnapOffsets(snapOffsetsAsFloat);
else
@@ -141,14 +142,7 @@
#if ENABLE(CSS_SCROLL_SNAP)
frameView.updateSnapOffsets();
- if (const Vector<LayoutUnit>* horizontalSnapOffsets = frameView.horizontalSnapOffsets())
- setStateScrollingNodeSnapOffsetsAsFloat(*node, ScrollEventAxis::Horizontal, *horizontalSnapOffsets, m_page->deviceScaleFactor());
-
- if (const Vector<LayoutUnit>* verticalSnapOffsets = frameView.verticalSnapOffsets())
- setStateScrollingNodeSnapOffsetsAsFloat(*node, ScrollEventAxis::Vertical, *verticalSnapOffsets, m_page->deviceScaleFactor());
-
- node->setCurrentHorizontalSnapPointIndex(frameView.currentHorizontalSnapPointIndex());
- node->setCurrentVerticalSnapPointIndex(frameView.currentVerticalSnapPointIndex());
+ updateScrollSnapPropertiesWithFrameView(frameView);
#endif
#if PLATFORM(COCOA)
@@ -485,8 +479,8 @@
node->setReachableContentsSize(scrollingGeometry->reachableContentSize);
node->setScrollableAreaSize(scrollingGeometry->scrollableAreaSize);
#if ENABLE(CSS_SCROLL_SNAP)
- setStateScrollingNodeSnapOffsetsAsFloat(*node, ScrollEventAxis::Horizontal, scrollingGeometry->horizontalSnapOffsets, m_page->deviceScaleFactor());
- setStateScrollingNodeSnapOffsetsAsFloat(*node, ScrollEventAxis::Vertical, scrollingGeometry->verticalSnapOffsets, m_page->deviceScaleFactor());
+ setStateScrollingNodeSnapOffsetsAsFloat(*node, ScrollEventAxis::Horizontal, &scrollingGeometry->horizontalSnapOffsets, m_page->deviceScaleFactor());
+ setStateScrollingNodeSnapOffsetsAsFloat(*node, ScrollEventAxis::Vertical, &scrollingGeometry->verticalSnapOffsets, m_page->deviceScaleFactor());
node->setCurrentHorizontalSnapPointIndex(scrollingGeometry->currentHorizontalSnapPointIndex);
node->setCurrentVerticalSnapPointIndex(scrollingGeometry->currentVerticalSnapPointIndex);
#endif
@@ -621,6 +615,16 @@
{
return scrollingTree()->isScrollSnapInProgress();
}
+
+void AsyncScrollingCoordinator::updateScrollSnapPropertiesWithFrameView(const FrameView& frameView)
+{
+ if (auto node = downcast<ScrollingStateFrameScrollingNode>(m_scrollingStateTree->stateNodeForID(frameView.scrollLayerID()))) {
+ setStateScrollingNodeSnapOffsetsAsFloat(*node, ScrollEventAxis::Horizontal, frameView.horizontalSnapOffsets(), m_page->deviceScaleFactor());
+ setStateScrollingNodeSnapOffsetsAsFloat(*node, ScrollEventAxis::Vertical, frameView.verticalSnapOffsets(), m_page->deviceScaleFactor());
+ node->setCurrentHorizontalSnapPointIndex(frameView.currentHorizontalSnapPointIndex());
+ node->setCurrentVerticalSnapPointIndex(frameView.currentVerticalSnapPointIndex());
+ }
+}
#endif
} // namespace WebCore
Modified: trunk/Source/WebCore/page/scrolling/AsyncScrollingCoordinator.h (190329 => 190330)
--- trunk/Source/WebCore/page/scrolling/AsyncScrollingCoordinator.h 2015-09-29 21:25:11 UTC (rev 190329)
+++ trunk/Source/WebCore/page/scrolling/AsyncScrollingCoordinator.h 2015-09-29 22:56:20 UTC (rev 190330)
@@ -62,6 +62,10 @@
void removeTestDeferralForReason(WheelEventTestTrigger::ScrollableAreaIdentifier, WheelEventTestTrigger::DeferTestTriggerReason) const;
#endif
+#if ENABLE(CSS_SCROLL_SNAP)
+ WEBCORE_EXPORT void updateScrollSnapPropertiesWithFrameView(const FrameView&) override;
+#endif
+
protected:
WEBCORE_EXPORT AsyncScrollingCoordinator(Page*);
Modified: trunk/Source/WebCore/page/scrolling/ScrollingCoordinator.h (190329 => 190330)
--- trunk/Source/WebCore/page/scrolling/ScrollingCoordinator.h 2015-09-29 21:25:11 UTC (rev 190329)
+++ trunk/Source/WebCore/page/scrolling/ScrollingCoordinator.h 2015-09-29 22:56:20 UTC (rev 190330)
@@ -179,6 +179,7 @@
virtual String scrollingStateTreeAsText() const;
virtual bool isRubberBandInProgress() const { return false; }
virtual bool isScrollSnapInProgress() const { return false; }
+ virtual void updateScrollSnapPropertiesWithFrameView(const FrameView&) { }
virtual void setScrollPinningBehavior(ScrollPinningBehavior) { }
// Generated a unique id for scroll layers.
Modified: trunk/Source/WebCore/rendering/RenderLayerCompositor.cpp (190329 => 190330)
--- trunk/Source/WebCore/rendering/RenderLayerCompositor.cpp 2015-09-29 21:25:11 UTC (rev 190329)
+++ trunk/Source/WebCore/rendering/RenderLayerCompositor.cpp 2015-09-29 22:56:20 UTC (rev 190330)
@@ -4264,4 +4264,12 @@
return m_compositingUpdateCount;
}
+#if ENABLE(CSS_SCROLL_SNAP)
+void RenderLayerCompositor::updateScrollSnapPropertiesWithFrameView(const FrameView& frameView)
+{
+ if (ScrollingCoordinator* coordinator = scrollingCoordinator())
+ coordinator->updateScrollSnapPropertiesWithFrameView(frameView);
+}
+#endif
+
} // namespace WebCore
Modified: trunk/Source/WebCore/rendering/RenderLayerCompositor.h (190329 => 190330)
--- trunk/Source/WebCore/rendering/RenderLayerCompositor.h 2015-09-29 21:25:11 UTC (rev 190329)
+++ trunk/Source/WebCore/rendering/RenderLayerCompositor.h 2015-09-29 22:56:20 UTC (rev 190330)
@@ -313,6 +313,10 @@
void setRootExtendedBackgroundColor(const Color&);
Color rootExtendedBackgroundColor() const { return m_rootExtendedBackgroundColor; }
+#if ENABLE(CSS_SCROLL_SNAP)
+ void updateScrollSnapPropertiesWithFrameView(const FrameView&);
+#endif
+
// For testing.
WEBCORE_EXPORT void startTrackingLayerFlushes();
WEBCORE_EXPORT unsigned layerFlushCount() const;
Modified: trunk/Source/WebCore/rendering/RenderLayerModelObject.cpp (190329 => 190330)
--- trunk/Source/WebCore/rendering/RenderLayerModelObject.cpp 2015-09-29 21:25:11 UTC (rev 190329)
+++ trunk/Source/WebCore/rendering/RenderLayerModelObject.cpp 2015-09-29 22:56:20 UTC (rev 190330)
@@ -26,6 +26,7 @@
#include "RenderLayerModelObject.h"
#include "RenderLayer.h"
+#include "RenderLayerCompositor.h"
#include "RenderView.h"
namespace WebCore {
@@ -124,6 +125,16 @@
RenderElement::styleWillChange(diff, newStyle);
}
+#if ENABLE(CSS_SCROLL_SNAP)
+static bool scrollSnapContainerRequiresUpdateForStyleUpdate(const RenderStyle& oldStyle, const RenderStyle& newStyle)
+{
+ return !(oldStyle.scrollSnapType() == newStyle.scrollSnapType()
+ && oldStyle.scrollSnapPointsX() == newStyle.scrollSnapPointsX()
+ && oldStyle.scrollSnapPointsY() == newStyle.scrollSnapPointsY()
+ && oldStyle.scrollSnapDestination() == newStyle.scrollSnapDestination());
+}
+#endif
+
void RenderLayerModelObject::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
{
RenderElement::styleDidChange(diff, oldStyle);
@@ -169,6 +180,33 @@
else
view().frameView().removeViewportConstrainedObject(this);
}
+
+#if ENABLE(CSS_SCROLL_SNAP)
+ const RenderStyle& newStyle = style();
+ if (oldStyle && scrollSnapContainerRequiresUpdateForStyleUpdate(*oldStyle, newStyle)) {
+ if (RenderLayer* renderLayer = layer()) {
+ renderLayer->updateSnapOffsets();
+ renderLayer->updateScrollSnapState();
+ } else if (isBody() || isRoot()) {
+ FrameView& frameView = view().frameView();
+ frameView.updateSnapOffsets();
+ frameView.updateScrollSnapState();
+ frameView.updateScrollingCoordinatorScrollSnapProperties();
+ }
+ }
+ if (oldStyle && oldStyle->scrollSnapCoordinates() != newStyle.scrollSnapCoordinates()) {
+ const RenderBox* scrollSnapBox = enclosingBox().findEnclosingScrollableContainer();
+ if (scrollSnapBox && scrollSnapBox->layer()) {
+ const RenderStyle& style = scrollSnapBox->style();
+ if (style.scrollSnapType() != ScrollSnapType::None) {
+ scrollSnapBox->layer()->updateSnapOffsets();
+ scrollSnapBox->layer()->updateScrollSnapState();
+ if (scrollSnapBox->isBody() || scrollSnapBox->isRoot())
+ scrollSnapBox->view().frameView().updateScrollingCoordinatorScrollSnapProperties();
+ }
+ }
+ }
+#endif
}
} // namespace WebCore