Changeset 209411 in webkit
- Timestamp:
- Dec 6, 2016 12:00:28 PM (7 years ago)
- Location:
- trunk
- Files:
-
- 6 added
- 21 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r209410 r209411 1 2016-12-05 Simon Fraser <simon.fraser@apple.com> 2 3 Improve the behavior of scroll-into-view when the target is inside position:fixed 4 https://bugs.webkit.org/show_bug.cgi?id=165354 5 6 Reviewed by Zalan Bujtas. 7 8 * fast/overflow/scroll-anchor-in-position-fixed-expected.txt: Added. 9 * fast/overflow/scroll-anchor-in-position-fixed.html: Added. 10 * fast/transforms/selection-bounds-in-transformed-view.html: 11 * fast/visual-viewport/zoomed-scroll-into-view-fixed-expected.txt: Added. 12 * fast/visual-viewport/zoomed-scroll-into-view-fixed.html: Added. 13 * fast/visual-viewport/zoomed-scroll-to-anchor-in-position-fixed-expected.txt: Added. 14 * fast/visual-viewport/zoomed-scroll-to-anchor-in-position-fixed.html: Added. 15 * platform/ios-simulator/TestExpectations: 16 1 17 2016-12-06 Myles C. Maxfield <mmaxfield@apple.com> 2 18 -
trunk/LayoutTests/fast/transforms/selection-bounds-in-transformed-view.html
r209348 r209411 11 11 12 12 document.execCommand("FindString", false, "target"); 13 document.getElementById("result").innerText = document.body.scrollTop === 864? "PASS" : "FAIL";13 document.getElementById("result").innerText = document.body.scrollTop === 937 ? "PASS" : "FAIL"; 14 14 </script> 15 15 </body> -
trunk/LayoutTests/platform/ios-simulator/TestExpectations
r209410 r209411 2737 2737 # Test relies on window.scrollTo 2738 2738 fast/zooming/client-rect-in-fixed-zoomed.html [ Skip ] 2739 fast/visual-viewport/zoomed-scroll-to-anchor-in-position-fixed.html [ Skip ] 2740 fast/visual-viewport/zoomed-scroll-into-view-fixed.html [ Skip ] 2739 2741 2740 2742 # This test relies on Arial being used to draw Arabic. However, on iOS, -
trunk/Source/WebCore/ChangeLog
r209410 r209411 1 2016-12-05 Simon Fraser <simon.fraser@apple.com> 2 3 Improve the behavior of scroll-into-view when the target is inside position:fixed 4 https://bugs.webkit.org/show_bug.cgi?id=165354 5 6 Reviewed by Zalan Bujtas. 7 8 The existing RenderLayer::scrollRectToVisible() code paid no heed to whether the 9 target was inside position:fixed, resulting in unwanted scrolls. 10 11 Fix this by plumbing through from the call sites a "insideFixed" flag which we get 12 when we call localToAbsolute(), and use this flag to avoid scrolling at all if 13 unzoomed. 14 15 If zoomed and we're focussing something inside position:fixed, and if visual viewports 16 are enabled, we can compute the visual viewport required to reveal the target rect, 17 which gives us the ideal scroll position. 18 19 Fix a bug on non-iOS platforms when zoomed, which is to scale the viewRect since 20 frameView.visibleContentRect() gives an unscaled rect on those platforms. 21 22 Not all callers of scrollRectToVisible() are fixed, but those that are not will get 23 the current behavior. 24 25 Tests: fast/overflow/scroll-anchor-in-position-fixed.html 26 fast/visual-viewport/zoomed-scroll-into-view-fixed.html 27 fast/visual-viewport/zoomed-scroll-to-anchor-in-position-fixed.html 28 29 * dom/Element.cpp: 30 (WebCore::Element::scrollIntoView): 31 (WebCore::Element::scrollIntoViewIfNeeded): 32 (WebCore::Element::scrollIntoViewIfNotVisible): 33 (WebCore::Element::updateFocusAppearance): 34 * editing/FrameSelection.cpp: 35 (WebCore::FrameSelection::FrameSelection): 36 (WebCore::FrameSelection::absoluteCaretBounds): 37 (WebCore::FrameSelection::recomputeCaretRect): 38 (WebCore::FrameSelection::revealSelection): 39 * editing/FrameSelection.h: 40 * editing/VisiblePosition.cpp: 41 (WebCore::VisiblePosition::absoluteCaretBounds): 42 * editing/VisiblePosition.h: 43 * editing/htmlediting.cpp: 44 (WebCore::absoluteBoundsForLocalCaretRect): 45 * editing/htmlediting.h: 46 * page/FrameView.cpp: 47 (WebCore::FrameView::scrollElementToRect): 48 (WebCore::FrameView::scrollToAnchor): 49 * page/PrintContext.cpp: 50 (WebCore::PrintContext::outputLinkedDestinations): 51 * rendering/RenderElement.cpp: 52 (WebCore::RenderElement::getLeadingCorner): 53 (WebCore::RenderElement::getTrailingCorner): 54 (WebCore::RenderElement::absoluteAnchorRect): 55 (WebCore::RenderElement::anchorRect): Deleted. 56 * rendering/RenderElement.h: 57 * rendering/RenderLayer.cpp: 58 (WebCore::RenderLayer::scrollRectToVisible): 59 (WebCore::RenderLayer::getRectToExpose): 60 (WebCore::RenderLayer::autoscroll): 61 * rendering/RenderLayer.h: 62 * rendering/RenderObject.cpp: 63 (WebCore::RenderObject::scrollRectToVisible): 64 * rendering/RenderObject.h: 65 1 66 2016-12-06 Myles C. Maxfield <mmaxfield@apple.com> 2 67 -
trunk/Source/WebCore/dom/Element.cpp
r209394 r209411 650 650 return; 651 651 652 LayoutRect bounds = renderer()->anchorRect(); 652 bool insideFixed; 653 LayoutRect absoluteBounds = renderer()->absoluteAnchorRect(&insideFixed); 653 654 // Align to the top / bottom and to the closest edge. 654 655 if (alignToTop) 655 renderer()->scrollRectToVisible(SelectionRevealMode::Reveal, bounds, ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignTopAlways);656 renderer()->scrollRectToVisible(SelectionRevealMode::Reveal, absoluteBounds, insideFixed, ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignTopAlways); 656 657 else 657 renderer()->scrollRectToVisible(SelectionRevealMode::Reveal, bounds, ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignBottomAlways);658 renderer()->scrollRectToVisible(SelectionRevealMode::Reveal, absoluteBounds, insideFixed, ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignBottomAlways); 658 659 } 659 660 … … 665 666 return; 666 667 667 LayoutRect bounds = renderer()->anchorRect(); 668 bool insideFixed; 669 LayoutRect absoluteBounds = renderer()->absoluteAnchorRect(&insideFixed); 668 670 if (centerIfNeeded) 669 renderer()->scrollRectToVisible(SelectionRevealMode::Reveal, bounds, ScrollAlignment::alignCenterIfNeeded, ScrollAlignment::alignCenterIfNeeded);671 renderer()->scrollRectToVisible(SelectionRevealMode::Reveal, absoluteBounds, insideFixed, ScrollAlignment::alignCenterIfNeeded, ScrollAlignment::alignCenterIfNeeded); 670 672 else 671 renderer()->scrollRectToVisible(SelectionRevealMode::Reveal, bounds, ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignToEdgeIfNeeded);673 renderer()->scrollRectToVisible(SelectionRevealMode::Reveal, absoluteBounds, insideFixed, ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignToEdgeIfNeeded); 672 674 } 673 675 … … 679 681 return; 680 682 681 LayoutRect bounds = renderer()->anchorRect(); 683 bool insideFixed; 684 LayoutRect absoluteBounds = renderer()->absoluteAnchorRect(&insideFixed); 682 685 if (centerIfNotVisible) 683 renderer()->scrollRectToVisible(SelectionRevealMode::Reveal, bounds, ScrollAlignment::alignCenterIfNotVisible, ScrollAlignment::alignCenterIfNotVisible);686 renderer()->scrollRectToVisible(SelectionRevealMode::Reveal, absoluteBounds, insideFixed, ScrollAlignment::alignCenterIfNotVisible, ScrollAlignment::alignCenterIfNotVisible); 684 687 else 685 renderer()->scrollRectToVisible(SelectionRevealMode::Reveal, bounds, ScrollAlignment::alignToEdgeIfNotVisible, ScrollAlignment::alignToEdgeIfNotVisible);688 renderer()->scrollRectToVisible(SelectionRevealMode::Reveal, absoluteBounds, insideFixed, ScrollAlignment::alignToEdgeIfNotVisible, ScrollAlignment::alignToEdgeIfNotVisible); 686 689 } 687 690 … … 2427 2430 frame->selection().revealSelection(revealMode); 2428 2431 } 2429 } else if (renderer() && !renderer()->isWidget()) 2430 renderer()->scrollRectToVisible(revealMode, renderer()->anchorRect()); 2432 } else if (renderer() && !renderer()->isWidget()) { 2433 bool insideFixed; 2434 LayoutRect absoluteBounds = renderer()->absoluteAnchorRect(&insideFixed); 2435 renderer()->scrollRectToVisible(revealMode, absoluteBounds, insideFixed); 2436 } 2431 2437 } 2432 2438 -
trunk/Source/WebCore/editing/FrameSelection.cpp
r209348 r209411 113 113 , m_granularity(CharacterGranularity) 114 114 , m_caretBlinkTimer(*this, &FrameSelection::caretBlinkTimerFired) 115 , m_caretInsidePositionFixed(false) 115 116 , m_absCaretBoundsDirty(true) 116 117 , m_caretPaint(true) … … 1578 1579 } 1579 1580 1580 IntRect FrameSelection::absoluteCaretBounds( )1581 IntRect FrameSelection::absoluteCaretBounds(bool* insideFixed) 1581 1582 { 1582 1583 if (!m_frame) … … 1584 1585 updateSelectionByUpdatingLayoutOrStyle(*m_frame); 1585 1586 recomputeCaretRect(); 1587 if (insideFixed) 1588 *insideFixed = m_caretInsidePositionFixed; 1586 1589 return m_absCaretBounds; 1587 1590 } … … 1625 1628 1626 1629 IntRect oldAbsCaretBounds = m_absCaretBounds; 1627 m_absCaretBounds = absoluteBoundsForLocalCaretRect(rendererForCaretPainting(caretNode.get()), newRect); 1630 bool isInsideFixed; 1631 m_absCaretBounds = absoluteBoundsForLocalCaretRect(rendererForCaretPainting(caretNode.get()), newRect, &isInsideFixed); 1632 m_caretInsidePositionFixed = isInsideFixed; 1628 1633 1629 1634 if (m_absCaretBoundsDirty && m_selection.isCaret()) // We should be able to always assert this condition. … … 2301 2306 2302 2307 LayoutRect rect; 2303 2308 bool insideFixed = false; 2304 2309 switch (m_selection.selectionType()) { 2305 2310 case VisibleSelection::NoSelection: 2306 2311 return; 2307 2312 case VisibleSelection::CaretSelection: 2308 rect = absoluteCaretBounds( );2313 rect = absoluteCaretBounds(&insideFixed); 2309 2314 break; 2310 2315 case VisibleSelection::RangeSelection: … … 2320 2325 if (!m_scrollingSuppressCount) { 2321 2326 layer->setAdjustForIOSCaretWhenScrolling(true); 2322 layer->scrollRectToVisible(revealMode, rect, alignment, alignment);2327 layer->scrollRectToVisible(revealMode, rect, insideFixed, alignment, alignment); 2323 2328 layer->setAdjustForIOSCaretWhenScrolling(false); 2324 2329 updateAppearance(); … … 2331 2336 // the selection rect could intersect more than just that. 2332 2337 // See <rdar://problem/4799899>. 2333 if (start.deprecatedNode()->renderer()->scrollRectToVisible(revealMode, rect, alignment, alignment))2338 if (start.deprecatedNode()->renderer()->scrollRectToVisible(revealMode, rect, insideFixed, alignment, alignment)) 2334 2339 updateAppearance(); 2335 2340 #endif -
trunk/Source/WebCore/editing/FrameSelection.h
r209348 r209411 174 174 175 175 // Bounds of (possibly transformed) caret in absolute coords 176 WEBCORE_EXPORT IntRect absoluteCaretBounds( );176 WEBCORE_EXPORT IntRect absoluteCaretBounds(bool* insideFixed = nullptr); 177 177 void setCaretRectNeedsUpdate() { CaretBase::setCaretRectNeedsUpdate(); } 178 178 … … 337 337 // The painted bounds of the caret in absolute coordinates 338 338 IntRect m_absCaretBounds; 339 bool m_caretInsidePositionFixed : 1; 339 340 bool m_absCaretBoundsDirty : 1; 340 341 bool m_caretPaint : 1; -
trunk/Source/WebCore/editing/VisiblePosition.cpp
r209348 r209411 661 661 } 662 662 663 IntRect VisiblePosition::absoluteCaretBounds( ) const663 IntRect VisiblePosition::absoluteCaretBounds(bool* insideFixed) const 664 664 { 665 665 RenderBlock* renderer = nullptr; 666 666 LayoutRect localRect = localCaretRectInRendererForCaretPainting(*this, renderer); 667 return absoluteBoundsForLocalCaretRect(renderer, localRect );667 return absoluteBoundsForLocalCaretRect(renderer, localRect, insideFixed); 668 668 } 669 669 -
trunk/Source/WebCore/editing/VisiblePosition.h
r209348 r209411 96 96 WEBCORE_EXPORT LayoutRect localCaretRect(RenderObject*&) const; 97 97 // Bounds of (possibly transformed) caret in absolute coords 98 WEBCORE_EXPORT IntRect absoluteCaretBounds( ) const;98 WEBCORE_EXPORT IntRect absoluteCaretBounds(bool* insideFixed = nullptr) const; 99 99 // Abs x/y position of the caret ignoring transforms. 100 100 // FIXME: navigation with transforms should be smarter. -
trunk/Source/WebCore/editing/htmlediting.cpp
r209348 r209411 1291 1291 } 1292 1292 1293 IntRect absoluteBoundsForLocalCaretRect(RenderBlock* rendererForCaretPainting, const LayoutRect& rect )1293 IntRect absoluteBoundsForLocalCaretRect(RenderBlock* rendererForCaretPainting, const LayoutRect& rect, bool* insideFixed) 1294 1294 { 1295 1295 if (!rendererForCaretPainting || rect.isEmpty()) … … 1298 1298 LayoutRect localRect(rect); 1299 1299 rendererForCaretPainting->flipForWritingMode(localRect); 1300 return rendererForCaretPainting->localToAbsoluteQuad(FloatRect(localRect) ).enclosingBoundingBox();1300 return rendererForCaretPainting->localToAbsoluteQuad(FloatRect(localRect), UseTransforms, insideFixed).enclosingBoundingBox(); 1301 1301 } 1302 1302 -
trunk/Source/WebCore/editing/htmlediting.h
r209348 r209411 201 201 LayoutRect localCaretRectInRendererForCaretPainting(const VisiblePosition&, RenderBlock*&); 202 202 LayoutRect localCaretRectInRendererForRect(LayoutRect&, Node*, RenderObject*, RenderBlock*&); 203 IntRect absoluteBoundsForLocalCaretRect(RenderBlock* rendererForCaretPainting, const LayoutRect& );203 IntRect absoluteBoundsForLocalCaretRect(RenderBlock* rendererForCaretPainting, const LayoutRect&, bool* insideFixed = nullptr); 204 204 205 205 // ------------------------------------------------------------------------- -
trunk/Source/WebCore/page/FrameView.cpp
r209409 r209411 2357 2357 LayoutRect bounds; 2358 2358 if (RenderElement* renderer = element.renderer()) 2359 bounds = renderer->a nchorRect();2359 bounds = renderer->absoluteAnchorRect(); 2360 2360 int centeringOffsetX = (rect.width() - bounds.width()) / 2; 2361 2361 int centeringOffsetY = (rect.height() - bounds.height()) / 2; … … 3277 3277 3278 3278 LayoutRect rect; 3279 bool insideFixed = false; 3279 3280 if (anchorNode != frame().document() && anchorNode->renderer()) 3280 rect = anchorNode->renderer()->a nchorRect();3281 rect = anchorNode->renderer()->absoluteAnchorRect(&insideFixed); 3281 3282 3282 3283 // Scroll nested layers and frames to reveal the anchor. 3283 3284 // Align to the top and to the closest side (this matches other browsers). 3284 3285 if (anchorNode->renderer()->style().isHorizontalWritingMode()) 3285 anchorNode->renderer()->scrollRectToVisible(SelectionRevealMode::Reveal, rect, ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignTopAlways);3286 anchorNode->renderer()->scrollRectToVisible(SelectionRevealMode::Reveal, rect, insideFixed, ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignTopAlways); 3286 3287 else if (anchorNode->renderer()->style().isFlippedBlocksWritingMode()) 3287 anchorNode->renderer()->scrollRectToVisible(SelectionRevealMode::Reveal, rect, ScrollAlignment::alignRightAlways, ScrollAlignment::alignToEdgeIfNeeded);3288 anchorNode->renderer()->scrollRectToVisible(SelectionRevealMode::Reveal, rect, insideFixed, ScrollAlignment::alignRightAlways, ScrollAlignment::alignToEdgeIfNeeded); 3288 3289 else 3289 anchorNode->renderer()->scrollRectToVisible(SelectionRevealMode::Reveal, rect, ScrollAlignment::alignLeftAlways, ScrollAlignment::alignToEdgeIfNeeded);3290 anchorNode->renderer()->scrollRectToVisible(SelectionRevealMode::Reveal, rect, insideFixed, ScrollAlignment::alignLeftAlways, ScrollAlignment::alignToEdgeIfNeeded); 3290 3291 3291 3292 if (AXObjectCache* cache = frame().document()->existingAXObjectCache()) -
trunk/Source/WebCore/page/PrintContext.cpp
r209348 r209411 275 275 continue; 276 276 277 FloatPoint point = renderer->a nchorRect().minXMinYCorner();277 FloatPoint point = renderer->absoluteAnchorRect().minXMinYCorner(); 278 278 point.expandedTo(FloatPoint()); 279 279 -
trunk/Source/WebCore/rendering/RenderElement.cpp
r209348 r209411 1626 1626 } 1627 1627 1628 bool RenderElement::getLeadingCorner(FloatPoint& point ) const1628 bool RenderElement::getLeadingCorner(FloatPoint& point, bool& insideFixed) const 1629 1629 { 1630 1630 if (!isInline() || isReplaced()) { 1631 point = localToAbsolute(FloatPoint(), UseTransforms );1631 point = localToAbsolute(FloatPoint(), UseTransforms, &insideFixed); 1632 1632 return true; 1633 1633 } … … 1655 1655 1656 1656 if (!o->isInline() || o->isReplaced()) { 1657 point = o->localToAbsolute(FloatPoint(), UseTransforms );1657 point = o->localToAbsolute(FloatPoint(), UseTransforms, &insideFixed); 1658 1658 return true; 1659 1659 } … … 1667 1667 else if (is<RenderBox>(*o)) 1668 1668 point.moveBy(downcast<RenderBox>(*o).location()); 1669 point = o->container()->localToAbsolute(point, UseTransforms );1669 point = o->container()->localToAbsolute(point, UseTransforms, &insideFixed); 1670 1670 return true; 1671 1671 } … … 1681 1681 } 1682 1682 1683 bool RenderElement::getTrailingCorner(FloatPoint& point ) const1683 bool RenderElement::getTrailingCorner(FloatPoint& point, bool& insideFixed) const 1684 1684 { 1685 1685 if (!isInline() || isReplaced()) { 1686 point = localToAbsolute(LayoutPoint(downcast<RenderBox>(*this).size()), UseTransforms );1686 point = localToAbsolute(LayoutPoint(downcast<RenderBox>(*this).size()), UseTransforms, &insideFixed); 1687 1687 return true; 1688 1688 } … … 1715 1715 } else 1716 1716 point.moveBy(downcast<RenderBox>(*o).frameRect().maxXMaxYCorner()); 1717 point = o->container()->localToAbsolute(point, UseTransforms );1717 point = o->container()->localToAbsolute(point, UseTransforms, &insideFixed); 1718 1718 return true; 1719 1719 } … … 1722 1722 } 1723 1723 1724 LayoutRect RenderElement::a nchorRect() const1724 LayoutRect RenderElement::absoluteAnchorRect(bool* insideFixed) const 1725 1725 { 1726 1726 FloatPoint leading, trailing; 1727 getLeadingCorner(leading); 1728 getTrailingCorner(trailing); 1727 bool leadingInFixed = false; 1728 bool trailingInFixed = false; 1729 getLeadingCorner(leading, leadingInFixed); 1730 getTrailingCorner(trailing, trailingInFixed); 1729 1731 1730 1732 FloatPoint upperLeft = leading; … … 1736 1738 lowerRight = FloatPoint(std::max(leading.x(), trailing.x()), std::max(leading.y(), trailing.y())); 1737 1739 } // Otherwise, it's not obvious what to do. 1740 1741 if (insideFixed) { 1742 // For now, just look at the leading corner. Handling one inside fixed and one not would be tricky. 1743 *insideFixed = leadingInFixed; 1744 } 1738 1745 1739 1746 return enclosingLayoutRect(FloatRect(upperLeft, lowerRight.expandedTo(upperLeft) - upperLeft)); -
trunk/Source/WebCore/rendering/RenderElement.h
r209348 r209411 165 165 // For inline renderers, this gets the logical top left of the first leaf child and the logical bottom right of the 166 166 // last leaf child, converts them to absolute coordinates, and makes a box out of them. 167 LayoutRect a nchorRect() const;167 LayoutRect absoluteAnchorRect(bool* insideFixed = nullptr) const; 168 168 169 169 bool hasFilter() const { return style().hasFilter(); } … … 308 308 void newImageAnimationFrameAvailable(CachedImage&) final; 309 309 310 bool getLeadingCorner(FloatPoint& output ) const;311 bool getTrailingCorner(FloatPoint& output ) const;310 bool getLeadingCorner(FloatPoint& output, bool& insideFixed) const; 311 bool getTrailingCorner(FloatPoint& output, bool& insideFixed) const; 312 312 313 313 void clearLayoutRootIfNeeded() const; -
trunk/Source/WebCore/rendering/RenderLayer.cpp
r209348 r209411 2507 2507 } 2508 2508 2509 void RenderLayer::scrollRectToVisible(SelectionRevealMode revealMode, const LayoutRect& rect, const ScrollAlignment& alignX, const ScrollAlignment& alignY)2510 { 2511 LOG_WITH_STREAM(Scrolling, stream << "Layer " << this << " scrollRectToVisible " << rect);2509 void RenderLayer::scrollRectToVisible(SelectionRevealMode revealMode, const LayoutRect& absoluteRect, bool insideFixed, const ScrollAlignment& alignX, const ScrollAlignment& alignY) 2510 { 2511 LOG_WITH_STREAM(Scrolling, stream << "Layer " << this << " scrollRectToVisible " << absoluteRect); 2512 2512 2513 2513 RenderLayer* parentLayer = nullptr; 2514 LayoutRect newRect = rect;2514 LayoutRect newRect = absoluteRect; 2515 2515 2516 2516 // We may end up propagating a scroll event. It is important that we suspend events until … … 2526 2526 RenderBox* box = renderBox(); 2527 2527 ASSERT(box); 2528 LayoutRect localExposeRect(box->absoluteToLocalQuad(FloatQuad(FloatRect( rect))).boundingBox());2528 LayoutRect localExposeRect(box->absoluteToLocalQuad(FloatQuad(FloatRect(absoluteRect))).boundingBox()); 2529 2529 LayoutRect layerBounds(0, 0, box->clientWidth(), box->clientHeight()); 2530 LayoutRect r = getRectToExpose(layerBounds, layerBounds, localExposeRect, alignX, alignY);2531 2532 ScrollOffset clampedScrollOffset = clampScrollOffset(scrollOffset() + toIntSize(roundedIntRect(r ).location()));2530 LayoutRect revealRect = getRectToExpose(layerBounds, layerBounds, localExposeRect, insideFixed, alignX, alignY); 2531 2532 ScrollOffset clampedScrollOffset = clampScrollOffset(scrollOffset() + toIntSize(roundedIntRect(revealRect).location())); 2533 2533 if (clampedScrollOffset != scrollOffset()) { 2534 2534 ScrollOffset oldScrollOffset = scrollOffset(); … … 2552 2552 2553 2553 LayoutRect viewRect = frameView.visibleContentRect(LegacyIOSDocumentVisibleRect); 2554 LayoutRect exposeRect = getRectToExpose(viewRect, viewRect, rect, alignX, alignY);2554 LayoutRect exposeRect = getRectToExpose(viewRect, viewRect, absoluteRect, insideFixed, alignX, alignY); 2555 2555 2556 2556 IntPoint scrollOffset(roundedIntPoint(exposeRect.location())); … … 2563 2563 // Convert the rect into the coordinate space of the parent frame's document. 2564 2564 newRect = frameView.contentsToContainingViewContents(enclosingIntRect(newRect)); 2565 insideFixed = false; // FIXME: ideally need to determine if this <iframe> is inside position:fixed. 2565 2566 } else 2566 2567 parentLayer = nullptr; … … 2572 2573 #if !PLATFORM(IOS) 2573 2574 LayoutRect viewRect = frameView.visibleContentRect(); 2575 viewRect.scale(1 / frameView.frameScaleFactor()); 2576 2574 2577 LayoutRect visibleRectRelativeToDocument = viewRect; 2575 2578 visibleRectRelativeToDocument.setLocation(frameView.documentScrollPositionRelativeToScrollableAreaOrigin()); … … 2578 2581 LayoutRect visibleRectRelativeToDocument = viewRect; 2579 2582 #endif 2580 2581 LayoutRect r = getRectToExpose(viewRect, visibleRectRelativeToDocument, rect, alignX, alignY); 2583 LayoutRect revealRect = getRectToExpose(viewRect, visibleRectRelativeToDocument, absoluteRect, insideFixed, alignX, alignY); 2582 2584 2583 frameView.setScrollPosition(roundedIntPoint(r .location()));2585 frameView.setScrollPosition(roundedIntPoint(revealRect.location())); 2584 2586 2585 2587 // This is the outermost view of a web page, so after scrolling this view we … … 2589 2591 // The canAutoscroll function in EventHandler also knows about this. 2590 2592 if (Page* page = frameView.frame().page()) 2591 page->chrome().scrollRectIntoView(snappedIntRect( rect));2593 page->chrome().scrollRectIntoView(snappedIntRect(absoluteRect)); 2592 2594 } 2593 2595 } 2594 2596 2595 2597 if (parentLayer) 2596 parentLayer->scrollRectToVisible(revealMode, newRect, alignX, alignY);2598 parentLayer->scrollRectToVisible(revealMode, newRect, insideFixed, alignX, alignY); 2597 2599 } 2598 2600 … … 2611 2613 } 2612 2614 2613 LayoutRect RenderLayer::getRectToExpose(const LayoutRect &visibleRect, const LayoutRect &visibleRectRelativeToDocument, const LayoutRect &exposeRect, const ScrollAlignment& alignX, const ScrollAlignment& alignY) 2614 { 2615 LayoutRect RenderLayer::getRectToExpose(const LayoutRect &visibleRect, const LayoutRect &visibleRectRelativeToDocument, const LayoutRect &exposeRect, bool insideFixed, const ScrollAlignment& alignX, const ScrollAlignment& alignY) 2616 { 2617 FrameView& frameView = renderer().view().frameView(); 2618 if (insideFixed) { 2619 // If the element is inside position:fixed and we're not scaled, no amount of scrolling is going to move things around. 2620 if (frameView.frameScaleFactor() == 1) 2621 return visibleRect; 2622 2623 if (frameView.frame().settings().visualViewportEnabled()) { 2624 // exposeRect is in absolute coords, affected by page scale. Unscale it. 2625 LayoutRect unscaledExposeRect = exposeRect; 2626 unscaledExposeRect.scale(1 / frameView.frameScaleFactor()); 2627 // These are both in unscaled coordinates. 2628 LayoutRect layoutViewport = frameView.layoutViewportRect(); 2629 LayoutRect visualViewport = frameView.visualViewportRect(); 2630 2631 // The rect to expose may be partially offscreen, which we can't do anything about with position:fixed. 2632 unscaledExposeRect.intersect(layoutViewport); 2633 // Make sure it's not larger than the visual viewport; if so, we'll just move to the top left. 2634 unscaledExposeRect.setSize(unscaledExposeRect.size().shrunkTo(visualViewport.size())); 2635 2636 // Compute how much we have to move the visualViewport to reveal the part of the layoutViewport that contains exposeRect. 2637 LayoutRect requiredVisualViewport = getRectToExpose(visualViewport, visualViewport, unscaledExposeRect, false, alignX, alignY); 2638 // Scale it back up. 2639 requiredVisualViewport.scale(frameView.frameScaleFactor()); 2640 return requiredVisualViewport; 2641 } 2642 } 2643 2615 2644 // Determine the appropriate X behavior. 2616 2645 ScrollAlignment::Behavior scrollX; … … 2687 2716 { 2688 2717 IntPoint currentDocumentPosition = renderer().view().frameView().windowToContents(position); 2689 scrollRectToVisible(SelectionRevealMode::Reveal, LayoutRect(currentDocumentPosition, LayoutSize(1, 1)), ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignToEdgeIfNeeded);2718 scrollRectToVisible(SelectionRevealMode::Reveal, LayoutRect(currentDocumentPosition, LayoutSize(1, 1)), false, ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignToEdgeIfNeeded); 2690 2719 } 2691 2720 -
trunk/Source/WebCore/rendering/RenderLayer.h
r209348 r209411 205 205 void availableContentSizeChanged(AvailableSizeChangeReason) override; 206 206 207 void scrollRectToVisible(SelectionRevealMode, const LayoutRect& , const ScrollAlignment& alignX, const ScrollAlignment& alignY);208 209 LayoutRect getRectToExpose(const LayoutRect& visibleRect, const LayoutRect& visibleRectRelativeToDocument, const LayoutRect& exposeRect, const ScrollAlignment& alignX, const ScrollAlignment& alignY);207 void scrollRectToVisible(SelectionRevealMode, const LayoutRect& absoluteRect, bool insideFixed, const ScrollAlignment& alignX, const ScrollAlignment& alignY); 208 209 LayoutRect getRectToExpose(const LayoutRect& visibleRect, const LayoutRect& visibleRectRelativeToDocument, const LayoutRect& exposeRect, bool insideFixed, const ScrollAlignment& alignX, const ScrollAlignment& alignY); 210 210 211 211 bool scrollsOverflow() const; -
trunk/Source/WebCore/rendering/RenderObject.cpp
r209348 r209411 397 397 } 398 398 399 bool RenderObject::scrollRectToVisible(SelectionRevealMode revealMode, const LayoutRect& rect, const ScrollAlignment& alignX, const ScrollAlignment& alignY)399 bool RenderObject::scrollRectToVisible(SelectionRevealMode revealMode, const LayoutRect& absoluteRect, bool insideFixed, const ScrollAlignment& alignX, const ScrollAlignment& alignY) 400 400 { 401 401 if (revealMode == SelectionRevealMode::DoNotReveal) … … 406 406 return false; 407 407 408 enclosingLayer->scrollRectToVisible(revealMode, rect, alignX, alignY);408 enclosingLayer->scrollRectToVisible(revealMode, absoluteRect, insideFixed, alignX, alignY); 409 409 return true; 410 410 } -
trunk/Source/WebCore/rendering/RenderObject.h
r209348 r209411 155 155 156 156 // Scrolling is a RenderBox concept, however some code just cares about recursively scrolling our enclosing ScrollableArea(s). 157 WEBCORE_EXPORT bool scrollRectToVisible(SelectionRevealMode, const LayoutRect& , const ScrollAlignment& alignX = ScrollAlignment::alignCenterIfNeeded, const ScrollAlignment& alignY = ScrollAlignment::alignCenterIfNeeded);157 WEBCORE_EXPORT bool scrollRectToVisible(SelectionRevealMode, const LayoutRect& absoluteRect, bool insideFixed, const ScrollAlignment& alignX = ScrollAlignment::alignCenterIfNeeded, const ScrollAlignment& alignY = ScrollAlignment::alignCenterIfNeeded); 158 158 159 159 // Convenience function for getting to the nearest enclosing box of a RenderObject. -
trunk/Source/WebKit/mac/ChangeLog
r209409 r209411 1 2016-12-05 Simon Fraser <simon.fraser@apple.com> 2 3 Improve the behavior of scroll-into-view when the target is inside position:fixed 4 https://bugs.webkit.org/show_bug.cgi?id=165354 5 6 Reviewed by Zalan Bujtas. 7 8 Plumb through 'insideFixed'. We don't get compute it, so behavior from 9 these call sites won't change. 10 11 * WebView/WebFrame.mm: 12 (-[WebFrame _scrollDOMRangeToVisible:]): 13 (-[WebFrame _scrollDOMRangeToVisible:withInset:]): 14 1 15 2016-12-06 Simon Fraser <simon.fraser@apple.com> 2 16 -
trunk/Source/WebKit/mac/WebView/WebFrame.mm
r209348 r209411 712 712 - (void)_scrollDOMRangeToVisible:(DOMRange *)range 713 713 { 714 bool insideFixed = false; // FIXME: get via firstRectForRange(). 714 715 NSRect rangeRect = [self _firstRectForDOMRange:range]; 715 716 Node *startNode = core([range startContainer]); … … 717 718 if (startNode && startNode->renderer()) { 718 719 #if !PLATFORM(IOS) 719 startNode->renderer()->scrollRectToVisible(SelectionRevealMode::Reveal, enclosingIntRect(rangeRect), ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignToEdgeIfNeeded);720 startNode->renderer()->scrollRectToVisible(SelectionRevealMode::Reveal, enclosingIntRect(rangeRect), insideFixed, ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignToEdgeIfNeeded); 720 721 #else 721 722 RenderLayer* layer = startNode->renderer()->enclosingLayer(); 722 723 if (layer) { 723 724 layer->setAdjustForIOSCaretWhenScrolling(true); 724 startNode->renderer()->scrollRectToVisible(SelectionRevealMode::Reveal, enclosingIntRect(rangeRect), ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignToEdgeIfNeeded);725 startNode->renderer()->scrollRectToVisible(SelectionRevealMode::Reveal, enclosingIntRect(rangeRect), insideFixed, ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignToEdgeIfNeeded); 725 726 layer->setAdjustForIOSCaretWhenScrolling(false); 726 727 _private->coreFrame->selection().setCaretRectNeedsUpdate(); … … 734 735 - (void)_scrollDOMRangeToVisible:(DOMRange *)range withInset:(CGFloat)inset 735 736 { 737 bool insideFixed = false; // FIXME: get via firstRectForRange(). 736 738 NSRect rangeRect = NSInsetRect([self _firstRectForDOMRange:range], inset, inset); 737 739 Node *startNode = core([range startContainer]); … … 741 743 if (layer) { 742 744 layer->setAdjustForIOSCaretWhenScrolling(true); 743 startNode->renderer()->scrollRectToVisible(SelectionRevealMode::Reveal, enclosingIntRect(rangeRect), ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignToEdgeIfNeeded);745 startNode->renderer()->scrollRectToVisible(SelectionRevealMode::Reveal, enclosingIntRect(rangeRect), insideFixed, ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignToEdgeIfNeeded); 744 746 layer->setAdjustForIOSCaretWhenScrolling(false); 745 747
Note: See TracChangeset
for help on using the changeset viewer.