Changeset 194405 in webkit
- Timestamp:
- Dec 23, 2015, 4:35:04 PM (11 years ago)
- Location:
- trunk
- Files:
-
- 2 added
- 13 edited
-
LayoutTests/ChangeLog (modified) (1 diff)
-
LayoutTests/fast/events/autoscroll-in-iframe-body-expected.txt (added)
-
LayoutTests/fast/events/autoscroll-in-iframe-body.html (added)
-
LayoutTests/fast/forms/input-readonly-autoscroll.html (modified) (1 diff)
-
Source/WebCore/ChangeLog (modified) (1 diff)
-
Source/WebCore/page/scrolling/ScrollingCoordinator.cpp (modified) (1 diff)
-
Source/WebCore/platform/Logging.h (modified) (1 diff)
-
Source/WebCore/platform/ScrollView.cpp (modified) (3 diffs)
-
Source/WebCore/platform/ScrollView.h (modified) (1 diff)
-
Source/WebCore/platform/graphics/IntPoint.cpp (modified) (1 diff)
-
Source/WebCore/platform/graphics/IntPoint.h (modified) (1 diff)
-
Source/WebCore/rendering/RenderBox.cpp (modified) (1 diff)
-
Source/WebCore/rendering/RenderLayer.cpp (modified) (10 diffs)
-
Source/WebCore/rendering/RenderLayer.h (modified) (2 diffs)
-
Source/WebCore/rendering/RenderTextControlSingleLine.h (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r194404 r194405 1 2015-12-23 Simon Fraser <simon.fraser@apple.com> 2 3 REGRESSION (r187593): Scroll position jumps when selecting text in an iframe 4 https://bugs.webkit.org/show_bug.cgi?id=152541 5 rdar://problem/23886181 6 7 Reviewed by Tim Horton. 8 9 New test for autoscrolling iframe contents (an existing test scrolled an overflow:scroll 10 inside an iframe, and didn't catch the bug). 11 12 * fast/events/autoscroll-in-iframe-body-expected.txt: Added. 13 * fast/events/autoscroll-in-iframe-body.html: Added. 14 * fast/forms/input-readonly-autoscroll.html: Fix a missing double quote. 15 1 16 2015-12-22 Simon Fraser <simon.fraser@apple.com> 2 17 -
trunk/LayoutTests/fast/forms/input-readonly-autoscroll.html
r121008 r194405 39 39 </head> 40 40 <body onload="test()"> 41 <p>Test for <a href= http://bugs.webkit.org/show_bug.cgi?id=11534">bug 11534</a>.</p>41 <p>Test for <a href="http://bugs.webkit.org/show_bug.cgi?id=11534">bug 11534</a>.</p> 42 42 <p>Readonly text fields don't scroll when selecting content.</p> 43 43 <input id="tf" readonly value="abcdefghijklmnopqrstuvwxyz"></input> -
trunk/Source/WebCore/ChangeLog
r194404 r194405 1 2015-12-23 Simon Fraser <simon.fraser@apple.com> 2 3 REGRESSION (r187593): Scroll position jumps when selecting text in an iframe 4 https://bugs.webkit.org/show_bug.cgi?id=152541 5 rdar://problem/23886181 6 7 Reviewed by Tim Horton. 8 9 r154382 added code that modifies parentLayer traversal, looking for ancestor 10 scrollable layers. However, it confusingly added another code path in which 11 the ancestor layer traversal cross a frame boundary, when RenderLayer::scrollRectToVisible() 12 already has one. I fixed this new location to adjust the rect coordinates in r187593, 13 but then code that hit both crossing points double-mapped the coordinates, causing 14 autoscroll jumping. 15 16 Fix by reverting r154382 and r187593, going back to doing the ancestor walk in 17 one place. Re-fix r154382 by implementing RenderLayer::allowsCurrentScroll(), 18 which contains the logic for line clamp, autoscroll and ensuring that overflow:hidden 19 can be programmatically scrolled. 20 21 Form controls are special; they can have overflow:hidden but still be user-scrollable 22 during autoscroll; this is handled via the confusingly-named canBeProgramaticallyScrolled(). 23 RenderTextControlSingleLine implements this to ensure that readonly text inputs 24 autoscroll (which is exercised by a test). 25 26 The frame-to-parent-frame rect mapping in RenderLayer::scrollRectToVisible() is 27 fixed to use the coordinate mapping functions from Widget/ScrollView, with the 28 addition of a new utility function contentsToContainingViewContents(). 29 30 A "Scrolling" logging channel is added with a few log points. 31 32 Test: fast/events/autoscroll-in-iframe-body.html 33 34 * page/scrolling/ScrollingCoordinator.cpp: 35 (WebCore::ScrollingCoordinator::absoluteNonFastScrollableRegionForFrame): 36 use contentsToContainingViewContents(). 37 * platform/Logging.h: 38 * platform/ScrollView.cpp: 39 (WebCore::ScrollView::contentsToContainingViewContents): 40 * platform/ScrollView.h: 41 * platform/graphics/IntPoint.cpp: 42 (WebCore::IntPoint::constrainedBetween): New helper to constrain a point between 43 two other points. 44 * platform/graphics/IntPoint.h: 45 (WebCore::IntPoint::expandedTo): 46 (WebCore::IntPoint::shrunkTo): 47 * rendering/RenderBox.cpp: 48 * rendering/RenderLayer.cpp: 49 (WebCore::parentLayerCrossFrame): 50 (WebCore::RenderLayer::enclosingScrollableLayer): 51 (WebCore::frameElementAndViewPermitScroll): 52 (WebCore::RenderLayer::allowsCurrentScroll): 53 (WebCore::RenderLayer::scrollRectToVisible): 54 * rendering/RenderLayer.h: 55 * rendering/RenderTextControlSingleLine.h: 56 1 57 2015-12-22 Simon Fraser <simon.fraser@apple.com> 2 58 -
trunk/Source/WebCore/page/scrolling/ScrollingCoordinator.cpp
r192193 r194405 161 161 Region subframeRegion = absoluteNonFastScrollableRegionForFrame(*subframe); 162 162 // Map from the frame document to our document. 163 IntPoint offset = subframeView->contentsToView(IntPoint()); 164 offset = subframeView->convertToContainingView(offset); 165 offset = frameView->viewToContents(offset); 163 IntPoint offset = subframeView->contentsToContainingViewContents(IntPoint()); 166 164 167 165 // FIXME: this translation ignores non-trival transforms on the frame. -
trunk/Source/WebCore/platform/Logging.h
r191474 r194405 78 78 M(SVG) \ 79 79 M(Services) \ 80 M(Scrolling) \ 80 81 M(SpellingAndGrammar) \ 81 82 M(StorageAPI) \ -
trunk/Source/WebCore/platform/ScrollView.cpp
r194210 r194405 30 30 #include "GraphicsLayer.h" 31 31 #include "HostWindow.h" 32 #include "Logging.h" 32 33 #include "PlatformMouseEvent.h" 33 34 #include "PlatformWheelEvent.h" … … 35 36 #include "Scrollbar.h" 36 37 #include "ScrollbarTheme.h" 38 #include "TextStream.h" 37 39 #include <wtf/StdLibExtras.h> 38 40 … … 872 874 } 873 875 876 IntPoint ScrollView::contentsToContainingViewContents(const IntPoint& point) const 877 { 878 if (const ScrollView* parentScrollView = parent()) { 879 IntPoint pointInContainingView = convertToContainingView(contentsToView(point)); 880 return parentScrollView->viewToContents(pointInContainingView); 881 } 882 883 return contentsToView(point); 884 } 885 886 IntRect ScrollView::contentsToContainingViewContents(IntRect rect) const 887 { 888 if (const ScrollView* parentScrollView = parent()) { 889 IntRect rectInContainingView = convertToContainingView(contentsToView(rect)); 890 return parentScrollView->viewToContents(rectInContainingView); 891 } 892 893 return contentsToView(rect); 894 } 895 874 896 IntPoint ScrollView::rootViewToContents(const IntPoint& rootViewPoint) const 875 897 { -
trunk/Source/WebCore/platform/ScrollView.h
r189144 r194405 295 295 IntRect contentsToView(IntRect) const; 296 296 297 IntPoint contentsToContainingViewContents(const IntPoint&) const; 298 IntRect contentsToContainingViewContents(IntRect) const; 299 297 300 WEBCORE_EXPORT IntPoint rootViewToTotalContents(const IntPoint&) const; 298 301 -
trunk/Source/WebCore/platform/graphics/IntPoint.cpp
r191216 r194405 38 38 } 39 39 40 IntPoint IntPoint::constrainedBetween(const IntPoint& min, const IntPoint& max) const 41 { 42 return { 43 std::max(min.x(), std::min(max.x(), m_x)), 44 std::max(min.y(), std::min(max.y(), m_y)) 45 }; 46 } 47 48 40 49 TextStream& operator<<(TextStream& ts, const IntPoint& p) 41 50 { -
trunk/Source/WebCore/platform/graphics/IntPoint.h
r191216 r194405 85 85 IntPoint expandedTo(const IntPoint& other) const 86 86 { 87 return IntPoint(m_x > other.m_x ? m_x : other.m_x, 88 m_y > other.m_y ? m_y : other.m_y); 87 return { 88 m_x > other.m_x ? m_x : other.m_x, 89 m_y > other.m_y ? m_y : other.m_y 90 }; 89 91 } 90 92 91 93 IntPoint shrunkTo(const IntPoint& other) const 92 94 { 93 return IntPoint(m_x < other.m_x ? m_x : other.m_x, 94 m_y < other.m_y ? m_y : other.m_y); 95 } 95 return { 96 m_x < other.m_x ? m_x : other.m_x, 97 m_y < other.m_y ? m_y : other.m_y 98 }; 99 } 100 101 IntPoint constrainedBetween(const IntPoint& min, const IntPoint& max) const; 96 102 97 103 int distanceSquaredToPoint(const IntPoint&) const; -
trunk/Source/WebCore/rendering/RenderBox.cpp
r194404 r194405 876 876 } 877 877 878 // FIXME: This is badly named. overflow:hidden can be programmatically scrolled, yet this returns false in that case. 878 879 bool RenderBox::canBeProgramaticallyScrolled() const 879 880 { -
trunk/Source/WebCore/rendering/RenderLayer.cpp
r194184 r194405 79 79 #include "HitTestRequest.h" 80 80 #include "HitTestResult.h" 81 #include "Logging.h" 81 82 #include "OverflowEvent.h" 82 83 #include "OverlapTestRequestClient.h" … … 1455 1456 } 1456 1457 1457 static RenderLayer* parentLayerCrossFrame(const RenderLayer& layer , LayoutRect* rect = nullptr)1458 static RenderLayer* parentLayerCrossFrame(const RenderLayer& layer) 1458 1459 { 1459 1460 if (layer.parent()) … … 1468 1469 return nullptr; 1469 1470 1470 // Convert the rect into the coordinate space of the parent frame's document.1471 if (rect) {1472 IntRect viewRect = layer.renderer().frame().view()->convertToContainingView(enclosingIntRect(*rect));1473 *rect = ownerRenderer->frame().view()->viewToContents(viewRect);1474 }1475 1476 1471 return ownerRenderer->enclosingLayer(); 1477 1472 } 1478 1473 1479 RenderLayer* RenderLayer::enclosingScrollableLayer( LayoutRect* rect) const1480 { 1481 for (RenderLayer* nextLayer = parentLayerCrossFrame(*this , rect); nextLayer; nextLayer = parentLayerCrossFrame(*nextLayer, rect)) {1474 RenderLayer* RenderLayer::enclosingScrollableLayer() const 1475 { 1476 for (RenderLayer* nextLayer = parentLayerCrossFrame(*this); nextLayer; nextLayer = parentLayerCrossFrame(*nextLayer)) { 1482 1477 if (is<RenderBox>(nextLayer->renderer()) && downcast<RenderBox>(nextLayer->renderer()).canBeScrolledAndHasScrollableArea()) 1483 1478 return nextLayer; … … 2284 2279 } 2285 2280 2281 // FIXME: unify with the scrollRectToVisible() code below. 2286 2282 void RenderLayer::scrollByRecursively(const IntSize& delta, ScrollOffsetClamping clamp, ScrollableArea** scrolledArea) 2287 2283 { … … 2437 2433 } 2438 2434 2439 static inline bool frameElementAndViewPermitScroll(HTMLFrameElementBase* frameElementBase, FrameView * frameView)2435 static inline bool frameElementAndViewPermitScroll(HTMLFrameElementBase* frameElementBase, FrameView& frameView) 2440 2436 { 2441 2437 // If scrollbars aren't explicitly forbidden, permit scrolling. … … 2444 2440 2445 2441 // If scrollbars are forbidden, user initiated scrolls should obviously be ignored. 2446 if (frameView ->wasScrolledByUser())2442 if (frameView.wasScrolledByUser()) 2447 2443 return false; 2448 2444 2449 2445 // Forbid autoscrolls when scrollbars are off, but permits other programmatic scrolls, 2450 2446 // like navigation to an anchor. 2451 return !frameView->frame().eventHandler().autoscrollInProgress(); 2447 return !frameView.frame().eventHandler().autoscrollInProgress(); 2448 } 2449 2450 bool RenderLayer::allowsCurrentScroll() const 2451 { 2452 if (!renderer().hasOverflowClip()) 2453 return false; 2454 2455 // Don't scroll to reveal an overflow layer that is restricted by the -webkit-line-clamp property. 2456 // FIXME: Is this still needed? It used to be relevant for Safari RSS. 2457 if (renderer().parent() && !renderer().parent()->style().lineClamp().isNone()) 2458 return false; 2459 2460 RenderBox* box = renderBox(); 2461 ASSERT(box); // Only boxes can have overflowClip set. 2462 2463 if (renderer().frame().eventHandler().autoscrollInProgress()) { 2464 // The "programmatically" here is misleading; this asks whether the box has scrollable overflow, 2465 // or is a special case like a form control. 2466 return box->canBeProgramaticallyScrolled(); 2467 } 2468 2469 // Programmatic scrolls can scroll overflow:hidden. 2470 return box->hasHorizontalOverflow() || box->hasVerticalOverflow(); 2452 2471 } 2453 2472 2454 2473 void RenderLayer::scrollRectToVisible(const LayoutRect& rect, const ScrollAlignment& alignX, const ScrollAlignment& alignY) 2455 2474 { 2475 LOG_WITH_STREAM(Scrolling, stream << "Layer " << this << " scrollRectToVisible " << rect); 2476 2456 2477 RenderLayer* parentLayer = nullptr; 2457 2478 LayoutRect newRect = rect; … … 2461 2482 FrameView& frameView = renderer().view().frameView(); 2462 2483 2463 bool restrictedByLineClamp = false; 2464 if (renderer().parent()) { 2484 if (renderer().parent()) 2465 2485 parentLayer = renderer().parent()->enclosingLayer(); 2466 restrictedByLineClamp = !renderer().parent()->style().lineClamp().isNone(); 2467 } 2468 2469 if (renderer().hasOverflowClip() && !restrictedByLineClamp) { 2486 2487 if (allowsCurrentScroll()) { 2470 2488 // Don't scroll to reveal an overflow layer that is restricted by the -webkit-line-clamp property. 2471 2489 // This will prevent us from revealing text hidden by the slider in Safari RSS. … … 2484 2502 newRect = LayoutRect(box->localToAbsoluteQuad(FloatQuad(FloatRect(localExposeRect)), UseTransforms).boundingBox()); 2485 2503 } 2486 } else if (!parentLayer && renderer().is Box() && renderBox()->canBeProgramaticallyScrolled()) {2504 } else if (!parentLayer && renderer().isRenderView()) { 2487 2505 HTMLFrameOwnerElement* ownerElement = renderer().document().ownerElement(); 2488 2506 … … 2493 2511 frameElementBase = downcast<HTMLFrameElementBase>(ownerElement); 2494 2512 2495 if (frameElementAndViewPermitScroll(frameElementBase, &frameView)) {2513 if (frameElementAndViewPermitScroll(frameElementBase, frameView)) { 2496 2514 LayoutRect viewRect = frameView.visibleContentRect(LegacyIOSDocumentVisibleRect); 2497 2515 LayoutRect exposeRect = getRectToExpose(viewRect, viewRect, rect, alignX, alignY); 2498 2516 2499 int xOffset = roundToInt(exposeRect.x()); 2500 int yOffset = roundToInt(exposeRect.y()); 2517 IntPoint scrollOffset(roundedIntPoint(exposeRect.location())); 2501 2518 // Adjust offsets if they're outside of the allowable range. 2502 xOffset = std::max(0, std::min(frameView.contentsWidth(), xOffset)); 2503 yOffset = std::max(0, std::min(frameView.contentsHeight(), yOffset)); 2504 2505 frameView.setScrollPosition(IntPoint(xOffset, yOffset)); 2519 scrollOffset = scrollOffset.constrainedBetween(IntPoint(), IntPoint(frameView.contentsSize())); 2520 frameView.setScrollPosition(scrollOffset); 2521 2506 2522 if (frameView.safeToPropagateScrollToParent()) { 2507 2523 parentLayer = ownerElement->renderer()->enclosingLayer(); 2508 // FIXME: This doesn't correctly convert the rect to 2509 // absolute coordinates in the parent. 2510 newRect.setX(rect.x() - frameView.scrollX() + frameView.x()); 2511 newRect.setY(rect.y() - frameView.scrollY() + frameView.y()); 2524 // Convert the rect into the coordinate space of the parent frame's document. 2525 newRect = frameView.contentsToContainingViewContents(enclosingIntRect(newRect)); 2512 2526 } else 2513 2527 parentLayer = nullptr; … … 2538 2552 } 2539 2553 2540 if (renderer().frame().eventHandler().autoscrollInProgress())2541 parentLayer = enclosingScrollableLayer(&newRect);2542 2543 2554 if (parentLayer) 2544 2555 parentLayer->scrollRectToVisible(newRect, alignX, alignY); -
trunk/Source/WebCore/rendering/RenderLayer.h
r192193 r194405 405 405 406 406 // Returns the nearest enclosing layer that is scrollable. 407 RenderLayer* enclosingScrollableLayer( LayoutRect* = nullptr) const;407 RenderLayer* enclosingScrollableLayer() const; 408 408 409 409 // The layer relative to which clipping rects for this layer are computed. … … 898 898 899 899 void updateScrollableAreaSet(bool hasOverflow); 900 901 bool allowsCurrentScroll() const; 900 902 901 903 void dirtyAncestorChainVisibleDescendantStatus(); -
trunk/Source/WebCore/rendering/RenderTextControlSingleLine.h
r180490 r194405 106 106 virtual bool hasLineIfEmpty() const override { return true; } 107 107 virtual bool isTextControlInnerBlock() const override { return true; } 108 virtual bool canBeProgramaticallyScrolled() const override { return true; } 108 109 }; 109 110
Note:
See TracChangeset
for help on using the changeset viewer.