1/*
2 * Copyright (C) 2014 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 "ScrollingTreeFrameScrollingNode.h"
28
29#if ENABLE(ASYNC_SCROLLING)
30
31#include "FrameView.h"
32#include "Logging.h"
33#include "ScrollingStateFrameScrollingNode.h"
34#include "ScrollingStateTree.h"
35#include "ScrollingTree.h"
36#include <wtf/text/TextStream.h>
37
38namespace WebCore {
39
40ScrollingTreeFrameScrollingNode::ScrollingTreeFrameScrollingNode(ScrollingTree& scrollingTree, ScrollingNodeType nodeType, ScrollingNodeID nodeID)
41 : ScrollingTreeScrollingNode(scrollingTree, nodeType, nodeID)
42{
43 ASSERT(isFrameScrollingNode());
44}
45
46ScrollingTreeFrameScrollingNode::~ScrollingTreeFrameScrollingNode() = default;
47
48void ScrollingTreeFrameScrollingNode::commitStateBeforeChildren(const ScrollingStateNode& stateNode)
49{
50 ScrollingTreeScrollingNode::commitStateBeforeChildren(stateNode);
51
52 const ScrollingStateFrameScrollingNode& state = downcast<ScrollingStateFrameScrollingNode>(stateNode);
53
54 if (state.hasChangedProperty(ScrollingStateFrameScrollingNode::FrameScaleFactor))
55 m_frameScaleFactor = state.frameScaleFactor();
56
57 if (state.hasChangedProperty(ScrollingStateFrameScrollingNode::ReasonsForSynchronousScrolling))
58 m_synchronousScrollingReasons = state.synchronousScrollingReasons();
59
60 if (state.hasChangedProperty(ScrollingStateFrameScrollingNode::HeaderHeight))
61 m_headerHeight = state.headerHeight();
62
63 if (state.hasChangedProperty(ScrollingStateFrameScrollingNode::FooterHeight))
64 m_footerHeight = state.footerHeight();
65
66 if (state.hasChangedProperty(ScrollingStateFrameScrollingNode::BehaviorForFixedElements))
67 m_behaviorForFixed = state.scrollBehaviorForFixedElements();
68
69 if (state.hasChangedProperty(ScrollingStateFrameScrollingNode::TopContentInset))
70 m_topContentInset = state.topContentInset();
71
72 if (state.hasChangedProperty(ScrollingStateFrameScrollingNode::FixedElementsLayoutRelativeToFrame))
73 m_fixedElementsLayoutRelativeToFrame = state.fixedElementsLayoutRelativeToFrame();
74
75 if (state.hasChangedProperty(ScrollingStateFrameScrollingNode::LayoutViewport)) {
76 m_layoutViewport = state.layoutViewport();
77 updateViewportForCurrentScrollPosition({ });
78 }
79
80 if (state.hasChangedProperty(ScrollingStateFrameScrollingNode::MinLayoutViewportOrigin))
81 m_minLayoutViewportOrigin = state.minLayoutViewportOrigin();
82
83 if (state.hasChangedProperty(ScrollingStateFrameScrollingNode::MaxLayoutViewportOrigin))
84 m_maxLayoutViewportOrigin = state.maxLayoutViewportOrigin();
85}
86
87bool ScrollingTreeFrameScrollingNode::scrollPositionAndLayoutViewportMatch(const FloatPoint& position, Optional<FloatRect> overrideLayoutViewport)
88{
89 return position == currentScrollPosition() && (!overrideLayoutViewport || overrideLayoutViewport.value() == m_layoutViewport);
90}
91
92FloatRect ScrollingTreeFrameScrollingNode::layoutViewportForScrollPosition(const FloatPoint& visibleContentOrigin, float scale) const
93{
94 FloatRect visibleContentRect(visibleContentOrigin, scrollableAreaSize());
95 LayoutRect visualViewport(FrameView::visibleDocumentRect(visibleContentRect, headerHeight(), footerHeight(), totalContentsSize(), scale));
96 LayoutRect layoutViewport(m_layoutViewport);
97
98 LOG_WITH_STREAM(Scrolling, stream << "\nScrolling thread: " << "(visibleContentOrigin " << visibleContentOrigin << ") fixed behavior " << m_behaviorForFixed);
99 LOG_WITH_STREAM(Scrolling, stream << " layoutViewport: " << layoutViewport);
100 LOG_WITH_STREAM(Scrolling, stream << " visualViewport: " << visualViewport);
101 LOG_WITH_STREAM(Scrolling, stream << " scroll positions: min: " << minLayoutViewportOrigin() << " max: "<< maxLayoutViewportOrigin());
102
103 LayoutPoint newLocation = FrameView::computeLayoutViewportOrigin(LayoutRect(visualViewport), LayoutPoint(minLayoutViewportOrigin()), LayoutPoint(maxLayoutViewportOrigin()), layoutViewport, m_behaviorForFixed);
104
105 if (layoutViewport.location() != newLocation) {
106 layoutViewport.setLocation(newLocation);
107 LOG_WITH_STREAM(Scrolling, stream << " new layoutViewport " << layoutViewport);
108 }
109
110 return layoutViewport;
111}
112
113void ScrollingTreeFrameScrollingNode::updateViewportForCurrentScrollPosition(Optional<FloatRect> overrideLayoutViewport)
114{
115 if (overrideLayoutViewport)
116 setLayoutViewport(overrideLayoutViewport.value());
117 else
118 setLayoutViewport(layoutViewportForScrollPosition(currentScrollPosition(), frameScaleFactor()));
119}
120
121FloatSize ScrollingTreeFrameScrollingNode::viewToContentsOffset(const FloatPoint& scrollPosition) const
122{
123 return toFloatSize(scrollPosition) - FloatSize(0, headerHeight() + topContentInset());
124}
125
126LayoutPoint ScrollingTreeFrameScrollingNode::parentToLocalPoint(LayoutPoint point) const
127{
128 return point - LayoutSize(0, headerHeight() + topContentInset());
129}
130
131LayoutPoint ScrollingTreeFrameScrollingNode::localToContentsPoint(LayoutPoint point) const
132{
133 auto scrolledPoint = point + LayoutPoint(currentScrollPosition());
134 return scrolledPoint.scaled(1 / frameScaleFactor());
135}
136
137void ScrollingTreeFrameScrollingNode::dumpProperties(TextStream& ts, ScrollingStateTreeAsTextBehavior behavior) const
138{
139 ts << "frame scrolling node";
140 ScrollingTreeScrollingNode::dumpProperties(ts, behavior);
141
142 ts.dumpProperty("layout viewport", m_layoutViewport);
143 ts.dumpProperty("min layoutViewport origin", m_minLayoutViewportOrigin);
144 ts.dumpProperty("max layoutViewport origin", m_maxLayoutViewportOrigin);
145
146 if (m_frameScaleFactor != 1)
147 ts.dumpProperty("frame scale factor", m_frameScaleFactor);
148 if (m_topContentInset)
149 ts.dumpProperty("top content inset", m_topContentInset);
150
151 if (m_headerHeight)
152 ts.dumpProperty("header height", m_headerHeight);
153 if (m_footerHeight)
154 ts.dumpProperty("footer height", m_footerHeight);
155 if (m_synchronousScrollingReasons)
156 ts.dumpProperty("synchronous scrolling reasons", ScrollingCoordinator::synchronousScrollingReasonsAsText(m_synchronousScrollingReasons));
157
158 ts.dumpProperty("behavior for fixed", m_behaviorForFixed);
159 if (m_fixedElementsLayoutRelativeToFrame)
160 ts.dumpProperty("fixed elements lay out relative to frame", m_fixedElementsLayoutRelativeToFrame);
161}
162
163
164} // namespace WebCore
165
166#endif // ENABLE(ASYNC_SCROLLING)
167