Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright (C) 1998, 1999 Torben Weis <weis@kde.org> | 2 * Copyright (C) 1998, 1999 Torben Weis <weis@kde.org> |
| 3 * 1999 Lars Knoll <knoll@kde.org> | 3 * 1999 Lars Knoll <knoll@kde.org> |
| 4 * 1999 Antti Koivisto <koivisto@kde.org> | 4 * 1999 Antti Koivisto <koivisto@kde.org> |
| 5 * 2000 Dirk Mueller <mueller@kde.org> | 5 * 2000 Dirk Mueller <mueller@kde.org> |
| 6 * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. | 6 * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. |
| 7 * (C) 2006 Graham Dennis (graham.dennis@gmail.com) | 7 * (C) 2006 Graham Dennis (graham.dennis@gmail.com) |
| 8 * (C) 2006 Alexey Proskuryakov (ap@nypop.com) | 8 * (C) 2006 Alexey Proskuryakov (ap@nypop.com) |
| 9 * Copyright (C) 2009 Google Inc. All rights reserved. | 9 * Copyright (C) 2009 Google Inc. All rights reserved. |
| 10 * | 10 * |
| (...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 187 m_hiddenForThrottling(false), | 187 m_hiddenForThrottling(false), |
| 188 m_subtreeThrottled(false), | 188 m_subtreeThrottled(false), |
| 189 m_lifecycleUpdatesThrottled(false), | 189 m_lifecycleUpdatesThrottled(false), |
| 190 m_needsPaintPropertyUpdate(true), | 190 m_needsPaintPropertyUpdate(true), |
| 191 m_currentUpdateLifecyclePhasesTargetState( | 191 m_currentUpdateLifecyclePhasesTargetState( |
| 192 DocumentLifecycle::Uninitialized), | 192 DocumentLifecycle::Uninitialized), |
| 193 m_scrollAnchor(this), | 193 m_scrollAnchor(this), |
| 194 m_scrollbarManager(*this), | 194 m_scrollbarManager(*this), |
| 195 m_needsScrollbarsUpdate(false), | 195 m_needsScrollbarsUpdate(false), |
| 196 m_suppressAdjustViewSize(false), | 196 m_suppressAdjustViewSize(false), |
| 197 m_allowsLayoutInvalidationAfterLayoutClean(true) { | 197 m_allowsLayoutInvalidationAfterLayoutClean(true), |
| 198 m_mainThreadScrollingReasons(0) { | |
| 198 init(); | 199 init(); |
| 199 } | 200 } |
| 200 | 201 |
| 201 FrameView* FrameView::create(LocalFrame& frame) { | 202 FrameView* FrameView::create(LocalFrame& frame) { |
| 202 FrameView* view = new FrameView(frame); | 203 FrameView* view = new FrameView(frame); |
| 203 view->show(); | 204 view->show(); |
| 204 return view; | 205 return view; |
| 205 } | 206 } |
| 206 | 207 |
| 207 FrameView* FrameView::create(LocalFrame& frame, const IntSize& initialSize) { | 208 FrameView* FrameView::create(LocalFrame& frame, const IntSize& initialSize) { |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 250 m_firstLayout = true; | 251 m_firstLayout = true; |
| 251 m_safeToPropagateScrollToParent = true; | 252 m_safeToPropagateScrollToParent = true; |
| 252 m_lastViewportSize = IntSize(); | 253 m_lastViewportSize = IntSize(); |
| 253 m_lastZoomFactor = 1.0f; | 254 m_lastZoomFactor = 1.0f; |
| 254 m_trackedObjectPaintInvalidations = WTF::wrapUnique( | 255 m_trackedObjectPaintInvalidations = WTF::wrapUnique( |
| 255 s_initialTrackAllPaintInvalidations ? new Vector<ObjectPaintInvalidation> | 256 s_initialTrackAllPaintInvalidations ? new Vector<ObjectPaintInvalidation> |
| 256 : nullptr); | 257 : nullptr); |
| 257 m_visuallyNonEmptyCharacterCount = 0; | 258 m_visuallyNonEmptyCharacterCount = 0; |
| 258 m_visuallyNonEmptyPixelCount = 0; | 259 m_visuallyNonEmptyPixelCount = 0; |
| 259 m_isVisuallyNonEmpty = false; | 260 m_isVisuallyNonEmpty = false; |
| 261 m_mainThreadScrollingReasons = 0; | |
| 260 m_layoutObjectCounter.reset(); | 262 m_layoutObjectCounter.reset(); |
| 261 clearFragmentAnchor(); | 263 clearFragmentAnchor(); |
| 262 m_viewportConstrainedObjects.reset(); | 264 m_viewportConstrainedObjects.reset(); |
| 263 m_layoutSubtreeRootList.clear(); | 265 m_layoutSubtreeRootList.clear(); |
| 264 m_orthogonalWritingModeRootList.clear(); | 266 m_orthogonalWritingModeRootList.clear(); |
| 265 } | 267 } |
| 266 | 268 |
| 267 // Call function for each non-throttled frame view in pre tree order. | 269 // Call function for each non-throttled frame view in pre tree order. |
| 268 // Note it needs a null check of the frame's layoutView to access it in case of | 270 // Note it needs a null check of the frame's layoutView to access it in case of |
| 269 // detached frames. | 271 // detached frames. |
| (...skipping 421 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 691 adjustViewSize(); | 693 adjustViewSize(); |
| 692 if (needsLayout()) { | 694 if (needsLayout()) { |
| 693 AutoReset<bool> suppressAdjustViewSize(&m_suppressAdjustViewSize, true); | 695 AutoReset<bool> suppressAdjustViewSize(&m_suppressAdjustViewSize, true); |
| 694 layout(); | 696 layout(); |
| 695 } | 697 } |
| 696 } | 698 } |
| 697 | 699 |
| 698 void FrameView::calculateScrollbarModesFromOverflowStyle( | 700 void FrameView::calculateScrollbarModesFromOverflowStyle( |
| 699 const ComputedStyle* style, | 701 const ComputedStyle* style, |
| 700 ScrollbarMode& hMode, | 702 ScrollbarMode& hMode, |
| 701 ScrollbarMode& vMode) { | 703 ScrollbarMode& vMode) const { |
| 702 hMode = vMode = ScrollbarAuto; | 704 hMode = vMode = ScrollbarAuto; |
| 703 | 705 |
| 704 EOverflow overflowX = style->overflowX(); | 706 EOverflow overflowX = style->overflowX(); |
| 705 EOverflow overflowY = style->overflowY(); | 707 EOverflow overflowY = style->overflowY(); |
| 706 | 708 |
| 707 if (!shouldIgnoreOverflowHidden()) { | 709 if (!shouldIgnoreOverflowHidden()) { |
| 708 if (overflowX == EOverflow::Hidden) | 710 if (overflowX == EOverflow::Hidden) |
| 709 hMode = ScrollbarAlwaysOff; | 711 hMode = ScrollbarAlwaysOff; |
| 710 if (overflowY == EOverflow::Hidden) | 712 if (overflowY == EOverflow::Hidden) |
| 711 vMode = ScrollbarAlwaysOff; | 713 vMode = ScrollbarAlwaysOff; |
| 712 } | 714 } |
| 713 | 715 |
| 714 if (overflowX == EOverflow::Scroll) | 716 if (overflowX == EOverflow::Scroll) |
| 715 hMode = ScrollbarAlwaysOn; | 717 hMode = ScrollbarAlwaysOn; |
| 716 if (overflowY == EOverflow::Scroll) | 718 if (overflowY == EOverflow::Scroll) |
| 717 vMode = ScrollbarAlwaysOn; | 719 vMode = ScrollbarAlwaysOn; |
| 718 } | 720 } |
| 719 | 721 |
| 720 void FrameView::calculateScrollbarModes( | 722 void FrameView::calculateScrollbarModes( |
| 721 ScrollbarMode& hMode, | 723 ScrollbarMode& hMode, |
| 722 ScrollbarMode& vMode, | 724 ScrollbarMode& vMode, |
| 723 ScrollbarModesCalculationStrategy strategy) { | 725 ScrollbarModesCalculationStrategy strategy) const { |
| 724 #define RETURN_SCROLLBAR_MODE(mode) \ | 726 #define RETURN_SCROLLBAR_MODE(mode) \ |
| 725 { \ | 727 { \ |
| 726 hMode = vMode = mode; \ | 728 hMode = vMode = mode; \ |
| 727 return; \ | 729 return; \ |
| 728 } | 730 } |
| 729 | 731 |
| 730 // Setting scrolling="no" on an iframe element disables scrolling. | 732 // Setting scrolling="no" on an iframe element disables scrolling. |
| 731 if (m_frame->owner() && | 733 if (m_frame->owner() && |
| 732 m_frame->owner()->scrollingMode() == ScrollbarAlwaysOff) | 734 m_frame->owner()->scrollingMode() == ScrollbarAlwaysOff) |
| 733 RETURN_SCROLLBAR_MODE(ScrollbarAlwaysOff); | 735 RETURN_SCROLLBAR_MODE(ScrollbarAlwaysOff); |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 820 LayoutViewItem layoutView = this->layoutViewItem(); | 822 LayoutViewItem layoutView = this->layoutViewItem(); |
| 821 if (layoutView.isNull()) | 823 if (layoutView.isNull()) |
| 822 return false; | 824 return false; |
| 823 if (m_frame->settings() && | 825 if (m_frame->settings() && |
| 824 m_frame->settings()->preferCompositingToLCDTextEnabled()) | 826 m_frame->settings()->preferCompositingToLCDTextEnabled()) |
| 825 return layoutView.compositor()->inCompositingMode(); | 827 return layoutView.compositor()->inCompositingMode(); |
| 826 return false; | 828 return false; |
| 827 } | 829 } |
| 828 | 830 |
| 829 bool FrameView::shouldScrollOnMainThread() const { | 831 bool FrameView::shouldScrollOnMainThread() const { |
| 830 if (ScrollingCoordinator* sc = scrollingCoordinator()) { | 832 if (mainThreadScrollingReasons()) |
| 831 if (sc->shouldUpdateScrollLayerPositionOnMainThread()) | 833 return true; |
| 832 return true; | |
| 833 } | |
| 834 return ScrollableArea::shouldScrollOnMainThread(); | 834 return ScrollableArea::shouldScrollOnMainThread(); |
| 835 } | 835 } |
| 836 | 836 |
| 837 GraphicsLayer* FrameView::layerForScrolling() const { | 837 GraphicsLayer* FrameView::layerForScrolling() const { |
| 838 LayoutViewItem layoutView = this->layoutViewItem(); | 838 LayoutViewItem layoutView = this->layoutViewItem(); |
| 839 if (layoutView.isNull()) | 839 if (layoutView.isNull()) |
| 840 return nullptr; | 840 return nullptr; |
| 841 return layoutView.compositor()->frameScrollLayer(); | 841 return layoutView.compositor()->frameScrollLayer(); |
| 842 } | 842 } |
| 843 | 843 |
| (...skipping 1685 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2529 } | 2529 } |
| 2530 | 2530 |
| 2531 bool FrameView::isScrollable() { | 2531 bool FrameView::isScrollable() { |
| 2532 return getScrollingReasons() == Scrollable; | 2532 return getScrollingReasons() == Scrollable; |
| 2533 } | 2533 } |
| 2534 | 2534 |
| 2535 bool FrameView::isProgrammaticallyScrollable() { | 2535 bool FrameView::isProgrammaticallyScrollable() { |
| 2536 return !m_inUpdateScrollbars; | 2536 return !m_inUpdateScrollbars; |
| 2537 } | 2537 } |
| 2538 | 2538 |
| 2539 FrameView::ScrollingReasons FrameView::getScrollingReasons() { | 2539 FrameView::ScrollingReasons FrameView::getScrollingReasons() const { |
| 2540 // Check for: | 2540 // Check for: |
| 2541 // 1) If there an actual overflow. | 2541 // 1) If there an actual overflow. |
| 2542 // 2) display:none or visibility:hidden set to self or inherited. | 2542 // 2) display:none or visibility:hidden set to self or inherited. |
| 2543 // 3) overflow{-x,-y}: hidden; | 2543 // 3) overflow{-x,-y}: hidden; |
| 2544 // 4) scrolling: no; | 2544 // 4) scrolling: no; |
| 2545 | 2545 |
| 2546 // Covers #1 | 2546 // Covers #1 |
| 2547 IntSize contentsSize = this->contentsSize(); | 2547 IntSize contentsSize = this->contentsSize(); |
| 2548 IntSize visibleContentSize = visibleContentRect().size(); | 2548 IntSize visibleContentSize = visibleContentRect().size(); |
| 2549 if ((contentsSize.height() <= visibleContentSize.height() && | 2549 if ((contentsSize.height() <= visibleContentSize.height() && |
| (...skipping 2142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4692 int FrameView::initialViewportWidth() const { | 4692 int FrameView::initialViewportWidth() const { |
| 4693 DCHECK(m_frame->isMainFrame()); | 4693 DCHECK(m_frame->isMainFrame()); |
| 4694 return m_initialViewportSize.width(); | 4694 return m_initialViewportSize.width(); |
| 4695 } | 4695 } |
| 4696 | 4696 |
| 4697 int FrameView::initialViewportHeight() const { | 4697 int FrameView::initialViewportHeight() const { |
| 4698 DCHECK(m_frame->isMainFrame()); | 4698 DCHECK(m_frame->isMainFrame()); |
| 4699 return m_initialViewportSize.height(); | 4699 return m_initialViewportSize.height(); |
| 4700 } | 4700 } |
| 4701 | 4701 |
| 4702 bool FrameView::hasVisibleSlowRepaintViewportConstrainedObjects() const { | |
| 4703 if (!viewportConstrainedObjects()) | |
| 4704 return false; | |
| 4705 | |
| 4706 for (const LayoutObject* layoutObject : *viewportConstrainedObjects()) { | |
| 4707 DCHECK(layoutObject->isBoxModelObject() && layoutObject->hasLayer()); | |
| 4708 DCHECK(layoutObject->style()->position() == FixedPosition || | |
| 4709 layoutObject->style()->position() == StickyPosition); | |
| 4710 PaintLayer* layer = toLayoutBoxModelObject(layoutObject)->layer(); | |
| 4711 | |
| 4712 // Whether the Layer sticks to the viewport is a tree-depenent | |
| 4713 // property and our viewportConstrainedObjects collection is maintained | |
| 4714 // with only LayoutObject-level information. | |
| 4715 if (!layer->sticksToViewport()) | |
| 4716 continue; | |
| 4717 | |
| 4718 // If the whole subtree is invisible, there's no reason to scroll on | |
| 4719 // the main thread because we don't need to generate invalidations | |
| 4720 // for invisible content. | |
| 4721 if (layer->subtreeIsInvisible()) | |
| 4722 continue; | |
| 4723 | |
| 4724 // We're only smart enough to scroll viewport-constrainted objects | |
| 4725 // in the compositor if they have their own backing or they paint | |
| 4726 // into a grouped back (which necessarily all have the same viewport | |
| 4727 // constraints). | |
| 4728 CompositingState compositingState = layer->compositingState(); | |
| 4729 if (compositingState != PaintsIntoOwnBacking && | |
| 4730 compositingState != PaintsIntoGroupedBacking) | |
| 4731 return true; | |
| 4732 } | |
| 4733 return false; | |
| 4734 } | |
| 4735 | |
| 4736 void FrameView::updateSubFrameScrollOnMainReason( | |
| 4737 const Frame& frame, | |
| 4738 MainThreadScrollingReasons parentReason) { | |
| 4739 MainThreadScrollingReasons reasons = parentReason; | |
| 4740 | |
| 4741 if (!page()->settings().threadedScrollingEnabled()) | |
| 4742 reasons |= MainThreadScrollingReason::kThreadedScrollingDisabled; | |
| 4743 | |
| 4744 if (!frame.isLocalFrame()) | |
| 4745 return; | |
| 4746 | |
| 4747 if (!toLocalFrame(frame).view()->layerForScrolling()) | |
| 4748 return; | |
| 4749 | |
| 4750 reasons |= toLocalFrame(frame).view()->mainThreadScrollingReasonsPerFrame(); | |
| 4751 if (WebLayer* scrollLayer = | |
| 4752 toLocalFrame(frame).view()->layerForScrolling()->platformLayer()) { | |
| 4753 if (reasons) { | |
| 4754 scrollLayer->addMainThreadScrollingReasons(reasons); | |
| 4755 } else { | |
| 4756 scrollLayer->clearMainThreadScrollingReasons( | |
|
pdr.
2016/12/19 04:04:28
Please add a comment here:
// Clear all main threa
yigu
2016/12/20 00:48:34
Done. Filed the bug as crbug.com/675677.
| |
| 4757 ~MainThreadScrollingReason::kHandlingScrollFromMainThread); | |
| 4758 } | |
| 4759 } | |
| 4760 | |
| 4761 Frame* child = frame.tree().firstChild(); | |
| 4762 while (child) { | |
| 4763 updateSubFrameScrollOnMainReason(*child, reasons); | |
| 4764 child = child->tree().nextSibling(); | |
| 4765 } | |
| 4766 | |
| 4767 if (frame.isMainFrame()) | |
| 4768 m_mainThreadScrollingReasons = reasons; | |
| 4769 } | |
| 4770 | |
| 4771 MainThreadScrollingReasons FrameView::mainThreadScrollingReasonsPerFrame() | |
| 4772 const { | |
| 4773 MainThreadScrollingReasons reasons = | |
| 4774 static_cast<MainThreadScrollingReasons>(0); | |
| 4775 | |
| 4776 if (shouldThrottleRendering()) | |
| 4777 return reasons; | |
| 4778 | |
| 4779 if (hasBackgroundAttachmentFixedObjects()) | |
| 4780 reasons |= MainThreadScrollingReason::kHasBackgroundAttachmentFixedObjects; | |
| 4781 ScrollingReasons scrollingReasons = getScrollingReasons(); | |
|
pdr.
2016/12/19 04:04:28
I think there's a bug similar to https://crbug.com
yigu
2016/12/20 00:48:34
It seems we can handle it now. Unit test added.
| |
| 4782 const bool mayBeScrolledByInput = (scrollingReasons == Scrollable); | |
| 4783 const bool mayBeScrolledByScript = | |
| 4784 mayBeScrolledByInput || | |
| 4785 (scrollingReasons == NotScrollableExplicitlyDisabled); | |
| 4786 | |
| 4787 // TODO(awoloszyn) Currently crbug.com/304810 will let certain | |
| 4788 // overflow:hidden elements scroll on the compositor thread, so we should | |
| 4789 // not let this move there path as an optimization, when we have | |
| 4790 // slow-repaint elements. | |
| 4791 if (mayBeScrolledByScript && | |
| 4792 hasVisibleSlowRepaintViewportConstrainedObjects()) { | |
| 4793 reasons |= | |
| 4794 MainThreadScrollingReason::kHasNonLayerViewportConstrainedObjects; | |
| 4795 } | |
| 4796 return reasons; | |
| 4797 } | |
| 4798 | |
| 4799 MainThreadScrollingReasons FrameView::mainThreadScrollingReasons() const { | |
| 4800 MainThreadScrollingReasons reasons = | |
| 4801 static_cast<MainThreadScrollingReasons>(0); | |
| 4802 | |
| 4803 if (!page()->settings().threadedScrollingEnabled()) | |
| 4804 reasons |= MainThreadScrollingReason::kThreadedScrollingDisabled; | |
| 4805 | |
| 4806 if (!page()->mainFrame()->isLocalFrame()) | |
| 4807 return reasons; | |
| 4808 | |
| 4809 // TODO(alexmos,kenrb): For OOPIF, local roots that are different from | |
| 4810 // the main frame can't be used in the calculation, since they use | |
| 4811 // different compositors with unrelated state, which breaks some of the | |
| 4812 // calculations below. | |
| 4813 if (m_frame->localFrameRoot() != page()->mainFrame()) | |
| 4814 return reasons; | |
| 4815 | |
| 4816 // Walk the tree to the root. Use the gathered reasons to determine | |
| 4817 // whether the target frame should be scrolled on main thread regardless | |
| 4818 // other subframes on the same page. | |
| 4819 for (Frame* frame = m_frame; frame; frame = frame->tree().parent()) { | |
| 4820 if (!frame->isLocalFrame()) | |
| 4821 continue; | |
| 4822 reasons |= | |
| 4823 toLocalFrame(frame)->view()->mainThreadScrollingReasonsPerFrame(); | |
| 4824 } | |
| 4825 | |
| 4826 return reasons; | |
| 4827 } | |
| 4828 | |
| 4829 String FrameView::mainThreadScrollingReasonsAsText() const { | |
| 4830 DCHECK(lifecycle().state() >= DocumentLifecycle::CompositingClean); | |
| 4831 if (layerForScrolling() && layerForScrolling()->platformLayer()) { | |
| 4832 String result( | |
| 4833 MainThreadScrollingReason::mainThreadScrollingReasonsAsText( | |
| 4834 layerForScrolling()->platformLayer()->mainThreadScrollingReasons()) | |
| 4835 .c_str()); | |
| 4836 return result; | |
| 4837 } | |
| 4838 | |
| 4839 String result(MainThreadScrollingReason::mainThreadScrollingReasonsAsText( | |
| 4840 m_mainThreadScrollingReasons) | |
| 4841 .c_str()); | |
| 4842 return result; | |
| 4843 } | |
| 4844 | |
| 4702 } // namespace blink | 4845 } // namespace blink |
| OLD | NEW |