summaryrefslogtreecommitdiffstats
path: root/src/3rdparty/webkit/WebCore/page/FrameView.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/3rdparty/webkit/WebCore/page/FrameView.cpp')
-rw-r--r--src/3rdparty/webkit/WebCore/page/FrameView.cpp223
1 files changed, 199 insertions, 24 deletions
diff --git a/src/3rdparty/webkit/WebCore/page/FrameView.cpp b/src/3rdparty/webkit/WebCore/page/FrameView.cpp
index 41f2c5cc39..d57e845eae 100644
--- a/src/3rdparty/webkit/WebCore/page/FrameView.cpp
+++ b/src/3rdparty/webkit/WebCore/page/FrameView.cpp
@@ -111,7 +111,6 @@ FrameView::FrameView(Frame* frame)
, m_shouldUpdateWhileOffscreen(true)
, m_deferSetNeedsLayouts(0)
, m_setNeedsLayoutWasDeferred(false)
- , m_lockedToAnchor(false)
{
init();
}
@@ -185,7 +184,7 @@ void FrameView::reset()
m_isPainting = false;
m_isVisuallyNonEmpty = false;
m_firstVisuallyNonEmptyLayoutCallbackPending = true;
- m_lockedToAnchor = false;
+ m_maintainScrollPositionAnchor = 0;
}
bool FrameView::isFrameView() const
@@ -417,20 +416,18 @@ void FrameView::applyOverflowToViewport(RenderObject* o, ScrollbarMode& hMode, S
}
#if USE(ACCELERATED_COMPOSITING)
-void FrameView::updateCompositingLayers(CompositingUpdate updateType)
+void FrameView::updateCompositingLayers()
{
RenderView* view = m_frame->contentRenderer();
- if (view && view->compositor()) {
- // This call will make sure the cached hasAcceleratedCompositing is updated from the pref
- view->compositor()->cacheAcceleratedCompositingEnabledFlag();
- }
-
- if (!view || !view->usesCompositing())
+ if (!view)
return;
- if (updateType == ForcedCompositingUpdate)
- view->compositor()->setCompositingLayersNeedUpdate();
+ // This call will make sure the cached hasAcceleratedCompositing is updated from the pref
+ view->compositor()->cacheAcceleratedCompositingEnabledFlag();
+ if (!view->usesCompositing())
+ return;
+
view->compositor()->updateCompositingLayers();
}
@@ -624,7 +621,9 @@ void FrameView::layout(bool allowSubtree)
// Now update the positions of all layers.
beginDeferredRepaints();
- layer->updateLayerPositions(m_doFullRepaint);
+ layer->updateLayerPositions((m_doFullRepaint ? RenderLayer::DoFullRepaint : 0)
+ | RenderLayer::CheckForRepaint
+ | RenderLayer::UpdateCompositingLayers);
endDeferredRepaints();
#if USE(ACCELERATED_COMPOSITING)
@@ -666,9 +665,6 @@ void FrameView::layout(bool allowSubtree)
ASSERT(m_enqueueEvents);
}
- if (lockedToAnchor())
- m_frame->loader()->gotoAnchor();
-
m_nestedLayoutCount--;
}
@@ -751,11 +747,27 @@ void FrameView::restoreScrollbar()
setScrollbarsSuppressed(false);
}
+void FrameView::maintainScrollPositionAtAnchor(Node* anchorNode)
+{
+ m_maintainScrollPositionAnchor = anchorNode;
+ if (!m_maintainScrollPositionAnchor)
+ return;
+
+ // We need to update the layout before scrolling, otherwise we could
+ // really mess things up if an anchor scroll comes at a bad moment.
+ m_frame->document()->updateStyleIfNeeded();
+ // Only do a layout if changes have occurred that make it necessary.
+ if (m_frame->contentRenderer() && m_frame->contentRenderer()->needsLayout())
+ layout();
+ else
+ scrollToAnchor();
+}
+
void FrameView::scrollRectIntoViewRecursively(const IntRect& r)
{
bool wasInProgrammaticScroll = m_inProgrammaticScroll;
m_inProgrammaticScroll = true;
- setLockedToAnchor(false);
+ m_maintainScrollPositionAnchor = 0;
ScrollView::scrollRectIntoViewRecursively(r);
m_inProgrammaticScroll = wasInProgrammaticScroll;
}
@@ -764,7 +776,7 @@ void FrameView::setScrollPosition(const IntPoint& scrollPoint)
{
bool wasInProgrammaticScroll = m_inProgrammaticScroll;
m_inProgrammaticScroll = true;
- setLockedToAnchor(false);
+ m_maintainScrollPositionAnchor = 0;
ScrollView::setScrollPosition(scrollPoint);
m_inProgrammaticScroll = wasInProgrammaticScroll;
}
@@ -1118,6 +1130,27 @@ void FrameView::resumeScheduledEvents()
ASSERT(m_scheduledEvents.isEmpty() || m_enqueueEvents);
}
+void FrameView::scrollToAnchor()
+{
+ RefPtr<Node> anchorNode = m_maintainScrollPositionAnchor;
+ if (!anchorNode)
+ return;
+
+ if (!anchorNode->renderer())
+ return;
+
+ IntRect rect;
+ if (anchorNode != m_frame->document())
+ rect = anchorNode->getRect();
+
+ // Scroll nested layers and frames to reveal the anchor.
+ // Align to the top and to the closest side (this matches other browsers).
+ anchorNode->renderer()->enclosingLayer()->scrollRectToVisible(rect, true, ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignTopAlways);
+
+ // scrollRectToVisible can call into scrollRectIntoViewRecursively(), which resets m_maintainScrollPositionAnchor.
+ m_maintainScrollPositionAnchor = anchorNode;
+}
+
bool FrameView::updateWidgets()
{
if (m_nestedLayoutCount > 1 || !m_widgetUpdateSet || m_widgetUpdateSet->isEmpty())
@@ -1161,7 +1194,9 @@ void FrameView::performPostLayoutTasks()
if (updateWidgets())
break;
}
-
+
+ scrollToAnchor();
+
resumeScheduledEvents();
if (!root->printing()) {
@@ -1351,7 +1386,7 @@ void FrameView::setWasScrolledByUser(bool wasScrolledByUser)
{
if (m_inProgrammaticScroll)
return;
- setLockedToAnchor(false);
+ m_maintainScrollPositionAnchor = 0;
m_wasScrolledByUser = wasScrolledByUser;
}
@@ -1447,11 +1482,13 @@ void FrameView::layoutIfNeededRecursive()
if (needsLayout())
layout();
- const HashSet<Widget*>* viewChildren = children();
- HashSet<Widget*>::const_iterator end = viewChildren->end();
- for (HashSet<Widget*>::const_iterator current = viewChildren->begin(); current != end; ++current)
- if ((*current)->isFrameView())
- static_cast<FrameView*>(*current)->layoutIfNeededRecursive();
+ const HashSet<RefPtr<Widget> >* viewChildren = children();
+ HashSet<RefPtr<Widget> >::const_iterator end = viewChildren->end();
+ for (HashSet<RefPtr<Widget> >::const_iterator current = viewChildren->begin(); current != end; ++current) {
+ Widget* widget = (*current).get();
+ if (widget->isFrameView())
+ static_cast<FrameView*>(widget)->layoutIfNeededRecursive();
+ }
// layoutIfNeededRecursive is called when we need to make sure layout is up-to-date before
// painting, so we need to flush out any deferred repaints too.
@@ -1517,4 +1554,142 @@ void FrameView::adjustPageHeight(float *newBottom, float oldTop, float oldBottom
*newBottom = oldBottom;
}
+IntRect FrameView::convertFromRenderer(const RenderObject* renderer, const IntRect& rendererRect) const
+{
+ IntRect rect = renderer->localToAbsoluteQuad(FloatRect(rendererRect)).enclosingBoundingBox();
+
+ // Convert from page ("absolute") to FrameView coordinates.
+ rect.move(-scrollX(), -scrollY());
+
+ return rect;
+}
+
+IntRect FrameView::convertToRenderer(const RenderObject* renderer, const IntRect& viewRect) const
+{
+ IntRect rect = viewRect;
+
+ // Convert from FrameView coords into page ("absolute") coordinates.
+ rect.move(scrollX(), scrollY());
+
+ // FIXME: we don't have a way to map an absolute rect down to a local quad, so just
+ // move the rect for now.
+ rect.setLocation(roundedIntPoint(renderer->absoluteToLocal(rect.location(), false, true /* use transforms */)));
+ return rect;
+}
+
+IntPoint FrameView::convertFromRenderer(const RenderObject* renderer, const IntPoint& rendererPoint) const
+{
+ IntPoint point = roundedIntPoint(renderer->localToAbsolute(rendererPoint, false, true /* use transforms */));
+
+ // Convert from page ("absolute") to FrameView coordinates.
+ point.move(-scrollX(), -scrollY());
+ return point;
+}
+
+IntPoint FrameView::convertToRenderer(const RenderObject* renderer, const IntPoint& viewPoint) const
+{
+ IntPoint point = viewPoint;
+
+ // Convert from FrameView coords into page ("absolute") coordinates.
+ point += IntSize(scrollX(), scrollY());
+
+ return roundedIntPoint(renderer->absoluteToLocal(point, false, true /* use transforms */));
+}
+
+IntRect FrameView::convertToContainingView(const IntRect& localRect) const
+{
+ if (const ScrollView* parentScrollView = parent()) {
+ if (parentScrollView->isFrameView()) {
+ const FrameView* parentView = static_cast<const FrameView*>(parentScrollView);
+ // Get our renderer in the parent view
+ RenderPart* renderer = m_frame->ownerRenderer();
+ if (!renderer)
+ return localRect;
+
+ IntRect rect(localRect);
+ // Add borders and padding??
+ rect.move(renderer->borderLeft() + renderer->paddingLeft(),
+ renderer->borderTop() + renderer->paddingTop());
+ return parentView->convertFromRenderer(renderer, rect);
+ }
+
+ return Widget::convertToContainingView(localRect);
+ }
+
+ return localRect;
+}
+
+IntRect FrameView::convertFromContainingView(const IntRect& parentRect) const
+{
+ if (const ScrollView* parentScrollView = parent()) {
+ if (parentScrollView->isFrameView()) {
+ const FrameView* parentView = static_cast<const FrameView*>(parentScrollView);
+
+ // Get our renderer in the parent view
+ RenderPart* renderer = m_frame->ownerRenderer();
+ if (!renderer)
+ return parentRect;
+
+ IntRect rect = parentView->convertToRenderer(renderer, parentRect);
+ // Subtract borders and padding
+ rect.move(-renderer->borderLeft() - renderer->paddingLeft(),
+ -renderer->borderTop() - renderer->paddingTop());
+ return rect;
+ }
+
+ return Widget::convertFromContainingView(parentRect);
+ }
+
+ return parentRect;
+}
+
+IntPoint FrameView::convertToContainingView(const IntPoint& localPoint) const
+{
+ if (const ScrollView* parentScrollView = parent()) {
+ if (parentScrollView->isFrameView()) {
+ const FrameView* parentView = static_cast<const FrameView*>(parentScrollView);
+
+ // Get our renderer in the parent view
+ RenderPart* renderer = m_frame->ownerRenderer();
+ if (!renderer)
+ return localPoint;
+
+ IntPoint point(localPoint);
+
+ // Add borders and padding
+ point.move(renderer->borderLeft() + renderer->paddingLeft(),
+ renderer->borderTop() + renderer->paddingTop());
+ return parentView->convertFromRenderer(renderer, point);
+ }
+
+ return Widget::convertToContainingView(localPoint);
+ }
+
+ return localPoint;
+}
+
+IntPoint FrameView::convertFromContainingView(const IntPoint& parentPoint) const
+{
+ if (const ScrollView* parentScrollView = parent()) {
+ if (parentScrollView->isFrameView()) {
+ const FrameView* parentView = static_cast<const FrameView*>(parentScrollView);
+
+ // Get our renderer in the parent view
+ RenderPart* renderer = m_frame->ownerRenderer();
+ if (!renderer)
+ return parentPoint;
+
+ IntPoint point = parentView->convertToRenderer(renderer, parentPoint);
+ // Subtract borders and padding
+ point.move(-renderer->borderLeft() - renderer->paddingLeft(),
+ -renderer->borderTop() - renderer->paddingTop());
+ return point;
+ }
+
+ return Widget::convertFromContainingView(parentPoint);
+ }
+
+ return parentPoint;
+}
+
} // namespace WebCore