1 /* 2 * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26 #include "config.h" 27 #include "ScrollView.h" 28 29 #include "AXObjectCache.h" 30 #include "GraphicsContext.h" 31 #include "GraphicsLayer.h" 32 #include "HostWindow.h" 33 #include "PlatformMouseEvent.h" 34 #include "PlatformWheelEvent.h" 35 #include "ScrollAnimator.h" 36 #include "Scrollbar.h" 37 #include "ScrollbarTheme.h" 38 #include <wtf/StdLibExtras.h> 39 40 using namespace std; 41 42 namespace WebCore { 43 44 ScrollView::ScrollView() 45 : m_horizontalScrollbarMode(ScrollbarAuto) 46 , m_verticalScrollbarMode(ScrollbarAuto) 47 , m_horizontalScrollbarLock(false) 48 , m_verticalScrollbarLock(false) 49 , m_prohibitsScrolling(false) 50 , m_canBlitOnScroll(true) 51 , m_scrollbarsAvoidingResizer(0) 52 , m_scrollbarsSuppressed(false) 53 , m_inUpdateScrollbars(false) 54 , m_updateScrollbarsPass(0) 55 , m_drawPanScrollIcon(false) 56 , m_useFixedLayout(false) 57 , m_paintsEntireContents(false) 58 , m_clipsRepaints(true) 59 , m_delegatesScrolling(false) 60 , m_containsScrollableAreaWithOverlayScrollbars(false) 61 { 62 platformInit(); 63 } 64 65 ScrollView::~ScrollView() 66 { 67 platformDestroy(); 68 } 69 70 void ScrollView::addChild(PassRefPtr<Widget> prpChild) 71 { 72 Widget* child = prpChild.get(); 73 ASSERT(child != this && !child->parent()); 74 child->setParent(this); 75 m_children.add(prpChild); 76 if (child->platformWidget()) 77 platformAddChild(child); 78 } 79 80 void ScrollView::removeChild(Widget* child) 81 { 82 ASSERT(child->parent() == this); 83 child->setParent(0); 84 m_children.remove(child); 85 if (child->platformWidget()) 86 platformRemoveChild(child); 87 } 88 89 void ScrollView::setHasHorizontalScrollbar(bool hasBar) 90 { 91 if (hasBar && avoidScrollbarCreation()) 92 return; 93 94 if (hasBar && !m_horizontalScrollbar) { 95 m_horizontalScrollbar = createScrollbar(HorizontalScrollbar); 96 addChild(m_horizontalScrollbar.get()); 97 didAddHorizontalScrollbar(m_horizontalScrollbar.get()); 98 m_horizontalScrollbar->styleChanged(); 99 } else if (!hasBar && m_horizontalScrollbar) { 100 willRemoveHorizontalScrollbar(m_horizontalScrollbar.get()); 101 removeChild(m_horizontalScrollbar.get()); 102 m_horizontalScrollbar = 0; 103 } 104 105 if (AXObjectCache::accessibilityEnabled() && axObjectCache()) 106 axObjectCache()->handleScrollbarUpdate(this); 107 } 108 109 void ScrollView::setHasVerticalScrollbar(bool hasBar) 110 { 111 if (hasBar && avoidScrollbarCreation()) 112 return; 113 114 if (hasBar && !m_verticalScrollbar) { 115 m_verticalScrollbar = createScrollbar(VerticalScrollbar); 116 addChild(m_verticalScrollbar.get()); 117 didAddVerticalScrollbar(m_verticalScrollbar.get()); 118 m_verticalScrollbar->styleChanged(); 119 } else if (!hasBar && m_verticalScrollbar) { 120 willRemoveVerticalScrollbar(m_verticalScrollbar.get()); 121 removeChild(m_verticalScrollbar.get()); 122 m_verticalScrollbar = 0; 123 } 124 125 if (AXObjectCache::accessibilityEnabled() && axObjectCache()) 126 axObjectCache()->handleScrollbarUpdate(this); 127 } 128 129 #if !USE(NATIVE_GTK_MAIN_FRAME_SCROLLBAR) 130 PassRefPtr<Scrollbar> ScrollView::createScrollbar(ScrollbarOrientation orientation) 131 { 132 return Scrollbar::createNativeScrollbar(this, orientation, RegularScrollbar); 133 } 134 135 void ScrollView::setScrollbarModes(ScrollbarMode horizontalMode, ScrollbarMode verticalMode, 136 bool horizontalLock, bool verticalLock) 137 { 138 bool needsUpdate = false; 139 140 if (horizontalMode != horizontalScrollbarMode() && !m_horizontalScrollbarLock) { 141 m_horizontalScrollbarMode = horizontalMode; 142 needsUpdate = true; 143 } 144 145 if (verticalMode != verticalScrollbarMode() && !m_verticalScrollbarLock) { 146 m_verticalScrollbarMode = verticalMode; 147 needsUpdate = true; 148 } 149 150 if (horizontalLock) 151 setHorizontalScrollbarLock(); 152 153 if (verticalLock) 154 setVerticalScrollbarLock(); 155 156 if (!needsUpdate) 157 return; 158 159 if (platformWidget()) 160 platformSetScrollbarModes(); 161 else 162 updateScrollbars(scrollOffset()); 163 } 164 #endif 165 166 void ScrollView::scrollbarModes(ScrollbarMode& horizontalMode, ScrollbarMode& verticalMode) const 167 { 168 if (platformWidget()) { 169 platformScrollbarModes(horizontalMode, verticalMode); 170 return; 171 } 172 horizontalMode = m_horizontalScrollbarMode; 173 verticalMode = m_verticalScrollbarMode; 174 } 175 176 void ScrollView::setCanHaveScrollbars(bool canScroll) 177 { 178 ScrollbarMode newHorizontalMode; 179 ScrollbarMode newVerticalMode; 180 181 scrollbarModes(newHorizontalMode, newVerticalMode); 182 183 if (canScroll && newVerticalMode == ScrollbarAlwaysOff) 184 newVerticalMode = ScrollbarAuto; 185 else if (!canScroll) 186 newVerticalMode = ScrollbarAlwaysOff; 187 188 if (canScroll && newHorizontalMode == ScrollbarAlwaysOff) 189 newHorizontalMode = ScrollbarAuto; 190 else if (!canScroll) 191 newHorizontalMode = ScrollbarAlwaysOff; 192 193 setScrollbarModes(newHorizontalMode, newVerticalMode); 194 } 195 196 void ScrollView::setCanBlitOnScroll(bool b) 197 { 198 if (platformWidget()) { 199 platformSetCanBlitOnScroll(b); 200 return; 201 } 202 203 m_canBlitOnScroll = b; 204 } 205 206 bool ScrollView::canBlitOnScroll() const 207 { 208 if (platformWidget()) 209 return platformCanBlitOnScroll(); 210 211 return m_canBlitOnScroll; 212 } 213 214 void ScrollView::setPaintsEntireContents(bool paintsEntireContents) 215 { 216 m_paintsEntireContents = paintsEntireContents; 217 } 218 219 void ScrollView::setClipsRepaints(bool clipsRepaints) 220 { 221 m_clipsRepaints = clipsRepaints; 222 } 223 224 void ScrollView::setDelegatesScrolling(bool delegatesScrolling) 225 { 226 m_delegatesScrolling = delegatesScrolling; 227 } 228 229 #if !USE(NATIVE_GTK_MAIN_FRAME_SCROLLBAR) 230 IntRect ScrollView::visibleContentRect(bool includeScrollbars) const 231 { 232 if (platformWidget()) 233 return platformVisibleContentRect(includeScrollbars); 234 235 if (paintsEntireContents()) 236 return IntRect(IntPoint(0, 0), contentsSize()); 237 238 int verticalScrollbarWidth = verticalScrollbar() && !verticalScrollbar()->isOverlayScrollbar() 239 && !includeScrollbars ? verticalScrollbar()->width() : 0; 240 int horizontalScrollbarHeight = horizontalScrollbar() && !horizontalScrollbar()->isOverlayScrollbar() 241 && !includeScrollbars ? horizontalScrollbar()->height() : 0; 242 243 return IntRect(IntPoint(m_scrollOffset.width(), m_scrollOffset.height()), 244 IntSize(max(0, m_boundsSize.width() - verticalScrollbarWidth), 245 max(0, m_boundsSize.height() - horizontalScrollbarHeight))); 246 } 247 #endif 248 249 int ScrollView::layoutWidth() const 250 { 251 return m_fixedLayoutSize.isEmpty() || !m_useFixedLayout ? visibleWidth() : m_fixedLayoutSize.width(); 252 } 253 254 int ScrollView::layoutHeight() const 255 { 256 return m_fixedLayoutSize.isEmpty() || !m_useFixedLayout ? visibleHeight() : m_fixedLayoutSize.height(); 257 } 258 259 IntSize ScrollView::fixedLayoutSize() const 260 { 261 return m_fixedLayoutSize; 262 } 263 264 void ScrollView::setFixedLayoutSize(const IntSize& newSize) 265 { 266 if (fixedLayoutSize() == newSize) 267 return; 268 m_fixedLayoutSize = newSize; 269 updateScrollbars(scrollOffset()); 270 } 271 272 bool ScrollView::useFixedLayout() const 273 { 274 return m_useFixedLayout; 275 } 276 277 void ScrollView::setUseFixedLayout(bool enable) 278 { 279 if (useFixedLayout() == enable) 280 return; 281 m_useFixedLayout = enable; 282 updateScrollbars(scrollOffset()); 283 } 284 285 IntSize ScrollView::contentsSize() const 286 { 287 if (platformWidget()) 288 return platformContentsSize(); 289 return m_contentsSize; 290 } 291 292 void ScrollView::setContentsSize(const IntSize& newSize) 293 { 294 if (contentsSize() == newSize) 295 return; 296 m_contentsSize = newSize; 297 if (platformWidget()) 298 platformSetContentsSize(); 299 else 300 updateScrollbars(scrollOffset()); 301 } 302 303 #if PLATFORM(ANDROID) 304 int ScrollView::actualWidth() const 305 { 306 if (platformWidget()) 307 return platformActualWidth(); 308 return width(); 309 } 310 311 int ScrollView::actualHeight() const 312 { 313 if (platformWidget()) 314 return platformActualHeight(); 315 return height(); 316 } 317 318 int ScrollView::actualScrollX() const 319 { 320 if (platformWidget()) 321 return platformActualScrollX(); 322 return scrollX(); 323 } 324 325 int ScrollView::actualScrollY() const 326 { 327 if (platformWidget()) 328 return platformActualScrollY(); 329 return scrollY(); 330 } 331 #endif 332 333 IntPoint ScrollView::maximumScrollPosition() const 334 { 335 IntPoint maximumOffset(contentsWidth() - visibleWidth() - m_scrollOrigin.x(), contentsHeight() - visibleHeight() - m_scrollOrigin.y()); 336 maximumOffset.clampNegativeToZero(); 337 return maximumOffset; 338 } 339 340 IntPoint ScrollView::minimumScrollPosition() const 341 { 342 return IntPoint(-m_scrollOrigin.x(), -m_scrollOrigin.y()); 343 } 344 345 IntPoint ScrollView::adjustScrollPositionWithinRange(const IntPoint& scrollPoint) const 346 { 347 IntPoint newScrollPosition = scrollPoint.shrunkTo(maximumScrollPosition()); 348 newScrollPosition = newScrollPosition.expandedTo(minimumScrollPosition()); 349 return newScrollPosition; 350 } 351 352 int ScrollView::scrollSize(ScrollbarOrientation orientation) const 353 { 354 Scrollbar* scrollbar = ((orientation == HorizontalScrollbar) ? m_horizontalScrollbar : m_verticalScrollbar).get(); 355 return scrollbar ? (scrollbar->totalSize() - scrollbar->visibleSize()) : 0; 356 } 357 358 void ScrollView::didCompleteRubberBand(const IntSize&) const 359 { 360 } 361 362 void ScrollView::notifyPageThatContentAreaWillPaint() const 363 { 364 } 365 366 void ScrollView::setScrollOffset(const IntPoint& offset) 367 { 368 int horizontalOffset = offset.x(); 369 int verticalOffset = offset.y(); 370 if (constrainsScrollingToContentEdge()) { 371 horizontalOffset = max(min(horizontalOffset, contentsWidth() - visibleWidth()), 0); 372 verticalOffset = max(min(verticalOffset, contentsHeight() - visibleHeight()), 0); 373 } 374 375 IntSize newOffset = m_scrollOffset; 376 newOffset.setWidth(horizontalOffset - m_scrollOrigin.x()); 377 newOffset.setHeight(verticalOffset - m_scrollOrigin.y()); 378 379 scrollTo(newOffset); 380 } 381 382 void ScrollView::scrollTo(const IntSize& newOffset) 383 { 384 IntSize scrollDelta = newOffset - m_scrollOffset; 385 if (scrollDelta == IntSize()) 386 return; 387 m_scrollOffset = newOffset; 388 389 if (scrollbarsSuppressed()) 390 return; 391 392 repaintFixedElementsAfterScrolling(); 393 scrollContents(scrollDelta); 394 } 395 396 int ScrollView::scrollPosition(Scrollbar* scrollbar) const 397 { 398 if (scrollbar->orientation() == HorizontalScrollbar) 399 return scrollPosition().x() + m_scrollOrigin.x(); 400 if (scrollbar->orientation() == VerticalScrollbar) 401 return scrollPosition().y() + m_scrollOrigin.y(); 402 return 0; 403 } 404 405 void ScrollView::setScrollPosition(const IntPoint& scrollPoint) 406 { 407 if (prohibitsScrolling()) 408 return; 409 410 if (platformWidget()) { 411 platformSetScrollPosition(scrollPoint); 412 return; 413 } 414 415 #if ENABLE(TILED_BACKING_STORE) 416 if (delegatesScrolling()) { 417 hostWindow()->delegatedScrollRequested(scrollPoint); 418 if (!m_actualVisibleContentRect.isEmpty()) 419 m_actualVisibleContentRect.setLocation(scrollPoint); 420 return; 421 } 422 #endif 423 424 IntPoint newScrollPosition = adjustScrollPositionWithinRange(scrollPoint); 425 426 if (newScrollPosition == scrollPosition()) 427 return; 428 429 updateScrollbars(IntSize(newScrollPosition.x(), newScrollPosition.y())); 430 } 431 432 bool ScrollView::scroll(ScrollDirection direction, ScrollGranularity granularity) 433 { 434 if (platformWidget()) 435 return platformScroll(direction, granularity); 436 437 return ScrollableArea::scroll(direction, granularity); 438 } 439 440 bool ScrollView::logicalScroll(ScrollLogicalDirection direction, ScrollGranularity granularity) 441 { 442 return scroll(logicalToPhysical(direction, isVerticalDocument(), isFlippedDocument()), granularity); 443 } 444 445 IntSize ScrollView::overhangAmount() const 446 { 447 IntSize stretch; 448 449 int physicalScrollY = scrollPosition().y() + m_scrollOrigin.y(); 450 if (physicalScrollY < 0) 451 stretch.setHeight(physicalScrollY); 452 else if (physicalScrollY > contentsHeight() - visibleContentRect().height()) 453 stretch.setHeight(physicalScrollY - (contentsHeight() - visibleContentRect().height())); 454 455 int physicalScrollX = scrollPosition().x() + m_scrollOrigin.x(); 456 if (physicalScrollX < 0) 457 stretch.setWidth(physicalScrollX); 458 else if (physicalScrollX > contentsWidth() - visibleContentRect().width()) 459 stretch.setWidth(physicalScrollX - (contentsWidth() - visibleContentRect().width())); 460 461 return stretch; 462 } 463 464 void ScrollView::windowResizerRectChanged() 465 { 466 if (platformWidget()) 467 return; 468 469 updateScrollbars(scrollOffset()); 470 } 471 472 static const unsigned cMaxUpdateScrollbarsPass = 2; 473 474 void ScrollView::updateScrollbars(const IntSize& desiredOffset) 475 { 476 if (m_inUpdateScrollbars || prohibitsScrolling() || delegatesScrolling() || platformWidget()) 477 return; 478 479 // If we came in here with the view already needing a layout, then go ahead and do that 480 // first. (This will be the common case, e.g., when the page changes due to window resizing for example). 481 // This layout will not re-enter updateScrollbars and does not count towards our max layout pass total. 482 if (!m_scrollbarsSuppressed) { 483 m_inUpdateScrollbars = true; 484 visibleContentsResized(); 485 m_inUpdateScrollbars = false; 486 } 487 488 bool hasHorizontalScrollbar = m_horizontalScrollbar; 489 bool hasVerticalScrollbar = m_verticalScrollbar; 490 491 bool newHasHorizontalScrollbar = hasHorizontalScrollbar; 492 bool newHasVerticalScrollbar = hasVerticalScrollbar; 493 494 ScrollbarMode hScroll = m_horizontalScrollbarMode; 495 ScrollbarMode vScroll = m_verticalScrollbarMode; 496 497 if (hScroll != ScrollbarAuto) 498 newHasHorizontalScrollbar = (hScroll == ScrollbarAlwaysOn); 499 if (vScroll != ScrollbarAuto) 500 newHasVerticalScrollbar = (vScroll == ScrollbarAlwaysOn); 501 502 if (m_scrollbarsSuppressed || (hScroll != ScrollbarAuto && vScroll != ScrollbarAuto)) { 503 if (hasHorizontalScrollbar != newHasHorizontalScrollbar) 504 setHasHorizontalScrollbar(newHasHorizontalScrollbar); 505 if (hasVerticalScrollbar != newHasVerticalScrollbar) 506 setHasVerticalScrollbar(newHasVerticalScrollbar); 507 } else { 508 bool sendContentResizedNotification = false; 509 510 IntSize docSize = contentsSize(); 511 IntSize frameSize = m_boundsSize; 512 513 if (hScroll == ScrollbarAuto) { 514 newHasHorizontalScrollbar = docSize.width() > visibleWidth(); 515 if (newHasHorizontalScrollbar && !m_updateScrollbarsPass && docSize.width() <= frameSize.width() && docSize.height() <= frameSize.height()) 516 newHasHorizontalScrollbar = false; 517 } 518 if (vScroll == ScrollbarAuto) { 519 newHasVerticalScrollbar = docSize.height() > visibleHeight(); 520 if (newHasVerticalScrollbar && !m_updateScrollbarsPass && docSize.width() <= frameSize.width() && docSize.height() <= frameSize.height()) 521 newHasVerticalScrollbar = false; 522 } 523 524 // If we ever turn one scrollbar off, always turn the other one off too. Never ever 525 // try to both gain/lose a scrollbar in the same pass. 526 if (!newHasHorizontalScrollbar && hasHorizontalScrollbar && vScroll != ScrollbarAlwaysOn) 527 newHasVerticalScrollbar = false; 528 if (!newHasVerticalScrollbar && hasVerticalScrollbar && hScroll != ScrollbarAlwaysOn) 529 newHasHorizontalScrollbar = false; 530 531 if (hasHorizontalScrollbar != newHasHorizontalScrollbar) { 532 if (m_scrollOrigin.y() && !newHasHorizontalScrollbar) 533 m_scrollOrigin.setY(m_scrollOrigin.y() - m_horizontalScrollbar->height()); 534 setHasHorizontalScrollbar(newHasHorizontalScrollbar); 535 sendContentResizedNotification = true; 536 } 537 538 if (hasVerticalScrollbar != newHasVerticalScrollbar) { 539 if (m_scrollOrigin.x() && !newHasVerticalScrollbar) 540 m_scrollOrigin.setX(m_scrollOrigin.x() - m_verticalScrollbar->width()); 541 setHasVerticalScrollbar(newHasVerticalScrollbar); 542 sendContentResizedNotification = true; 543 } 544 545 if (sendContentResizedNotification && m_updateScrollbarsPass < cMaxUpdateScrollbarsPass) { 546 m_updateScrollbarsPass++; 547 contentsResized(); 548 visibleContentsResized(); 549 IntSize newDocSize = contentsSize(); 550 if (newDocSize == docSize) { 551 // The layout with the new scroll state had no impact on 552 // the document's overall size, so updateScrollbars didn't get called. 553 // Recur manually. 554 updateScrollbars(desiredOffset); 555 } 556 m_updateScrollbarsPass--; 557 } 558 } 559 560 // Set up the range (and page step/line step), but only do this if we're not in a nested call (to avoid 561 // doing it multiple times). 562 if (m_updateScrollbarsPass) 563 return; 564 565 m_inUpdateScrollbars = true; 566 567 IntPoint scrollPoint = adjustScrollPositionWithinRange(IntPoint(desiredOffset)); 568 IntSize scroll(scrollPoint.x(), scrollPoint.y()); 569 570 if (m_horizontalScrollbar) { 571 int clientWidth = visibleWidth(); 572 m_horizontalScrollbar->setEnabled(contentsWidth() > clientWidth); 573 int pageStep = max(max<int>(clientWidth * Scrollbar::minFractionToStepWhenPaging(), clientWidth - Scrollbar::maxOverlapBetweenPages()), 1); 574 IntRect oldRect(m_horizontalScrollbar->frameRect()); 575 IntRect hBarRect = IntRect(0, 576 m_boundsSize.height() - m_horizontalScrollbar->height(), 577 m_boundsSize.width() - (m_verticalScrollbar ? m_verticalScrollbar->width() : 0), 578 m_horizontalScrollbar->height()); 579 m_horizontalScrollbar->setFrameRect(hBarRect); 580 if (!m_scrollbarsSuppressed && oldRect != m_horizontalScrollbar->frameRect()) 581 m_horizontalScrollbar->invalidate(); 582 583 if (m_scrollbarsSuppressed) 584 m_horizontalScrollbar->setSuppressInvalidation(true); 585 m_horizontalScrollbar->setSteps(Scrollbar::pixelsPerLineStep(), pageStep); 586 m_horizontalScrollbar->setProportion(clientWidth, contentsWidth()); 587 if (m_scrollbarsSuppressed) 588 m_horizontalScrollbar->setSuppressInvalidation(false); 589 } 590 591 if (m_verticalScrollbar) { 592 int clientHeight = visibleHeight(); 593 m_verticalScrollbar->setEnabled(contentsHeight() > clientHeight); 594 int pageStep = max(max<int>(clientHeight * Scrollbar::minFractionToStepWhenPaging(), clientHeight - Scrollbar::maxOverlapBetweenPages()), 1); 595 IntRect oldRect(m_verticalScrollbar->frameRect()); 596 IntRect vBarRect = IntRect(m_boundsSize.width() - m_verticalScrollbar->width(), 597 0, 598 m_verticalScrollbar->width(), 599 m_boundsSize.height() - (m_horizontalScrollbar ? m_horizontalScrollbar->height() : 0)); 600 m_verticalScrollbar->setFrameRect(vBarRect); 601 if (!m_scrollbarsSuppressed && oldRect != m_verticalScrollbar->frameRect()) 602 m_verticalScrollbar->invalidate(); 603 604 if (m_scrollbarsSuppressed) 605 m_verticalScrollbar->setSuppressInvalidation(true); 606 m_verticalScrollbar->setSteps(Scrollbar::pixelsPerLineStep(), pageStep); 607 m_verticalScrollbar->setProportion(clientHeight, contentsHeight()); 608 if (m_scrollbarsSuppressed) 609 m_verticalScrollbar->setSuppressInvalidation(false); 610 } 611 612 if (hasHorizontalScrollbar != (m_horizontalScrollbar != 0) || hasVerticalScrollbar != (m_verticalScrollbar != 0)) { 613 frameRectsChanged(); 614 updateScrollCorner(); 615 } 616 617 ScrollableArea::scrollToOffsetWithoutAnimation(FloatPoint(scroll.width() + m_scrollOrigin.x(), scroll.height() + m_scrollOrigin.y())); 618 619 // Make sure the scrollbar offsets are up to date. 620 if (m_horizontalScrollbar) 621 m_horizontalScrollbar->offsetDidChange(); 622 if (m_verticalScrollbar) 623 m_verticalScrollbar->offsetDidChange(); 624 625 m_inUpdateScrollbars = false; 626 } 627 628 const int panIconSizeLength = 16; 629 630 void ScrollView::scrollContents(const IntSize& scrollDelta) 631 { 632 if (!hostWindow()) 633 return; 634 635 // Since scrolling is double buffered, we will be blitting the scroll view's intersection 636 // with the clip rect every time to keep it smooth. 637 IntRect clipRect = windowClipRect(); 638 IntRect scrollViewRect = convertToContainingWindow(IntRect(0, 0, visibleWidth(), visibleHeight())); 639 if (hasOverlayScrollbars()) { 640 int verticalScrollbarWidth = verticalScrollbar() ? verticalScrollbar()->width() : 0; 641 int horizontalScrollbarHeight = horizontalScrollbar() ? horizontalScrollbar()->height() : 0; 642 643 scrollViewRect.setWidth(scrollViewRect.width() - verticalScrollbarWidth); 644 scrollViewRect.setHeight(scrollViewRect.height() - horizontalScrollbarHeight); 645 } 646 647 IntRect updateRect = clipRect; 648 updateRect.intersect(scrollViewRect); 649 650 // Invalidate the window (not the backing store). 651 hostWindow()->invalidateWindow(updateRect, false /*immediate*/); 652 653 if (m_drawPanScrollIcon) { 654 // FIXME: the pan icon is broken when accelerated compositing is on, since it will draw under the compositing layers. 655 // https://bugs.webkit.org/show_bug.cgi?id=47837 656 int panIconDirtySquareSizeLength = 2 * (panIconSizeLength + max(abs(scrollDelta.width()), abs(scrollDelta.height()))); // We only want to repaint what's necessary 657 IntPoint panIconDirtySquareLocation = IntPoint(m_panScrollIconPoint.x() - (panIconDirtySquareSizeLength / 2), m_panScrollIconPoint.y() - (panIconDirtySquareSizeLength / 2)); 658 IntRect panScrollIconDirtyRect = IntRect(panIconDirtySquareLocation , IntSize(panIconDirtySquareSizeLength, panIconDirtySquareSizeLength)); 659 panScrollIconDirtyRect.intersect(clipRect); 660 hostWindow()->invalidateContentsAndWindow(panScrollIconDirtyRect, false /*immediate*/); 661 } 662 663 if (canBlitOnScroll()) { // The main frame can just blit the WebView window 664 // FIXME: Find a way to scroll subframes with this faster path 665 if (!scrollContentsFastPath(-scrollDelta, scrollViewRect, clipRect)) 666 scrollContentsSlowPath(updateRect); 667 } else { 668 // We need to go ahead and repaint the entire backing store. Do it now before moving the 669 // windowed plugins. 670 scrollContentsSlowPath(updateRect); 671 } 672 673 // Invalidate the overhang areas if they are visible. 674 IntRect horizontalOverhangRect; 675 IntRect verticalOverhangRect; 676 calculateOverhangAreasForPainting(horizontalOverhangRect, verticalOverhangRect); 677 if (!horizontalOverhangRect.isEmpty()) 678 hostWindow()->invalidateContentsAndWindow(horizontalOverhangRect, false /*immediate*/); 679 if (!verticalOverhangRect.isEmpty()) 680 hostWindow()->invalidateContentsAndWindow(verticalOverhangRect, false /*immediate*/); 681 682 // This call will move children with native widgets (plugins) and invalidate them as well. 683 frameRectsChanged(); 684 685 // Now blit the backingstore into the window which should be very fast. 686 hostWindow()->invalidateWindow(IntRect(), true); 687 } 688 689 bool ScrollView::scrollContentsFastPath(const IntSize& scrollDelta, const IntRect& rectToScroll, const IntRect& clipRect) 690 { 691 hostWindow()->scroll(scrollDelta, rectToScroll, clipRect); 692 return true; 693 } 694 695 void ScrollView::scrollContentsSlowPath(const IntRect& updateRect) 696 { 697 hostWindow()->invalidateContentsForSlowScroll(updateRect, false); 698 } 699 700 IntPoint ScrollView::windowToContents(const IntPoint& windowPoint) const 701 { 702 IntPoint viewPoint = convertFromContainingWindow(windowPoint); 703 return viewPoint + scrollOffset(); 704 } 705 706 IntPoint ScrollView::contentsToWindow(const IntPoint& contentsPoint) const 707 { 708 IntPoint viewPoint = contentsPoint - scrollOffset(); 709 return convertToContainingWindow(viewPoint); 710 } 711 712 IntRect ScrollView::windowToContents(const IntRect& windowRect) const 713 { 714 IntRect viewRect = convertFromContainingWindow(windowRect); 715 viewRect.move(scrollOffset()); 716 return viewRect; 717 } 718 719 IntRect ScrollView::contentsToWindow(const IntRect& contentsRect) const 720 { 721 IntRect viewRect = contentsRect; 722 viewRect.move(-scrollOffset()); 723 return convertToContainingWindow(viewRect); 724 } 725 726 IntRect ScrollView::contentsToScreen(const IntRect& rect) const 727 { 728 if (platformWidget()) 729 return platformContentsToScreen(rect); 730 if (!hostWindow()) 731 return IntRect(); 732 return hostWindow()->windowToScreen(contentsToWindow(rect)); 733 } 734 735 IntPoint ScrollView::screenToContents(const IntPoint& point) const 736 { 737 if (platformWidget()) 738 return platformScreenToContents(point); 739 if (!hostWindow()) 740 return IntPoint(); 741 return windowToContents(hostWindow()->screenToWindow(point)); 742 } 743 744 bool ScrollView::containsScrollbarsAvoidingResizer() const 745 { 746 return !m_scrollbarsAvoidingResizer; 747 } 748 749 void ScrollView::adjustScrollbarsAvoidingResizerCount(int overlapDelta) 750 { 751 int oldCount = m_scrollbarsAvoidingResizer; 752 m_scrollbarsAvoidingResizer += overlapDelta; 753 if (parent()) 754 parent()->adjustScrollbarsAvoidingResizerCount(overlapDelta); 755 else if (!scrollbarsSuppressed()) { 756 // If we went from n to 0 or from 0 to n and we're the outermost view, 757 // we need to invalidate the windowResizerRect(), since it will now need to paint 758 // differently. 759 if ((oldCount > 0 && m_scrollbarsAvoidingResizer == 0) || 760 (oldCount == 0 && m_scrollbarsAvoidingResizer > 0)) 761 invalidateRect(windowResizerRect()); 762 } 763 } 764 765 void ScrollView::setParent(ScrollView* parentView) 766 { 767 if (parentView == parent()) 768 return; 769 770 if (m_scrollbarsAvoidingResizer && parent()) 771 parent()->adjustScrollbarsAvoidingResizerCount(-m_scrollbarsAvoidingResizer); 772 773 Widget::setParent(parentView); 774 775 if (m_scrollbarsAvoidingResizer && parent()) 776 parent()->adjustScrollbarsAvoidingResizerCount(m_scrollbarsAvoidingResizer); 777 } 778 779 void ScrollView::setScrollbarsSuppressed(bool suppressed, bool repaintOnUnsuppress) 780 { 781 if (suppressed == m_scrollbarsSuppressed) 782 return; 783 784 m_scrollbarsSuppressed = suppressed; 785 786 if (platformWidget()) 787 platformSetScrollbarsSuppressed(repaintOnUnsuppress); 788 else if (repaintOnUnsuppress && !suppressed) { 789 if (m_horizontalScrollbar) 790 m_horizontalScrollbar->invalidate(); 791 if (m_verticalScrollbar) 792 m_verticalScrollbar->invalidate(); 793 794 // Invalidate the scroll corner too on unsuppress. 795 invalidateRect(scrollCornerRect()); 796 } 797 } 798 799 Scrollbar* ScrollView::scrollbarAtPoint(const IntPoint& windowPoint) 800 { 801 if (platformWidget()) 802 return 0; 803 804 IntPoint viewPoint = convertFromContainingWindow(windowPoint); 805 if (m_horizontalScrollbar && m_horizontalScrollbar->frameRect().contains(viewPoint)) 806 return m_horizontalScrollbar.get(); 807 if (m_verticalScrollbar && m_verticalScrollbar->frameRect().contains(viewPoint)) 808 return m_verticalScrollbar.get(); 809 return 0; 810 } 811 812 void ScrollView::wheelEvent(PlatformWheelEvent& e) 813 { 814 // We don't allow mouse wheeling to happen in a ScrollView that has had its scrollbars explicitly disabled. 815 #if PLATFORM(WX) 816 if (!canHaveScrollbars()) { 817 #else 818 if (!canHaveScrollbars() || platformWidget()) { 819 #endif 820 return; 821 } 822 823 ScrollableArea::handleWheelEvent(e); 824 } 825 826 #if ENABLE(GESTURE_EVENTS) 827 void ScrollView::gestureEvent(const PlatformGestureEvent& gestureEvent) 828 { 829 if (platformWidget()) 830 return; 831 832 ScrollableArea::handleGestureEvent(gestureEvent); 833 } 834 #endif 835 836 void ScrollView::setFrameRect(const IntRect& newRect) 837 { 838 IntRect oldRect = frameRect(); 839 840 if (newRect == oldRect) 841 return; 842 843 Widget::setFrameRect(newRect); 844 } 845 846 void ScrollView::setBoundsSize(const IntSize& newSize) 847 { 848 if (newSize == m_boundsSize) 849 return; 850 851 Widget::setBoundsSize(newSize); 852 m_boundsSize = newSize; 853 854 if (platformWidget()) 855 return; 856 857 updateScrollbars(m_scrollOffset); 858 if (!m_useFixedLayout) 859 contentsResized(); 860 861 frameRectsChanged(); 862 } 863 864 void ScrollView::setInitialBoundsSize(const IntSize& newSize) 865 { 866 ASSERT(m_boundsSize.isZero()); 867 m_boundsSize = newSize; 868 } 869 870 void ScrollView::frameRectsChanged() 871 { 872 if (platformWidget()) 873 return; 874 875 HashSet<RefPtr<Widget> >::const_iterator end = m_children.end(); 876 for (HashSet<RefPtr<Widget> >::const_iterator current = m_children.begin(); current != end; ++current) 877 (*current)->frameRectsChanged(); 878 positionScrollbarLayers(); 879 } 880 881 #if USE(ACCELERATED_COMPOSITING) 882 static void positionScrollbarLayer(GraphicsLayer* graphicsLayer, Scrollbar* scrollbar) 883 { 884 if (!graphicsLayer || !scrollbar) 885 return; 886 graphicsLayer->setDrawsContent(true); 887 IntRect scrollbarRect = scrollbar->frameRect(); 888 graphicsLayer->setPosition(scrollbarRect.location()); 889 if (scrollbarRect.size() != graphicsLayer->size()) 890 graphicsLayer->setNeedsDisplay(); 891 graphicsLayer->setSize(scrollbarRect.size()); 892 } 893 894 static void positionScrollCornerLayer(GraphicsLayer* graphicsLayer, const IntRect& cornerRect) 895 { 896 if (!graphicsLayer) 897 return; 898 graphicsLayer->setDrawsContent(!cornerRect.isEmpty()); 899 graphicsLayer->setPosition(cornerRect.location()); 900 if (cornerRect.size() != graphicsLayer->size()) 901 graphicsLayer->setNeedsDisplay(); 902 graphicsLayer->setSize(cornerRect.size()); 903 } 904 #endif 905 906 907 void ScrollView::positionScrollbarLayers() 908 { 909 #if USE(ACCELERATED_COMPOSITING) 910 positionScrollbarLayer(layerForHorizontalScrollbar(), horizontalScrollbar()); 911 positionScrollbarLayer(layerForVerticalScrollbar(), verticalScrollbar()); 912 positionScrollCornerLayer(layerForScrollCorner(), scrollCornerRect()); 913 #endif 914 } 915 916 917 void ScrollView::repaintContentRectangle(const IntRect& rect, bool now) 918 { 919 IntRect paintRect = rect; 920 if (clipsRepaints() && !paintsEntireContents()) 921 paintRect.intersect(visibleContentRect()); 922 #ifdef ANDROID_CAPTURE_OFFSCREEN_PAINTS 923 if (rect != paintRect) 924 platformOffscreenContentRectangle(visibleContentRect(), rect); 925 #endif 926 if (paintRect.isEmpty()) 927 return; 928 if (platformWidget()) { 929 platformRepaintContentRectangle(paintRect, now); 930 return; 931 } 932 933 if (hostWindow()) 934 hostWindow()->invalidateContentsAndWindow(contentsToWindow(paintRect), now /*immediate*/); 935 } 936 937 IntRect ScrollView::scrollCornerRect() const 938 { 939 IntRect cornerRect; 940 941 if (hasOverlayScrollbars()) 942 return cornerRect; 943 944 if (m_horizontalScrollbar && m_boundsSize.width() - m_horizontalScrollbar->width() > 0) { 945 cornerRect.unite(IntRect(m_horizontalScrollbar->width(), 946 m_boundsSize.height() - m_horizontalScrollbar->height(), 947 m_boundsSize.width() - m_horizontalScrollbar->width(), 948 m_horizontalScrollbar->height())); 949 } 950 951 if (m_verticalScrollbar && m_boundsSize.height() - m_verticalScrollbar->height() > 0) { 952 cornerRect.unite(IntRect(m_boundsSize.width() - m_verticalScrollbar->width(), 953 m_verticalScrollbar->height(), 954 m_verticalScrollbar->width(), 955 m_boundsSize.height() - m_verticalScrollbar->height())); 956 } 957 958 return cornerRect; 959 } 960 961 bool ScrollView::isScrollCornerVisible() const 962 { 963 return !scrollCornerRect().isEmpty(); 964 } 965 966 void ScrollView::updateScrollCorner() 967 { 968 } 969 970 void ScrollView::paintScrollCorner(GraphicsContext* context, const IntRect& cornerRect) 971 { 972 ScrollbarTheme::nativeTheme()->paintScrollCorner(this, context, cornerRect); 973 } 974 975 void ScrollView::invalidateScrollCornerRect(const IntRect& rect) 976 { 977 invalidateRect(rect); 978 } 979 980 void ScrollView::paintScrollbars(GraphicsContext* context, const IntRect& rect) 981 { 982 if (m_horizontalScrollbar 983 #if USE(ACCELERATED_COMPOSITING) 984 && !layerForHorizontalScrollbar() 985 #endif 986 ) 987 m_horizontalScrollbar->paint(context, rect); 988 if (m_verticalScrollbar 989 #if USE(ACCELERATED_COMPOSITING) 990 && !layerForVerticalScrollbar() 991 #endif 992 ) 993 m_verticalScrollbar->paint(context, rect); 994 995 #if USE(ACCELERATED_COMPOSITING) 996 if (layerForScrollCorner()) 997 return; 998 #endif 999 paintScrollCorner(context, scrollCornerRect()); 1000 } 1001 1002 void ScrollView::paintPanScrollIcon(GraphicsContext* context) 1003 { 1004 static Image* panScrollIcon = Image::loadPlatformResource("panIcon").releaseRef(); 1005 context->drawImage(panScrollIcon, ColorSpaceDeviceRGB, m_panScrollIconPoint); 1006 } 1007 1008 void ScrollView::paint(GraphicsContext* context, const IntRect& rect) 1009 { 1010 if (platformWidget()) { 1011 Widget::paint(context, rect); 1012 return; 1013 } 1014 1015 if (context->paintingDisabled() && !context->updatingControlTints()) 1016 return; 1017 1018 notifyPageThatContentAreaWillPaint(); 1019 1020 // If we encounter any overlay scrollbars as we paint, this will be set to true. 1021 m_containsScrollableAreaWithOverlayScrollbars = false; 1022 1023 IntRect documentDirtyRect = rect; 1024 documentDirtyRect.intersect(frameRect()); 1025 1026 context->save(); 1027 1028 context->translate(x(), y()); 1029 documentDirtyRect.move(-x(), -y()); 1030 1031 if (!paintsEntireContents()) { 1032 context->translate(-scrollX(), -scrollY()); 1033 documentDirtyRect.move(scrollX(), scrollY()); 1034 1035 context->clip(visibleContentRect()); 1036 } 1037 1038 paintContents(context, documentDirtyRect); 1039 1040 context->restore(); 1041 1042 IntRect horizontalOverhangRect; 1043 IntRect verticalOverhangRect; 1044 calculateOverhangAreasForPainting(horizontalOverhangRect, verticalOverhangRect); 1045 1046 if (rect.intersects(horizontalOverhangRect) || rect.intersects(verticalOverhangRect)) 1047 paintOverhangAreas(context, horizontalOverhangRect, verticalOverhangRect, rect); 1048 1049 // Now paint the scrollbars. 1050 if (!m_scrollbarsSuppressed && (m_horizontalScrollbar || m_verticalScrollbar)) { 1051 context->save(); 1052 IntRect scrollViewDirtyRect = rect; 1053 scrollViewDirtyRect.intersect(frameRect()); 1054 context->translate(x(), y()); 1055 scrollViewDirtyRect.move(-x(), -y()); 1056 1057 paintScrollbars(context, scrollViewDirtyRect); 1058 1059 context->restore(); 1060 } 1061 1062 // Paint the panScroll Icon 1063 if (m_drawPanScrollIcon) 1064 paintPanScrollIcon(context); 1065 } 1066 1067 void ScrollView::calculateOverhangAreasForPainting(IntRect& horizontalOverhangRect, IntRect& verticalOverhangRect) 1068 { 1069 int verticalScrollbarWidth = (verticalScrollbar() && !verticalScrollbar()->isOverlayScrollbar()) 1070 ? verticalScrollbar()->width() : 0; 1071 int horizontalScrollbarHeight = (horizontalScrollbar() && !horizontalScrollbar()->isOverlayScrollbar()) 1072 ? horizontalScrollbar()->height() : 0; 1073 1074 int physicalScrollY = scrollPosition().y() + m_scrollOrigin.y(); 1075 if (physicalScrollY < 0) { 1076 horizontalOverhangRect = frameRect(); 1077 horizontalOverhangRect.setHeight(-physicalScrollY); 1078 } else if (physicalScrollY > contentsHeight() - visibleContentRect().height()) { 1079 int height = physicalScrollY - (contentsHeight() - visibleContentRect().height()); 1080 horizontalOverhangRect = frameRect(); 1081 horizontalOverhangRect.setY(frameRect().maxY() - height - horizontalScrollbarHeight); 1082 horizontalOverhangRect.setHeight(height); 1083 } 1084 1085 int physicalScrollX = scrollPosition().x() + m_scrollOrigin.x(); 1086 if (physicalScrollX < 0) { 1087 verticalOverhangRect.setWidth(-physicalScrollX); 1088 verticalOverhangRect.setHeight(frameRect().height() - horizontalOverhangRect.height()); 1089 verticalOverhangRect.setX(frameRect().x()); 1090 if (horizontalOverhangRect.y() == frameRect().y()) 1091 verticalOverhangRect.setY(frameRect().y() + horizontalOverhangRect.height()); 1092 else 1093 verticalOverhangRect.setY(frameRect().y()); 1094 } else if (physicalScrollX > contentsWidth() - visibleContentRect().width()) { 1095 int width = physicalScrollX - (contentsWidth() - visibleContentRect().width()); 1096 verticalOverhangRect.setWidth(width); 1097 verticalOverhangRect.setHeight(frameRect().height() - horizontalOverhangRect.height()); 1098 verticalOverhangRect.setX(frameRect().maxX() - width - verticalScrollbarWidth); 1099 if (horizontalOverhangRect.y() == frameRect().y()) 1100 verticalOverhangRect.setY(frameRect().y() + horizontalOverhangRect.height()); 1101 else 1102 verticalOverhangRect.setY(frameRect().y()); 1103 } 1104 } 1105 1106 void ScrollView::paintOverhangAreas(GraphicsContext* context, const IntRect& horizontalOverhangRect, const IntRect& verticalOverhangRect, const IntRect&) 1107 { 1108 // FIXME: This should be checking the dirty rect. 1109 1110 context->setFillColor(Color::white, ColorSpaceDeviceRGB); 1111 if (!horizontalOverhangRect.isEmpty()) 1112 context->fillRect(horizontalOverhangRect); 1113 1114 context->setFillColor(Color::white, ColorSpaceDeviceRGB); 1115 if (!verticalOverhangRect.isEmpty()) 1116 context->fillRect(verticalOverhangRect); 1117 } 1118 1119 bool ScrollView::isPointInScrollbarCorner(const IntPoint& windowPoint) 1120 { 1121 if (!scrollbarCornerPresent()) 1122 return false; 1123 1124 IntPoint viewPoint = convertFromContainingWindow(windowPoint); 1125 1126 if (m_horizontalScrollbar) { 1127 int horizontalScrollbarYMin = m_horizontalScrollbar->frameRect().y(); 1128 int horizontalScrollbarYMax = m_horizontalScrollbar->frameRect().y() + m_horizontalScrollbar->frameRect().height(); 1129 int horizontalScrollbarXMin = m_horizontalScrollbar->frameRect().x() + m_horizontalScrollbar->frameRect().width(); 1130 1131 return viewPoint.y() > horizontalScrollbarYMin && viewPoint.y() < horizontalScrollbarYMax && viewPoint.x() > horizontalScrollbarXMin; 1132 } 1133 1134 int verticalScrollbarXMin = m_verticalScrollbar->frameRect().x(); 1135 int verticalScrollbarXMax = m_verticalScrollbar->frameRect().x() + m_verticalScrollbar->frameRect().width(); 1136 int verticalScrollbarYMin = m_verticalScrollbar->frameRect().y() + m_verticalScrollbar->frameRect().height(); 1137 1138 return viewPoint.x() > verticalScrollbarXMin && viewPoint.x() < verticalScrollbarXMax && viewPoint.y() > verticalScrollbarYMin; 1139 } 1140 1141 bool ScrollView::scrollbarCornerPresent() const 1142 { 1143 return (m_horizontalScrollbar && m_boundsSize.width() - m_horizontalScrollbar->width() > 0) || 1144 (m_verticalScrollbar && m_boundsSize.height() - m_verticalScrollbar->height() > 0); 1145 } 1146 1147 IntRect ScrollView::convertFromScrollbarToContainingView(const Scrollbar* scrollbar, const IntRect& localRect) const 1148 { 1149 // Scrollbars won't be transformed within us 1150 IntRect newRect = localRect; 1151 newRect.move(scrollbar->x(), scrollbar->y()); 1152 return newRect; 1153 } 1154 1155 IntRect ScrollView::convertFromContainingViewToScrollbar(const Scrollbar* scrollbar, const IntRect& parentRect) const 1156 { 1157 IntRect newRect = parentRect; 1158 // Scrollbars won't be transformed within us 1159 newRect.move(-scrollbar->x(), -scrollbar->y()); 1160 return newRect; 1161 } 1162 1163 // FIXME: test these on windows 1164 IntPoint ScrollView::convertFromScrollbarToContainingView(const Scrollbar* scrollbar, const IntPoint& localPoint) const 1165 { 1166 // Scrollbars won't be transformed within us 1167 IntPoint newPoint = localPoint; 1168 newPoint.move(scrollbar->x(), scrollbar->y()); 1169 return newPoint; 1170 } 1171 1172 IntPoint ScrollView::convertFromContainingViewToScrollbar(const Scrollbar* scrollbar, const IntPoint& parentPoint) const 1173 { 1174 IntPoint newPoint = parentPoint; 1175 // Scrollbars won't be transformed within us 1176 newPoint.move(-scrollbar->x(), -scrollbar->y()); 1177 return newPoint; 1178 } 1179 1180 void ScrollView::setParentVisible(bool visible) 1181 { 1182 if (isParentVisible() == visible) 1183 return; 1184 1185 Widget::setParentVisible(visible); 1186 1187 if (!isSelfVisible()) 1188 return; 1189 1190 HashSet<RefPtr<Widget> >::iterator end = m_children.end(); 1191 for (HashSet<RefPtr<Widget> >::iterator it = m_children.begin(); it != end; ++it) 1192 (*it)->setParentVisible(visible); 1193 } 1194 1195 void ScrollView::show() 1196 { 1197 if (!isSelfVisible()) { 1198 setSelfVisible(true); 1199 if (isParentVisible()) { 1200 HashSet<RefPtr<Widget> >::iterator end = m_children.end(); 1201 for (HashSet<RefPtr<Widget> >::iterator it = m_children.begin(); it != end; ++it) 1202 (*it)->setParentVisible(true); 1203 } 1204 } 1205 1206 Widget::show(); 1207 } 1208 1209 void ScrollView::hide() 1210 { 1211 if (isSelfVisible()) { 1212 if (isParentVisible()) { 1213 HashSet<RefPtr<Widget> >::iterator end = m_children.end(); 1214 for (HashSet<RefPtr<Widget> >::iterator it = m_children.begin(); it != end; ++it) 1215 (*it)->setParentVisible(false); 1216 } 1217 setSelfVisible(false); 1218 } 1219 1220 Widget::hide(); 1221 } 1222 1223 bool ScrollView::isOffscreen() const 1224 { 1225 if (platformWidget()) 1226 return platformIsOffscreen(); 1227 1228 if (!isVisible()) 1229 return true; 1230 1231 // FIXME: Add a HostWindow::isOffscreen method here. Since only Mac implements this method 1232 // currently, we can add the method when the other platforms decide to implement this concept. 1233 return false; 1234 } 1235 1236 1237 void ScrollView::addPanScrollIcon(const IntPoint& iconPosition) 1238 { 1239 if (!hostWindow()) 1240 return; 1241 m_drawPanScrollIcon = true; 1242 m_panScrollIconPoint = IntPoint(iconPosition.x() - panIconSizeLength / 2 , iconPosition.y() - panIconSizeLength / 2) ; 1243 hostWindow()->invalidateContentsAndWindow(IntRect(m_panScrollIconPoint, IntSize(panIconSizeLength, panIconSizeLength)), true /*immediate*/); 1244 } 1245 1246 void ScrollView::removePanScrollIcon() 1247 { 1248 if (!hostWindow()) 1249 return; 1250 m_drawPanScrollIcon = false; 1251 hostWindow()->invalidateContentsAndWindow(IntRect(m_panScrollIconPoint, IntSize(panIconSizeLength, panIconSizeLength)), true /*immediate*/); 1252 } 1253 1254 void ScrollView::setScrollOrigin(const IntPoint& origin, bool updatePositionAtAll, bool updatePositionSynchronously) 1255 { 1256 if (m_scrollOrigin == origin) 1257 return; 1258 1259 m_scrollOrigin = origin; 1260 1261 if (platformWidget()) { 1262 platformSetScrollOrigin(origin, updatePositionAtAll, updatePositionSynchronously); 1263 return; 1264 } 1265 1266 // Update if the scroll origin changes, since our position will be different if the content size did not change. 1267 if (updatePositionAtAll && updatePositionSynchronously) 1268 updateScrollbars(scrollOffset()); 1269 } 1270 1271 #if !PLATFORM(WX) && !USE(NATIVE_GTK_MAIN_FRAME_SCROLLBAR) && !PLATFORM(EFL) 1272 1273 void ScrollView::platformInit() 1274 { 1275 } 1276 1277 void ScrollView::platformDestroy() 1278 { 1279 } 1280 1281 #endif 1282 1283 #if !PLATFORM(WX) && !PLATFORM(QT) && !PLATFORM(MAC) 1284 1285 void ScrollView::platformAddChild(Widget*) 1286 { 1287 } 1288 1289 void ScrollView::platformRemoveChild(Widget*) 1290 { 1291 } 1292 1293 #endif 1294 1295 #if !PLATFORM(MAC) 1296 1297 void ScrollView::platformSetScrollbarsSuppressed(bool) 1298 { 1299 } 1300 1301 void ScrollView::platformSetScrollOrigin(const IntPoint&, bool updatePositionAtAll, bool updatePositionSynchronously) 1302 { 1303 } 1304 1305 #endif 1306 1307 #if !PLATFORM(MAC) && !PLATFORM(WX) 1308 1309 #if !PLATFORM(ANDROID) 1310 void ScrollView::platformSetScrollbarModes() 1311 { 1312 } 1313 1314 void ScrollView::platformScrollbarModes(ScrollbarMode& horizontal, ScrollbarMode& vertical) const 1315 { 1316 horizontal = ScrollbarAuto; 1317 vertical = ScrollbarAuto; 1318 } 1319 #endif 1320 1321 void ScrollView::platformSetCanBlitOnScroll(bool) 1322 { 1323 } 1324 1325 bool ScrollView::platformCanBlitOnScroll() const 1326 { 1327 return false; 1328 } 1329 1330 #if !PLATFORM(ANDROID) 1331 IntRect ScrollView::platformVisibleContentRect(bool) const 1332 { 1333 return IntRect(); 1334 } 1335 #endif 1336 1337 #if !PLATFORM(ANDROID) 1338 IntSize ScrollView::platformContentsSize() const 1339 { 1340 return IntSize(); 1341 } 1342 #endif 1343 1344 void ScrollView::platformSetContentsSize() 1345 { 1346 } 1347 1348 IntRect ScrollView::platformContentsToScreen(const IntRect& rect) const 1349 { 1350 return rect; 1351 } 1352 1353 IntPoint ScrollView::platformScreenToContents(const IntPoint& point) const 1354 { 1355 return point; 1356 } 1357 1358 #if !PLATFORM(ANDROID) 1359 void ScrollView::platformSetScrollPosition(const IntPoint&) 1360 { 1361 } 1362 #endif 1363 1364 bool ScrollView::platformScroll(ScrollDirection, ScrollGranularity) 1365 { 1366 return true; 1367 } 1368 1369 #if !PLATFORM(ANDROID) 1370 void ScrollView::platformRepaintContentRectangle(const IntRect&, bool /*now*/) 1371 { 1372 } 1373 1374 #ifdef ANDROID_CAPTURE_OFFSCREEN_PAINTS 1375 void ScrollView::platformOffscreenContentRectangle(const IntRect& ) 1376 { 1377 } 1378 #endif 1379 1380 bool ScrollView::platformIsOffscreen() const 1381 { 1382 return false; 1383 } 1384 1385 #endif 1386 #endif 1387 1388 } 1389