| OLD | NEW | 
|---|
|  | (Empty) | 
| 1 /* |  | 
| 2  * Copyright (c) 2010, Google Inc. All rights reserved. |  | 
| 3  * Copyright (C) 2008, 2011 Apple Inc. All Rights Reserved. |  | 
| 4  * |  | 
| 5  * Redistribution and use in source and binary forms, with or without |  | 
| 6  * modification, are permitted provided that the following conditions are |  | 
| 7  * met: |  | 
| 8  * |  | 
| 9  *     * Redistributions of source code must retain the above copyright |  | 
| 10  * notice, this list of conditions and the following disclaimer. |  | 
| 11  *     * Redistributions in binary form must reproduce the above |  | 
| 12  * copyright notice, this list of conditions and the following disclaimer |  | 
| 13  * in the documentation and/or other materials provided with the |  | 
| 14  * distribution. |  | 
| 15  *     * Neither the name of Google Inc. nor the names of its |  | 
| 16  * contributors may be used to endorse or promote products derived from |  | 
| 17  * this software without specific prior written permission. |  | 
| 18  * |  | 
| 19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |  | 
| 20  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |  | 
| 21  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |  | 
| 22  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |  | 
| 23  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |  | 
| 24  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |  | 
| 25  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |  | 
| 26  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |  | 
| 27  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |  | 
| 28  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |  | 
| 29  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |  | 
| 30  */ |  | 
| 31 |  | 
| 32 #include "config.h" |  | 
| 33 #include "core/platform/ScrollableArea.h" |  | 
| 34 |  | 
| 35 #include "core/platform/ScrollAnimator.h" |  | 
| 36 #include "core/platform/ScrollbarTheme.h" |  | 
| 37 #include "core/platform/graphics/GraphicsLayer.h" |  | 
| 38 #include "platform/geometry/FloatPoint.h" |  | 
| 39 #include "wtf/PassOwnPtr.h" |  | 
| 40 |  | 
| 41 #include "platform/TraceEvent.h" |  | 
| 42 |  | 
| 43 static const int kPixelsPerLineStep = 40; |  | 
| 44 static const float kMinFractionToStepWhenPaging = 0.875f; |  | 
| 45 |  | 
| 46 namespace WebCore { |  | 
| 47 |  | 
| 48 struct SameSizeAsScrollableArea { |  | 
| 49     virtual ~SameSizeAsScrollableArea(); |  | 
| 50     void* pointer; |  | 
| 51     unsigned bitfields : 16; |  | 
| 52     IntPoint origin; |  | 
| 53 }; |  | 
| 54 |  | 
| 55 COMPILE_ASSERT(sizeof(ScrollableArea) == sizeof(SameSizeAsScrollableArea), Scrol
     lableArea_should_stay_small); |  | 
| 56 |  | 
| 57 int ScrollableArea::pixelsPerLineStep() |  | 
| 58 { |  | 
| 59     return kPixelsPerLineStep; |  | 
| 60 } |  | 
| 61 |  | 
| 62 float ScrollableArea::minFractionToStepWhenPaging() |  | 
| 63 { |  | 
| 64     return kMinFractionToStepWhenPaging; |  | 
| 65 } |  | 
| 66 |  | 
| 67 int ScrollableArea::maxOverlapBetweenPages() |  | 
| 68 { |  | 
| 69     static int maxOverlapBetweenPages = ScrollbarTheme::theme()->maxOverlapBetwe
     enPages(); |  | 
| 70     return maxOverlapBetweenPages; |  | 
| 71 } |  | 
| 72 |  | 
| 73 ScrollableArea::ScrollableArea() |  | 
| 74     : m_constrainsScrollingToContentEdge(true) |  | 
| 75     , m_inLiveResize(false) |  | 
| 76     , m_verticalScrollElasticity(ScrollElasticityNone) |  | 
| 77     , m_horizontalScrollElasticity(ScrollElasticityNone) |  | 
| 78     , m_scrollbarOverlayStyle(ScrollbarOverlayStyleDefault) |  | 
| 79     , m_scrollOriginChanged(false) |  | 
| 80 { |  | 
| 81 } |  | 
| 82 |  | 
| 83 ScrollableArea::~ScrollableArea() |  | 
| 84 { |  | 
| 85 } |  | 
| 86 |  | 
| 87 ScrollAnimator* ScrollableArea::scrollAnimator() const |  | 
| 88 { |  | 
| 89     if (!m_scrollAnimator) |  | 
| 90         m_scrollAnimator = ScrollAnimator::create(const_cast<ScrollableArea*>(th
     is)); |  | 
| 91 |  | 
| 92     return m_scrollAnimator.get(); |  | 
| 93 } |  | 
| 94 |  | 
| 95 void ScrollableArea::setScrollOrigin(const IntPoint& origin) |  | 
| 96 { |  | 
| 97     if (m_scrollOrigin != origin) { |  | 
| 98         m_scrollOrigin = origin; |  | 
| 99         m_scrollOriginChanged = true; |  | 
| 100     } |  | 
| 101 } |  | 
| 102 |  | 
| 103 bool ScrollableArea::scroll(ScrollDirection direction, ScrollGranularity granula
     rity, float multiplier) |  | 
| 104 { |  | 
| 105     ScrollbarOrientation orientation; |  | 
| 106 |  | 
| 107     if (direction == ScrollUp || direction == ScrollDown) |  | 
| 108         orientation = VerticalScrollbar; |  | 
| 109     else |  | 
| 110         orientation = HorizontalScrollbar; |  | 
| 111 |  | 
| 112     if (!userInputScrollable(orientation)) |  | 
| 113         return false; |  | 
| 114 |  | 
| 115     float step = 0; |  | 
| 116     switch (granularity) { |  | 
| 117     case ScrollByLine: |  | 
| 118         step = lineStep(orientation); |  | 
| 119         break; |  | 
| 120     case ScrollByPage: |  | 
| 121         step = pageStep(orientation); |  | 
| 122         break; |  | 
| 123     case ScrollByDocument: |  | 
| 124         step = documentStep(orientation); |  | 
| 125         break; |  | 
| 126     case ScrollByPixel: |  | 
| 127     case ScrollByPrecisePixel: |  | 
| 128         step = pixelStep(orientation); |  | 
| 129         break; |  | 
| 130     } |  | 
| 131 |  | 
| 132     if (direction == ScrollUp || direction == ScrollLeft) |  | 
| 133         multiplier = -multiplier; |  | 
| 134 |  | 
| 135     return scrollAnimator()->scroll(orientation, granularity, step, multiplier); |  | 
| 136 } |  | 
| 137 |  | 
| 138 void ScrollableArea::scrollToOffsetWithoutAnimation(const FloatPoint& offset) |  | 
| 139 { |  | 
| 140     scrollAnimator()->scrollToOffsetWithoutAnimation(offset); |  | 
| 141 } |  | 
| 142 |  | 
| 143 void ScrollableArea::scrollToOffsetWithoutAnimation(ScrollbarOrientation orienta
     tion, float offset) |  | 
| 144 { |  | 
| 145     if (orientation == HorizontalScrollbar) |  | 
| 146         scrollToOffsetWithoutAnimation(FloatPoint(offset, scrollAnimator()->curr
     entPosition().y())); |  | 
| 147     else |  | 
| 148         scrollToOffsetWithoutAnimation(FloatPoint(scrollAnimator()->currentPosit
     ion().x(), offset)); |  | 
| 149 } |  | 
| 150 |  | 
| 151 void ScrollableArea::notifyScrollPositionChanged(const IntPoint& position) |  | 
| 152 { |  | 
| 153     scrollPositionChanged(position); |  | 
| 154     scrollAnimator()->setCurrentPosition(position); |  | 
| 155 } |  | 
| 156 |  | 
| 157 void ScrollableArea::scrollPositionChanged(const IntPoint& position) |  | 
| 158 { |  | 
| 159     TRACE_EVENT0("webkit", "ScrollableArea::scrollPositionChanged"); |  | 
| 160 |  | 
| 161     IntPoint oldPosition = scrollPosition(); |  | 
| 162     // Tell the derived class to scroll its contents. |  | 
| 163     setScrollOffset(position); |  | 
| 164 |  | 
| 165     Scrollbar* verticalScrollbar = this->verticalScrollbar(); |  | 
| 166 |  | 
| 167     // Tell the scrollbars to update their thumb postions. |  | 
| 168     if (Scrollbar* horizontalScrollbar = this->horizontalScrollbar()) { |  | 
| 169         horizontalScrollbar->offsetDidChange(); |  | 
| 170         if (horizontalScrollbar->isOverlayScrollbar() && !hasLayerForHorizontalS
     crollbar()) { |  | 
| 171             if (!verticalScrollbar) |  | 
| 172                 horizontalScrollbar->invalidate(); |  | 
| 173             else { |  | 
| 174                 // If there is both a horizontalScrollbar and a verticalScrollba
     r, |  | 
| 175                 // then we must also invalidate the corner between them. |  | 
| 176                 IntRect boundsAndCorner = horizontalScrollbar->boundsRect(); |  | 
| 177                 boundsAndCorner.setWidth(boundsAndCorner.width() + verticalScrol
     lbar->width()); |  | 
| 178                 horizontalScrollbar->invalidateRect(boundsAndCorner); |  | 
| 179             } |  | 
| 180         } |  | 
| 181     } |  | 
| 182     if (verticalScrollbar) { |  | 
| 183         verticalScrollbar->offsetDidChange(); |  | 
| 184         if (verticalScrollbar->isOverlayScrollbar() && !hasLayerForVerticalScrol
     lbar()) |  | 
| 185             verticalScrollbar->invalidate(); |  | 
| 186     } |  | 
| 187 |  | 
| 188     if (scrollPosition() != oldPosition) |  | 
| 189         scrollAnimator()->notifyContentAreaScrolled(scrollPosition() - oldPositi
     on); |  | 
| 190 } |  | 
| 191 |  | 
| 192 bool ScrollableArea::handleWheelEvent(const PlatformWheelEvent& wheelEvent) |  | 
| 193 { |  | 
| 194     return scrollAnimator()->handleWheelEvent(wheelEvent); |  | 
| 195 } |  | 
| 196 |  | 
| 197 // NOTE: Only called from Internals for testing. |  | 
| 198 void ScrollableArea::setScrollOffsetFromInternals(const IntPoint& offset) |  | 
| 199 { |  | 
| 200     setScrollOffsetFromAnimation(offset); |  | 
| 201 } |  | 
| 202 |  | 
| 203 void ScrollableArea::setScrollOffsetFromAnimation(const IntPoint& offset) |  | 
| 204 { |  | 
| 205     scrollPositionChanged(offset); |  | 
| 206 } |  | 
| 207 |  | 
| 208 void ScrollableArea::willStartLiveResize() |  | 
| 209 { |  | 
| 210     if (m_inLiveResize) |  | 
| 211         return; |  | 
| 212     m_inLiveResize = true; |  | 
| 213     if (ScrollAnimator* scrollAnimator = existingScrollAnimator()) |  | 
| 214         scrollAnimator->willStartLiveResize(); |  | 
| 215 } |  | 
| 216 |  | 
| 217 void ScrollableArea::willEndLiveResize() |  | 
| 218 { |  | 
| 219     if (!m_inLiveResize) |  | 
| 220         return; |  | 
| 221     m_inLiveResize = false; |  | 
| 222     if (ScrollAnimator* scrollAnimator = existingScrollAnimator()) |  | 
| 223         scrollAnimator->willEndLiveResize(); |  | 
| 224 } |  | 
| 225 |  | 
| 226 void ScrollableArea::contentAreaWillPaint() const |  | 
| 227 { |  | 
| 228     if (ScrollAnimator* scrollAnimator = existingScrollAnimator()) |  | 
| 229         scrollAnimator->contentAreaWillPaint(); |  | 
| 230 } |  | 
| 231 |  | 
| 232 void ScrollableArea::mouseEnteredContentArea() const |  | 
| 233 { |  | 
| 234     if (ScrollAnimator* scrollAnimator = existingScrollAnimator()) |  | 
| 235         scrollAnimator->mouseEnteredContentArea(); |  | 
| 236 } |  | 
| 237 |  | 
| 238 void ScrollableArea::mouseExitedContentArea() const |  | 
| 239 { |  | 
| 240     if (ScrollAnimator* scrollAnimator = existingScrollAnimator()) |  | 
| 241         scrollAnimator->mouseEnteredContentArea(); |  | 
| 242 } |  | 
| 243 |  | 
| 244 void ScrollableArea::mouseMovedInContentArea() const |  | 
| 245 { |  | 
| 246     if (ScrollAnimator* scrollAnimator = existingScrollAnimator()) |  | 
| 247         scrollAnimator->mouseMovedInContentArea(); |  | 
| 248 } |  | 
| 249 |  | 
| 250 void ScrollableArea::mouseEnteredScrollbar(Scrollbar* scrollbar) const |  | 
| 251 { |  | 
| 252     scrollAnimator()->mouseEnteredScrollbar(scrollbar); |  | 
| 253 } |  | 
| 254 |  | 
| 255 void ScrollableArea::mouseExitedScrollbar(Scrollbar* scrollbar) const |  | 
| 256 { |  | 
| 257     scrollAnimator()->mouseExitedScrollbar(scrollbar); |  | 
| 258 } |  | 
| 259 |  | 
| 260 void ScrollableArea::contentAreaDidShow() const |  | 
| 261 { |  | 
| 262     if (ScrollAnimator* scrollAnimator = existingScrollAnimator()) |  | 
| 263         scrollAnimator->contentAreaDidShow(); |  | 
| 264 } |  | 
| 265 |  | 
| 266 void ScrollableArea::contentAreaDidHide() const |  | 
| 267 { |  | 
| 268     if (ScrollAnimator* scrollAnimator = existingScrollAnimator()) |  | 
| 269         scrollAnimator->contentAreaDidHide(); |  | 
| 270 } |  | 
| 271 |  | 
| 272 void ScrollableArea::finishCurrentScrollAnimations() const |  | 
| 273 { |  | 
| 274     if (ScrollAnimator* scrollAnimator = existingScrollAnimator()) |  | 
| 275         scrollAnimator->finishCurrentScrollAnimations(); |  | 
| 276 } |  | 
| 277 |  | 
| 278 void ScrollableArea::didAddScrollbar(Scrollbar* scrollbar, ScrollbarOrientation 
     orientation) |  | 
| 279 { |  | 
| 280     if (orientation == VerticalScrollbar) |  | 
| 281         scrollAnimator()->didAddVerticalScrollbar(scrollbar); |  | 
| 282     else |  | 
| 283         scrollAnimator()->didAddHorizontalScrollbar(scrollbar); |  | 
| 284 |  | 
| 285     // <rdar://problem/9797253> AppKit resets the scrollbar's style when you att
     ach a scrollbar |  | 
| 286     setScrollbarOverlayStyle(scrollbarOverlayStyle()); |  | 
| 287 } |  | 
| 288 |  | 
| 289 void ScrollableArea::willRemoveScrollbar(Scrollbar* scrollbar, ScrollbarOrientat
     ion orientation) |  | 
| 290 { |  | 
| 291     if (orientation == VerticalScrollbar) |  | 
| 292         scrollAnimator()->willRemoveVerticalScrollbar(scrollbar); |  | 
| 293     else |  | 
| 294         scrollAnimator()->willRemoveHorizontalScrollbar(scrollbar); |  | 
| 295 } |  | 
| 296 |  | 
| 297 void ScrollableArea::contentsResized() |  | 
| 298 { |  | 
| 299     if (ScrollAnimator* scrollAnimator = existingScrollAnimator()) |  | 
| 300         scrollAnimator->contentsResized(); |  | 
| 301 } |  | 
| 302 |  | 
| 303 bool ScrollableArea::hasOverlayScrollbars() const |  | 
| 304 { |  | 
| 305     return (verticalScrollbar() && verticalScrollbar()->isOverlayScrollbar()) |  | 
| 306         || (horizontalScrollbar() && horizontalScrollbar()->isOverlayScrollbar()
     ); |  | 
| 307 } |  | 
| 308 |  | 
| 309 void ScrollableArea::setScrollbarOverlayStyle(ScrollbarOverlayStyle overlayStyle
     ) |  | 
| 310 { |  | 
| 311     m_scrollbarOverlayStyle = overlayStyle; |  | 
| 312 |  | 
| 313     if (horizontalScrollbar()) { |  | 
| 314         ScrollbarTheme::theme()->updateScrollbarOverlayStyle(horizontalScrollbar
     ()); |  | 
| 315         horizontalScrollbar()->invalidate(); |  | 
| 316     } |  | 
| 317 |  | 
| 318     if (verticalScrollbar()) { |  | 
| 319         ScrollbarTheme::theme()->updateScrollbarOverlayStyle(verticalScrollbar()
     ); |  | 
| 320         verticalScrollbar()->invalidate(); |  | 
| 321     } |  | 
| 322 } |  | 
| 323 |  | 
| 324 void ScrollableArea::invalidateScrollbar(Scrollbar* scrollbar, const IntRect& re
     ct) |  | 
| 325 { |  | 
| 326     if (scrollbar == horizontalScrollbar()) { |  | 
| 327         if (GraphicsLayer* graphicsLayer = layerForHorizontalScrollbar()) { |  | 
| 328             graphicsLayer->setNeedsDisplay(); |  | 
| 329             graphicsLayer->setContentsNeedsDisplay(); |  | 
| 330             return; |  | 
| 331         } |  | 
| 332     } else if (scrollbar == verticalScrollbar()) { |  | 
| 333         if (GraphicsLayer* graphicsLayer = layerForVerticalScrollbar()) { |  | 
| 334             graphicsLayer->setNeedsDisplay(); |  | 
| 335             graphicsLayer->setContentsNeedsDisplay(); |  | 
| 336             return; |  | 
| 337         } |  | 
| 338     } |  | 
| 339     invalidateScrollbarRect(scrollbar, rect); |  | 
| 340 } |  | 
| 341 |  | 
| 342 void ScrollableArea::invalidateScrollCorner(const IntRect& rect) |  | 
| 343 { |  | 
| 344     if (GraphicsLayer* graphicsLayer = layerForScrollCorner()) { |  | 
| 345         graphicsLayer->setNeedsDisplay(); |  | 
| 346         return; |  | 
| 347     } |  | 
| 348     invalidateScrollCornerRect(rect); |  | 
| 349 } |  | 
| 350 |  | 
| 351 bool ScrollableArea::hasLayerForHorizontalScrollbar() const |  | 
| 352 { |  | 
| 353     return layerForHorizontalScrollbar(); |  | 
| 354 } |  | 
| 355 |  | 
| 356 bool ScrollableArea::hasLayerForVerticalScrollbar() const |  | 
| 357 { |  | 
| 358     return layerForVerticalScrollbar(); |  | 
| 359 } |  | 
| 360 |  | 
| 361 bool ScrollableArea::hasLayerForScrollCorner() const |  | 
| 362 { |  | 
| 363     return layerForScrollCorner(); |  | 
| 364 } |  | 
| 365 |  | 
| 366 void ScrollableArea::serviceScrollAnimations() |  | 
| 367 { |  | 
| 368     if (ScrollAnimator* scrollAnimator = existingScrollAnimator()) |  | 
| 369         scrollAnimator->serviceScrollAnimations(); |  | 
| 370 } |  | 
| 371 |  | 
| 372 IntRect ScrollableArea::visibleContentRect(IncludeScrollbarsInRect scrollbarIncl
     usion) const |  | 
| 373 { |  | 
| 374     int verticalScrollbarWidth = 0; |  | 
| 375     int horizontalScrollbarHeight = 0; |  | 
| 376 |  | 
| 377     if (scrollbarInclusion == IncludeScrollbars) { |  | 
| 378         if (Scrollbar* verticalBar = verticalScrollbar()) |  | 
| 379             verticalScrollbarWidth = !verticalBar->isOverlayScrollbar() ? vertic
     alBar->width() : 0; |  | 
| 380         if (Scrollbar* horizontalBar = horizontalScrollbar()) |  | 
| 381             horizontalScrollbarHeight = !horizontalBar->isOverlayScrollbar() ? h
     orizontalBar->height() : 0; |  | 
| 382     } |  | 
| 383 |  | 
| 384     return IntRect(scrollPosition().x(), |  | 
| 385                    scrollPosition().y(), |  | 
| 386                    std::max(0, visibleWidth() + verticalScrollbarWidth), |  | 
| 387                    std::max(0, visibleHeight() + horizontalScrollbarHeight)); |  | 
| 388 } |  | 
| 389 |  | 
| 390 IntPoint ScrollableArea::clampScrollPosition(const IntPoint& scrollPosition) con
     st |  | 
| 391 { |  | 
| 392     return scrollPosition.shrunkTo(maximumScrollPosition()).expandedTo(minimumSc
     rollPosition()); |  | 
| 393 } |  | 
| 394 |  | 
| 395 int ScrollableArea::lineStep(ScrollbarOrientation) const |  | 
| 396 { |  | 
| 397     return pixelsPerLineStep(); |  | 
| 398 } |  | 
| 399 |  | 
| 400 int ScrollableArea::documentStep(ScrollbarOrientation orientation) const |  | 
| 401 { |  | 
| 402     return scrollSize(orientation); |  | 
| 403 } |  | 
| 404 |  | 
| 405 float ScrollableArea::pixelStep(ScrollbarOrientation) const |  | 
| 406 { |  | 
| 407     return 1; |  | 
| 408 } |  | 
| 409 |  | 
| 410 } // namespace WebCore |  | 
| OLD | NEW | 
|---|