| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012 Apple Inc. All rights
reserved. | 2 * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012 Apple Inc. All rights
reserved. |
| 3 * | 3 * |
| 4 * Portions are Copyright (C) 1998 Netscape Communications Corporation. | 4 * Portions are Copyright (C) 1998 Netscape Communications Corporation. |
| 5 * | 5 * |
| 6 * Other contributors: | 6 * Other contributors: |
| 7 * Robert O'Callahan <roc+@cs.cmu.edu> | 7 * Robert O'Callahan <roc+@cs.cmu.edu> |
| 8 * David Baron <dbaron@fas.harvard.edu> | 8 * David Baron <dbaron@fas.harvard.edu> |
| 9 * Christian Biesinger <cbiesinger@web.de> | 9 * Christian Biesinger <cbiesinger@web.de> |
| 10 * Randall Jesup <rjesup@wgate.com> | 10 * Randall Jesup <rjesup@wgate.com> |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 63 #include "platform/PlatformGestureEvent.h" | 63 #include "platform/PlatformGestureEvent.h" |
| 64 #include "platform/PlatformMouseEvent.h" | 64 #include "platform/PlatformMouseEvent.h" |
| 65 #include "platform/graphics/GraphicsContextStateSaver.h" | 65 #include "platform/graphics/GraphicsContextStateSaver.h" |
| 66 #include "platform/graphics/GraphicsLayer.h" | 66 #include "platform/graphics/GraphicsLayer.h" |
| 67 #include "platform/scroll/ScrollAnimator.h" | 67 #include "platform/scroll/ScrollAnimator.h" |
| 68 #include "platform/scroll/Scrollbar.h" | 68 #include "platform/scroll/Scrollbar.h" |
| 69 #include "public/platform/Platform.h" | 69 #include "public/platform/Platform.h" |
| 70 | 70 |
| 71 namespace blink { | 71 namespace blink { |
| 72 | 72 |
| 73 const int ResizerControlExpandRatioForTouch = 2; | |
| 74 | |
| 75 RenderLayerScrollableArea::RenderLayerScrollableArea(RenderLayer& layer) | 73 RenderLayerScrollableArea::RenderLayerScrollableArea(RenderLayer& layer) |
| 76 : m_layer(layer) | 74 : m_layer(layer) |
| 77 , m_inResizeMode(false) | |
| 78 , m_scrollsOverflow(false) | 75 , m_scrollsOverflow(false) |
| 79 , m_scrollDimensionsDirty(true) | 76 , m_scrollDimensionsDirty(true) |
| 80 , m_inOverflowRelayout(false) | 77 , m_inOverflowRelayout(false) |
| 81 , m_nextTopmostScrollChild(0) | 78 , m_nextTopmostScrollChild(0) |
| 82 , m_topmostScrollChild(0) | 79 , m_topmostScrollChild(0) |
| 83 , m_needsCompositedScrolling(false) | 80 , m_needsCompositedScrolling(false) |
| 84 { | 81 { |
| 85 ScrollableArea::setConstrainsScrollingToContentEdge(false); | 82 ScrollableArea::setConstrainsScrollingToContentEdge(false); |
| 86 | 83 |
| 87 Node* node = box().node(); | 84 Node* node = box().node(); |
| 88 if (node && node->isElementNode()) { | 85 if (node && node->isElementNode()) { |
| 89 // We save and restore only the scrollOffset as the other scroll values
are recalculated. | 86 // We save and restore only the scrollOffset as the other scroll values
are recalculated. |
| 90 Element* element = toElement(node); | 87 Element* element = toElement(node); |
| 91 m_scrollOffset = element->savedLayerScrollOffset(); | 88 m_scrollOffset = element->savedLayerScrollOffset(); |
| 92 if (!m_scrollOffset.isZero()) | 89 if (!m_scrollOffset.isZero()) |
| 93 scrollAnimator()->setCurrentPosition(FloatPoint(m_scrollOffset.width
(), m_scrollOffset.height())); | 90 scrollAnimator()->setCurrentPosition(FloatPoint(m_scrollOffset.width
(), m_scrollOffset.height())); |
| 94 element->setSavedLayerScrollOffset(IntSize()); | 91 element->setSavedLayerScrollOffset(IntSize()); |
| 95 } | 92 } |
| 96 | |
| 97 updateResizerAreaSet(); | |
| 98 } | 93 } |
| 99 | 94 |
| 100 RenderLayerScrollableArea::~RenderLayerScrollableArea() | 95 RenderLayerScrollableArea::~RenderLayerScrollableArea() |
| 101 { | 96 { |
| 102 if (inResizeMode() && !box().documentBeingDestroyed()) { | |
| 103 if (LocalFrame* frame = box().frame()) | |
| 104 frame->eventHandler().resizeScrollableAreaDestroyed(); | |
| 105 } | |
| 106 | |
| 107 if (box().frame() && box().frame()->page()) { | 97 if (box().frame() && box().frame()->page()) { |
| 108 if (ScrollingCoordinator* scrollingCoordinator = box().frame()->page()->
scrollingCoordinator()) | 98 if (ScrollingCoordinator* scrollingCoordinator = box().frame()->page()->
scrollingCoordinator()) |
| 109 scrollingCoordinator->willDestroyScrollableArea(this); | 99 scrollingCoordinator->willDestroyScrollableArea(this); |
| 110 } | 100 } |
| 111 | 101 |
| 112 if (!box().documentBeingDestroyed()) { | 102 if (!box().documentBeingDestroyed()) { |
| 113 Node* node = box().node(); | 103 Node* node = box().node(); |
| 114 if (node && node->isElementNode()) | 104 if (node && node->isElementNode()) |
| 115 toElement(node)->setSavedLayerScrollOffset(m_scrollOffset); | 105 toElement(node)->setSavedLayerScrollOffset(m_scrollOffset); |
| 116 } | 106 } |
| 117 | 107 |
| 118 if (LocalFrame* frame = box().frame()) { | |
| 119 if (FrameView* frameView = frame->view()) | |
| 120 frameView->removeResizerArea(box()); | |
| 121 } | |
| 122 | |
| 123 destroyScrollbar(HorizontalScrollbar); | 108 destroyScrollbar(HorizontalScrollbar); |
| 124 destroyScrollbar(VerticalScrollbar); | 109 destroyScrollbar(VerticalScrollbar); |
| 125 } | 110 } |
| 126 | 111 |
| 127 HostWindow* RenderLayerScrollableArea::hostWindow() const | 112 HostWindow* RenderLayerScrollableArea::hostWindow() const |
| 128 { | 113 { |
| 129 if (Page* page = box().frame()->page()) | 114 if (Page* page = box().frame()->page()) |
| 130 return &page->chrome(); | 115 return &page->chrome(); |
| 131 return nullptr; | 116 return nullptr; |
| 132 } | 117 } |
| (...skipping 12 matching lines...) Expand all Loading... |
| 145 } | 130 } |
| 146 | 131 |
| 147 GraphicsLayer* RenderLayerScrollableArea::layerForVerticalScrollbar() const | 132 GraphicsLayer* RenderLayerScrollableArea::layerForVerticalScrollbar() const |
| 148 { | 133 { |
| 149 // See crbug.com/343132. | 134 // See crbug.com/343132. |
| 150 DisableCompositingQueryAsserts disabler; | 135 DisableCompositingQueryAsserts disabler; |
| 151 | 136 |
| 152 return layer()->hasCompositedLayerMapping() ? layer()->compositedLayerMappin
g()->layerForVerticalScrollbar() : 0; | 137 return layer()->hasCompositedLayerMapping() ? layer()->compositedLayerMappin
g()->layerForVerticalScrollbar() : 0; |
| 153 } | 138 } |
| 154 | 139 |
| 155 GraphicsLayer* RenderLayerScrollableArea::layerForScrollCorner() const | |
| 156 { | |
| 157 // See crbug.com/343132. | |
| 158 DisableCompositingQueryAsserts disabler; | |
| 159 | |
| 160 return layer()->hasCompositedLayerMapping() ? layer()->compositedLayerMappin
g()->layerForScrollCorner() : 0; | |
| 161 } | |
| 162 | |
| 163 void RenderLayerScrollableArea::invalidateScrollbarRect(Scrollbar* scrollbar, co
nst IntRect& rect) | 140 void RenderLayerScrollableArea::invalidateScrollbarRect(Scrollbar* scrollbar, co
nst IntRect& rect) |
| 164 { | 141 { |
| 165 // See crbug.com/343132. | 142 // See crbug.com/343132. |
| 166 DisableCompositingQueryAsserts disabler; | 143 DisableCompositingQueryAsserts disabler; |
| 167 | 144 |
| 168 if (scrollbar == m_vBar.get()) { | 145 if (scrollbar == m_vBar.get()) { |
| 169 if (GraphicsLayer* layer = layerForVerticalScrollbar()) { | 146 if (GraphicsLayer* layer = layerForVerticalScrollbar()) { |
| 170 layer->setNeedsDisplayInRect(rect); | 147 layer->setNeedsDisplayInRect(rect); |
| 171 return; | 148 return; |
| 172 } | 149 } |
| (...skipping 18 matching lines...) Expand all Loading... |
| 191 return; | 168 return; |
| 192 | 169 |
| 193 IntRect intRect = pixelSnappedIntRect(scrollRect); | 170 IntRect intRect = pixelSnappedIntRect(scrollRect); |
| 194 | 171 |
| 195 if (box().frameView()->isInPerformLayout()) | 172 if (box().frameView()->isInPerformLayout()) |
| 196 addScrollbarDamage(scrollbar, intRect); | 173 addScrollbarDamage(scrollbar, intRect); |
| 197 else | 174 else |
| 198 box().invalidatePaintRectangle(intRect); | 175 box().invalidatePaintRectangle(intRect); |
| 199 } | 176 } |
| 200 | 177 |
| 201 void RenderLayerScrollableArea::invalidateScrollCornerRect(const IntRect& rect) | |
| 202 { | |
| 203 if (GraphicsLayer* layer = layerForScrollCorner()) { | |
| 204 layer->setNeedsDisplayInRect(rect); | |
| 205 return; | |
| 206 } | |
| 207 } | |
| 208 | |
| 209 bool RenderLayerScrollableArea::isActive() const | 178 bool RenderLayerScrollableArea::isActive() const |
| 210 { | 179 { |
| 211 Page* page = box().frame()->page(); | 180 Page* page = box().frame()->page(); |
| 212 return page && page->focusController().isActive(); | 181 return page && page->focusController().isActive(); |
| 213 } | 182 } |
| 214 | 183 |
| 215 bool RenderLayerScrollableArea::isScrollCornerVisible() const | |
| 216 { | |
| 217 return !scrollCornerRect().isEmpty(); | |
| 218 } | |
| 219 | |
| 220 static int cornerStart(const RenderStyle* style, int minX, int maxX, int thickne
ss) | 184 static int cornerStart(const RenderStyle* style, int minX, int maxX, int thickne
ss) |
| 221 { | 185 { |
| 222 if (style->shouldPlaceBlockDirectionScrollbarOnLogicalLeft()) | 186 if (style->shouldPlaceBlockDirectionScrollbarOnLogicalLeft()) |
| 223 return minX + style->borderLeftWidth(); | 187 return minX + style->borderLeftWidth(); |
| 224 return maxX - thickness - style->borderRightWidth(); | 188 return maxX - thickness - style->borderRightWidth(); |
| 225 } | 189 } |
| 226 | 190 |
| 227 static IntRect cornerRect(const RenderStyle* style, const Scrollbar* horizontalS
crollbar, const Scrollbar* verticalScrollbar, const IntRect& bounds) | 191 IntRect RenderLayerScrollableArea::scrollCornerRect() const |
| 228 { | 192 { |
| 229 int horizontalThickness; | 193 // We have a scrollbar corner when a scrollbar is visible and not filling th
e entire length of the box. |
| 230 int verticalThickness; | 194 // This happens when both scrollbars are present. |
| 231 if (!verticalScrollbar && !horizontalScrollbar) { | 195 const Scrollbar* horizontalBar = horizontalScrollbar(); |
| 232 // FIXME: This isn't right. We need to know the thickness of custom scro
llbars | 196 const Scrollbar* verticalBar = verticalScrollbar(); |
| 233 // even when they don't exist in order to set the resizer square size pr
operly. | 197 if (!horizontalBar || !verticalBar) |
| 234 horizontalThickness = Scrollbar::scrollbarThickness(); | 198 return IntRect(); |
| 235 verticalThickness = horizontalThickness; | 199 |
| 236 } else if (verticalScrollbar && !horizontalScrollbar) { | 200 const RenderStyle* style = box().style(); |
| 237 horizontalThickness = verticalScrollbar->width(); | 201 int horizontalThickness = verticalBar->width(); |
| 238 verticalThickness = horizontalThickness; | 202 int verticalThickness = horizontalBar->height(); |
| 239 } else if (horizontalScrollbar && !verticalScrollbar) { | 203 const IntRect& bounds = box().pixelSnappedBorderBoxRect(); |
| 240 verticalThickness = horizontalScrollbar->height(); | |
| 241 horizontalThickness = verticalThickness; | |
| 242 } else { | |
| 243 horizontalThickness = verticalScrollbar->width(); | |
| 244 verticalThickness = horizontalScrollbar->height(); | |
| 245 } | |
| 246 return IntRect(cornerStart(style, bounds.x(), bounds.maxX(), horizontalThick
ness), | 204 return IntRect(cornerStart(style, bounds.x(), bounds.maxX(), horizontalThick
ness), |
| 247 bounds.maxY() - verticalThickness - style->borderBottomWidth(), | 205 bounds.maxY() - verticalThickness - style->borderBottomWidth(), |
| 248 horizontalThickness, verticalThickness); | 206 horizontalThickness, verticalThickness); |
| 249 } | 207 } |
| 250 | 208 |
| 251 IntRect RenderLayerScrollableArea::scrollCornerRect() const | |
| 252 { | |
| 253 // We have a scrollbar corner when a scrollbar is visible and not filling th
e entire length of the box. | |
| 254 // This happens when: | |
| 255 // (a) A resizer is present and at least one scrollbar is present | |
| 256 // (b) Both scrollbars are present. | |
| 257 bool hasHorizontalBar = horizontalScrollbar(); | |
| 258 bool hasVerticalBar = verticalScrollbar(); | |
| 259 bool hasResizer = box().style()->resize() != RESIZE_NONE; | |
| 260 if ((hasHorizontalBar && hasVerticalBar) || (hasResizer && (hasHorizontalBar
|| hasVerticalBar))) | |
| 261 return cornerRect(box().style(), horizontalScrollbar(), verticalScrollba
r(), box().pixelSnappedBorderBoxRect()); | |
| 262 return IntRect(); | |
| 263 } | |
| 264 | |
| 265 IntRect RenderLayerScrollableArea::convertFromScrollbarToContainingView(const Sc
rollbar* scrollbar, const IntRect& scrollbarRect) const | 209 IntRect RenderLayerScrollableArea::convertFromScrollbarToContainingView(const Sc
rollbar* scrollbar, const IntRect& scrollbarRect) const |
| 266 { | 210 { |
| 267 RenderView* view = box().view(); | 211 RenderView* view = box().view(); |
| 268 if (!view) | 212 if (!view) |
| 269 return scrollbarRect; | 213 return scrollbarRect; |
| 270 | 214 |
| 271 IntRect rect = scrollbarRect; | 215 IntRect rect = scrollbarRect; |
| 272 rect.move(scrollbarOffset(scrollbar)); | 216 rect.move(scrollbarOffset(scrollbar)); |
| 273 | 217 |
| 274 return view->frameView()->convertFromRenderer(box(), rect); | 218 return view->frameView()->convertFromRenderer(box(), rect); |
| (...skipping 393 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 668 // When switching to another value, we need to re-enable them (see bug 11985
). | 612 // When switching to another value, we need to re-enable them (see bug 11985
). |
| 669 if (needsHorizontalScrollbar && oldStyle && oldStyle->overflowX() == OSCROLL
&& overflowX != OSCROLL) { | 613 if (needsHorizontalScrollbar && oldStyle && oldStyle->overflowX() == OSCROLL
&& overflowX != OSCROLL) { |
| 670 ASSERT(hasHorizontalScrollbar()); | 614 ASSERT(hasHorizontalScrollbar()); |
| 671 m_hBar->setEnabled(true); | 615 m_hBar->setEnabled(true); |
| 672 } | 616 } |
| 673 | 617 |
| 674 if (needsVerticalScrollbar && oldStyle && oldStyle->overflowY() == OSCROLL &
& overflowY != OSCROLL) { | 618 if (needsVerticalScrollbar && oldStyle && oldStyle->overflowY() == OSCROLL &
& overflowY != OSCROLL) { |
| 675 ASSERT(hasVerticalScrollbar()); | 619 ASSERT(hasVerticalScrollbar()); |
| 676 m_vBar->setEnabled(true); | 620 m_vBar->setEnabled(true); |
| 677 } | 621 } |
| 678 | |
| 679 updateResizerAreaSet(); | |
| 680 } | 622 } |
| 681 | 623 |
| 682 bool RenderLayerScrollableArea::updateAfterCompositingChange() | 624 bool RenderLayerScrollableArea::updateAfterCompositingChange() |
| 683 { | 625 { |
| 684 layer()->updateScrollingStateAfterCompositingChange(); | 626 layer()->updateScrollingStateAfterCompositingChange(); |
| 685 const bool layersChanged = m_topmostScrollChild != m_nextTopmostScrollChild; | 627 const bool layersChanged = m_topmostScrollChild != m_nextTopmostScrollChild; |
| 686 m_topmostScrollChild = m_nextTopmostScrollChild; | 628 m_topmostScrollChild = m_nextTopmostScrollChild; |
| 687 m_nextTopmostScrollChild = nullptr; | 629 m_nextTopmostScrollChild = nullptr; |
| 688 return layersChanged; | 630 return layersChanged; |
| 689 } | 631 } |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 746 | 688 |
| 747 LayoutUnit RenderLayerScrollableArea::verticalScrollbarStart(int minX, int maxX)
const | 689 LayoutUnit RenderLayerScrollableArea::verticalScrollbarStart(int minX, int maxX)
const |
| 748 { | 690 { |
| 749 if (box().style()->shouldPlaceBlockDirectionScrollbarOnLogicalLeft()) | 691 if (box().style()->shouldPlaceBlockDirectionScrollbarOnLogicalLeft()) |
| 750 return minX + box().borderLeft(); | 692 return minX + box().borderLeft(); |
| 751 return maxX - box().borderRight() - m_vBar->width(); | 693 return maxX - box().borderRight() - m_vBar->width(); |
| 752 } | 694 } |
| 753 | 695 |
| 754 LayoutUnit RenderLayerScrollableArea::horizontalScrollbarStart(int minX) const | 696 LayoutUnit RenderLayerScrollableArea::horizontalScrollbarStart(int minX) const |
| 755 { | 697 { |
| 756 int x = minX + box().borderLeft(); | 698 return minX + box().borderLeft(); |
| 757 if (box().style()->shouldPlaceBlockDirectionScrollbarOnLogicalLeft()) | |
| 758 x += m_vBar ? m_vBar->width() : resizerCornerRect(box().pixelSnappedBord
erBoxRect(), ResizerForPointer).width(); | |
| 759 return x; | |
| 760 } | 699 } |
| 761 | 700 |
| 762 IntSize RenderLayerScrollableArea::scrollbarOffset(const Scrollbar* scrollbar) c
onst | 701 IntSize RenderLayerScrollableArea::scrollbarOffset(const Scrollbar* scrollbar) c
onst |
| 763 { | 702 { |
| 764 if (scrollbar == m_vBar.get()) | 703 if (scrollbar == m_vBar.get()) |
| 765 return IntSize(verticalScrollbarStart(0, box().width()), box().borderTop
()); | 704 return IntSize(verticalScrollbarStart(0, box().width()), box().borderTop
()); |
| 766 | 705 |
| 767 if (scrollbar == m_hBar.get()) | 706 if (scrollbar == m_hBar.get()) |
| 768 return IntSize(horizontalScrollbarStart(0), box().height() - box().borde
rBottom() - scrollbar->height()); | 707 return IntSize(horizontalScrollbarStart(0), box().height() - box().borde
rBottom() - scrollbar->height()); |
| 769 | 708 |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 831 | 770 |
| 832 int RenderLayerScrollableArea::horizontalScrollbarHeight(OverlayScrollbarSizeRel
evancy relevancy) const | 771 int RenderLayerScrollableArea::horizontalScrollbarHeight(OverlayScrollbarSizeRel
evancy relevancy) const |
| 833 { | 772 { |
| 834 if (!m_hBar || (m_hBar->isOverlayScrollbar() && (relevancy == IgnoreOverlayS
crollbarSize || !m_hBar->shouldParticipateInHitTesting()))) | 773 if (!m_hBar || (m_hBar->isOverlayScrollbar() && (relevancy == IgnoreOverlayS
crollbarSize || !m_hBar->shouldParticipateInHitTesting()))) |
| 835 return 0; | 774 return 0; |
| 836 return m_hBar->height(); | 775 return m_hBar->height(); |
| 837 } | 776 } |
| 838 | 777 |
| 839 void RenderLayerScrollableArea::positionOverflowControls(const IntSize& offsetFr
omRoot) | 778 void RenderLayerScrollableArea::positionOverflowControls(const IntSize& offsetFr
omRoot) |
| 840 { | 779 { |
| 841 if (!hasScrollbar() && !box().canResize()) | 780 if (!hasScrollbar()) |
| 842 return; | 781 return; |
| 843 | 782 |
| 844 const IntRect borderBox = box().pixelSnappedBorderBoxRect(); | 783 const IntRect borderBox = box().pixelSnappedBorderBoxRect(); |
| 845 if (Scrollbar* verticalScrollbar = this->verticalScrollbar()) { | 784 if (Scrollbar* verticalScrollbar = this->verticalScrollbar()) { |
| 846 IntRect vBarRect = rectForVerticalScrollbar(borderBox); | 785 IntRect vBarRect = rectForVerticalScrollbar(borderBox); |
| 847 vBarRect.move(offsetFromRoot); | 786 vBarRect.move(offsetFromRoot); |
| 848 verticalScrollbar->setFrameRect(vBarRect); | 787 verticalScrollbar->setFrameRect(vBarRect); |
| 849 } | 788 } |
| 850 | 789 |
| 851 if (Scrollbar* horizontalScrollbar = this->horizontalScrollbar()) { | 790 if (Scrollbar* horizontalScrollbar = this->horizontalScrollbar()) { |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 904 | 843 |
| 905 // This check is required to avoid painting custom CSS scrollbars twice. | 844 // This check is required to avoid painting custom CSS scrollbars twice. |
| 906 if (paintingOverlayControls && !hasOverlayScrollbars()) | 845 if (paintingOverlayControls && !hasOverlayScrollbars()) |
| 907 return; | 846 return; |
| 908 | 847 |
| 909 // Now that we're sure the scrollbars are in the right place, paint them. | 848 // Now that we're sure the scrollbars are in the right place, paint them. |
| 910 if (m_hBar && !layerForHorizontalScrollbar()) | 849 if (m_hBar && !layerForHorizontalScrollbar()) |
| 911 m_hBar->paint(context, damageRect); | 850 m_hBar->paint(context, damageRect); |
| 912 if (m_vBar && !layerForVerticalScrollbar()) | 851 if (m_vBar && !layerForVerticalScrollbar()) |
| 913 m_vBar->paint(context, damageRect); | 852 m_vBar->paint(context, damageRect); |
| 914 | |
| 915 if (layerForScrollCorner()) | |
| 916 return; | |
| 917 | |
| 918 // We fill our scroll corner with white if we have a scrollbar that doesn't
run all the way up to the | |
| 919 // edge of the box. | |
| 920 paintScrollCorner(context, adjustedPaintOffset, damageRect); | |
| 921 | |
| 922 // Paint our resizer last, since it sits on top of the scroll corner. | |
| 923 paintResizer(context, adjustedPaintOffset, damageRect); | |
| 924 } | |
| 925 | |
| 926 void RenderLayerScrollableArea::paintScrollCorner(GraphicsContext* context, cons
t IntPoint& paintOffset, const IntRect& damageRect) | |
| 927 { | |
| 928 IntRect absRect = scrollCornerRect(); | |
| 929 absRect.moveBy(paintOffset); | |
| 930 if (!absRect.intersects(damageRect)) | |
| 931 return; | |
| 932 | |
| 933 // We don't want to paint white if we have overlay scrollbars, since we need | |
| 934 // to see what is behind it. | |
| 935 if (!hasOverlayScrollbars()) | |
| 936 context->fillRect(absRect, Color::white); | |
| 937 } | |
| 938 | |
| 939 bool RenderLayerScrollableArea::hitTestOverflowControls(HitTestResult& result, c
onst IntPoint& localPoint) | |
| 940 { | |
| 941 if (!hasScrollbar() && !box().canResize()) | |
| 942 return false; | |
| 943 | |
| 944 IntRect resizeControlRect; | |
| 945 if (box().style()->resize() != RESIZE_NONE) { | |
| 946 resizeControlRect = resizerCornerRect(box().pixelSnappedBorderBoxRect(),
ResizerForPointer); | |
| 947 if (resizeControlRect.contains(localPoint)) | |
| 948 return true; | |
| 949 } | |
| 950 | |
| 951 int resizeControlSize = max(resizeControlRect.height(), 0); | |
| 952 if (m_vBar && m_vBar->shouldParticipateInHitTesting()) { | |
| 953 LayoutRect vBarRect(verticalScrollbarStart(0, box().width()), | |
| 954 box().borderTop(), | |
| 955 m_vBar->width(), | |
| 956 box().height() - (box().borderTop() + box().borderBottom()) - (m_hBa
r ? m_hBar->height() : resizeControlSize)); | |
| 957 if (vBarRect.contains(localPoint)) { | |
| 958 result.setScrollbar(m_vBar.get()); | |
| 959 return true; | |
| 960 } | |
| 961 } | |
| 962 | |
| 963 resizeControlSize = max(resizeControlRect.width(), 0); | |
| 964 if (m_hBar && m_hBar->shouldParticipateInHitTesting()) { | |
| 965 LayoutRect hBarRect(horizontalScrollbarStart(0), | |
| 966 box().height() - box().borderBottom() - m_hBar->height(), | |
| 967 box().width() - (box().borderLeft() + box().borderRight()) - (m_vBar
? m_vBar->width() : resizeControlSize), | |
| 968 m_hBar->height()); | |
| 969 if (hBarRect.contains(localPoint)) { | |
| 970 result.setScrollbar(m_hBar.get()); | |
| 971 return true; | |
| 972 } | |
| 973 } | |
| 974 | |
| 975 return false; | |
| 976 } | |
| 977 | |
| 978 IntRect RenderLayerScrollableArea::resizerCornerRect(const IntRect& bounds, Resi
zerHitTestType resizerHitTestType) const | |
| 979 { | |
| 980 if (box().style()->resize() == RESIZE_NONE) | |
| 981 return IntRect(); | |
| 982 IntRect corner = cornerRect(box().style(), horizontalScrollbar(), verticalSc
rollbar(), bounds); | |
| 983 | |
| 984 if (resizerHitTestType == ResizerForTouch) { | |
| 985 // We make the resizer virtually larger for touch hit testing. With the | |
| 986 // expanding ratio k = ResizerControlExpandRatioForTouch, we first move | |
| 987 // the resizer rect (of width w & height h), by (-w * (k-1), -h * (k-1))
, | |
| 988 // then expand the rect by new_w/h = w/h * k. | |
| 989 int expandRatio = ResizerControlExpandRatioForTouch - 1; | |
| 990 corner.move(-corner.width() * expandRatio, -corner.height() * expandRati
o); | |
| 991 corner.expand(corner.width() * expandRatio, corner.height() * expandRati
o); | |
| 992 } | |
| 993 | |
| 994 return corner; | |
| 995 } | |
| 996 | |
| 997 IntRect RenderLayerScrollableArea::scrollCornerAndResizerRect() const | |
| 998 { | |
| 999 IntRect scrollCornerAndResizer = scrollCornerRect(); | |
| 1000 if (scrollCornerAndResizer.isEmpty()) | |
| 1001 scrollCornerAndResizer = resizerCornerRect(box().pixelSnappedBorderBoxRe
ct(), ResizerForPointer); | |
| 1002 return scrollCornerAndResizer; | |
| 1003 } | 853 } |
| 1004 | 854 |
| 1005 bool RenderLayerScrollableArea::overflowControlsIntersectRect(const IntRect& loc
alRect) const | 855 bool RenderLayerScrollableArea::overflowControlsIntersectRect(const IntRect& loc
alRect) const |
| 1006 { | 856 { |
| 1007 const IntRect borderBox = box().pixelSnappedBorderBoxRect(); | 857 const IntRect borderBox = box().pixelSnappedBorderBoxRect(); |
| 1008 | 858 |
| 1009 if (rectForHorizontalScrollbar(borderBox).intersects(localRect)) | 859 if (rectForHorizontalScrollbar(borderBox).intersects(localRect)) |
| 1010 return true; | 860 return true; |
| 1011 | 861 |
| 1012 if (rectForVerticalScrollbar(borderBox).intersects(localRect)) | 862 if (rectForVerticalScrollbar(borderBox).intersects(localRect)) |
| 1013 return true; | 863 return true; |
| 1014 | 864 |
| 1015 if (scrollCornerRect().intersects(localRect)) | |
| 1016 return true; | |
| 1017 | |
| 1018 if (resizerCornerRect(borderBox, ResizerForPointer).intersects(localRect)) | |
| 1019 return true; | |
| 1020 | |
| 1021 return false; | 865 return false; |
| 1022 } | 866 } |
| 1023 | 867 |
| 1024 void RenderLayerScrollableArea::paintResizer(GraphicsContext* context, const Int
Point& paintOffset, const IntRect& damageRect) | |
| 1025 { | |
| 1026 if (box().style()->resize() == RESIZE_NONE) | |
| 1027 return; | |
| 1028 | |
| 1029 IntRect absRect = resizerCornerRect(box().pixelSnappedBorderBoxRect(), Resiz
erForPointer); | |
| 1030 absRect.moveBy(paintOffset); | |
| 1031 if (!absRect.intersects(damageRect)) | |
| 1032 return; | |
| 1033 | |
| 1034 drawPlatformResizerImage(context, absRect); | |
| 1035 | |
| 1036 // Draw a frame around the resizer (1px grey line) if there are any scrollba
rs present. | |
| 1037 // Clipping will exclude the right and bottom edges of this frame. | |
| 1038 if (!hasOverlayScrollbars() && hasScrollbar()) { | |
| 1039 GraphicsContextStateSaver stateSaver(*context); | |
| 1040 context->clip(absRect); | |
| 1041 IntRect largerCorner = absRect; | |
| 1042 largerCorner.setSize(IntSize(largerCorner.width() + 1, largerCorner.heig
ht() + 1)); | |
| 1043 context->setStrokeColor(Color(217, 217, 217)); | |
| 1044 context->setStrokeThickness(1.0f); | |
| 1045 context->setFillColor(Color::transparent); | |
| 1046 context->drawRect(largerCorner); | |
| 1047 } | |
| 1048 } | |
| 1049 | |
| 1050 bool RenderLayerScrollableArea::isPointInResizeControl(const IntPoint& absoluteP
oint, ResizerHitTestType resizerHitTestType) const | |
| 1051 { | |
| 1052 if (!box().canResize()) | |
| 1053 return false; | |
| 1054 | |
| 1055 IntPoint localPoint = roundedIntPoint(box().absoluteToLocal(absolutePoint, U
seTransforms)); | |
| 1056 IntRect localBounds(0, 0, box().pixelSnappedWidth(), box().pixelSnappedHeigh
t()); | |
| 1057 return resizerCornerRect(localBounds, resizerHitTestType).contains(localPoin
t); | |
| 1058 } | |
| 1059 | |
| 1060 bool RenderLayerScrollableArea::hitTestResizerInFragments(const LayerFragments&
layerFragments, const HitTestLocation& hitTestLocation) const | |
| 1061 { | |
| 1062 if (!box().canResize()) | |
| 1063 return false; | |
| 1064 | |
| 1065 if (layerFragments.isEmpty()) | |
| 1066 return false; | |
| 1067 | |
| 1068 for (int i = layerFragments.size() - 1; i >= 0; --i) { | |
| 1069 const LayerFragment& fragment = layerFragments.at(i); | |
| 1070 if (fragment.backgroundRect.intersects(hitTestLocation) && resizerCorner
Rect(pixelSnappedIntRect(fragment.layerBounds), ResizerForPointer).contains(hitT
estLocation.roundedPoint())) | |
| 1071 return true; | |
| 1072 } | |
| 1073 | |
| 1074 return false; | |
| 1075 } | |
| 1076 | |
| 1077 void RenderLayerScrollableArea::updateResizerAreaSet() | |
| 1078 { | |
| 1079 LocalFrame* frame = box().frame(); | |
| 1080 if (!frame) | |
| 1081 return; | |
| 1082 FrameView* frameView = frame->view(); | |
| 1083 if (!frameView) | |
| 1084 return; | |
| 1085 if (box().canResize()) | |
| 1086 frameView->addResizerArea(box()); | |
| 1087 else | |
| 1088 frameView->removeResizerArea(box()); | |
| 1089 } | |
| 1090 | |
| 1091 void RenderLayerScrollableArea::drawPlatformResizerImage(GraphicsContext* contex
t, IntRect resizerCornerRect) | |
| 1092 { | |
| 1093 float deviceScaleFactor = blink::deviceScaleFactor(box().frame()); | |
| 1094 | |
| 1095 RefPtr<Image> resizeCornerImage; | |
| 1096 IntSize cornerResizerSize; | |
| 1097 if (deviceScaleFactor >= 2) { | |
| 1098 DEFINE_STATIC_REF(Image, resizeCornerImageHiRes, (Image::loadPlatformRes
ource("textAreaResizeCorner@2x"))); | |
| 1099 resizeCornerImage = resizeCornerImageHiRes; | |
| 1100 cornerResizerSize = resizeCornerImage->size(); | |
| 1101 cornerResizerSize.scale(0.5f); | |
| 1102 } else { | |
| 1103 DEFINE_STATIC_REF(Image, resizeCornerImageLoRes, (Image::loadPlatformRes
ource("textAreaResizeCorner"))); | |
| 1104 resizeCornerImage = resizeCornerImageLoRes; | |
| 1105 cornerResizerSize = resizeCornerImage->size(); | |
| 1106 } | |
| 1107 | |
| 1108 if (box().style()->shouldPlaceBlockDirectionScrollbarOnLogicalLeft()) { | |
| 1109 context->save(); | |
| 1110 context->translate(resizerCornerRect.x() + cornerResizerSize.width(), re
sizerCornerRect.y() + resizerCornerRect.height() - cornerResizerSize.height()); | |
| 1111 context->scale(-1.0, 1.0); | |
| 1112 context->drawImage(resizeCornerImage.get(), IntRect(IntPoint(), cornerRe
sizerSize)); | |
| 1113 context->restore(); | |
| 1114 return; | |
| 1115 } | |
| 1116 IntRect imageRect(resizerCornerRect.maxXMaxYCorner() - cornerResizerSize, co
rnerResizerSize); | |
| 1117 context->drawImage(resizeCornerImage.get(), imageRect); | |
| 1118 } | |
| 1119 | |
| 1120 IntSize RenderLayerScrollableArea::offsetFromResizeCorner(const IntPoint& absolu
tePoint) const | |
| 1121 { | |
| 1122 // Currently the resize corner is either the bottom right corner or the bott
om left corner. | |
| 1123 // FIXME: This assumes the location is 0, 0. Is this guaranteed to always be
the case? | |
| 1124 IntSize elementSize = layer()->size(); | |
| 1125 if (box().style()->shouldPlaceBlockDirectionScrollbarOnLogicalLeft()) | |
| 1126 elementSize.setWidth(0); | |
| 1127 IntPoint resizerPoint = IntPoint(elementSize); | |
| 1128 IntPoint localPoint = roundedIntPoint(box().absoluteToLocal(absolutePoint, U
seTransforms)); | |
| 1129 return localPoint - resizerPoint; | |
| 1130 } | |
| 1131 | |
| 1132 void RenderLayerScrollableArea::resize(const PlatformEvent& evt, const LayoutSiz
e& oldOffset) | |
| 1133 { | |
| 1134 // FIXME: This should be possible on generated content but is not right now. | |
| 1135 if (!inResizeMode() || !box().canResize() || !box().node()) | |
| 1136 return; | |
| 1137 | |
| 1138 ASSERT(box().node()->isElementNode()); | |
| 1139 Element* element = toElement(box().node()); | |
| 1140 | |
| 1141 Document& document = element->document(); | |
| 1142 | |
| 1143 IntPoint pos; | |
| 1144 const PlatformGestureEvent* gevt = 0; | |
| 1145 | |
| 1146 switch (evt.type()) { | |
| 1147 case PlatformEvent::MouseMoved: | |
| 1148 if (!document.frame()->eventHandler().mousePressed()) | |
| 1149 return; | |
| 1150 pos = static_cast<const PlatformMouseEvent*>(&evt)->position(); | |
| 1151 break; | |
| 1152 case PlatformEvent::GestureScrollUpdate: | |
| 1153 case PlatformEvent::GestureScrollUpdateWithoutPropagation: | |
| 1154 pos = static_cast<const PlatformGestureEvent*>(&evt)->position(); | |
| 1155 gevt = static_cast<const PlatformGestureEvent*>(&evt); | |
| 1156 pos = gevt->position(); | |
| 1157 pos.move(gevt->deltaX(), gevt->deltaY()); | |
| 1158 break; | |
| 1159 default: | |
| 1160 ASSERT_NOT_REACHED(); | |
| 1161 } | |
| 1162 | |
| 1163 float zoomFactor = box().style()->effectiveZoom(); | |
| 1164 | |
| 1165 LayoutSize newOffset = offsetFromResizeCorner(document.view()->windowToConte
nts(pos)); | |
| 1166 newOffset.setWidth(newOffset.width() / zoomFactor); | |
| 1167 newOffset.setHeight(newOffset.height() / zoomFactor); | |
| 1168 | |
| 1169 LayoutSize currentSize = LayoutSize(box().width() / zoomFactor, box().height
() / zoomFactor); | |
| 1170 LayoutSize minimumSize = element->minimumSizeForResizing().shrunkTo(currentS
ize); | |
| 1171 element->setMinimumSizeForResizing(minimumSize); | |
| 1172 | |
| 1173 LayoutSize adjustedOldOffset = LayoutSize(oldOffset.width() / zoomFactor, ol
dOffset.height() / zoomFactor); | |
| 1174 if (box().style()->shouldPlaceBlockDirectionScrollbarOnLogicalLeft()) { | |
| 1175 newOffset.setWidth(-newOffset.width()); | |
| 1176 adjustedOldOffset.setWidth(-adjustedOldOffset.width()); | |
| 1177 } | |
| 1178 | |
| 1179 LayoutSize difference = (currentSize + newOffset - adjustedOldOffset).expand
edTo(minimumSize) - currentSize; | |
| 1180 | |
| 1181 bool isBoxSizingBorder = box().style()->boxSizing() == BORDER_BOX; | |
| 1182 | |
| 1183 EResize resize = box().style()->resize(); | |
| 1184 if (resize != RESIZE_VERTICAL && difference.width()) { | |
| 1185 LayoutUnit baseWidth = box().width() - (isBoxSizingBorder ? LayoutUnit()
: box().borderAndPaddingWidth()); | |
| 1186 baseWidth = baseWidth / zoomFactor; | |
| 1187 element->setInlineStyleProperty(CSSPropertyWidth, roundToInt(baseWidth +
difference.width()), CSSPrimitiveValue::CSS_PX); | |
| 1188 } | |
| 1189 | |
| 1190 if (resize != RESIZE_HORIZONTAL && difference.height()) { | |
| 1191 LayoutUnit baseHeight = box().height() - (isBoxSizingBorder ? LayoutUnit
() : box().borderAndPaddingHeight()); | |
| 1192 baseHeight = baseHeight / zoomFactor; | |
| 1193 element->setInlineStyleProperty(CSSPropertyHeight, roundToInt(baseHeight
+ difference.height()), CSSPrimitiveValue::CSS_PX); | |
| 1194 } | |
| 1195 | |
| 1196 document.updateLayout(); | |
| 1197 | |
| 1198 // FIXME (Radar 4118564): We should also autoscroll the window as necessary
to keep the point under the cursor in view. | |
| 1199 } | |
| 1200 | |
| 1201 LayoutRect RenderLayerScrollableArea::exposeRect(const LayoutRect& rect, const S
crollAlignment& alignX, const ScrollAlignment& alignY) | 868 LayoutRect RenderLayerScrollableArea::exposeRect(const LayoutRect& rect, const S
crollAlignment& alignX, const ScrollAlignment& alignY) |
| 1202 { | 869 { |
| 1203 LayoutRect localExposeRect(box().absoluteToLocalQuad(FloatQuad(FloatRect(rec
t)), UseTransforms).boundingBox()); | 870 LayoutRect localExposeRect(box().absoluteToLocalQuad(FloatQuad(FloatRect(rec
t)), UseTransforms).boundingBox()); |
| 1204 LayoutRect layerBounds(0, 0, box().clientWidth(), box().clientHeight()); | 871 LayoutRect layerBounds(0, 0, box().clientWidth(), box().clientHeight()); |
| 1205 LayoutRect r = ScrollAlignment::getRectToExpose(layerBounds, localExposeRect
, alignX, alignY); | 872 LayoutRect r = ScrollAlignment::getRectToExpose(layerBounds, localExposeRect
, alignX, alignY); |
| 1206 | 873 |
| 1207 IntSize clampedScrollOffset = clampScrollOffset(adjustedScrollOffset() + toI
ntSize(roundedIntRect(r).location())); | 874 IntSize clampedScrollOffset = clampScrollOffset(adjustedScrollOffset() + toI
ntSize(roundedIntRect(r).location())); |
| 1208 if (clampedScrollOffset == adjustedScrollOffset()) | 875 if (clampedScrollOffset == adjustedScrollOffset()) |
| 1209 return rect; | 876 return rect; |
| 1210 | 877 |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1285 void RenderLayerScrollableArea::setTopmostScrollChild(RenderLayer* scrollChild) | 952 void RenderLayerScrollableArea::setTopmostScrollChild(RenderLayer* scrollChild) |
| 1286 { | 953 { |
| 1287 // We only want to track the topmost scroll child for scrollable areas with | 954 // We only want to track the topmost scroll child for scrollable areas with |
| 1288 // overlay scrollbars. | 955 // overlay scrollbars. |
| 1289 if (!hasOverlayScrollbars()) | 956 if (!hasOverlayScrollbars()) |
| 1290 return; | 957 return; |
| 1291 m_nextTopmostScrollChild = scrollChild; | 958 m_nextTopmostScrollChild = scrollChild; |
| 1292 } | 959 } |
| 1293 | 960 |
| 1294 } // namespace blink | 961 } // namespace blink |
| OLD | NEW |