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 26 matching lines...) Expand all Loading... |
37 * version of this file under the LGPL, indicate your decision by | 37 * version of this file under the LGPL, indicate your decision by |
38 * deletingthe provisions above and replace them with the notice and | 38 * deletingthe provisions above and replace them with the notice and |
39 * other provisions required by the MPL or the GPL, as the case may be. | 39 * other provisions required by the MPL or the GPL, as the case may be. |
40 * If you do not delete the provisions above, a recipient may use your | 40 * If you do not delete the provisions above, a recipient may use your |
41 * version of this file under any of the LGPL, the MPL or the GPL. | 41 * version of this file under any of the LGPL, the MPL or the GPL. |
42 */ | 42 */ |
43 | 43 |
44 #include "config.h" | 44 #include "config.h" |
45 #include "core/rendering/RenderLayer.h" | 45 #include "core/rendering/RenderLayer.h" |
46 | 46 |
| 47 #include "core/editing/FrameSelection.h" |
| 48 #include "core/inspector/InspectorInstrumentation.h" |
| 49 #include "core/page/EventHandler.h" |
47 #include "core/page/Frame.h" | 50 #include "core/page/Frame.h" |
48 #include "core/page/FrameView.h" | 51 #include "core/page/FrameView.h" |
49 #include "core/page/Page.h" | 52 #include "core/page/Page.h" |
50 #include "core/page/scrolling/ScrollingCoordinator.h" | 53 #include "core/page/scrolling/ScrollingCoordinator.h" |
51 #include "core/platform/ScrollAnimator.h" | 54 #include "core/platform/ScrollAnimator.h" |
| 55 #include "core/rendering/RenderLayerCompositor.h" |
| 56 #include "core/rendering/RenderView.h" |
52 | 57 |
53 namespace WebCore { | 58 namespace WebCore { |
54 | 59 |
55 RenderLayerScrollableArea::RenderLayerScrollableArea(RenderLayer* layer) | 60 RenderLayerScrollableArea::RenderLayerScrollableArea(RenderLayer* layer) |
56 : m_layer(layer) | 61 : m_layer(layer) |
| 62 , m_scrollDimensionsDirty(true) |
57 { | 63 { |
58 ScrollableArea::setConstrainsScrollingToContentEdge(false); | 64 ScrollableArea::setConstrainsScrollingToContentEdge(false); |
59 | 65 |
60 Node* node = renderer()->node(); | 66 Node* node = renderer()->node(); |
61 if (node && node->isElementNode()) { | 67 if (node && node->isElementNode()) { |
62 // We save and restore only the scrollOffset as the other scroll values
are recalculated. | 68 // We save and restore only the scrollOffset as the other scroll values
are recalculated. |
63 Element* element = toElement(node); | 69 Element* element = toElement(node); |
64 m_scrollOffset = element->savedLayerScrollOffset(); | 70 m_scrollOffset = element->savedLayerScrollOffset(); |
65 if (!m_scrollOffset.isZero()) | 71 if (!m_scrollOffset.isZero()) |
66 scrollAnimator()->setCurrentPosition(FloatPoint(m_scrollOffset.width
(), m_scrollOffset.height())); | 72 scrollAnimator()->setCurrentPosition(FloatPoint(m_scrollOffset.width
(), m_scrollOffset.height())); |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
178 IntPoint RenderLayerScrollableArea::convertFromContainingViewToScrollbar(const S
crollbar* scrollbar, const IntPoint& point) const | 184 IntPoint RenderLayerScrollableArea::convertFromContainingViewToScrollbar(const S
crollbar* scrollbar, const IntPoint& point) const |
179 { | 185 { |
180 return m_layer->convertFromContainingViewToScrollbar(scrollbar, point); | 186 return m_layer->convertFromContainingViewToScrollbar(scrollbar, point); |
181 } | 187 } |
182 | 188 |
183 int RenderLayerScrollableArea::scrollSize(ScrollbarOrientation orientation) cons
t | 189 int RenderLayerScrollableArea::scrollSize(ScrollbarOrientation orientation) cons
t |
184 { | 190 { |
185 return m_layer->scrollSize(orientation); | 191 return m_layer->scrollSize(orientation); |
186 } | 192 } |
187 | 193 |
188 void RenderLayerScrollableArea::setScrollOffset(const IntPoint& offset) | 194 void RenderLayerScrollableArea::setScrollOffset(const IntPoint& newScrollOffset) |
189 { | 195 { |
190 m_layer->setScrollOffset(offset); | 196 if (!toRenderBox(renderer())->isMarquee()) { |
| 197 // Ensure that the dimensions will be computed if they need to be (for o
verflow:hidden blocks). |
| 198 if (m_scrollDimensionsDirty) |
| 199 computeScrollDimensions(); |
| 200 } |
| 201 |
| 202 if (scrollOffset() == toIntSize(newScrollOffset)) |
| 203 return; |
| 204 |
| 205 setScrollOffset(toIntSize(newScrollOffset)); |
| 206 |
| 207 Frame* frame = renderer()->frame(); |
| 208 InspectorInstrumentation::willScrollLayer(renderer()); |
| 209 |
| 210 RenderView* view = renderer()->view(); |
| 211 |
| 212 // We should have a RenderView if we're trying to scroll. |
| 213 ASSERT(view); |
| 214 |
| 215 // Update the positions of our child layers (if needed as only fixed layers
should be impacted by a scroll). |
| 216 // We don't update compositing layers, because we need to do a deep update f
rom the compositing ancestor. |
| 217 bool inLayout = view ? view->frameView()->isInLayout() : false; |
| 218 if (!inLayout) { |
| 219 // If we're in the middle of layout, we'll just update layers once layou
t has finished. |
| 220 m_layer->updateLayerPositionsAfterOverflowScroll(); |
| 221 if (view) { |
| 222 // Update regions, scrolling may change the clip of a particular reg
ion. |
| 223 view->frameView()->updateAnnotatedRegions(); |
| 224 view->updateWidgetPositions(); |
| 225 } |
| 226 |
| 227 m_layer->updateCompositingLayersAfterScroll(); |
| 228 } |
| 229 |
| 230 RenderLayerModelObject* repaintContainer = renderer()->containerForRepaint()
; |
| 231 if (frame) { |
| 232 // The caret rect needs to be invalidated after scrolling |
| 233 frame->selection().setCaretRectNeedsUpdate(); |
| 234 |
| 235 FloatQuad quadForFakeMouseMoveEvent = FloatQuad(m_layer->m_repaintRect); |
| 236 if (repaintContainer) |
| 237 quadForFakeMouseMoveEvent = repaintContainer->localToAbsoluteQuad(qu
adForFakeMouseMoveEvent); |
| 238 frame->eventHandler()->dispatchFakeMouseMoveEventSoonInQuad(quadForFakeM
ouseMoveEvent); |
| 239 } |
| 240 |
| 241 bool requiresRepaint = true; |
| 242 |
| 243 if (m_layer->compositor()->inCompositingMode() && m_layer->usesCompositedScr
olling()) |
| 244 requiresRepaint = false; |
| 245 |
| 246 // Just schedule a full repaint of our object. |
| 247 if (view && requiresRepaint) |
| 248 renderer()->repaintUsingContainer(repaintContainer, pixelSnappedIntRect(
m_layer->m_repaintRect)); |
| 249 |
| 250 // Schedule the scroll DOM event. |
| 251 if (renderer()->node()) |
| 252 renderer()->node()->document().eventQueue()->enqueueOrDispatchScrollEven
t(renderer()->node(), DocumentEventQueue::ScrollEventElementTarget); |
| 253 |
| 254 InspectorInstrumentation::didScrollLayer(renderer()); |
191 } | 255 } |
192 | 256 |
193 IntPoint RenderLayerScrollableArea::scrollPosition() const | 257 IntPoint RenderLayerScrollableArea::scrollPosition() const |
194 { | 258 { |
195 return IntPoint(m_scrollOffset); | 259 return IntPoint(m_scrollOffset); |
196 } | 260 } |
197 | 261 |
198 IntPoint RenderLayerScrollableArea::minimumScrollPosition() const | 262 IntPoint RenderLayerScrollableArea::minimumScrollPosition() const |
199 { | 263 { |
200 return m_layer->minimumScrollPosition(); | 264 return -scrollOrigin(); |
201 } | 265 } |
202 | 266 |
203 IntPoint RenderLayerScrollableArea::maximumScrollPosition() const | 267 IntPoint RenderLayerScrollableArea::maximumScrollPosition() const |
204 { | 268 { |
205 return m_layer->maximumScrollPosition(); | 269 RenderBox* box = toRenderBox(renderer()); |
| 270 |
| 271 if (!box->hasOverflowClip()) |
| 272 return -scrollOrigin(); |
| 273 |
| 274 return -scrollOrigin() + enclosingIntRect(m_overflowRect).size() - enclosing
IntRect(box->clientBoxRect()).size(); |
206 } | 275 } |
207 | 276 |
208 IntRect RenderLayerScrollableArea::visibleContentRect(VisibleContentRectIncludes
Scrollbars scrollbarInclusion) const | 277 IntRect RenderLayerScrollableArea::visibleContentRect(VisibleContentRectIncludes
Scrollbars scrollbarInclusion) const |
209 { | 278 { |
210 int verticalScrollbarWidth = 0; | 279 int verticalScrollbarWidth = 0; |
211 int horizontalScrollbarHeight = 0; | 280 int horizontalScrollbarHeight = 0; |
212 if (scrollbarInclusion == IncludeScrollbars) { | 281 if (scrollbarInclusion == IncludeScrollbars) { |
213 verticalScrollbarWidth = (verticalScrollbar() && !verticalScrollbar()->i
sOverlayScrollbar()) ? verticalScrollbar()->width() : 0; | 282 verticalScrollbarWidth = (verticalScrollbar() && !verticalScrollbar()->i
sOverlayScrollbar()) ? verticalScrollbar()->width() : 0; |
214 horizontalScrollbarHeight = (horizontalScrollbar() && !horizontalScrollb
ar()->isOverlayScrollbar()) ? horizontalScrollbar()->height() : 0; | 283 horizontalScrollbarHeight = (horizontalScrollbar() && !horizontalScrollb
ar()->isOverlayScrollbar()) ? horizontalScrollbar()->height() : 0; |
215 } | 284 } |
216 | 285 |
217 return IntRect(IntPoint(scrollXOffset(), scrollYOffset()), | 286 return IntRect(IntPoint(scrollXOffset(), scrollYOffset()), |
218 IntSize(max(0, m_layer->size().width() - verticalScrollbarWidth), max(0,
m_layer->size().height() - horizontalScrollbarHeight))); | 287 IntSize(max(0, m_layer->size().width() - verticalScrollbarWidth), max(0,
m_layer->size().height() - horizontalScrollbarHeight))); |
219 } | 288 } |
220 | 289 |
221 int RenderLayerScrollableArea::visibleHeight() const | 290 int RenderLayerScrollableArea::visibleHeight() const |
222 { | 291 { |
223 return m_layer->visibleHeight(); | 292 return m_layer->visibleHeight(); |
224 } | 293 } |
225 | 294 |
226 int RenderLayerScrollableArea::visibleWidth() const | 295 int RenderLayerScrollableArea::visibleWidth() const |
227 { | 296 { |
228 return m_layer->visibleWidth(); | 297 return m_layer->visibleWidth(); |
229 } | 298 } |
230 | 299 |
231 IntSize RenderLayerScrollableArea::contentsSize() const | 300 IntSize RenderLayerScrollableArea::contentsSize() const |
232 { | 301 { |
233 return m_layer->contentsSize(); | 302 return IntSize(scrollWidth(), scrollHeight()); |
234 } | 303 } |
235 | 304 |
236 IntSize RenderLayerScrollableArea::overhangAmount() const | 305 IntSize RenderLayerScrollableArea::overhangAmount() const |
237 { | 306 { |
238 return m_layer->overhangAmount(); | 307 return m_layer->overhangAmount(); |
239 } | 308 } |
240 | 309 |
241 IntPoint RenderLayerScrollableArea::lastKnownMousePosition() const | 310 IntPoint RenderLayerScrollableArea::lastKnownMousePosition() const |
242 { | 311 { |
243 return m_layer->lastKnownMousePosition(); | 312 return m_layer->lastKnownMousePosition(); |
(...skipping 24 matching lines...) Expand all Loading... |
268 return m_layer->pageStep(orientation); | 337 return m_layer->pageStep(orientation); |
269 } | 338 } |
270 | 339 |
271 RenderLayerModelObject* RenderLayerScrollableArea::renderer() const | 340 RenderLayerModelObject* RenderLayerScrollableArea::renderer() const |
272 { | 341 { |
273 // Only RenderBoxes can have a scrollable area, however we allocate an | 342 // Only RenderBoxes can have a scrollable area, however we allocate an |
274 // RenderLayerScrollableArea for any renderers (FIXME). | 343 // RenderLayerScrollableArea for any renderers (FIXME). |
275 return m_layer->renderer(); | 344 return m_layer->renderer(); |
276 } | 345 } |
277 | 346 |
| 347 int RenderLayerScrollableArea::scrollWidth() const |
| 348 { |
| 349 RenderBox* box = toRenderBox(renderer()); |
| 350 if (m_scrollDimensionsDirty) |
| 351 const_cast<RenderLayerScrollableArea*>(this)->computeScrollDimensions(); |
| 352 return snapSizeToPixel(m_overflowRect.width(), box->clientLeft() + box->x())
; |
| 353 } |
| 354 |
| 355 int RenderLayerScrollableArea::scrollHeight() const |
| 356 { |
| 357 RenderBox* box = toRenderBox(renderer()); |
| 358 if (m_scrollDimensionsDirty) |
| 359 const_cast<RenderLayerScrollableArea*>(this)->computeScrollDimensions(); |
| 360 return snapSizeToPixel(m_overflowRect.height(), box->clientTop() + box->y())
; |
| 361 } |
| 362 |
| 363 void RenderLayerScrollableArea::computeScrollDimensions() |
| 364 { |
| 365 RenderBox* box = toRenderBox(renderer()); |
| 366 |
| 367 m_scrollDimensionsDirty = false; |
| 368 |
| 369 m_overflowRect = box->layoutOverflowRect(); |
| 370 box->flipForWritingMode(m_overflowRect); |
| 371 |
| 372 int scrollableLeftOverflow = m_overflowRect.x() - box->borderLeft(); |
| 373 int scrollableTopOverflow = m_overflowRect.y() - box->borderTop(); |
| 374 setScrollOrigin(IntPoint(-scrollableLeftOverflow, -scrollableTopOverflow)); |
| 375 } |
| 376 |
| 377 void RenderLayerScrollableArea::scrollToOffset(const IntSize& scrollOffset, Scro
llOffsetClamping clamp) |
| 378 { |
| 379 IntSize newScrollOffset = clamp == ScrollOffsetClamped ? clampScrollOffset(s
crollOffset) : scrollOffset; |
| 380 if (newScrollOffset != adjustedScrollOffset()) |
| 381 scrollToOffsetWithoutAnimation(-scrollOrigin() + newScrollOffset); |
| 382 } |
| 383 |
| 384 void RenderLayerScrollableArea::updateAfterLayout() |
| 385 { |
| 386 m_scrollDimensionsDirty = true; |
| 387 IntSize originalScrollOffset = adjustedScrollOffset(); |
| 388 |
| 389 computeScrollDimensions(); |
| 390 |
| 391 if (!toRenderBox(renderer())->isMarquee()) { |
| 392 // Layout may cause us to be at an invalid scroll position. In this case
we need |
| 393 // to pull our scroll offsets back to the max (or push them up to the mi
n). |
| 394 IntSize clampedScrollOffset = clampScrollOffset(adjustedScrollOffset()); |
| 395 if (clampedScrollOffset != adjustedScrollOffset()) |
| 396 scrollToOffset(clampedScrollOffset); |
| 397 } |
| 398 |
| 399 if (originalScrollOffset != adjustedScrollOffset()) |
| 400 scrollToOffsetWithoutAnimation(-scrollOrigin() + adjustedScrollOffset())
; |
| 401 } |
| 402 |
| 403 bool RenderLayerScrollableArea::hasHorizontalOverflow() const |
| 404 { |
| 405 ASSERT(!m_scrollDimensionsDirty); |
| 406 |
| 407 return scrollWidth() > toRenderBox(renderer())->pixelSnappedClientWidth(); |
| 408 } |
| 409 |
| 410 bool RenderLayerScrollableArea::hasVerticalOverflow() const |
| 411 { |
| 412 ASSERT(!m_scrollDimensionsDirty); |
| 413 |
| 414 return scrollHeight() > toRenderBox(renderer())->pixelSnappedClientHeight(); |
| 415 } |
| 416 |
| 417 bool RenderLayerScrollableArea::hasScrollableHorizontalOverflow() const |
| 418 { |
| 419 return hasHorizontalOverflow() && toRenderBox(renderer())->scrollsOverflowX(
); |
| 420 } |
| 421 |
| 422 bool RenderLayerScrollableArea::hasScrollableVerticalOverflow() const |
| 423 { |
| 424 return hasVerticalOverflow() && toRenderBox(renderer())->scrollsOverflowY(); |
| 425 } |
| 426 |
| 427 void RenderLayerScrollableArea::updateAfterStyleChange(const RenderStyle*) |
| 428 { |
| 429 if (!m_scrollDimensionsDirty) |
| 430 m_layer->updateScrollableAreaSet(hasScrollableHorizontalOverflow() || ha
sScrollableVerticalOverflow()); |
| 431 } |
| 432 |
| 433 IntSize RenderLayerScrollableArea::clampScrollOffset(const IntSize& scrollOffset
) const |
| 434 { |
| 435 RenderBox* box = toRenderBox(renderer()); |
| 436 |
| 437 int maxX = scrollWidth() - box->pixelSnappedClientWidth(); |
| 438 int maxY = scrollHeight() - box->pixelSnappedClientHeight(); |
| 439 |
| 440 int x = std::max(std::min(scrollOffset.width(), maxX), 0); |
| 441 int y = std::max(std::min(scrollOffset.height(), maxY), 0); |
| 442 return IntSize(x, y); |
| 443 } |
| 444 |
278 } // Namespace WebCore | 445 } // Namespace WebCore |
OLD | NEW |