| /* |
| * Copyright (C) 2003, 2009, 2012 Apple Inc. All rights reserved. |
| * |
| * Portions are Copyright (C) 1998 Netscape Communications Corporation. |
| * |
| * Other contributors: |
| * Robert O'Callahan <roc+@cs.cmu.edu> |
| * David Baron <dbaron@fas.harvard.edu> |
| * Christian Biesinger <cbiesinger@web.de> |
| * Randall Jesup <rjesup@wgate.com> |
| * Roland Mainz <roland.mainz@informatik.med.uni-giessen.de> |
| * Josh Soref <timeless@mac.com> |
| * Boris Zbarsky <bzbarsky@mit.edu> |
| * |
| * This library is free software; you can redistribute it and/or |
| * modify it under the terms of the GNU Lesser General Public |
| * License as published by the Free Software Foundation; either |
| * version 2.1 of the License, or (at your option) any later version. |
| * |
| * This library is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| * Lesser General Public License for more details. |
| * |
| * You should have received a copy of the GNU Lesser General Public |
| * License along with this library; if not, write to the Free Software |
| * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA |
| * |
| * Alternatively, the contents of this file may be used under the terms |
| * of either the Mozilla Public License Version 1.1, found at |
| * http://www.mozilla.org/MPL/ (the "MPL") or the GNU General Public |
| * License Version 2.0, found at http://www.fsf.org/copyleft/gpl.html |
| * (the "GPL"), in which case the provisions of the MPL or the GPL are |
| * applicable instead of those above. If you wish to allow use of your |
| * version of this file only under the terms of one of those two |
| * licenses (the MPL or the GPL) and not to allow others to use your |
| * version of this file under the LGPL, indicate your decision by |
| * deletingthe provisions above and replace them with the notice and |
| * other provisions required by the MPL or the GPL, as the case may be. |
| * If you do not delete the provisions above, a recipient may use your |
| * version of this file under any of the LGPL, the MPL or the GPL. |
| */ |
| |
| #ifndef PaintLayerScrollableArea_h |
| #define PaintLayerScrollableArea_h |
| |
| #include "core/CoreExport.h" |
| #include "core/layout/ScrollAnchor.h" |
| #include "core/layout/ScrollEnums.h" |
| #include "core/page/scrolling/StickyPositionScrollingConstraints.h" |
| #include "core/paint/PaintInvalidationCapableScrollableArea.h" |
| #include "core/paint/PaintLayerFragment.h" |
| #include "platform/heap/Handle.h" |
| #include "wtf/PtrUtil.h" |
| #include <memory> |
| |
| namespace blink { |
| |
| enum ResizerHitTestType { ResizerForPointer, ResizerForTouch }; |
| |
| class ComputedStyle; |
| class HitTestResult; |
| class LayoutBox; |
| class LayoutScrollbarPart; |
| class PaintLayer; |
| class PlatformEvent; |
| class StickyPositionScrollingConstraints; |
| class SubtreeLayoutScope; |
| |
| typedef WTF::HashMap<PaintLayer*, StickyPositionScrollingConstraints> |
| StickyConstraintsMap; |
| |
| struct CORE_EXPORT PaintLayerScrollableAreaRareData { |
| WTF_MAKE_NONCOPYABLE(PaintLayerScrollableAreaRareData); |
| USING_FAST_MALLOC(PaintLayerScrollableAreaRareData); |
| |
| public: |
| PaintLayerScrollableAreaRareData(); |
| |
| StickyConstraintsMap m_stickyConstraintsMap; |
| }; |
| |
| // PaintLayerScrollableArea represents the scrollable area of a LayoutBox. |
| // |
| // To be scrollable, an element requires ‘overflow’ != visible. Note that this |
| // doesn’t imply having scrollbars as you can always programmatically scroll |
| // when ‘overflow’ is hidden (using JavaScript's element.scrollTo or |
| // scrollLeft). |
| // |
| // The size and scroll origin of the scrollable area are based on layout |
| // dimensions. They are recomputed after layout in updateScrollDimensions. |
| // |
| // updateScrollDimensions also determines if scrollbars need to be allocated, |
| // destroyed or updated as a result of layout. This is based on the value of the |
| // 'overflow' property. Having non-overlay scrollbars automatically allocates a |
| // scrollcorner (m_scrollCorner), which is used to style the intersection of the |
| // two scrollbars. |
| // |
| // Note that scrollbars are placed based on the LayoutBox's computed |
| // 'direction'. See https://webkit.org/b/54623 for some context. |
| // |
| // The ‘resize' property allocates a resizer (m_resizer), which is overlaid on |
| // top of the scroll corner. It is used to resize an element using the mouse. |
| // |
| // The scrollbars and scroll corner can also be hardware accelerated |
| // and thus get their own GraphicsLayer (see the layerFor* functions). |
| // This only happens if the associated PaintLayer is itself composited. |
| // |
| // |
| // ***** OVERLAY SCROLLBARS ***** |
| // Overlay scrollbars are painted on top of the box's content. As such they |
| // don't use any space in the box. Software overlay scrollbars are painted by |
| // PaintLayerPainter::paintOverlayScrollbars after all content as part of a |
| // separate tree traversal. The reason for this 2nd traversal is that they need |
| // to be painted on top of everything. Hardware accelerated overlay scrollbars |
| // are painted by their associated GraphicsLayer that sets the paint flag |
| // PaintLayerPaintingOverlayScrollbars. |
| class CORE_EXPORT PaintLayerScrollableArea final |
| : public GarbageCollectedFinalized<PaintLayerScrollableArea>, |
| public PaintInvalidationCapableScrollableArea { |
| USING_GARBAGE_COLLECTED_MIXIN(PaintLayerScrollableArea); |
| friend class Internals; |
| |
| private: |
| class ScrollbarManager { |
| DISALLOW_NEW(); |
| |
| // Helper class to manage the life cycle of Scrollbar objects. Some layout |
| // containers (e.g., flexbox, table) run multi-pass layout on their |
| // children, applying different constraints. If a child has overflow:auto, |
| // it may gain and lose scrollbars multiple times during multi-pass layout, |
| // causing pointless allocation/deallocation thrashing, and potentially |
| // leading to other problems (crbug.com/528940). |
| |
| // ScrollbarManager allows a ScrollableArea to delay the destruction of a |
| // scrollbar that is no longer needed, until the end of multi-pass layout. |
| // If the scrollbar is then re-added before multi-pass layout finishes, the |
| // previously "deleted" scrollbar will be restored, rather than constructing |
| // a new one. |
| public: |
| ScrollbarManager(PaintLayerScrollableArea&); |
| |
| void dispose(); |
| |
| Scrollbar* horizontalScrollbar() const { |
| return m_hBarIsAttached ? m_hBar.get() : nullptr; |
| } |
| Scrollbar* verticalScrollbar() const { |
| return m_vBarIsAttached ? m_vBar.get() : nullptr; |
| } |
| bool hasHorizontalScrollbar() const { return horizontalScrollbar(); } |
| bool hasVerticalScrollbar() const { return verticalScrollbar(); } |
| |
| void setHasHorizontalScrollbar(bool hasScrollbar); |
| void setHasVerticalScrollbar(bool hasScrollbar); |
| void destroyDetachedScrollbars(); |
| |
| DECLARE_TRACE(); |
| |
| private: |
| Scrollbar* createScrollbar(ScrollbarOrientation); |
| void destroyScrollbar(ScrollbarOrientation); |
| |
| private: |
| Member<PaintLayerScrollableArea> m_scrollableArea; |
| |
| // The scrollbars associated with m_scrollableArea. Both can nullptr. |
| Member<Scrollbar> m_hBar; |
| Member<Scrollbar> m_vBar; |
| |
| unsigned m_hBarIsAttached : 1; |
| unsigned m_vBarIsAttached : 1; |
| }; |
| |
| public: |
| // If a PreventRelayoutScope object is alive, updateAfterLayout() will not |
| // re-run box layout as a result of adding or removing scrollbars. |
| // Instead, it will mark the PLSA as needing relayout of its box. |
| // When the last PreventRelayoutScope object is popped off the stack, |
| // box().setNeedsLayout(), and box().scrollbarsChanged() for LayoutBlock's, |
| // will be called as appropriate for all marked PLSA's. |
| class PreventRelayoutScope { |
| STACK_ALLOCATED(); |
| |
| public: |
| PreventRelayoutScope(SubtreeLayoutScope&); |
| ~PreventRelayoutScope(); |
| |
| static bool relayoutIsPrevented() { return s_count; } |
| static void setBoxNeedsLayout(PaintLayerScrollableArea&, |
| bool hadHorizontalScrollbar, |
| bool hadVerticalScrollbar); |
| static bool relayoutNeeded() { return s_count == 0 && s_relayoutNeeded; } |
| static void resetRelayoutNeeded(); |
| |
| private: |
| static int s_count; |
| static SubtreeLayoutScope* s_layoutScope; |
| static bool s_relayoutNeeded; |
| static PersistentHeapVector<Member<PaintLayerScrollableArea>>* |
| s_needsRelayout; |
| }; |
| |
| // If a FreezeScrollbarScope object is alive, updateAfterLayout() will not |
| // recompute the existence of overflow:auto scrollbars. |
| class FreezeScrollbarsScope { |
| STACK_ALLOCATED(); |
| |
| public: |
| FreezeScrollbarsScope() { s_count++; } |
| ~FreezeScrollbarsScope() { s_count--; } |
| |
| static bool scrollbarsAreFrozen() { return s_count; } |
| |
| private: |
| static int s_count; |
| }; |
| |
| // If a DelayScrollPositionClampScope object is alive, updateAfterLayout() |
| // will not clamp scroll positions to ensure they are in the valid range. |
| // When the last DelayScrollPositionClampScope object is destructed, all |
| // PaintLayerScrollableArea's that delayed clamping their positions will |
| // immediately clamp them. |
| class DelayScrollPositionClampScope { |
| STACK_ALLOCATED(); |
| |
| public: |
| DelayScrollPositionClampScope(); |
| ~DelayScrollPositionClampScope(); |
| |
| static bool clampingIsDelayed() { return s_count; } |
| static void setNeedsClamp(PaintLayerScrollableArea*); |
| |
| private: |
| static void clampScrollableAreas(); |
| |
| static int s_count; |
| static PersistentHeapVector<Member<PaintLayerScrollableArea>>* s_needsClamp; |
| }; |
| |
| // FIXME: We should pass in the LayoutBox but this opens a window |
| // for crashers during PaintLayer setup (see crbug.com/368062). |
| static PaintLayerScrollableArea* create(PaintLayer& layer) { |
| return new PaintLayerScrollableArea(layer); |
| } |
| |
| ~PaintLayerScrollableArea() override; |
| void dispose(); |
| |
| bool hasHorizontalScrollbar() const { return horizontalScrollbar(); } |
| bool hasVerticalScrollbar() const { return verticalScrollbar(); } |
| |
| Scrollbar* horizontalScrollbar() const override { |
| return m_scrollbarManager.horizontalScrollbar(); |
| } |
| Scrollbar* verticalScrollbar() const override { |
| return m_scrollbarManager.verticalScrollbar(); |
| } |
| |
| HostWindow* getHostWindow() const override; |
| |
| // For composited scrolling, we allocate an extra GraphicsLayer to hold |
| // onto the scrolling content. The layer can be shifted on the GPU and |
| // composited at little cost. |
| // Note that this is done in CompositedLayerMapping, this function being |
| // only a helper. |
| GraphicsLayer* layerForScrolling() const override; |
| |
| // GraphicsLayers for the scrolling components. |
| // |
| // Any function can return nullptr if they are not accelerated. |
| GraphicsLayer* layerForHorizontalScrollbar() const override; |
| GraphicsLayer* layerForVerticalScrollbar() const override; |
| GraphicsLayer* layerForScrollCorner() const override; |
| |
| bool usesCompositedScrolling() const override; |
| bool shouldScrollOnMainThread() const override; |
| bool shouldUseIntegerScrollOffset() const override; |
| bool isActive() const override; |
| bool isScrollCornerVisible() const override; |
| IntRect scrollCornerRect() const override; |
| IntRect convertFromScrollbarToContainingWidget(const Scrollbar&, |
| const IntRect&) const override; |
| IntRect convertFromContainingWidgetToScrollbar(const Scrollbar&, |
| const IntRect&) const override; |
| IntPoint convertFromScrollbarToContainingWidget( |
| const Scrollbar&, |
| const IntPoint&) const override; |
| IntPoint convertFromContainingWidgetToScrollbar( |
| const Scrollbar&, |
| const IntPoint&) const override; |
| int scrollSize(ScrollbarOrientation) const override; |
| IntPoint scrollPosition() const override; |
| DoublePoint scrollPositionDouble() const override; |
| IntPoint minimumScrollPosition() const override; |
| IntPoint maximumScrollPosition() const override; |
| IntRect visibleContentRect( |
| IncludeScrollbarsInRect = ExcludeScrollbars) const override; |
| int visibleHeight() const override; |
| int visibleWidth() const override; |
| IntSize contentsSize() const override; |
| IntPoint lastKnownMousePosition() const override; |
| bool scrollAnimatorEnabled() const override; |
| bool shouldSuspendScrollAnimations() const override; |
| bool scrollbarsCanBeActive() const override; |
| void scrollbarVisibilityChanged() override; |
| IntRect scrollableAreaBoundingBox() const override; |
| void registerForAnimation() override; |
| void deregisterForAnimation() override; |
| bool userInputScrollable(ScrollbarOrientation) const override; |
| bool shouldPlaceVerticalScrollbarOnLeft() const override; |
| int pageStep(ScrollbarOrientation) const override; |
| ScrollBehavior scrollBehaviorStyle() const override; |
| CompositorAnimationTimeline* compositorAnimationTimeline() const override; |
| |
| DoubleSize scrollOffset() const { return m_scrollOffset; } |
| |
| // FIXME: We shouldn't allow access to m_overflowRect outside this class. |
| LayoutRect overflowRect() const { return m_overflowRect; } |
| |
| void scrollToOffset(const DoubleSize& scrollOffset, |
| ScrollBehavior scrollBehavior = ScrollBehaviorInstant, |
| ScrollType scrollType = ProgrammaticScroll) { |
| ScrollableArea::setScrollPosition(-scrollOrigin() + scrollOffset, |
| scrollType, scrollBehavior); |
| } |
| |
| void setScrollPosition( |
| const DoublePoint& position, |
| ScrollType scrollType, |
| ScrollBehavior scrollBehavior = ScrollBehaviorInstant) override { |
| scrollToOffset(toDoubleSize(position), scrollBehavior, scrollType); |
| } |
| |
| // This will set the scroll position without clamping, and it will do all |
| // post-update work even if the scroll position didn't change. |
| void setScrollPositionUnconditionally(const DoublePoint&, |
| ScrollType = ProgrammaticScroll); |
| |
| // TODO(szager): Actually run these after all of layout is finished. |
| // Currently, they run at the end of box()'es layout (or after all flexbox |
| // layout has finished) but while document layout is still happening. |
| void updateAfterLayout(); |
| void clampScrollPositionsAfterLayout(); |
| |
| void updateAfterStyleChange(const ComputedStyle*); |
| void updateAfterOverflowRecalc(); |
| |
| bool updateAfterCompositingChange() override; |
| |
| bool hasScrollbar() const { |
| return hasHorizontalScrollbar() || hasVerticalScrollbar(); |
| } |
| bool hasOverflowControls() const { |
| return hasScrollbar() || scrollCorner() || resizer(); |
| } |
| |
| LayoutScrollbarPart* scrollCorner() const override { return m_scrollCorner; } |
| |
| void resize(const PlatformEvent&, const LayoutSize&); |
| IntSize offsetFromResizeCorner(const IntPoint& absolutePoint) const; |
| |
| bool inResizeMode() const { return m_inResizeMode; } |
| void setInResizeMode(bool inResizeMode) { m_inResizeMode = inResizeMode; } |
| |
| IntRect touchResizerCornerRect(const IntRect& bounds) const { |
| return resizerCornerRect(bounds, ResizerForTouch); |
| } |
| |
| LayoutUnit scrollWidth() const; |
| LayoutUnit scrollHeight() const; |
| int pixelSnappedScrollWidth() const; |
| int pixelSnappedScrollHeight() const; |
| |
| int verticalScrollbarWidth( |
| OverlayScrollbarClipBehavior = IgnoreOverlayScrollbarSize) const; |
| int horizontalScrollbarHeight( |
| OverlayScrollbarClipBehavior = IgnoreOverlayScrollbarSize) const; |
| |
| DoubleSize adjustedScrollOffset() const { |
| return toDoubleSize(DoublePoint(scrollOrigin()) + m_scrollOffset); |
| } |
| |
| void positionOverflowControls(); |
| |
| // isPointInResizeControl() is used for testing if a pointer/touch position is |
| // in the resize control area. |
| bool isPointInResizeControl(const IntPoint& absolutePoint, |
| ResizerHitTestType) const; |
| bool hitTestOverflowControls(HitTestResult&, const IntPoint& localPoint); |
| |
| bool hitTestResizerInFragments(const PaintLayerFragments&, |
| const HitTestLocation&) const; |
| |
| // Returns the new position, after scrolling, of the given rect in absolute |
| // coordinates, clipped by the parent's client rect. |
| LayoutRect scrollIntoView(const LayoutRect&, |
| const ScrollAlignment& alignX, |
| const ScrollAlignment& alignY, |
| ScrollType = ProgrammaticScroll) override; |
| |
| // Returns true if scrollable area is in the FrameView's collection of |
| // scrollable areas. This can only happen if we're scrollable, visible to hit |
| // test, and do in fact overflow. This means that 'overflow: hidden' or |
| // 'pointer-events: none' layers never get added to the FrameView's |
| // collection. |
| bool scrollsOverflow() const { return m_scrollsOverflow; } |
| |
| // Rectangle encompassing the scroll corner and resizer rect. |
| IntRect scrollCornerAndResizerRect() const final; |
| |
| enum LCDTextMode { ConsiderLCDText, IgnoreLCDText }; |
| |
| void updateNeedsCompositedScrolling(LCDTextMode = ConsiderLCDText); |
| bool needsCompositedScrolling() const { return m_needsCompositedScrolling; } |
| |
| // These are used during compositing updates to determine if the overflow |
| // controls need to be repositioned in the GraphicsLayer tree. |
| void setTopmostScrollChild(PaintLayer*); |
| PaintLayer* topmostScrollChild() const { |
| ASSERT(!m_nextTopmostScrollChild); |
| return m_topmostScrollChild; |
| } |
| |
| IntRect resizerCornerRect(const IntRect&, ResizerHitTestType) const; |
| |
| // TODO(ymalik): Remove box() and update callers to use layoutBox() instead. |
| LayoutBox& box() const; |
| PaintLayer* layer() const; |
| |
| LayoutScrollbarPart* resizer() const override { return m_resizer; } |
| |
| const IntPoint& cachedOverlayScrollbarOffset() { |
| return m_cachedOverlayScrollbarOffset; |
| } |
| void setCachedOverlayScrollbarOffset(const IntPoint& offset) { |
| m_cachedOverlayScrollbarOffset = offset; |
| } |
| |
| IntRect rectForHorizontalScrollbar(const IntRect& borderBoxRect) const; |
| IntRect rectForVerticalScrollbar(const IntRect& borderBoxRect) const; |
| |
| Widget* getWidget() override; |
| bool shouldPerformScrollAnchoring() const override; |
| ScrollAnchor* scrollAnchor() override { return &m_scrollAnchor; } |
| bool isPaintLayerScrollableArea() const override { return true; } |
| |
| LayoutBox* layoutBox() const override { return &box(); } |
| |
| bool shouldRebuildHorizontalScrollbarLayer() const { |
| return m_rebuildHorizontalScrollbarLayer; |
| } |
| bool shouldRebuildVerticalScrollbarLayer() const { |
| return m_rebuildVerticalScrollbarLayer; |
| } |
| void resetRebuildScrollbarLayerFlags(); |
| |
| // Did DelayScrollPositionClampScope prevent us from running |
| // clampScrollPositionsAfterLayout() |
| // in updateAfterLayout()? |
| bool needsScrollPositionClamp() const { return m_needsScrollPositionClamp; } |
| void setNeedsScrollPositionClamp(bool val) { |
| m_needsScrollPositionClamp = val; |
| } |
| |
| // Did PreventRelayoutScope prevent us from running re-layout due to |
| // adding/subtracting scrollbars in updateAfterLayout()? |
| bool needsRelayout() const { return m_needsRelayout; } |
| void setNeedsRelayout(bool val) { m_needsRelayout = val; } |
| |
| // Were we laid out with a horizontal scrollbar at the time we were marked as |
| // needing relayout by PreventRelayoutScope? |
| bool hadHorizontalScrollbarBeforeRelayout() const { |
| return m_hadHorizontalScrollbarBeforeRelayout; |
| } |
| void setHadHorizontalScrollbarBeforeRelayout(bool val) { |
| m_hadHorizontalScrollbarBeforeRelayout = val; |
| } |
| |
| // Were we laid out with a vertical scrollbar at the time we were marked as |
| // needing relayout by PreventRelayoutScope? |
| bool hadVerticalScrollbarBeforeRelayout() const { |
| return m_hadVerticalScrollbarBeforeRelayout; |
| } |
| void setHadVerticalScrollbarBeforeRelayout(bool val) { |
| m_hadVerticalScrollbarBeforeRelayout = val; |
| } |
| |
| StickyConstraintsMap& stickyConstraintsMap() { |
| return ensureRareData().m_stickyConstraintsMap; |
| } |
| void invalidateAllStickyConstraints(); |
| void invalidateStickyConstraintsFor(PaintLayer*, |
| bool needsCompositingUpdate = true); |
| |
| uint64_t id() const; |
| |
| DECLARE_VIRTUAL_TRACE(); |
| |
| private: |
| explicit PaintLayerScrollableArea(PaintLayer&); |
| |
| bool hasHorizontalOverflow() const; |
| bool hasVerticalOverflow() const; |
| bool hasScrollableHorizontalOverflow() const; |
| bool hasScrollableVerticalOverflow() const; |
| bool visualViewportSuppliesScrollbars() const; |
| |
| bool needsScrollbarReconstruction() const; |
| |
| void updateScrollOrigin(); |
| void updateScrollDimensions(); |
| |
| void setScrollOffset(const DoublePoint&, ScrollType) override; |
| |
| int verticalScrollbarStart(int minX, int maxX) const; |
| int horizontalScrollbarStart(int minX) const; |
| IntSize scrollbarOffset(const Scrollbar&) const; |
| |
| void setHasHorizontalScrollbar(bool hasScrollbar); |
| void setHasVerticalScrollbar(bool hasScrollbar); |
| |
| void updateScrollCornerStyle(); |
| |
| // See comments on isPointInResizeControl. |
| void updateResizerAreaSet(); |
| void updateResizerStyle(); |
| |
| void updateScrollableAreaSet(bool hasOverflow); |
| |
| void updateCompositingLayersAfterScroll(); |
| |
| PaintLayerScrollableAreaRareData* rareData() { return m_rareData.get(); } |
| |
| PaintLayerScrollableAreaRareData& ensureRareData() { |
| if (!m_rareData) |
| m_rareData = wrapUnique(new PaintLayerScrollableAreaRareData()); |
| return *m_rareData.get(); |
| } |
| |
| PaintLayer& m_layer; |
| |
| PaintLayer* m_nextTopmostScrollChild; |
| PaintLayer* m_topmostScrollChild; |
| |
| // Keeps track of whether the layer is currently resizing, so events can cause |
| // resizing to start and stop. |
| unsigned m_inResizeMode : 1; |
| unsigned m_scrollsOverflow : 1; |
| |
| unsigned m_inOverflowRelayout : 1; |
| |
| // FIXME: once cc can handle composited scrolling with clip paths, we will |
| // no longer need this bit. |
| unsigned m_needsCompositedScrolling : 1; |
| |
| // Set to indicate that a scrollbar layer, if present, needs to be rebuilt |
| // in the next compositing update because the underlying blink::Scrollbar |
| // instance has been reconstructed. |
| unsigned m_rebuildHorizontalScrollbarLayer : 1; |
| unsigned m_rebuildVerticalScrollbarLayer : 1; |
| |
| unsigned m_needsScrollPositionClamp : 1; |
| unsigned m_needsRelayout : 1; |
| unsigned m_hadHorizontalScrollbarBeforeRelayout : 1; |
| unsigned m_hadVerticalScrollbarBeforeRelayout : 1; |
| |
| // The width/height of our scrolled area. |
| // This is OverflowModel's layout overflow translated to physical |
| // coordinates. See OverflowModel for the different overflow and |
| // LayoutBoxModelObject for the coordinate systems. |
| LayoutRect m_overflowRect; |
| |
| // ScrollbarManager holds the Scrollbar instances. |
| ScrollbarManager m_scrollbarManager; |
| |
| // This is the (scroll) offset from scrollOrigin(). |
| DoubleSize m_scrollOffset; |
| |
| IntPoint m_cachedOverlayScrollbarOffset; |
| |
| // LayoutObject to hold our custom scroll corner. |
| LayoutScrollbarPart* m_scrollCorner; |
| |
| // LayoutObject to hold our custom resizer. |
| LayoutScrollbarPart* m_resizer; |
| |
| ScrollAnchor m_scrollAnchor; |
| |
| std::unique_ptr<PaintLayerScrollableAreaRareData> m_rareData; |
| |
| #if ENABLE(ASSERT) |
| bool m_hasBeenDisposed; |
| #endif |
| }; |
| |
| DEFINE_TYPE_CASTS(PaintLayerScrollableArea, |
| ScrollableArea, |
| scrollableArea, |
| scrollableArea->isPaintLayerScrollableArea(), |
| scrollableArea.isPaintLayerScrollableArea()); |
| |
| } // namespace blink |
| |
| #endif // LayerScrollableArea_h |