325
static const unsigned cMaxUpdateScrollbarsPass = 2;
318
327
void ScrollView::updateScrollbars(const IntSize& desiredOffset)
320
// Don't allow re-entrancy into this function.
321
329
if (m_inUpdateScrollbars || prohibitsScrolling() || platformWidget())
324
m_inUpdateScrollbars = true;
332
// If we came in here with the view already needing a layout, then go ahead and do that
333
// first. (This will be the common case, e.g., when the page changes due to window resizing for example).
334
// This layout will not re-enter updateScrollbars and does not count towards our max layout pass total.
335
if (!m_scrollbarsSuppressed) {
336
m_inUpdateScrollbars = true;
337
visibleContentsResized();
338
m_inUpdateScrollbars = false;
341
bool hasHorizontalScrollbar = m_horizontalScrollbar;
326
342
bool hasVerticalScrollbar = m_verticalScrollbar;
327
bool hasHorizontalScrollbar = m_horizontalScrollbar;
328
bool oldHasVertical = hasVerticalScrollbar;
329
bool oldHasHorizontal = hasHorizontalScrollbar;
344
bool newHasHorizontalScrollbar = hasHorizontalScrollbar;
345
bool newHasVerticalScrollbar = hasVerticalScrollbar;
330
347
ScrollbarMode hScroll = m_horizontalScrollbarMode;
331
348
ScrollbarMode vScroll = m_verticalScrollbarMode;
333
const int scrollbarThickness = ScrollbarTheme::nativeTheme()->scrollbarThickness();
335
for (int pass = 0; pass < 2; pass++) {
336
bool scrollsVertically;
337
bool scrollsHorizontally;
339
if (!m_scrollbarsSuppressed && (hScroll == ScrollbarAuto || vScroll == ScrollbarAuto)) {
340
// Do a layout if pending before checking if scrollbars are needed.
341
if (hasVerticalScrollbar != oldHasVertical || hasHorizontalScrollbar != oldHasHorizontal)
342
visibleContentsResized();
344
scrollsVertically = (vScroll == ScrollbarAlwaysOn) || (vScroll == ScrollbarAuto && contentsHeight() > height());
345
if (scrollsVertically)
346
scrollsHorizontally = (hScroll == ScrollbarAlwaysOn) || (hScroll == ScrollbarAuto && contentsWidth() + scrollbarThickness > width());
348
scrollsHorizontally = (hScroll == ScrollbarAlwaysOn) || (hScroll == ScrollbarAuto && contentsWidth() > width());
349
if (scrollsHorizontally)
350
scrollsVertically = (vScroll == ScrollbarAlwaysOn) || (vScroll == ScrollbarAuto && contentsHeight() + scrollbarThickness > height());
350
if (hScroll != ScrollbarAuto)
351
newHasHorizontalScrollbar = (hScroll == ScrollbarAlwaysOn);
352
if (vScroll != ScrollbarAuto)
353
newHasVerticalScrollbar = (vScroll == ScrollbarAlwaysOn);
355
if (m_scrollbarsSuppressed || (hScroll != ScrollbarAuto && vScroll != ScrollbarAuto)) {
356
if (hasHorizontalScrollbar != newHasHorizontalScrollbar)
357
setHasHorizontalScrollbar(newHasHorizontalScrollbar);
358
if (hasVerticalScrollbar != newHasVerticalScrollbar)
359
setHasVerticalScrollbar(newHasVerticalScrollbar);
361
bool sendContentResizedNotification = false;
363
IntSize docSize = contentsSize();
364
IntSize frameSize = frameRect().size();
366
if (hScroll == ScrollbarAuto) {
367
newHasHorizontalScrollbar = docSize.width() > visibleWidth();
368
if (newHasHorizontalScrollbar && !m_updateScrollbarsPass && docSize.width() <= frameSize.width() && docSize.height() <= frameSize.height())
369
newHasHorizontalScrollbar = false;
371
if (vScroll == ScrollbarAuto) {
372
newHasVerticalScrollbar = docSize.height() > visibleHeight();
373
if (newHasVerticalScrollbar && !m_updateScrollbarsPass && docSize.width() <= frameSize.width() && docSize.height() <= frameSize.height())
374
newHasVerticalScrollbar = false;
377
// If we ever turn one scrollbar off, always turn the other one off too. Never ever
378
// try to both gain/lose a scrollbar in the same pass.
379
if (!newHasHorizontalScrollbar && hasHorizontalScrollbar && vScroll != ScrollbarAlwaysOn)
380
newHasVerticalScrollbar = false;
381
if (!newHasVerticalScrollbar && hasVerticalScrollbar && hScroll != ScrollbarAlwaysOn)
382
newHasHorizontalScrollbar = false;
384
if (hasHorizontalScrollbar != newHasHorizontalScrollbar) {
385
setHasHorizontalScrollbar(newHasHorizontalScrollbar);
386
sendContentResizedNotification = true;
389
if (hasVerticalScrollbar != newHasVerticalScrollbar) {
390
setHasVerticalScrollbar(newHasVerticalScrollbar);
391
sendContentResizedNotification = true;
394
if (sendContentResizedNotification && m_updateScrollbarsPass < cMaxUpdateScrollbarsPass) {
395
m_updateScrollbarsPass++;
397
visibleContentsResized();
398
IntSize newDocSize = contentsSize();
399
if (newDocSize == docSize) {
400
// The layout with the new scroll state had no impact on
401
// the document's overall size, so updateScrollbars didn't get called.
403
updateScrollbars(desiredOffset);
353
scrollsHorizontally = (hScroll == ScrollbarAuto) ? hasHorizontalScrollbar : (hScroll == ScrollbarAlwaysOn);
354
scrollsVertically = (vScroll == ScrollbarAuto) ? hasVerticalScrollbar : (vScroll == ScrollbarAlwaysOn);
357
if (hasVerticalScrollbar != scrollsVertically) {
358
setHasVerticalScrollbar(scrollsVertically);
359
hasVerticalScrollbar = scrollsVertically;
362
if (hasHorizontalScrollbar != scrollsHorizontally) {
363
setHasHorizontalScrollbar(scrollsHorizontally);
364
hasHorizontalScrollbar = scrollsHorizontally;
405
m_updateScrollbarsPass--;
368
// Set up the range (and page step/line step).
409
// Set up the range (and page step/line step), but only do this if we're not in a nested call (to avoid
410
// doing it multiple times).
411
if (m_updateScrollbarsPass)
414
m_inUpdateScrollbars = true;
369
415
IntSize maxScrollPosition(contentsWidth() - visibleWidth(), contentsHeight() - visibleHeight());
370
416
IntSize scroll = desiredOffset.shrunkTo(maxScrollPosition);
371
417
scroll.clampNegativeToZero();
373
if (!platformHandleHorizontalAdjustment(scroll) && m_horizontalScrollbar) {
419
if (m_horizontalScrollbar) {
374
420
int clientWidth = visibleWidth();
375
421
m_horizontalScrollbar->setEnabled(contentsWidth() > clientWidth);
376
422
int pageStep = (clientWidth - cAmountToKeepWhenPaging);
564
627
m_verticalScrollbar->invalidate();
566
629
// Invalidate the scroll corner too on unsuppress.
568
if (m_horizontalScrollbar && width() - m_horizontalScrollbar->width() > 0) {
569
hCorner = IntRect(m_horizontalScrollbar->width(),
570
height() - m_horizontalScrollbar->height(),
571
width() - m_horizontalScrollbar->width(),
572
m_horizontalScrollbar->height());
573
invalidateRect(hCorner);
576
if (m_verticalScrollbar && height() - m_verticalScrollbar->height() > 0) {
577
IntRect vCorner(width() - m_verticalScrollbar->width(),
578
m_verticalScrollbar->height(),
579
m_verticalScrollbar->width(),
580
height() - m_verticalScrollbar->height());
581
if (vCorner != hCorner)
582
invalidateRect(vCorner);
630
invalidateRect(scrollCornerRect());
587
Scrollbar* ScrollView::scrollbarUnderMouse(const PlatformMouseEvent& mouseEvent)
634
Scrollbar* ScrollView::scrollbarAtPoint(const IntPoint& windowPoint)
589
636
if (platformWidget())
592
IntPoint viewPoint = convertFromContainingWindow(mouseEvent.pos());
639
IntPoint viewPoint = convertFromContainingWindow(windowPoint);
593
640
if (m_horizontalScrollbar && m_horizontalScrollbar->frameRect().contains(viewPoint))
594
641
return m_horizontalScrollbar.get();
595
642
if (m_verticalScrollbar && m_verticalScrollbar->frameRect().contains(viewPoint))
651
700
if (platformWidget())
654
HashSet<Widget*>::const_iterator end = m_children.end();
655
for (HashSet<Widget*>::const_iterator current = m_children.begin(); current != end; ++current)
703
HashSet<RefPtr<Widget> >::const_iterator end = m_children.end();
704
for (HashSet<RefPtr<Widget> >::const_iterator current = m_children.begin(); current != end; ++current)
656
705
(*current)->frameRectsChanged();
659
708
void ScrollView::repaintContentRectangle(const IntRect& rect, bool now)
710
IntRect visibleContent = visibleContentRect();
711
visibleContent.intersect(rect);
712
if (visibleContent.isEmpty())
664
715
if (platformWidget()) {
665
platformRepaintContentRectangle(rect, now);
716
platformRepaintContentRectangle(visibleContent, now);
669
hostWindow()->repaint(contentsToWindow(rect), true, now);
721
hostWindow()->repaint(contentsToWindow(visibleContent), true, now);
724
IntRect ScrollView::scrollCornerRect() const
728
if (m_horizontalScrollbar && width() - m_horizontalScrollbar->width() > 0) {
729
cornerRect.unite(IntRect(m_horizontalScrollbar->width(),
730
height() - m_horizontalScrollbar->height(),
731
width() - m_horizontalScrollbar->width(),
732
m_horizontalScrollbar->height()));
735
if (m_verticalScrollbar && height() - m_verticalScrollbar->height() > 0) {
736
cornerRect.unite(IntRect(width() - m_verticalScrollbar->width(),
737
m_verticalScrollbar->height(),
738
m_verticalScrollbar->width(),
739
height() - m_verticalScrollbar->height()));
745
void ScrollView::updateScrollCorner()
749
void ScrollView::paintScrollCorner(GraphicsContext* context, const IntRect& cornerRect)
751
ScrollbarTheme::nativeTheme()->paintScrollCorner(this, context, cornerRect);
672
754
void ScrollView::paint(GraphicsContext* context, const IntRect& rect)
708
790
if (m_verticalScrollbar)
709
791
m_verticalScrollbar->paint(context, scrollViewDirtyRect);
712
if (m_horizontalScrollbar && width() - m_horizontalScrollbar->width() > 0) {
713
hCorner = IntRect(m_horizontalScrollbar->width(),
714
height() - m_horizontalScrollbar->height(),
715
width() - m_horizontalScrollbar->width(),
716
m_horizontalScrollbar->height());
717
if (hCorner.intersects(scrollViewDirtyRect))
718
ScrollbarTheme::nativeTheme()->paintScrollCorner(this, context, hCorner);
721
if (m_verticalScrollbar && height() - m_verticalScrollbar->height() > 0) {
722
IntRect vCorner(width() - m_verticalScrollbar->width(),
723
m_verticalScrollbar->height(),
724
m_verticalScrollbar->width(),
725
height() - m_verticalScrollbar->height());
726
if (vCorner != hCorner && vCorner.intersects(scrollViewDirtyRect))
727
ScrollbarTheme::nativeTheme()->paintScrollCorner(this, context, vCorner);
793
paintScrollCorner(context, scrollCornerRect());
730
794
context->restore();
804
bool ScrollView::isPointInScrollbarCorner(const IntPoint& windowPoint)
806
if (!scrollbarCornerPresent())
809
IntPoint viewPoint = convertFromContainingWindow(windowPoint);
811
if (m_horizontalScrollbar) {
812
int horizontalScrollbarYMin = m_horizontalScrollbar->frameRect().y();
813
int horizontalScrollbarYMax = m_horizontalScrollbar->frameRect().y() + m_horizontalScrollbar->frameRect().height();
814
int horizontalScrollbarXMin = m_horizontalScrollbar->frameRect().x() + m_horizontalScrollbar->frameRect().width();
816
return viewPoint.y() > horizontalScrollbarYMin && viewPoint.y() < horizontalScrollbarYMax && viewPoint.x() > horizontalScrollbarXMin;
819
int verticalScrollbarXMin = m_verticalScrollbar->frameRect().x();
820
int verticalScrollbarXMax = m_verticalScrollbar->frameRect().x() + m_verticalScrollbar->frameRect().width();
821
int verticalScrollbarYMin = m_verticalScrollbar->frameRect().y() + m_verticalScrollbar->frameRect().height();
823
return viewPoint.x() > verticalScrollbarXMin && viewPoint.x() < verticalScrollbarXMax && viewPoint.y() > verticalScrollbarYMin;
740
826
bool ScrollView::scrollbarCornerPresent() const
742
828
return (m_horizontalScrollbar && width() - m_horizontalScrollbar->width() > 0) ||
743
829
(m_verticalScrollbar && height() - m_verticalScrollbar->height() > 0);
832
IntRect ScrollView::convertFromScrollbarToContainingView(const Scrollbar* scrollbar, const IntRect& localRect) const
834
// Scrollbars won't be transformed within us
835
IntRect newRect = localRect;
836
newRect.move(scrollbar->x(), scrollbar->y());
840
IntRect ScrollView::convertFromContainingViewToScrollbar(const Scrollbar* scrollbar, const IntRect& parentRect) const
842
IntRect newRect = parentRect;
843
// Scrollbars won't be transformed within us
844
newRect.move(-scrollbar->x(), -scrollbar->y());
848
// FIXME: test these on windows
849
IntPoint ScrollView::convertFromScrollbarToContainingView(const Scrollbar* scrollbar, const IntPoint& localPoint) const
851
// Scrollbars won't be transformed within us
852
IntPoint newPoint = localPoint;
853
newPoint.move(scrollbar->x(), scrollbar->y());
857
IntPoint ScrollView::convertFromContainingViewToScrollbar(const Scrollbar* scrollbar, const IntPoint& parentPoint) const
859
IntPoint newPoint = parentPoint;
860
// Scrollbars won't be transformed within us
861
newPoint.move(-scrollbar->x(), -scrollbar->y());
746
865
void ScrollView::setParentVisible(bool visible)
748
867
if (isParentVisible() == visible)