Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(118)

Side by Side Diff: sky/engine/core/rendering/RenderLayerScrollableArea.cpp

Issue 877043002: Remove RenderLayerScrollableArea (Closed) Base URL: git@github.com:domokit/mojo.git@master
Patch Set: Created 5 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 /*
2 * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012 Apple Inc. All rights reserved.
3 *
4 * Portions are Copyright (C) 1998 Netscape Communications Corporation.
5 *
6 * Other contributors:
7 * Robert O'Callahan <roc+@cs.cmu.edu>
8 * David Baron <dbaron@fas.harvard.edu>
9 * Christian Biesinger <cbiesinger@web.de>
10 * Randall Jesup <rjesup@wgate.com>
11 * Roland Mainz <roland.mainz@informatik.med.uni-giessen.de>
12 * Josh Soref <timeless@mac.com>
13 * Boris Zbarsky <bzbarsky@mit.edu>
14 *
15 * This library is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU Lesser General Public
17 * License as published by the Free Software Foundation; either
18 * version 2.1 of the License, or (at your option) any later version.
19 *
20 * This library is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23 * Lesser General Public License for more details.
24 *
25 * You should have received a copy of the GNU Lesser General Public
26 * License along with this library; if not, write to the Free Software
27 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 US A
28 *
29 * Alternatively, the contents of this file may be used under the terms
30 * of either the Mozilla Public License Version 1.1, found at
31 * http://www.mozilla.org/MPL/ (the "MPL") or the GNU General Public
32 * License Version 2.0, found at http://www.fsf.org/copyleft/gpl.html
33 * (the "GPL"), in which case the provisions of the MPL or the GPL are
34 * applicable instead of those above. If you wish to allow use of your
35 * version of this file only under the terms of one of those two
36 * licenses (the MPL or the GPL) and not to allow others to use your
37 * version of this file under the LGPL, indicate your decision by
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.
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.
42 */
43
44 #include "sky/engine/config.h"
45 #include "sky/engine/core/rendering/RenderLayer.h"
46
47 #include "sky/engine/core/dom/Node.h"
48 #include "sky/engine/core/dom/shadow/ShadowRoot.h"
49 #include "sky/engine/core/editing/FrameSelection.h"
50 #include "sky/engine/core/frame/FrameView.h"
51 #include "sky/engine/core/frame/LocalFrame.h"
52 #include "sky/engine/core/inspector/InspectorTraceEvents.h"
53 #include "sky/engine/core/page/EventHandler.h"
54 #include "sky/engine/core/page/FocusController.h"
55 #include "sky/engine/core/page/Page.h"
56 #include "sky/engine/core/rendering/HitTestResult.h"
57 #include "sky/engine/core/rendering/RenderGeometryMap.h"
58 #include "sky/engine/core/rendering/RenderView.h"
59 #include "sky/engine/platform/graphics/GraphicsContextStateSaver.h"
60 #include "sky/engine/platform/scroll/ScrollAnimator.h"
61 #include "sky/engine/platform/scroll/Scrollbar.h"
62 #include "sky/engine/public/platform/Platform.h"
63
64 namespace blink {
65
66 RenderLayerScrollableArea::RenderLayerScrollableArea(RenderLayer& layer)
67 : m_layer(layer)
68 , m_scrollsOverflow(false)
69 , m_scrollDimensionsDirty(true)
70 , m_nextTopmostScrollChild(0)
71 , m_topmostScrollChild(0)
72 , m_needsCompositedScrolling(false)
73 {
74 ScrollableArea::setConstrainsScrollingToContentEdge(false);
75
76 Node* node = box().node();
77 if (node && node->isElementNode()) {
78 // We save and restore only the scrollOffset as the other scroll values are recalculated.
79 Element* element = toElement(node);
80 m_scrollOffset = element->savedLayerScrollOffset();
81 if (!m_scrollOffset.isZero())
82 scrollAnimator()->setCurrentPosition(FloatPoint(m_scrollOffset.width (), m_scrollOffset.height()));
83 element->setSavedLayerScrollOffset(IntSize());
84 }
85 }
86
87 RenderLayerScrollableArea::~RenderLayerScrollableArea()
88 {
89 if (!box().documentBeingDestroyed()) {
90 Node* node = box().node();
91 if (node && node->isElementNode())
92 toElement(node)->setSavedLayerScrollOffset(m_scrollOffset);
93 }
94
95 destroyScrollbar(HorizontalScrollbar);
96 destroyScrollbar(VerticalScrollbar);
97 }
98
99 HostWindow* RenderLayerScrollableArea::hostWindow() const
100 {
101 return box().frame()->page();
102 }
103
104 bool RenderLayerScrollableArea::isActive() const
105 {
106 Page* page = box().frame()->page();
107 return page && page->focusController().isActive();
108 }
109
110 static int cornerStart(const RenderStyle* style, int minX, int maxX, int thickne ss)
111 {
112 if (style->shouldPlaceBlockDirectionScrollbarOnLogicalLeft())
113 return minX + style->borderLeftWidth();
114 return maxX - thickness - style->borderRightWidth();
115 }
116
117 IntRect RenderLayerScrollableArea::scrollCornerRect() const
118 {
119 // We have a scrollbar corner when a scrollbar is visible and not filling th e entire length of the box.
120 // This happens when both scrollbars are present.
121 const Scrollbar* horizontalBar = horizontalScrollbar();
122 const Scrollbar* verticalBar = verticalScrollbar();
123 if (!horizontalBar || !verticalBar)
124 return IntRect();
125
126 const RenderStyle* style = box().style();
127 int horizontalThickness = verticalBar->width();
128 int verticalThickness = horizontalBar->height();
129 const IntRect& bounds = box().pixelSnappedBorderBoxRect();
130 return IntRect(cornerStart(style, bounds.x(), bounds.maxX(), horizontalThick ness),
131 bounds.maxY() - verticalThickness - style->borderBottomWidth(),
132 horizontalThickness, verticalThickness);
133 }
134
135 IntRect RenderLayerScrollableArea::convertFromScrollbarToContainingView(const Sc rollbar* scrollbar, const IntRect& scrollbarRect) const
136 {
137 RenderView* view = box().view();
138 if (!view)
139 return scrollbarRect;
140
141 IntRect rect = scrollbarRect;
142 rect.move(scrollbarOffset(scrollbar));
143
144 return view->frameView()->convertFromRenderer(box(), rect);
145 }
146
147 IntRect RenderLayerScrollableArea::convertFromContainingViewToScrollbar(const Sc rollbar* scrollbar, const IntRect& parentRect) const
148 {
149 RenderView* view = box().view();
150 if (!view)
151 return parentRect;
152
153 IntRect rect = view->frameView()->convertToRenderer(box(), parentRect);
154 rect.move(-scrollbarOffset(scrollbar));
155 return rect;
156 }
157
158 IntPoint RenderLayerScrollableArea::convertFromScrollbarToContainingView(const S crollbar* scrollbar, const IntPoint& scrollbarPoint) const
159 {
160 RenderView* view = box().view();
161 if (!view)
162 return scrollbarPoint;
163
164 IntPoint point = scrollbarPoint;
165 point.move(scrollbarOffset(scrollbar));
166 return view->frameView()->convertFromRenderer(box(), point);
167 }
168
169 IntPoint RenderLayerScrollableArea::convertFromContainingViewToScrollbar(const S crollbar* scrollbar, const IntPoint& parentPoint) const
170 {
171 RenderView* view = box().view();
172 if (!view)
173 return parentPoint;
174
175 IntPoint point = view->frameView()->convertToRenderer(box(), parentPoint);
176
177 point.move(-scrollbarOffset(scrollbar));
178 return point;
179 }
180
181 int RenderLayerScrollableArea::scrollSize(ScrollbarOrientation orientation) cons t
182 {
183 IntSize scrollDimensions = maximumScrollPosition() - minimumScrollPosition() ;
184 return (orientation == HorizontalScrollbar) ? scrollDimensions.width() : scr ollDimensions.height();
185 }
186
187 void RenderLayerScrollableArea::setScrollOffset(const IntPoint& newScrollOffset)
188 {
189 // Ensure that the dimensions will be computed if they need to be (for overf low:hidden blocks).
190 if (m_scrollDimensionsDirty)
191 computeScrollDimensions();
192
193 if (scrollOffset() == toIntSize(newScrollOffset))
194 return;
195
196 setScrollOffset(toIntSize(newScrollOffset));
197
198 LocalFrame* frame = box().frame();
199 ASSERT(frame);
200
201 RefPtr<FrameView> frameView = box().frameView();
202
203 TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "ScrollLayer", "data", InspectorScrollLayerEvent::data(&box()));
204
205 // Update the positions of our child layers (if needed as only fixed layers should be impacted by a scroll).
206 // We don't update compositing layers, because we need to do a deep update f rom the compositing ancestor.
207 if (!frameView->isInPerformLayout()) {
208 // If we're in the middle of layout, we'll just update layers once layou t has finished.
209 // FIXME(sky): Do we still need this?
210 layer()->clipper().clearClipRectsIncludingDescendants();
211 }
212
213 // The caret rect needs to be invalidated after scrolling
214 frame->selection().setCaretRectNeedsUpdate();
215
216 // Schedule the scroll DOM event.
217 if (box().node())
218 box().node()->document().enqueueScrollEventForNode(box().node());
219 }
220
221 IntPoint RenderLayerScrollableArea::scrollPosition() const
222 {
223 return IntPoint(m_scrollOffset);
224 }
225
226 IntPoint RenderLayerScrollableArea::minimumScrollPosition() const
227 {
228 return -scrollOrigin();
229 }
230
231 IntPoint RenderLayerScrollableArea::maximumScrollPosition() const
232 {
233 if (!box().hasOverflowClip())
234 return -scrollOrigin();
235 return -scrollOrigin() + IntPoint(pixelSnappedScrollWidth(), pixelSnappedScr ollHeight()) - enclosingIntRect(box().clientBoxRect()).size();
236 }
237
238 IntRect RenderLayerScrollableArea::visibleContentRect(IncludeScrollbarsInRect sc rollbarInclusion) const
239 {
240 return IntRect(IntPoint(scrollXOffset(), scrollYOffset()),
241 IntSize(max(0, layer()->size().width()), max(0, layer()->size().height() )));
242 }
243
244 int RenderLayerScrollableArea::visibleHeight() const
245 {
246 return layer()->size().height();
247 }
248
249 int RenderLayerScrollableArea::visibleWidth() const
250 {
251 return layer()->size().width();
252 }
253
254 IntSize RenderLayerScrollableArea::contentsSize() const
255 {
256 return IntSize(scrollWidth(), scrollHeight());
257 }
258
259 IntSize RenderLayerScrollableArea::overhangAmount() const
260 {
261 return IntSize();
262 }
263
264 IntRect RenderLayerScrollableArea::scrollableAreaBoundingBox() const
265 {
266 return box().absoluteBoundingBoxRect();
267 }
268
269 bool RenderLayerScrollableArea::userInputScrollable(ScrollbarOrientation orienta tion) const
270 {
271 EOverflow overflowStyle = (orientation == HorizontalScrollbar) ?
272 box().style()->overflowX() : box().style()->overflowY();
273 return (overflowStyle == OSCROLL || overflowStyle == OAUTO || overflowStyle == OOVERLAY);
274 }
275
276 bool RenderLayerScrollableArea::shouldPlaceVerticalScrollbarOnLeft() const
277 {
278 return box().style()->shouldPlaceBlockDirectionScrollbarOnLogicalLeft();
279 }
280
281 int RenderLayerScrollableArea::pageStep(ScrollbarOrientation orientation) const
282 {
283 int length = (orientation == HorizontalScrollbar) ?
284 box().pixelSnappedClientWidth() : box().pixelSnappedClientHeight();
285 int minPageStep = static_cast<float>(length) * ScrollableArea::minFractionTo StepWhenPaging();
286 int pageStep = max(minPageStep, length - ScrollableArea::maxOverlapBetweenPa ges());
287
288 return max(pageStep, 1);
289 }
290
291 RenderBox& RenderLayerScrollableArea::box() const
292 {
293 return *m_layer.renderBox();
294 }
295
296 RenderLayer* RenderLayerScrollableArea::layer() const
297 {
298 return &m_layer;
299 }
300
301 LayoutUnit RenderLayerScrollableArea::scrollWidth() const
302 {
303 if (m_scrollDimensionsDirty)
304 const_cast<RenderLayerScrollableArea*>(this)->computeScrollDimensions();
305 return m_overflowRect.width();
306 }
307
308 LayoutUnit RenderLayerScrollableArea::scrollHeight() const
309 {
310 if (m_scrollDimensionsDirty)
311 const_cast<RenderLayerScrollableArea*>(this)->computeScrollDimensions();
312 return m_overflowRect.height();
313 }
314
315 int RenderLayerScrollableArea::pixelSnappedScrollWidth() const
316 {
317 return snapSizeToPixel(scrollWidth(), box().clientLeft() + box().x());
318 }
319
320 int RenderLayerScrollableArea::pixelSnappedScrollHeight() const
321 {
322 return snapSizeToPixel(scrollHeight(), box().clientTop() + box().y());
323 }
324
325 void RenderLayerScrollableArea::computeScrollDimensions()
326 {
327 m_scrollDimensionsDirty = false;
328
329 m_overflowRect = box().layoutOverflowRect();
330
331 int scrollableLeftOverflow = m_overflowRect.x() - box().borderLeft();
332 int scrollableTopOverflow = m_overflowRect.y() - box().borderTop();
333 setScrollOrigin(IntPoint(-scrollableLeftOverflow, -scrollableTopOverflow));
334 }
335
336 void RenderLayerScrollableArea::scrollToOffset(const IntSize& scrollOffset, Scro llOffsetClamping clamp)
337 {
338 IntSize newScrollOffset = clamp == ScrollOffsetClamped ? clampScrollOffset(s crollOffset) : scrollOffset;
339 if (newScrollOffset != adjustedScrollOffset())
340 scrollToOffsetWithoutAnimation(-scrollOrigin() + newScrollOffset);
341 }
342
343 void RenderLayerScrollableArea::updateAfterLayout()
344 {
345 m_scrollDimensionsDirty = true;
346 IntSize originalScrollOffset = adjustedScrollOffset();
347
348 computeScrollDimensions();
349
350 // Layout may cause us to be at an invalid scroll position. In this case we need
351 // to pull our scroll offsets back to the max (or push them up to the min).
352 IntSize clampedScrollOffset = clampScrollOffset(adjustedScrollOffset());
353 if (clampedScrollOffset != adjustedScrollOffset())
354 scrollToOffset(clampedScrollOffset);
355
356 if (originalScrollOffset != adjustedScrollOffset())
357 scrollToOffsetWithoutAnimation(-scrollOrigin() + adjustedScrollOffset()) ;
358
359 bool hasHorizontalOverflow = this->hasHorizontalOverflow();
360 bool hasVerticalOverflow = this->hasVerticalOverflow();
361
362 // overflow:auto may need to lay out again if scrollbars got added/removed.
363 if (box().hasAutoHorizontalScrollbar())
364 setHasHorizontalScrollbar(hasHorizontalOverflow);
365 if (box().hasAutoVerticalScrollbar())
366 setHasVerticalScrollbar(hasVerticalOverflow);
367
368 // Set up the range (and page step/line step).
369 if (Scrollbar* horizontalScrollbar = this->horizontalScrollbar()) {
370 int clientWidth = box().pixelSnappedClientWidth();
371 horizontalScrollbar->setProportion(clientWidth, overflowRect().width());
372 }
373 if (Scrollbar* verticalScrollbar = this->verticalScrollbar()) {
374 int clientHeight = box().pixelSnappedClientHeight();
375 verticalScrollbar->setProportion(clientHeight, overflowRect().height());
376 }
377
378 bool hasOverflow = hasScrollableHorizontalOverflow() || hasScrollableVertica lOverflow();
379 updateScrollableAreaSet(hasOverflow);
380
381 if (hasOverflow) {
382 positionOverflowControls(IntSize());
383 }
384 }
385
386 bool RenderLayerScrollableArea::hasHorizontalOverflow() const
387 {
388 ASSERT(!m_scrollDimensionsDirty);
389
390 return pixelSnappedScrollWidth() > box().pixelSnappedClientWidth();
391 }
392
393 bool RenderLayerScrollableArea::hasVerticalOverflow() const
394 {
395 ASSERT(!m_scrollDimensionsDirty);
396
397 return pixelSnappedScrollHeight() > box().pixelSnappedClientHeight();
398 }
399
400 bool RenderLayerScrollableArea::hasScrollableHorizontalOverflow() const
401 {
402 return hasHorizontalOverflow() && box().scrollsOverflowX();
403 }
404
405 bool RenderLayerScrollableArea::hasScrollableVerticalOverflow() const
406 {
407 return hasVerticalOverflow() && box().scrollsOverflowY();
408 }
409
410 static bool overflowRequiresScrollbar(EOverflow overflow)
411 {
412 return overflow == OSCROLL;
413 }
414
415 static bool overflowDefinesAutomaticScrollbar(EOverflow overflow)
416 {
417 return overflow == OAUTO || overflow == OOVERLAY;
418 }
419
420 void RenderLayerScrollableArea::updateAfterStyleChange(const RenderStyle* oldSty le)
421 {
422 if (!m_scrollDimensionsDirty)
423 updateScrollableAreaSet(hasScrollableHorizontalOverflow() || hasScrollab leVerticalOverflow());
424
425 EOverflow overflowX = box().style()->overflowX();
426 EOverflow overflowY = box().style()->overflowY();
427
428 // To avoid doing a relayout in updateScrollbarsAfterLayout, we try to keep any automatic scrollbar that was already present.
429 // FIXME(sky): We only have overlay scrollbars, so we never do a relayout
430 // due to scrollbars. We probably don't need to do this at all. Also,
431 // updateScrollbarsAfterLayout not longer exists.
432 bool needsHorizontalScrollbar = (hasHorizontalScrollbar() && overflowDefines AutomaticScrollbar(overflowX)) || overflowRequiresScrollbar(overflowX);
433 bool needsVerticalScrollbar = (hasVerticalScrollbar() && overflowDefinesAuto maticScrollbar(overflowY)) || overflowRequiresScrollbar(overflowY);
434 setHasHorizontalScrollbar(needsHorizontalScrollbar);
435 setHasVerticalScrollbar(needsVerticalScrollbar);
436 }
437
438 bool RenderLayerScrollableArea::updateAfterCompositingChange()
439 {
440 const bool layersChanged = m_topmostScrollChild != m_nextTopmostScrollChild;
441 m_topmostScrollChild = m_nextTopmostScrollChild;
442 m_nextTopmostScrollChild = nullptr;
443 return layersChanged;
444 }
445
446 void RenderLayerScrollableArea::updateAfterOverflowRecalc()
447 {
448 computeScrollDimensions();
449 if (Scrollbar* horizontalScrollbar = this->horizontalScrollbar()) {
450 int clientWidth = box().pixelSnappedClientWidth();
451 horizontalScrollbar->setProportion(clientWidth, overflowRect().width());
452 }
453 if (Scrollbar* verticalScrollbar = this->verticalScrollbar()) {
454 int clientHeight = box().pixelSnappedClientHeight();
455 verticalScrollbar->setProportion(clientHeight, overflowRect().height());
456 }
457
458 bool hasHorizontalOverflow = this->hasHorizontalOverflow();
459 bool hasVerticalOverflow = this->hasVerticalOverflow();
460 bool autoHorizontalScrollBarChanged = box().hasAutoHorizontalScrollbar() && (hasHorizontalScrollbar() != hasHorizontalOverflow);
461 bool autoVerticalScrollBarChanged = box().hasAutoVerticalScrollbar() && (has VerticalScrollbar() != hasVerticalOverflow);
462 if (autoHorizontalScrollBarChanged || autoVerticalScrollBarChanged)
463 box().setNeedsLayout();
464 }
465
466 IntSize RenderLayerScrollableArea::clampScrollOffset(const IntSize& scrollOffset ) const
467 {
468 int maxX = scrollWidth() - box().pixelSnappedClientWidth();
469 int maxY = scrollHeight() - box().pixelSnappedClientHeight();
470
471 int x = std::max(std::min(scrollOffset.width(), maxX), 0);
472 int y = std::max(std::min(scrollOffset.height(), maxY), 0);
473 return IntSize(x, y);
474 }
475
476 IntRect RenderLayerScrollableArea::rectForHorizontalScrollbar(const IntRect& bor derBoxRect) const
477 {
478 if (!m_hBar)
479 return IntRect();
480
481 const IntRect& scrollCorner = scrollCornerRect();
482
483 return IntRect(horizontalScrollbarStart(borderBoxRect.x()),
484 borderBoxRect.maxY() - box().borderBottom() - m_hBar->height(),
485 borderBoxRect.width() - (box().borderLeft() + box().borderRight()) - scr ollCorner.width(),
486 m_hBar->height());
487 }
488
489 IntRect RenderLayerScrollableArea::rectForVerticalScrollbar(const IntRect& borde rBoxRect) const
490 {
491 if (!m_vBar)
492 return IntRect();
493
494 const IntRect& scrollCorner = scrollCornerRect();
495
496 return IntRect(verticalScrollbarStart(borderBoxRect.x(), borderBoxRect.maxX( )),
497 borderBoxRect.y() + box().borderTop(),
498 m_vBar->width(),
499 borderBoxRect.height() - (box().borderTop() + box().borderBottom()) - sc rollCorner.height());
500 }
501
502 LayoutUnit RenderLayerScrollableArea::verticalScrollbarStart(int minX, int maxX) const
503 {
504 if (box().style()->shouldPlaceBlockDirectionScrollbarOnLogicalLeft())
505 return minX + box().borderLeft();
506 return maxX - box().borderRight() - m_vBar->width();
507 }
508
509 LayoutUnit RenderLayerScrollableArea::horizontalScrollbarStart(int minX) const
510 {
511 return minX + box().borderLeft();
512 }
513
514 IntSize RenderLayerScrollableArea::scrollbarOffset(const Scrollbar* scrollbar) c onst
515 {
516 if (scrollbar == m_vBar.get())
517 return IntSize(verticalScrollbarStart(0, box().width()), box().borderTop ());
518
519 if (scrollbar == m_hBar.get())
520 return IntSize(horizontalScrollbarStart(0), box().height() - box().borde rBottom() - scrollbar->height());
521
522 ASSERT_NOT_REACHED();
523 return IntSize();
524 }
525
526 PassRefPtr<Scrollbar> RenderLayerScrollableArea::createScrollbar(ScrollbarOrient ation orientation)
527 {
528 RefPtr<Scrollbar> widget = Scrollbar::create(this, orientation);
529 if (orientation == HorizontalScrollbar)
530 didAddScrollbar(widget.get(), HorizontalScrollbar);
531 else
532 didAddScrollbar(widget.get(), VerticalScrollbar);
533 return widget.release();
534 }
535
536 void RenderLayerScrollableArea::destroyScrollbar(ScrollbarOrientation orientatio n)
537 {
538 RefPtr<Scrollbar>& scrollbar = orientation == HorizontalScrollbar ? m_hBar : m_vBar;
539 if (!scrollbar)
540 return;
541
542 willRemoveScrollbar(scrollbar.get(), orientation);
543
544 scrollbar->disconnectFromScrollableArea();
545 scrollbar = nullptr;
546 }
547
548 void RenderLayerScrollableArea::setHasHorizontalScrollbar(bool hasScrollbar)
549 {
550 if (hasScrollbar == hasHorizontalScrollbar())
551 return;
552
553 if (hasScrollbar) {
554 m_hBar = createScrollbar(HorizontalScrollbar);
555 } else {
556 destroyScrollbar(HorizontalScrollbar);
557 }
558 }
559
560 void RenderLayerScrollableArea::setHasVerticalScrollbar(bool hasScrollbar)
561 {
562 if (hasScrollbar == hasVerticalScrollbar())
563 return;
564
565 if (hasScrollbar) {
566 m_vBar = createScrollbar(VerticalScrollbar);
567 } else {
568 destroyScrollbar(VerticalScrollbar);
569 }
570 }
571
572 void RenderLayerScrollableArea::positionOverflowControls(const IntSize& offsetFr omRoot)
573 {
574 if (!hasScrollbar())
575 return;
576
577 const IntRect borderBox = box().pixelSnappedBorderBoxRect();
578 if (Scrollbar* verticalScrollbar = this->verticalScrollbar()) {
579 IntRect vBarRect = rectForVerticalScrollbar(borderBox);
580 vBarRect.move(offsetFromRoot);
581 verticalScrollbar->setFrameRect(vBarRect);
582 }
583
584 if (Scrollbar* horizontalScrollbar = this->horizontalScrollbar()) {
585 IntRect hBarRect = rectForHorizontalScrollbar(borderBox);
586 hBarRect.move(offsetFromRoot);
587 horizontalScrollbar->setFrameRect(hBarRect);
588 }
589 }
590
591 void RenderLayerScrollableArea::paintOverflowControls(GraphicsContext* context, const IntPoint& paintOffset, const IntRect& damageRect, bool paintingOverlayCont rols)
592 {
593 // Don't do anything if we have no overflow.
594 if (!box().hasOverflowClip())
595 return;
596
597 IntPoint adjustedPaintOffset = paintOffset;
598 if (paintingOverlayControls)
599 adjustedPaintOffset = m_cachedOverlayScrollbarOffset;
600
601 // Move the scrollbar widgets if necessary. We normally move and resize widg ets during layout,
602 // but sometimes widgets can move without layout occurring (most notably whe n you scroll a
603 // document that contains fixed positioned elements).
604 positionOverflowControls(toIntSize(adjustedPaintOffset));
605
606 // Overlay scrollbars paint in a second pass through the layer tree so that they will paint
607 // on top of everything else. If this is the normal painting pass, paintingO verlayControls
608 // will be false, and we should just tell the root layer that there are over lay scrollbars
609 // that need to be painted. That will cause the second pass through the laye r tree to run,
610 // and we'll paint the scrollbars then. In the meantime, cache tx and ty so that the
611 // second pass doesn't need to re-enter the RenderTree to get it right.
612 if (hasOverlayScrollbars() && !paintingOverlayControls) {
613 m_cachedOverlayScrollbarOffset = paintOffset;
614 IntRect localDamgeRect = damageRect;
615 localDamgeRect.moveBy(-paintOffset);
616 if (!overflowControlsIntersectRect(localDamgeRect))
617 return;
618
619 box().view()->layer()->setContainsDirtyOverlayScrollbars(true);
620 return;
621 }
622
623 // This check is required to avoid painting custom CSS scrollbars twice.
624 if (paintingOverlayControls && !hasOverlayScrollbars())
625 return;
626
627 // Now that we're sure the scrollbars are in the right place, paint them.
628 if (m_hBar)
629 m_hBar->paint(context, damageRect);
630 if (m_vBar)
631 m_vBar->paint(context, damageRect);
632 }
633
634 bool RenderLayerScrollableArea::overflowControlsIntersectRect(const IntRect& loc alRect) const
635 {
636 const IntRect borderBox = box().pixelSnappedBorderBoxRect();
637
638 if (rectForHorizontalScrollbar(borderBox).intersects(localRect))
639 return true;
640
641 if (rectForVerticalScrollbar(borderBox).intersects(localRect))
642 return true;
643
644 return false;
645 }
646
647 LayoutRect RenderLayerScrollableArea::exposeRect(const LayoutRect& rect, const S crollAlignment& alignX, const ScrollAlignment& alignY)
648 {
649 LayoutRect localExposeRect(box().absoluteToLocalQuad(FloatQuad(FloatRect(rec t)), UseTransforms).boundingBox());
650 LayoutRect layerBounds(0, 0, box().clientWidth(), box().clientHeight());
651 LayoutRect r = ScrollAlignment::getRectToExpose(layerBounds, localExposeRect , alignX, alignY);
652
653 IntSize clampedScrollOffset = clampScrollOffset(adjustedScrollOffset() + toI ntSize(roundedIntRect(r).location()));
654 if (clampedScrollOffset == adjustedScrollOffset())
655 return rect;
656
657 IntSize oldScrollOffset = adjustedScrollOffset();
658 scrollToOffset(clampedScrollOffset);
659 IntSize scrollOffsetDifference = adjustedScrollOffset() - oldScrollOffset;
660 localExposeRect.move(-scrollOffsetDifference);
661 return LayoutRect(box().localToAbsoluteQuad(FloatQuad(FloatRect(localExposeR ect)), UseTransforms).boundingBox());
662 }
663
664 void RenderLayerScrollableArea::updateScrollableAreaSet(bool hasOverflow)
665 {
666 LocalFrame* frame = box().frame();
667 if (!frame)
668 return;
669
670 FrameView* frameView = frame->view();
671 if (!frameView)
672 return;
673
674 // FIXME: Does this need to be fixed later for OOPI?
675 bool isVisibleToHitTest = box().visibleToHitTesting();
676 bool didScrollOverflow = m_scrollsOverflow;
677
678 m_scrollsOverflow = hasOverflow && isVisibleToHitTest;
679 if (didScrollOverflow == scrollsOverflow())
680 return;
681
682 if (m_scrollsOverflow)
683 frameView->addScrollableArea(this);
684 else
685 frameView->removeScrollableArea(this);
686 }
687
688 void RenderLayerScrollableArea::setTopmostScrollChild(RenderLayer* scrollChild)
689 {
690 // We only want to track the topmost scroll child for scrollable areas with
691 // overlay scrollbars.
692 if (!hasOverlayScrollbars())
693 return;
694 m_nextTopmostScrollChild = scrollChild;
695 }
696
697 } // namespace blink
OLDNEW
« no previous file with comments | « sky/engine/core/rendering/RenderLayerScrollableArea.h ('k') | sky/engine/core/rendering/RenderObject.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698