| 1 | /* |
| 2 | * Copyright (C) 2004-2018 Apple Inc. All rights reserved. |
| 3 | * Copyright (C) 2009 Holger Hans Peter Freyther |
| 4 | * |
| 5 | * Redistribution and use in source and binary forms, with or without |
| 6 | * modification, are permitted provided that the following conditions |
| 7 | * are met: |
| 8 | * 1. Redistributions of source code must retain the above copyright |
| 9 | * notice, this list of conditions and the following disclaimer. |
| 10 | * 2. Redistributions in binary form must reproduce the above copyright |
| 11 | * notice, this list of conditions and the following disclaimer in the |
| 12 | * documentation and/or other materials provided with the distribution. |
| 13 | * |
| 14 | * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY |
| 15 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| 16 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
| 17 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR |
| 18 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
| 19 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
| 20 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
| 21 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY |
| 22 | * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 24 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 25 | */ |
| 26 | |
| 27 | #pragma once |
| 28 | |
| 29 | #include "FloatRect.h" |
| 30 | #include "IntRect.h" |
| 31 | #include "Scrollbar.h" |
| 32 | #include "ScrollableArea.h" |
| 33 | #include "ScrollTypes.h" |
| 34 | #include "Widget.h" |
| 35 | #include <wtf/HashSet.h> |
| 36 | #include <wtf/WeakPtr.h> |
| 37 | |
| 38 | #if PLATFORM(IOS_FAMILY) |
| 39 | |
| 40 | OBJC_CLASS WAKScrollView; |
| 41 | OBJC_CLASS WAKView; |
| 42 | |
| 43 | #ifndef NSScrollView |
| 44 | #define NSScrollView WAKScrollView |
| 45 | #endif |
| 46 | |
| 47 | #ifndef NSView |
| 48 | #define NSView WAKView |
| 49 | #endif |
| 50 | |
| 51 | #endif // PLATFORM(IOS_FAMILY) |
| 52 | |
| 53 | #if PLATFORM(COCOA) && defined __OBJC__ |
| 54 | @class NSScrollView; |
| 55 | @protocol WebCoreFrameScrollView; |
| 56 | #endif |
| 57 | |
| 58 | namespace WebCore { |
| 59 | |
| 60 | class HostWindow; |
| 61 | class LegacyTileCache; |
| 62 | class Scrollbar; |
| 63 | |
| 64 | class ScrollView : public Widget, public ScrollableArea { |
| 65 | public: |
| 66 | virtual ~ScrollView(); |
| 67 | |
| 68 | // ScrollableArea functions. |
| 69 | int scrollSize(ScrollbarOrientation) const final; |
| 70 | int scrollOffset(ScrollbarOrientation) const final; |
| 71 | WEBCORE_EXPORT void setScrollOffset(const ScrollOffset&) final; |
| 72 | bool isScrollCornerVisible() const final; |
| 73 | void scrollbarStyleChanged(ScrollbarStyle, bool forceUpdate) override; |
| 74 | |
| 75 | virtual void notifyPageThatContentAreaWillPaint() const; |
| 76 | |
| 77 | using Widget::weakPtrFactory; |
| 78 | |
| 79 | IntPoint locationOfContents() const; |
| 80 | |
| 81 | // NOTE: This should only be called by the overridden setScrollOffset from ScrollableArea. |
| 82 | virtual void scrollTo(const ScrollPosition&); |
| 83 | |
| 84 | // The window thats hosts the ScrollView. The ScrollView will communicate scrolls and repaints to the |
| 85 | // host window in the window's coordinate space. |
| 86 | virtual HostWindow* hostWindow() const = 0; |
| 87 | |
| 88 | // Returns a clip rect in host window coordinates. Used to clip the blit on a scroll. |
| 89 | virtual IntRect windowClipRect() const = 0; |
| 90 | |
| 91 | // Functions for child manipulation and inspection. |
| 92 | const HashSet<Ref<Widget>>& children() const { return m_children; } |
| 93 | WEBCORE_EXPORT virtual void addChild(Widget&); |
| 94 | WEBCORE_EXPORT virtual void removeChild(Widget&); |
| 95 | |
| 96 | // If the scroll view does not use a native widget, then it will have cross-platform Scrollbars. These functions |
| 97 | // can be used to obtain those scrollbars. |
| 98 | Scrollbar* horizontalScrollbar() const final { return m_horizontalScrollbar.get(); } |
| 99 | Scrollbar* verticalScrollbar() const final { return m_verticalScrollbar.get(); } |
| 100 | bool isScrollViewScrollbar(const Widget* child) const { return horizontalScrollbar() == child || verticalScrollbar() == child; } |
| 101 | |
| 102 | void positionScrollbarLayers(); |
| 103 | |
| 104 | // Functions for setting and retrieving the scrolling mode in each axis (horizontal/vertical). The mode has values of |
| 105 | // AlwaysOff, AlwaysOn, and Auto. AlwaysOff means never show a scrollbar, AlwaysOn means always show a scrollbar. |
| 106 | // Auto means show a scrollbar only when one is needed. |
| 107 | // Note that for platforms with native widgets, these modes are considered advisory. In other words the underlying native |
| 108 | // widget may choose not to honor the requested modes. |
| 109 | WEBCORE_EXPORT void setScrollbarModes(ScrollbarMode horizontalMode, ScrollbarMode verticalMode, bool horizontalLock = false, bool verticalLock = false); |
| 110 | void setHorizontalScrollbarMode(ScrollbarMode mode, bool lock = false) { setScrollbarModes(mode, verticalScrollbarMode(), lock, verticalScrollbarLock()); } |
| 111 | void setVerticalScrollbarMode(ScrollbarMode mode, bool lock = false) { setScrollbarModes(horizontalScrollbarMode(), mode, horizontalScrollbarLock(), lock); }; |
| 112 | WEBCORE_EXPORT void scrollbarModes(ScrollbarMode& horizontalMode, ScrollbarMode& verticalMode) const; |
| 113 | ScrollbarMode horizontalScrollbarMode() const final { ScrollbarMode horizontal, vertical; scrollbarModes(horizontal, vertical); return horizontal; } |
| 114 | ScrollbarMode verticalScrollbarMode() const final { ScrollbarMode horizontal, vertical; scrollbarModes(horizontal, vertical); return vertical; } |
| 115 | |
| 116 | void setHorizontalScrollbarLock(bool lock = true) { m_horizontalScrollbarLock = lock; } |
| 117 | bool horizontalScrollbarLock() const { return m_horizontalScrollbarLock; } |
| 118 | void setVerticalScrollbarLock(bool lock = true) { m_verticalScrollbarLock = lock; } |
| 119 | bool verticalScrollbarLock() const { return m_verticalScrollbarLock; } |
| 120 | |
| 121 | void setScrollingModesLock(bool lock = true) { m_horizontalScrollbarLock = m_verticalScrollbarLock = lock; } |
| 122 | |
| 123 | WEBCORE_EXPORT virtual void setCanHaveScrollbars(bool); |
| 124 | bool canHaveScrollbars() const { return horizontalScrollbarMode() != ScrollbarAlwaysOff || verticalScrollbarMode() != ScrollbarAlwaysOff; } |
| 125 | |
| 126 | virtual bool avoidScrollbarCreation() const { return false; } |
| 127 | |
| 128 | void setScrollbarOverlayStyle(ScrollbarOverlayStyle) final; |
| 129 | |
| 130 | // By default you only receive paint events for the area that is visible. In the case of using a |
| 131 | // tiled backing store, this function can be set, so that the view paints the entire contents. |
| 132 | bool paintsEntireContents() const { return m_paintsEntireContents; } |
| 133 | WEBCORE_EXPORT void setPaintsEntireContents(bool); |
| 134 | |
| 135 | // By default programmatic scrolling is handled by WebCore and not by the UI application. |
| 136 | // In the case of using a tiled backing store, this mode can be set, so that the scroll requests |
| 137 | // are delegated to the UI application. |
| 138 | bool delegatesScrolling() const { return m_delegatesScrolling; } |
| 139 | WEBCORE_EXPORT void setDelegatesScrolling(bool); |
| 140 | |
| 141 | // Overridden by FrameView to create custom CSS scrollbars if applicable. |
| 142 | virtual Ref<Scrollbar> createScrollbar(ScrollbarOrientation); |
| 143 | |
| 144 | void styleDidChange(); |
| 145 | |
| 146 | // If the prohibits scrolling flag is set, then all scrolling in the view (even programmatic scrolling) is turned off. |
| 147 | void setProhibitsScrolling(bool b) { m_prohibitsScrolling = b; } |
| 148 | bool prohibitsScrolling() const { return m_prohibitsScrolling; } |
| 149 | |
| 150 | // Whether or not a scroll view will blit visible contents when it is scrolled. Blitting is disabled in situations |
| 151 | // where it would cause rendering glitches (such as with fixed backgrounds or when the view is partially transparent). |
| 152 | void setCanBlitOnScroll(bool); |
| 153 | bool canBlitOnScroll() const; |
| 154 | |
| 155 | // There are at least three types of contentInset. Usually we just care about WebCoreContentInset, which is the inset |
| 156 | // that is set on a Page that requires WebCore to move its layers to accomodate the inset. However, there are platform |
| 157 | // concepts that are similar on both iOS and Mac when there is a platformWidget(). Sometimes we need the Mac platform value |
| 158 | // for topContentInset, so when the TopContentInsetType is WebCoreOrPlatformContentInset, platformTopContentInset() |
| 159 | // will be returned instead of the value set on Page. |
| 160 | enum class TopContentInsetType { WebCoreContentInset, WebCoreOrPlatformContentInset }; |
| 161 | virtual float topContentInset(TopContentInsetType = TopContentInsetType::WebCoreContentInset) const { return 0; } |
| 162 | |
| 163 | // The visible content rect has a location that is the scrolled offset of the document. The width and height are the unobscured viewport |
| 164 | // width and height. By default the scrollbars themselves are excluded from this rectangle, but an optional boolean argument allows them |
| 165 | // to be included. |
| 166 | // In the situation the client is responsible for the scrolling (ie. with a tiled backing store) it is possible to use |
| 167 | // the setFixedVisibleContentRect instead for the mainframe, though this must be updated manually, e.g just before resuming the page |
| 168 | // which usually will happen when panning, pinching and rotation ends, or when scale or position are changed manually. |
| 169 | IntSize visibleSize() const final { return visibleContentRect(LegacyIOSDocumentVisibleRect).size(); } |
| 170 | |
| 171 | #if USE(COORDINATED_GRAPHICS) |
| 172 | virtual void setFixedVisibleContentRect(const IntRect& visibleContentRect) { m_fixedVisibleContentRect = visibleContentRect; } |
| 173 | IntRect fixedVisibleContentRect() const { return m_fixedVisibleContentRect; } |
| 174 | #endif |
| 175 | |
| 176 | // Parts of the document can be visible through transparent or blured UI widgets of the chrome. Those parts |
| 177 | // contribute to painting but not to the scrollable area. |
| 178 | // The unobscuredContentRect is the area that is not covered by UI elements. |
| 179 | WEBCORE_EXPORT IntRect unobscuredContentRect(VisibleContentRectIncludesScrollbars = ExcludeScrollbars) const; |
| 180 | #if PLATFORM(IOS_FAMILY) |
| 181 | IntRect unobscuredContentRectIncludingScrollbars() const { return unobscuredContentRect(IncludeScrollbars); } |
| 182 | #else |
| 183 | IntRect unobscuredContentRectIncludingScrollbars() const { return visibleContentRectIncludingScrollbars(); } |
| 184 | #endif |
| 185 | |
| 186 | #if PLATFORM(IOS_FAMILY) |
| 187 | // This is the area that is partially or fully exposed, and may extend under overlapping UI elements. |
| 188 | WEBCORE_EXPORT FloatRect exposedContentRect() const; |
| 189 | |
| 190 | // The given rects are only used if there is no platform widget. |
| 191 | WEBCORE_EXPORT void setExposedContentRect(const FloatRect&); |
| 192 | const FloatSize& unobscuredContentSize() const { return m_unobscuredContentSize; } |
| 193 | WEBCORE_EXPORT void setUnobscuredContentSize(const FloatSize&); |
| 194 | |
| 195 | void setActualScrollPosition(const IntPoint&); |
| 196 | LegacyTileCache* legacyTileCache(); |
| 197 | #endif |
| 198 | |
| 199 | // Size available for view contents, including content inset areas. Not affected by zooming. |
| 200 | IntSize sizeForVisibleContent(VisibleContentRectIncludesScrollbars = ExcludeScrollbars) const; |
| 201 | // FIXME: remove this. It's only used for the incorrectly behaving ScrollView::unobscuredContentRectInternal(). |
| 202 | virtual float visibleContentScaleFactor() const { return 1; } |
| 203 | |
| 204 | // Functions for getting/setting the size webkit should use to layout the contents. By default this is the same as the visible |
| 205 | // content size. Explicitly setting a layout size value will cause webkit to layout the contents using this size instead. |
| 206 | WEBCORE_EXPORT IntSize layoutSize() const; |
| 207 | int layoutWidth() const { return layoutSize().width(); } |
| 208 | int layoutHeight() const { return layoutSize().height(); } |
| 209 | |
| 210 | WEBCORE_EXPORT IntSize fixedLayoutSize() const; |
| 211 | WEBCORE_EXPORT void setFixedLayoutSize(const IntSize&); |
| 212 | WEBCORE_EXPORT bool useFixedLayout() const; |
| 213 | WEBCORE_EXPORT void setUseFixedLayout(bool enable); |
| 214 | |
| 215 | // Functions for getting/setting the size of the document contained inside the ScrollView (as an IntSize or as individual width and height |
| 216 | // values). |
| 217 | WEBCORE_EXPORT IntSize contentsSize() const final; // Always at least as big as the visibleWidth()/visibleHeight(). |
| 218 | int contentsWidth() const { return contentsSize().width(); } |
| 219 | int contentsHeight() const { return contentsSize().height(); } |
| 220 | virtual void setContentsSize(const IntSize&); |
| 221 | |
| 222 | // Functions for querying the current scrolled position (both as a point, a size, or as individual X and Y values). |
| 223 | ScrollPosition scrollPosition() const final { return visibleContentRect(LegacyIOSDocumentVisibleRect).location(); } |
| 224 | |
| 225 | ScrollPosition maximumScrollPosition() const override; // The maximum position we can be scrolled to. |
| 226 | |
| 227 | // Adjust the passed in scroll position to keep it between the minimum and maximum positions. |
| 228 | ScrollPosition adjustScrollPositionWithinRange(const ScrollPosition&) const; |
| 229 | int scrollX() const { return scrollPosition().x(); } |
| 230 | int scrollY() const { return scrollPosition().y(); } |
| 231 | |
| 232 | // Scroll position used by web-exposed features (has legacy iOS behavior). |
| 233 | WEBCORE_EXPORT IntPoint contentsScrollPosition() const; |
| 234 | void setContentsScrollPosition(const IntPoint&); |
| 235 | |
| 236 | #if PLATFORM(IOS_FAMILY) |
| 237 | int actualScrollX() const { return unobscuredContentRect().x(); } |
| 238 | int actualScrollY() const { return unobscuredContentRect().y(); } |
| 239 | // FIXME: maybe fix scrollPosition() on iOS to return the actual scroll position. |
| 240 | IntPoint actualScrollPosition() const { return unobscuredContentRect().location(); } |
| 241 | #endif |
| 242 | |
| 243 | // scrollOffset() anchors its (0,0) point at the ScrollableArea's origin. When the Page has a |
| 244 | // header, the header is positioned at (0,0), ABOVE the start of the Document. So when a page with |
| 245 | // a header is pinned to the top, the scrollOffset() is (0,0), but the Document is actually at |
| 246 | // (0, -headerHeight()). documentScrollPositionRelativeToScrollableAreaOrigin() will return this |
| 247 | // version of the offset, which tracks the top of Document relative to where scrolling was achored. |
| 248 | ScrollPosition documentScrollPositionRelativeToScrollableAreaOrigin() const; |
| 249 | |
| 250 | // scrollPostion() anchors its (0,0) point at the ScrollableArea's origin. The top of the scrolling |
| 251 | // layer does not represent the top of the view when there is a topContentInset. Additionally, as |
| 252 | // detailed above, the origin of the scrolling layer also does not necessarily correspond with the |
| 253 | // top of the document anyway, since there could also be header. documentScrollPositionRelativeToViewOrigin() |
| 254 | // will return a version of the current scroll offset which tracks the top of the Document |
| 255 | // relative to the very top of the view. |
| 256 | WEBCORE_EXPORT ScrollPosition documentScrollPositionRelativeToViewOrigin() const; |
| 257 | |
| 258 | IntSize overhangAmount() const final; |
| 259 | |
| 260 | void cacheCurrentScrollPosition() { m_cachedScrollPosition = scrollPosition(); } |
| 261 | ScrollPosition cachedScrollPosition() const { return m_cachedScrollPosition; } |
| 262 | |
| 263 | // Functions for scrolling the view. |
| 264 | virtual void setScrollPosition(const ScrollPosition&); |
| 265 | void scrollBy(const IntSize& s) { return setScrollPosition(scrollPosition() + s); } |
| 266 | |
| 267 | // This function scrolls by lines, pages or pixels. |
| 268 | bool scroll(ScrollDirection, ScrollGranularity); |
| 269 | |
| 270 | // A logical scroll that just ends up calling the corresponding physical scroll() based off the document's writing mode. |
| 271 | bool logicalScroll(ScrollLogicalDirection, ScrollGranularity); |
| 272 | |
| 273 | // Scroll the actual contents of the view (either blitting or invalidating as needed). |
| 274 | void scrollContents(const IntSize& scrollDelta); |
| 275 | |
| 276 | // This gives us a means of blocking painting on our scrollbars until the first layout has occurred. |
| 277 | WEBCORE_EXPORT void (bool suppressed, bool repaintOnUnsuppress = false); |
| 278 | bool () const { return m_scrollbarsSuppressed; } |
| 279 | |
| 280 | WEBCORE_EXPORT IntPoint rootViewToContents(const IntPoint&) const; |
| 281 | WEBCORE_EXPORT IntPoint contentsToRootView(const IntPoint&) const; |
| 282 | WEBCORE_EXPORT FloatPoint contentsToRootView(const FloatPoint&) const; |
| 283 | WEBCORE_EXPORT IntRect rootViewToContents(const IntRect&) const; |
| 284 | WEBCORE_EXPORT IntRect contentsToRootView(const IntRect&) const; |
| 285 | WEBCORE_EXPORT FloatRect rootViewToContents(const FloatRect&) const; |
| 286 | WEBCORE_EXPORT FloatRect contentsToRootView(const FloatRect&) const; |
| 287 | |
| 288 | IntPoint viewToContents(const IntPoint&) const; |
| 289 | IntPoint contentsToView(const IntPoint&) const; |
| 290 | |
| 291 | FloatPoint viewToContents(const FloatPoint&) const; |
| 292 | FloatPoint contentsToView(const FloatPoint&) const; |
| 293 | |
| 294 | IntRect viewToContents(IntRect) const; |
| 295 | IntRect contentsToView(IntRect) const; |
| 296 | |
| 297 | FloatRect viewToContents(FloatRect) const; |
| 298 | FloatRect contentsToView(FloatRect) const; |
| 299 | |
| 300 | IntPoint contentsToContainingViewContents(const IntPoint&) const; |
| 301 | IntRect contentsToContainingViewContents(IntRect) const; |
| 302 | |
| 303 | WEBCORE_EXPORT IntPoint rootViewToTotalContents(const IntPoint&) const; |
| 304 | |
| 305 | // Event coordinates are assumed to be in the coordinate space of a window that contains |
| 306 | // the entire widget hierarchy. It is up to the platform to decide what the precise definition |
| 307 | // of containing window is. (For example on Mac it is the containing NSWindow.) |
| 308 | WEBCORE_EXPORT IntPoint windowToContents(const IntPoint&) const; |
| 309 | WEBCORE_EXPORT IntPoint contentsToWindow(const IntPoint&) const; |
| 310 | WEBCORE_EXPORT IntRect windowToContents(const IntRect&) const; |
| 311 | WEBCORE_EXPORT IntRect contentsToWindow(const IntRect&) const; |
| 312 | |
| 313 | // Functions for converting to and from screen coordinates. |
| 314 | WEBCORE_EXPORT IntRect contentsToScreen(const IntRect&) const; |
| 315 | IntPoint screenToContents(const IntPoint&) const; |
| 316 | |
| 317 | // The purpose of this function is to answer whether or not the scroll view is currently visible. Animations and painting updates can be suspended if |
| 318 | // we know that we are either not in a window right now or if that window is not visible. |
| 319 | bool isOffscreen() const; |
| 320 | |
| 321 | // Called when our frame rect changes (or the rect/scroll position of an ancestor changes). |
| 322 | void frameRectsChanged() final; |
| 323 | |
| 324 | // Widget override to update our scrollbars and notify our contents of the resize. |
| 325 | void setFrameRect(const IntRect&) override; |
| 326 | |
| 327 | // Widget override to notify our contents of a cliprect change. |
| 328 | void clipRectChanged() final; |
| 329 | |
| 330 | // For platforms that need to hit test scrollbars from within the engine's event handlers (like Win32). |
| 331 | Scrollbar* scrollbarAtPoint(const IntPoint& windowPoint); |
| 332 | |
| 333 | IntPoint convertChildToSelf(const Widget* child, const IntPoint& point) const |
| 334 | { |
| 335 | IntPoint newPoint = point; |
| 336 | if (!isScrollViewScrollbar(child)) |
| 337 | newPoint = point - toIntSize(scrollPosition()); |
| 338 | newPoint.moveBy(child->location()); |
| 339 | return newPoint; |
| 340 | } |
| 341 | |
| 342 | IntPoint convertSelfToChild(const Widget* child, const IntPoint& point) const |
| 343 | { |
| 344 | IntPoint newPoint = point; |
| 345 | if (!isScrollViewScrollbar(child)) |
| 346 | newPoint = point + toIntSize(scrollPosition()); |
| 347 | newPoint.moveBy(-child->location()); |
| 348 | return newPoint; |
| 349 | } |
| 350 | |
| 351 | // Widget override. Handles painting of the contents of the view as well as the scrollbars. |
| 352 | WEBCORE_EXPORT void paint(GraphicsContext&, const IntRect&, Widget::SecurityOriginPaintPolicy = SecurityOriginPaintPolicy::AnyOrigin) final; |
| 353 | void paintScrollbars(GraphicsContext&, const IntRect&); |
| 354 | |
| 355 | // Widget overrides to ensure that our children's visibility status is kept up to date when we get shown and hidden. |
| 356 | WEBCORE_EXPORT void show() override; |
| 357 | WEBCORE_EXPORT void hide() override; |
| 358 | WEBCORE_EXPORT void setParentVisible(bool) final; |
| 359 | |
| 360 | // Pan scrolling. |
| 361 | static const int noPanScrollRadius = 15; |
| 362 | void addPanScrollIcon(const IntPoint&); |
| 363 | void removePanScrollIcon(); |
| 364 | void paintPanScrollIcon(GraphicsContext&); |
| 365 | |
| 366 | bool isPointInScrollbarCorner(const IntPoint&); |
| 367 | bool scrollbarCornerPresent() const; |
| 368 | IntRect scrollCornerRect() const final; |
| 369 | virtual void paintScrollCorner(GraphicsContext&, const IntRect& cornerRect); |
| 370 | virtual void paintScrollbar(GraphicsContext&, Scrollbar&, const IntRect&); |
| 371 | |
| 372 | IntRect convertFromScrollbarToContainingView(const Scrollbar&, const IntRect&) const final; |
| 373 | IntRect convertFromContainingViewToScrollbar(const Scrollbar&, const IntRect&) const final; |
| 374 | IntPoint convertFromScrollbarToContainingView(const Scrollbar&, const IntPoint&) const final; |
| 375 | IntPoint convertFromContainingViewToScrollbar(const Scrollbar&, const IntPoint&) const final; |
| 376 | |
| 377 | void calculateAndPaintOverhangAreas(GraphicsContext&, const IntRect& dirtyRect); |
| 378 | |
| 379 | WEBCORE_EXPORT void scrollOffsetChangedViaPlatformWidget(const ScrollOffset& oldOffset, const ScrollOffset& newOffset); |
| 380 | |
| 381 | void setAllowsUnclampedScrollPositionForTesting(bool allowsUnclampedScrollPosition) { m_allowsUnclampedScrollPosition = allowsUnclampedScrollPosition; } |
| 382 | bool allowsUnclampedScrollPosition() const { return m_allowsUnclampedScrollPosition; } |
| 383 | |
| 384 | bool managesScrollbars() const; |
| 385 | |
| 386 | protected: |
| 387 | ScrollView(); |
| 388 | |
| 389 | virtual void repaintContentRectangle(const IntRect&); |
| 390 | virtual void paintContents(GraphicsContext&, const IntRect& damageRect, SecurityOriginPaintPolicy = SecurityOriginPaintPolicy::AnyOrigin) = 0; |
| 391 | |
| 392 | virtual void paintOverhangAreas(GraphicsContext&, const IntRect& horizontalOverhangArea, const IntRect& verticalOverhangArea, const IntRect& dirtyRect); |
| 393 | |
| 394 | void availableContentSizeChanged(AvailableSizeChangeReason) override; |
| 395 | virtual void addedOrRemovedScrollbar() = 0; |
| 396 | virtual void delegatesScrollingDidChange() = 0; |
| 397 | |
| 398 | // These functions are used to create/destroy scrollbars. |
| 399 | // They return true if the scrollbar was added or removed. |
| 400 | bool setHasHorizontalScrollbar(bool, bool* contentSizeAffected = nullptr); |
| 401 | bool setHasVerticalScrollbar(bool, bool* contentSizeAffected = nullptr); |
| 402 | |
| 403 | virtual void updateScrollCorner() = 0; |
| 404 | void invalidateScrollCornerRect(const IntRect&) final; |
| 405 | |
| 406 | // Scroll the content by blitting the pixels. |
| 407 | virtual bool scrollContentsFastPath(const IntSize& scrollDelta, const IntRect& rectToScroll, const IntRect& clipRect) = 0; |
| 408 | // Scroll the content by invalidating everything. |
| 409 | virtual void scrollContentsSlowPath(const IntRect& updateRect); |
| 410 | |
| 411 | void setScrollOrigin(const IntPoint&, bool updatePositionAtAll, bool updatePositionSynchronously); |
| 412 | |
| 413 | // Subclassed by FrameView to check the writing-mode of the document. |
| 414 | virtual bool isVerticalDocument() const = 0; |
| 415 | virtual bool isFlippedDocument() const = 0; |
| 416 | |
| 417 | // Called to update the scrollbars to accurately reflect the state of the view. |
| 418 | void updateScrollbars(const ScrollPosition& desiredPosition); |
| 419 | |
| 420 | float platformTopContentInset() const; |
| 421 | void platformSetTopContentInset(float); |
| 422 | |
| 423 | void handleDeferredScrollUpdateAfterContentSizeChange(); |
| 424 | |
| 425 | virtual bool shouldDeferScrollUpdateAfterContentSizeChange() = 0; |
| 426 | |
| 427 | virtual void scrollOffsetChangedViaPlatformWidgetImpl(const ScrollOffset&, const ScrollOffset&) = 0; |
| 428 | |
| 429 | #if PLATFORM(IOS_FAMILY) |
| 430 | virtual void unobscuredContentSizeChanged() = 0; |
| 431 | #endif |
| 432 | |
| 433 | #if PLATFORM(COCOA) && defined __OBJC__ |
| 434 | public: |
| 435 | WEBCORE_EXPORT NSView* documentView() const; |
| 436 | |
| 437 | private: |
| 438 | NSScrollView<WebCoreFrameScrollView>* scrollView() const; |
| 439 | #endif |
| 440 | |
| 441 | private: |
| 442 | // Size available for view contents, excluding content insets. Not affected by zooming. |
| 443 | IntSize sizeForUnobscuredContent(VisibleContentRectIncludesScrollbars = ExcludeScrollbars) const; |
| 444 | |
| 445 | IntRect visibleContentRectInternal(VisibleContentRectIncludesScrollbars, VisibleContentRectBehavior) const final; |
| 446 | WEBCORE_EXPORT IntRect unobscuredContentRectInternal(VisibleContentRectIncludesScrollbars = ExcludeScrollbars) const; |
| 447 | |
| 448 | void completeUpdatesAfterScrollTo(const IntSize& scrollDelta); |
| 449 | |
| 450 | bool setHasScrollbarInternal(RefPtr<Scrollbar>&, ScrollbarOrientation, bool hasBar, bool* contentSizeAffected); |
| 451 | |
| 452 | bool isScrollView() const final { return true; } |
| 453 | |
| 454 | void init(); |
| 455 | void destroy(); |
| 456 | |
| 457 | IntRect rectToCopyOnScroll() const; |
| 458 | |
| 459 | // Called when the scroll position within this view changes. FrameView overrides this to generate repaint invalidations. |
| 460 | virtual void updateLayerPositionsAfterScrolling() = 0; |
| 461 | virtual void updateCompositingLayersAfterScrolling() = 0; |
| 462 | |
| 463 | void platformAddChild(Widget*); |
| 464 | void platformRemoveChild(Widget*); |
| 465 | void platformSetScrollbarModes(); |
| 466 | void platformScrollbarModes(ScrollbarMode& horizontal, ScrollbarMode& vertical) const; |
| 467 | void platformSetCanBlitOnScroll(bool); |
| 468 | bool platformCanBlitOnScroll() const; |
| 469 | IntRect platformVisibleContentRect(bool includeScrollbars) const; |
| 470 | IntSize platformVisibleContentSize(bool includeScrollbars) const; |
| 471 | IntRect platformVisibleContentRectIncludingObscuredArea(bool includeScrollbars) const; |
| 472 | IntSize platformVisibleContentSizeIncludingObscuredArea(bool includeScrollbars) const; |
| 473 | void platformSetContentsSize(); |
| 474 | IntRect platformContentsToScreen(const IntRect&) const; |
| 475 | IntPoint platformScreenToContents(const IntPoint&) const; |
| 476 | void platformSetScrollPosition(const IntPoint&); |
| 477 | bool platformScroll(ScrollDirection, ScrollGranularity); |
| 478 | void (bool repaintOnUnsuppress); |
| 479 | void platformRepaintContentRectangle(const IntRect&); |
| 480 | bool platformIsOffscreen() const; |
| 481 | void platformSetScrollbarOverlayStyle(ScrollbarOverlayStyle); |
| 482 | void platformSetScrollOrigin(const IntPoint&, bool updatePositionAtAll, bool updatePositionSynchronously); |
| 483 | |
| 484 | void calculateOverhangAreasForPainting(IntRect& horizontalOverhangRect, IntRect& verticalOverhangRect); |
| 485 | void updateOverhangAreas(); |
| 486 | |
| 487 | HashSet<Ref<Widget>> m_children; |
| 488 | |
| 489 | RefPtr<Scrollbar> m_horizontalScrollbar; |
| 490 | RefPtr<Scrollbar> m_verticalScrollbar; |
| 491 | ScrollbarMode m_horizontalScrollbarMode { ScrollbarAuto }; |
| 492 | ScrollbarMode m_verticalScrollbarMode { ScrollbarAuto }; |
| 493 | |
| 494 | #if PLATFORM(IOS_FAMILY) |
| 495 | // FIXME: exposedContentRect is a very similar concept to fixedVisibleContentRect except it does not differentiate |
| 496 | // between exposed and unobscured areas. The two attributes should eventually be merged. |
| 497 | FloatRect m_exposedContentRect; |
| 498 | FloatSize m_unobscuredContentSize; |
| 499 | // This is only used for history scroll position restoration. |
| 500 | #else |
| 501 | IntRect m_fixedVisibleContentRect; |
| 502 | #endif |
| 503 | ScrollPosition m_scrollPosition; |
| 504 | IntPoint m_cachedScrollPosition; |
| 505 | IntSize m_fixedLayoutSize; |
| 506 | IntSize m_contentsSize; |
| 507 | |
| 508 | Optional<IntSize> m_deferredScrollDelta; // Needed for WebKit scrolling |
| 509 | Optional<std::pair<ScrollOffset, ScrollOffset>> m_deferredScrollOffsets; // Needed for platform widget scrolling |
| 510 | |
| 511 | IntPoint m_panScrollIconPoint; |
| 512 | |
| 513 | unsigned m_updateScrollbarsPass { 0 }; |
| 514 | |
| 515 | bool m_horizontalScrollbarLock { false }; |
| 516 | bool m_verticalScrollbarLock { false }; |
| 517 | |
| 518 | bool m_prohibitsScrolling { false }; |
| 519 | bool m_allowsUnclampedScrollPosition { false }; |
| 520 | |
| 521 | // This bool is unused on Mac OS because we directly ask the platform widget |
| 522 | // whether it is safe to blit on scroll. |
| 523 | bool m_canBlitOnScroll { true }; |
| 524 | |
| 525 | bool { false }; |
| 526 | bool m_inUpdateScrollbars { false }; |
| 527 | |
| 528 | bool m_drawPanScrollIcon { false }; |
| 529 | bool m_useFixedLayout { false }; |
| 530 | |
| 531 | bool m_paintsEntireContents { false }; |
| 532 | bool m_delegatesScrolling { false }; |
| 533 | }; // class ScrollView |
| 534 | |
| 535 | } // namespace WebCore |
| 536 | |
| 537 | SPECIALIZE_TYPE_TRAITS_WIDGET(ScrollView, isScrollView()) |
| 538 | |