1 /*
2 * Copyright (C) 1998, 1999 Torben Weis <weis@kde.org>
3 * 1999 Lars Knoll <knoll@kde.org>
4 * 1999 Antti Koivisto <koivisto@kde.org>
5 * 2000 Dirk Mueller <mueller@kde.org>
6 * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
7 * (C) 2006 Graham Dennis (graham.dennis@gmail.com)
8 * (C) 2006 Alexey Proskuryakov (ap@nypop.com)
9 * Copyright (C) 2009 Google Inc. All rights reserved.
10 *
11 * This library is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Library General Public
13 * License as published by the Free Software Foundation; either
14 * version 2 of the License, or (at your option) any later version.
15 *
16 * This library is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Library General Public License for more details.
20 *
21 * You should have received a copy of the GNU Library General Public License
22 * along with this library; see the file COPYING.LIB. If not, write to
23 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
24 * Boston, MA 02110-1301, USA.
25 */
26
27 #include "config.h"
28 #include "FrameView.h"
29
30 #include "AXObjectCache.h"
31 #include "CSSStyleSelector.h"
32 #include "CachedResourceLoader.h"
33 #include "Chrome.h"
34 #include "ChromeClient.h"
35 #include "DocumentMarkerController.h"
36 #include "EventHandler.h"
37 #include "FloatRect.h"
38 #include "FocusController.h"
39 #include "Frame.h"
40 #include "FrameActionScheduler.h"
41 #include "FrameLoader.h"
42 #include "FrameLoaderClient.h"
43 #include "FrameTree.h"
44 #include "GraphicsContext.h"
45 #include "HTMLDocument.h"
46 #include "HTMLFrameElement.h"
47 #include "HTMLFrameSetElement.h"
48 #include "HTMLNames.h"
49 #include "HTMLPlugInImageElement.h"
50 #include "InspectorInstrumentation.h"
51 #include "OverflowEvent.h"
52 #include "RenderEmbeddedObject.h"
53 #include "RenderFullScreen.h"
54 #include "RenderLayer.h"
55 #include "RenderPart.h"
56 #include "RenderScrollbar.h"
57 #include "RenderScrollbarPart.h"
58 #include "RenderTheme.h"
59 #include "RenderView.h"
60 #include "ScrollAnimator.h"
61 #include "Settings.h"
62 #include "TextResourceDecoder.h"
63 #include <wtf/CurrentTime.h>
64
65 #if USE(ACCELERATED_COMPOSITING)
66 #include "RenderLayerCompositor.h"
67 #endif
68
69 #if ENABLE(SVG)
70 #include "SVGDocument.h"
71 #include "SVGLocatable.h"
72 #include "SVGNames.h"
73 #include "SVGPreserveAspectRatio.h"
74 #include "SVGSVGElement.h"
75 #include "SVGViewElement.h"
76 #include "SVGViewSpec.h"
77 #endif
78
79 #if ENABLE(TILED_BACKING_STORE)
80 #include "TiledBackingStore.h"
81 #endif
82
83 namespace WebCore {
84
85 using namespace HTMLNames;
86
87 double FrameView::sCurrentPaintTimeStamp = 0.0;
88
89 // REPAINT_THROTTLING now chooses default values for throttling parameters.
90 // Should be removed when applications start using runtime configuration.
91 #if ENABLE(REPAINT_THROTTLING)
92 // Normal delay
93 double FrameView::s_deferredRepaintDelay = 0.025;
94 // Negative value would mean that first few repaints happen without a delay
95 double FrameView::s_initialDeferredRepaintDelayDuringLoading = 0;
96 // The delay grows on each repaint to this maximum value
97 double FrameView::s_maxDeferredRepaintDelayDuringLoading = 2.5;
98 // On each repaint the delay increses by this amount
99 double FrameView::s_deferredRepaintDelayIncrementDuringLoading = 0.5;
100 #else
101 // FIXME: Repaint throttling could be good to have on all platform.
102 // The balance between CPU use and repaint frequency will need some tuning for desktop.
103 // More hooks may be needed to reset the delay on things like GIF and CSS animations.
104 double FrameView::s_deferredRepaintDelay = 0;
105 double FrameView::s_initialDeferredRepaintDelayDuringLoading = 0;
106 double FrameView::s_maxDeferredRepaintDelayDuringLoading = 0;
107 double FrameView::s_deferredRepaintDelayIncrementDuringLoading = 0;
108 #endif
109
110 // The maximum number of updateWidgets iterations that should be done before returning.
111 static const unsigned maxUpdateWidgetsIterations = 2;
112
FrameView(Frame * frame)113 FrameView::FrameView(Frame* frame)
114 : m_frame(frame)
115 , m_canHaveScrollbars(true)
116 , m_slowRepaintObjectCount(0)
117 , m_fixedObjectCount(0)
118 , m_layoutTimer(this, &FrameView::layoutTimerFired)
119 , m_layoutRoot(0)
120 , m_hasPendingPostLayoutTasks(false)
121 , m_inSynchronousPostLayout(false)
122 , m_postLayoutTasksTimer(this, &FrameView::postLayoutTimerFired)
123 , m_isTransparent(false)
124 , m_baseBackgroundColor(Color::white)
125 , m_mediaType("screen")
126 , m_actionScheduler(adoptPtr(new FrameActionScheduler))
127 , m_overflowStatusDirty(true)
128 , m_viewportRenderer(0)
129 , m_wasScrolledByUser(false)
130 , m_inProgrammaticScroll(false)
131 , m_deferredRepaintTimer(this, &FrameView::deferredRepaintTimerFired)
132 , m_shouldUpdateWhileOffscreen(true)
133 , m_deferSetNeedsLayouts(0)
134 , m_setNeedsLayoutWasDeferred(false)
135 , m_scrollCorner(0)
136 {
137 init();
138
139 if (m_frame) {
140 if (Page* page = m_frame->page()) {
141 m_page = page;
142 m_page->addScrollableArea(this);
143
144 if (m_frame == m_page->mainFrame()) {
145 ScrollableArea::setVerticalScrollElasticity(ScrollElasticityAllowed);
146 ScrollableArea::setHorizontalScrollElasticity(ScrollElasticityAllowed);
147 }
148 }
149 }
150 }
151
create(Frame * frame)152 PassRefPtr<FrameView> FrameView::create(Frame* frame)
153 {
154 RefPtr<FrameView> view = adoptRef(new FrameView(frame));
155 view->show();
156 return view.release();
157 }
158
create(Frame * frame,const IntSize & initialSize)159 PassRefPtr<FrameView> FrameView::create(Frame* frame, const IntSize& initialSize)
160 {
161 RefPtr<FrameView> view = adoptRef(new FrameView(frame));
162 view->Widget::setFrameRect(IntRect(view->pos(), initialSize));
163 view->setInitialBoundsSize(initialSize);
164 view->show();
165 return view.release();
166 }
167
~FrameView()168 FrameView::~FrameView()
169 {
170 if (m_hasPendingPostLayoutTasks) {
171 m_postLayoutTasksTimer.stop();
172 m_actionScheduler->clear();
173 }
174
175 if (AXObjectCache::accessibilityEnabled() && axObjectCache())
176 axObjectCache()->remove(this);
177
178 resetScrollbars();
179
180 // Custom scrollbars should already be destroyed at this point
181 ASSERT(!horizontalScrollbar() || !horizontalScrollbar()->isCustomScrollbar());
182 ASSERT(!verticalScrollbar() || !verticalScrollbar()->isCustomScrollbar());
183
184 setHasHorizontalScrollbar(false); // Remove native scrollbars now before we lose the connection to the HostWindow.
185 setHasVerticalScrollbar(false);
186
187 ASSERT(!m_scrollCorner);
188 ASSERT(m_actionScheduler->isEmpty());
189
190 if (m_page)
191 m_page->removeScrollableArea(this);
192
193 if (m_frame) {
194 ASSERT(m_frame->view() != this || !m_frame->contentRenderer());
195 RenderPart* renderer = m_frame->ownerRenderer();
196 if (renderer && renderer->widget() == this)
197 renderer->setWidget(0);
198 }
199 }
200
reset()201 void FrameView::reset()
202 {
203 m_useSlowRepaints = false;
204 m_isOverlapped = false;
205 m_contentIsOpaque = false;
206 m_borderX = 30;
207 m_borderY = 30;
208 m_layoutTimer.stop();
209 m_layoutRoot = 0;
210 m_delayedLayout = false;
211 m_doFullRepaint = true;
212 m_layoutSchedulingEnabled = true;
213 m_inLayout = false;
214 m_inSynchronousPostLayout = false;
215 m_hasPendingPostLayoutTasks = false;
216 m_layoutCount = 0;
217 m_nestedLayoutCount = 0;
218 m_postLayoutTasksTimer.stop();
219 m_firstLayout = true;
220 m_firstLayoutCallbackPending = false;
221 m_wasScrolledByUser = false;
222 m_lastLayoutSize = IntSize();
223 m_lastZoomFactor = 1.0f;
224 m_deferringRepaints = 0;
225 m_repaintCount = 0;
226 m_repaintRects.clear();
227 m_deferredRepaintDelay = s_initialDeferredRepaintDelayDuringLoading;
228 m_deferredRepaintTimer.stop();
229 m_lastPaintTime = 0;
230 m_paintBehavior = PaintBehaviorNormal;
231 m_isPainting = false;
232 m_isVisuallyNonEmpty = false;
233 m_firstVisuallyNonEmptyLayoutCallbackPending = true;
234 m_maintainScrollPositionAnchor = 0;
235 }
236
isFrameView() const237 bool FrameView::isFrameView() const
238 {
239 return true;
240 }
241
clearFrame()242 void FrameView::clearFrame()
243 {
244 m_frame = 0;
245 }
246
resetScrollbars()247 void FrameView::resetScrollbars()
248 {
249 // Reset the document's scrollbars back to our defaults before we yield the floor.
250 m_firstLayout = true;
251 setScrollbarsSuppressed(true);
252 if (m_canHaveScrollbars)
253 setScrollbarModes(ScrollbarAuto, ScrollbarAuto);
254 else
255 setScrollbarModes(ScrollbarAlwaysOff, ScrollbarAlwaysOff);
256 setScrollbarsSuppressed(false);
257 }
258
resetScrollbarsAndClearContentsSize()259 void FrameView::resetScrollbarsAndClearContentsSize()
260 {
261 resetScrollbars();
262
263 setScrollbarsSuppressed(true);
264 setContentsSize(IntSize());
265 setScrollbarsSuppressed(false);
266 }
267
init()268 void FrameView::init()
269 {
270 reset();
271
272 m_margins = IntSize(-1, -1); // undefined
273 m_size = IntSize();
274
275 // Propagate the marginwidth/height and scrolling modes to the view.
276 Element* ownerElement = m_frame ? m_frame->ownerElement() : 0;
277 if (ownerElement && (ownerElement->hasTagName(frameTag) || ownerElement->hasTagName(iframeTag))) {
278 HTMLFrameElement* frameElt = static_cast<HTMLFrameElement*>(ownerElement);
279 if (frameElt->scrollingMode() == ScrollbarAlwaysOff)
280 setCanHaveScrollbars(false);
281 int marginWidth = frameElt->marginWidth();
282 int marginHeight = frameElt->marginHeight();
283 if (marginWidth != -1)
284 setMarginWidth(marginWidth);
285 if (marginHeight != -1)
286 setMarginHeight(marginHeight);
287 }
288 }
289
detachCustomScrollbars()290 void FrameView::detachCustomScrollbars()
291 {
292 if (!m_frame)
293 return;
294
295 Scrollbar* horizontalBar = horizontalScrollbar();
296 if (horizontalBar && horizontalBar->isCustomScrollbar())
297 setHasHorizontalScrollbar(false);
298
299 Scrollbar* verticalBar = verticalScrollbar();
300 if (verticalBar && verticalBar->isCustomScrollbar())
301 setHasVerticalScrollbar(false);
302
303 if (m_scrollCorner) {
304 m_scrollCorner->destroy();
305 m_scrollCorner = 0;
306 }
307 }
308
recommendedScrollbarOverlayStyle() const309 ScrollbarOverlayStyle FrameView::recommendedScrollbarOverlayStyle() const
310 {
311 Color bgColor = m_frame->getDocumentBackgroundColor();
312 if (!bgColor.isValid())
313 return ScrollbarOverlayStyleDefault;
314
315 // Reduce the background color from RGB to a lightness value
316 // and determine which scrollbar style to use based on a lightness
317 // heuristic.
318 double hue, saturation, lightness;
319 bgColor.getHSL(hue, saturation, lightness);
320 if (lightness > .5)
321 return ScrollbarOverlayStyleDefault;
322
323 return ScrollbarOverlayStyleLight;
324 }
325
clear()326 void FrameView::clear()
327 {
328 setCanBlitOnScroll(true);
329
330 reset();
331
332 if (m_frame) {
333 if (RenderPart* renderer = m_frame->ownerRenderer())
334 renderer->viewCleared();
335 }
336
337 setScrollbarsSuppressed(true);
338 }
339
didFirstLayout() const340 bool FrameView::didFirstLayout() const
341 {
342 return !m_firstLayout;
343 }
344
invalidateRect(const IntRect & rect)345 void FrameView::invalidateRect(const IntRect& rect)
346 {
347 if (!parent()) {
348 if (hostWindow())
349 hostWindow()->invalidateContentsAndWindow(rect, false /*immediate*/);
350 return;
351 }
352
353 if (!m_frame)
354 return;
355
356 RenderPart* renderer = m_frame->ownerRenderer();
357 if (!renderer)
358 return;
359
360 IntRect repaintRect = rect;
361 repaintRect.move(renderer->borderLeft() + renderer->paddingLeft(),
362 renderer->borderTop() + renderer->paddingTop());
363 renderer->repaintRectangle(repaintRect);
364 }
365
setFrameRect(const IntRect & newRect)366 void FrameView::setFrameRect(const IntRect& newRect)
367 {
368 IntRect oldRect = frameRect();
369 if (newRect == oldRect)
370 return;
371
372 ScrollView::setFrameRect(newRect);
373
374 #if USE(ACCELERATED_COMPOSITING)
375 if (RenderView* root = m_frame->contentRenderer()) {
376 if (root->usesCompositing())
377 root->compositor()->frameViewDidChangeSize();
378 }
379 #endif
380 }
381
382 #if ENABLE(REQUEST_ANIMATION_FRAME)
scheduleAnimation()383 void FrameView::scheduleAnimation()
384 {
385 if (hostWindow())
386 hostWindow()->scheduleAnimation();
387 }
388 #endif
389
setMarginWidth(int w)390 void FrameView::setMarginWidth(int w)
391 {
392 // make it update the rendering area when set
393 m_margins.setWidth(w);
394 }
395
setMarginHeight(int h)396 void FrameView::setMarginHeight(int h)
397 {
398 // make it update the rendering area when set
399 m_margins.setHeight(h);
400 }
401
avoidScrollbarCreation() const402 bool FrameView::avoidScrollbarCreation() const
403 {
404 ASSERT(m_frame);
405
406 // with frame flattening no subframe can have scrollbars
407 // but we also cannot turn scrollbars of as we determine
408 // our flattening policy using that.
409
410 if (!m_frame->ownerElement())
411 return false;
412
413 if (!m_frame->settings() || m_frame->settings()->frameFlatteningEnabled())
414 return true;
415
416 return false;
417 }
418
setCanHaveScrollbars(bool canHaveScrollbars)419 void FrameView::setCanHaveScrollbars(bool canHaveScrollbars)
420 {
421 m_canHaveScrollbars = canHaveScrollbars;
422 ScrollView::setCanHaveScrollbars(canHaveScrollbars);
423 }
424
updateCanHaveScrollbars()425 void FrameView::updateCanHaveScrollbars()
426 {
427 ScrollbarMode hMode;
428 ScrollbarMode vMode;
429 scrollbarModes(hMode, vMode);
430 if (hMode == ScrollbarAlwaysOff && vMode == ScrollbarAlwaysOff)
431 setCanHaveScrollbars(false);
432 else
433 setCanHaveScrollbars(true);
434 }
435
createScrollbar(ScrollbarOrientation orientation)436 PassRefPtr<Scrollbar> FrameView::createScrollbar(ScrollbarOrientation orientation)
437 {
438 // FIXME: We need to update the scrollbar dynamically as documents change (or as doc elements and bodies get discovered that have custom styles).
439 Document* doc = m_frame->document();
440
441 // Try the <body> element first as a scrollbar source.
442 Element* body = doc ? doc->body() : 0;
443 if (body && body->renderer() && body->renderer()->style()->hasPseudoStyle(SCROLLBAR))
444 return RenderScrollbar::createCustomScrollbar(this, orientation, body->renderer()->enclosingBox());
445
446 // If the <body> didn't have a custom style, then the root element might.
447 Element* docElement = doc ? doc->documentElement() : 0;
448 if (docElement && docElement->renderer() && docElement->renderer()->style()->hasPseudoStyle(SCROLLBAR))
449 return RenderScrollbar::createCustomScrollbar(this, orientation, docElement->renderBox());
450
451 // If we have an owning iframe/frame element, then it can set the custom scrollbar also.
452 RenderPart* frameRenderer = m_frame->ownerRenderer();
453 if (frameRenderer && frameRenderer->style()->hasPseudoStyle(SCROLLBAR))
454 return RenderScrollbar::createCustomScrollbar(this, orientation, 0, m_frame.get());
455
456 // Nobody set a custom style, so we just use a native scrollbar.
457 return ScrollView::createScrollbar(orientation);
458 }
459
setContentsSize(const IntSize & size)460 void FrameView::setContentsSize(const IntSize& size)
461 {
462 if (size == contentsSize())
463 return;
464
465 m_deferSetNeedsLayouts++;
466
467 ScrollView::setContentsSize(size);
468 scrollAnimator()->contentsResized();
469
470 Page* page = frame() ? frame()->page() : 0;
471 if (!page)
472 return;
473
474 page->chrome()->contentsSizeChanged(frame(), size); //notify only
475
476 m_deferSetNeedsLayouts--;
477
478 if (!m_deferSetNeedsLayouts)
479 m_setNeedsLayoutWasDeferred = false; // FIXME: Find a way to make the deferred layout actually happen.
480 }
481
adjustViewSize()482 void FrameView::adjustViewSize()
483 {
484 ASSERT(m_frame->view() == this);
485 RenderView* root = m_frame->contentRenderer();
486 if (!root)
487 return;
488
489 IntSize size = IntSize(root->docWidth(), root->docHeight());
490
491 ScrollView::setScrollOrigin(IntPoint(-root->docLeft(), -root->docTop()), !m_frame->document()->printing(), size == contentsSize());
492
493 setContentsSize(size);
494 }
495
applyOverflowToViewport(RenderObject * o,ScrollbarMode & hMode,ScrollbarMode & vMode)496 void FrameView::applyOverflowToViewport(RenderObject* o, ScrollbarMode& hMode, ScrollbarMode& vMode)
497 {
498 // Handle the overflow:hidden/scroll case for the body/html elements. WinIE treats
499 // overflow:hidden and overflow:scroll on <body> as applying to the document's
500 // scrollbars. The CSS2.1 draft states that HTML UAs should use the <html> or <body> element and XML/XHTML UAs should
501 // use the root element.
502 switch (o->style()->overflowX()) {
503 case OHIDDEN:
504 hMode = ScrollbarAlwaysOff;
505 break;
506 case OSCROLL:
507 hMode = ScrollbarAlwaysOn;
508 break;
509 case OAUTO:
510 hMode = ScrollbarAuto;
511 break;
512 default:
513 // Don't set it at all.
514 ;
515 }
516
517 switch (o->style()->overflowY()) {
518 case OHIDDEN:
519 vMode = ScrollbarAlwaysOff;
520 break;
521 case OSCROLL:
522 vMode = ScrollbarAlwaysOn;
523 break;
524 case OAUTO:
525 vMode = ScrollbarAuto;
526 break;
527 default:
528 // Don't set it at all.
529 ;
530 }
531
532 m_viewportRenderer = o;
533 }
534
calculateScrollbarModesForLayout(ScrollbarMode & hMode,ScrollbarMode & vMode)535 void FrameView::calculateScrollbarModesForLayout(ScrollbarMode& hMode, ScrollbarMode& vMode)
536 {
537 m_viewportRenderer = 0;
538
539 const HTMLFrameOwnerElement* owner = m_frame->ownerElement();
540 if (owner && (owner->scrollingMode() == ScrollbarAlwaysOff)) {
541 hMode = ScrollbarAlwaysOff;
542 vMode = ScrollbarAlwaysOff;
543 return;
544 }
545
546 if (m_canHaveScrollbars) {
547 hMode = ScrollbarAuto;
548 vMode = ScrollbarAuto;
549 } else {
550 hMode = ScrollbarAlwaysOff;
551 vMode = ScrollbarAlwaysOff;
552 }
553
554 if (!m_layoutRoot) {
555 Document* document = m_frame->document();
556 Node* documentElement = document->documentElement();
557 RenderObject* rootRenderer = documentElement ? documentElement->renderer() : 0;
558 Node* body = document->body();
559 if (body && body->renderer()) {
560 if (body->hasTagName(framesetTag) && m_frame->settings() && !m_frame->settings()->frameFlatteningEnabled()) {
561 vMode = ScrollbarAlwaysOff;
562 hMode = ScrollbarAlwaysOff;
563 } else if (body->hasTagName(bodyTag)) {
564 // It's sufficient to just check the X overflow,
565 // since it's illegal to have visible in only one direction.
566 RenderObject* o = rootRenderer->style()->overflowX() == OVISIBLE && document->documentElement()->hasTagName(htmlTag) ? body->renderer() : rootRenderer;
567 applyOverflowToViewport(o, hMode, vMode);
568 }
569 } else if (rootRenderer) {
570 #if ENABLE(SVG)
571 if (!documentElement->isSVGElement())
572 applyOverflowToViewport(rootRenderer, hMode, vMode);
573 #else
574 applyOverflowToViewport(rootRenderer, hMode, vMode);
575 #endif
576 }
577 }
578 }
579
580 #if ENABLE(FULLSCREEN_API) && USE(ACCELERATED_COMPOSITING)
isDocumentRunningFullScreenAnimation(Document * document)581 static bool isDocumentRunningFullScreenAnimation(Document* document)
582 {
583 return document->webkitIsFullScreen() && document->fullScreenRenderer() && document->fullScreenRenderer()->isAnimating();
584 }
585 #endif
586
587 #if USE(ACCELERATED_COMPOSITING)
updateCompositingLayers()588 void FrameView::updateCompositingLayers()
589 {
590 RenderView* view = m_frame->contentRenderer();
591 if (!view)
592 return;
593
594 // This call will make sure the cached hasAcceleratedCompositing is updated from the pref
595 view->compositor()->cacheAcceleratedCompositingFlags();
596 view->compositor()->updateCompositingLayers(CompositingUpdateAfterLayoutOrStyleChange);
597
598 #if ENABLE(FULLSCREEN_API)
599 Document* document = m_frame->document();
600 if (isDocumentRunningFullScreenAnimation(document))
601 view->compositor()->updateCompositingLayers(CompositingUpdateAfterLayoutOrStyleChange, document->fullScreenRenderer()->layer());
602 #endif
603 }
604
layerForHorizontalScrollbar() const605 GraphicsLayer* FrameView::layerForHorizontalScrollbar() const
606 {
607 RenderView* view = m_frame->contentRenderer();
608 if (!view)
609 return 0;
610 return view->compositor()->layerForHorizontalScrollbar();
611 }
612
layerForVerticalScrollbar() const613 GraphicsLayer* FrameView::layerForVerticalScrollbar() const
614 {
615 RenderView* view = m_frame->contentRenderer();
616 if (!view)
617 return 0;
618 return view->compositor()->layerForVerticalScrollbar();
619 }
620
layerForScrollCorner() const621 GraphicsLayer* FrameView::layerForScrollCorner() const
622 {
623 RenderView* view = m_frame->contentRenderer();
624 if (!view)
625 return 0;
626 return view->compositor()->layerForScrollCorner();
627 }
628
syncCompositingStateForThisFrame()629 bool FrameView::syncCompositingStateForThisFrame()
630 {
631 ASSERT(m_frame->view() == this);
632 RenderView* view = m_frame->contentRenderer();
633 if (!view)
634 return true; // We don't want to keep trying to update layers if we have no renderer.
635
636 // If we sync compositing layers when a layout is pending, we may cause painting of compositing
637 // layer content to occur before layout has happened, which will cause paintContents() to bail.
638 if (needsLayout())
639 return false;
640
641 if (GraphicsLayer* graphicsLayer = view->compositor()->layerForHorizontalScrollbar())
642 graphicsLayer->syncCompositingStateForThisLayerOnly();
643 if (GraphicsLayer* graphicsLayer = view->compositor()->layerForVerticalScrollbar())
644 graphicsLayer->syncCompositingStateForThisLayerOnly();
645 if (GraphicsLayer* graphicsLayer = view->compositor()->layerForScrollCorner())
646 graphicsLayer->syncCompositingStateForThisLayerOnly();
647
648 view->compositor()->flushPendingLayerChanges();
649
650 #if ENABLE(FULLSCREEN_API)
651 // The fullScreenRenderer's graphicsLayer has been re-parented, and the above recursive syncCompositingState
652 // call will not cause the subtree under it to repaint. Explicitly call the syncCompositingState on
653 // the fullScreenRenderer's graphicsLayer here:
654 Document* document = m_frame->document();
655 if (isDocumentRunningFullScreenAnimation(document)) {
656 RenderLayerBacking* backing = document->fullScreenRenderer()->layer()->backing();
657 if (GraphicsLayer* fullScreenLayer = backing->graphicsLayer())
658 fullScreenLayer->syncCompositingState();
659 }
660 #endif
661 return true;
662 }
663
setNeedsOneShotDrawingSynchronization()664 void FrameView::setNeedsOneShotDrawingSynchronization()
665 {
666 Page* page = frame() ? frame()->page() : 0;
667 if (page)
668 page->chrome()->client()->setNeedsOneShotDrawingSynchronization();
669 }
670
671 #endif // USE(ACCELERATED_COMPOSITING)
672
hasCompositedContent() const673 bool FrameView::hasCompositedContent() const
674 {
675 #if USE(ACCELERATED_COMPOSITING)
676 if (RenderView* view = m_frame->contentRenderer())
677 return view->compositor()->inCompositingMode();
678 #endif
679 return false;
680 }
681
hasCompositedContentIncludingDescendants() const682 bool FrameView::hasCompositedContentIncludingDescendants() const
683 {
684 #if USE(ACCELERATED_COMPOSITING)
685 for (Frame* frame = m_frame.get(); frame; frame = frame->tree()->traverseNext(m_frame.get())) {
686 RenderView* renderView = frame->contentRenderer();
687 RenderLayerCompositor* compositor = renderView ? renderView->compositor() : 0;
688 if (compositor) {
689 if (compositor->inCompositingMode())
690 return true;
691
692 if (!RenderLayerCompositor::allowsIndependentlyCompositedFrames(this))
693 break;
694 }
695 }
696 #endif
697 return false;
698 }
699
hasCompositingAncestor() const700 bool FrameView::hasCompositingAncestor() const
701 {
702 #if USE(ACCELERATED_COMPOSITING)
703 for (Frame* frame = m_frame->tree()->parent(); frame; frame = frame->tree()->parent()) {
704 if (FrameView* view = frame->view()) {
705 if (view->hasCompositedContent())
706 return true;
707 }
708 }
709 #endif
710 return false;
711 }
712
713 // Sometimes (for plug-ins) we need to eagerly go into compositing mode.
enterCompositingMode()714 void FrameView::enterCompositingMode()
715 {
716 #if USE(ACCELERATED_COMPOSITING)
717 if (RenderView* view = m_frame->contentRenderer()) {
718 view->compositor()->enableCompositingMode();
719 if (!needsLayout())
720 view->compositor()->scheduleCompositingLayerUpdate();
721 }
722 #endif
723 }
724
isEnclosedInCompositingLayer() const725 bool FrameView::isEnclosedInCompositingLayer() const
726 {
727 #if USE(ACCELERATED_COMPOSITING)
728 RenderObject* frameOwnerRenderer = m_frame->ownerRenderer();
729 if (frameOwnerRenderer && frameOwnerRenderer->containerForRepaint())
730 return true;
731
732 if (FrameView* parentView = parentFrameView())
733 return parentView->isEnclosedInCompositingLayer();
734 #endif
735 return false;
736 }
737
syncCompositingStateIncludingSubframes()738 bool FrameView::syncCompositingStateIncludingSubframes()
739 {
740 #if USE(ACCELERATED_COMPOSITING)
741 bool allFramesSynced = syncCompositingStateForThisFrame();
742
743 for (Frame* child = m_frame->tree()->firstChild(); child; child = child->tree()->traverseNext(m_frame.get())) {
744 bool synced = child->view()->syncCompositingStateForThisFrame();
745 allFramesSynced &= synced;
746 }
747 return allFramesSynced;
748 #else // USE(ACCELERATED_COMPOSITING)
749 return true;
750 #endif
751 }
752
isSoftwareRenderable() const753 bool FrameView::isSoftwareRenderable() const
754 {
755 #if USE(ACCELERATED_COMPOSITING)
756 RenderView* view = m_frame->contentRenderer();
757 if (!view)
758 return true;
759
760 return !view->compositor()->has3DContent();
761 #else
762 return true;
763 #endif
764 }
765
didMoveOnscreen()766 void FrameView::didMoveOnscreen()
767 {
768 RenderView* view = m_frame->contentRenderer();
769 if (view)
770 view->didMoveOnscreen();
771 scrollAnimator()->contentAreaDidShow();
772 }
773
willMoveOffscreen()774 void FrameView::willMoveOffscreen()
775 {
776 RenderView* view = m_frame->contentRenderer();
777 if (view)
778 view->willMoveOffscreen();
779 scrollAnimator()->contentAreaDidHide();
780 }
781
layoutRoot(bool onlyDuringLayout) const782 RenderObject* FrameView::layoutRoot(bool onlyDuringLayout) const
783 {
784 return onlyDuringLayout && layoutPending() ? 0 : m_layoutRoot;
785 }
786
layout(bool allowSubtree)787 void FrameView::layout(bool allowSubtree)
788 {
789 if (m_inLayout)
790 return;
791
792 bool inSubframeLayoutWithFrameFlattening = parent() && m_frame->settings() && m_frame->settings()->frameFlatteningEnabled();
793
794 if (inSubframeLayoutWithFrameFlattening) {
795 if (parent()->isFrameView()) {
796 FrameView* parentView = static_cast<FrameView*>(parent());
797 if (!parentView->m_nestedLayoutCount) {
798 while (parentView->parent() && parentView->parent()->isFrameView())
799 parentView = static_cast<FrameView*>(parentView->parent());
800 parentView->layout(allowSubtree);
801 return;
802 }
803 }
804 }
805
806 m_layoutTimer.stop();
807 m_delayedLayout = false;
808 m_setNeedsLayoutWasDeferred = false;
809
810 // Protect the view from being deleted during layout (in recalcStyle)
811 RefPtr<FrameView> protector(this);
812
813 if (!m_frame) {
814 // FIXME: Do we need to set m_size.width here?
815 // FIXME: Should we set m_size.height here too?
816 m_size.setWidth(layoutWidth());
817 return;
818 }
819
820 // we shouldn't enter layout() while painting
821 ASSERT(!isPainting());
822 if (isPainting())
823 return;
824
825 InspectorInstrumentationCookie cookie = InspectorInstrumentation::willLayout(m_frame.get());
826
827 if (!allowSubtree && m_layoutRoot) {
828 m_layoutRoot->markContainingBlocksForLayout(false);
829 m_layoutRoot = 0;
830 }
831
832 ASSERT(m_frame->view() == this);
833
834 Document* document = m_frame->document();
835
836 m_layoutSchedulingEnabled = false;
837
838 if (!m_nestedLayoutCount && !m_inSynchronousPostLayout && m_hasPendingPostLayoutTasks && !inSubframeLayoutWithFrameFlattening) {
839 // This is a new top-level layout. If there are any remaining tasks from the previous
840 // layout, finish them now.
841 m_inSynchronousPostLayout = true;
842 m_postLayoutTasksTimer.stop();
843 performPostLayoutTasks();
844 m_inSynchronousPostLayout = false;
845 }
846
847 // Viewport-dependent media queries may cause us to need completely different style information.
848 // Check that here.
849 if (document->styleSelector()->affectedByViewportChange())
850 document->styleSelectorChanged(RecalcStyleImmediately);
851
852 // Always ensure our style info is up-to-date. This can happen in situations where
853 // the layout beats any sort of style recalc update that needs to occur.
854 document->updateStyleIfNeeded();
855
856 bool subtree = m_layoutRoot;
857
858 // If there is only one ref to this view left, then its going to be destroyed as soon as we exit,
859 // so there's no point to continuing to layout
860 if (protector->hasOneRef())
861 return;
862
863 RenderObject* root = subtree ? m_layoutRoot : document->renderer();
864 if (!root) {
865 // FIXME: Do we need to set m_size here?
866 m_layoutSchedulingEnabled = true;
867 return;
868 }
869
870 m_nestedLayoutCount++;
871
872 if (!m_layoutRoot) {
873 Document* document = m_frame->document();
874 Node* documentElement = document->documentElement();
875 RenderObject* rootRenderer = documentElement ? documentElement->renderer() : 0;
876 Node* body = document->body();
877 if (body && body->renderer()) {
878 if (body->hasTagName(framesetTag) && m_frame->settings() && !m_frame->settings()->frameFlatteningEnabled()) {
879 body->renderer()->setChildNeedsLayout(true);
880 } else if (body->hasTagName(bodyTag)) {
881 if (!m_firstLayout && m_size.height() != layoutHeight() && body->renderer()->enclosingBox()->stretchesToViewport())
882 body->renderer()->setChildNeedsLayout(true);
883 }
884 } else if (rootRenderer) {
885 #if ENABLE(SVG)
886 if (documentElement->isSVGElement()) {
887 if (!m_firstLayout && (m_size.width() != layoutWidth() || m_size.height() != layoutHeight()))
888 rootRenderer->setChildNeedsLayout(true);
889 }
890 #endif
891 }
892
893 #ifdef INSTRUMENT_LAYOUT_SCHEDULING
894 if (m_firstLayout && !m_frame->ownerElement())
895 printf("Elapsed time before first layout: %d\n", document->elapsedTime());
896 #endif
897 }
898
899 ScrollbarMode hMode;
900 ScrollbarMode vMode;
901 calculateScrollbarModesForLayout(hMode, vMode);
902
903 m_doFullRepaint = !subtree && (m_firstLayout || toRenderView(root)->printing());
904
905 if (!subtree) {
906 // Now set our scrollbar state for the layout.
907 ScrollbarMode currentHMode = horizontalScrollbarMode();
908 ScrollbarMode currentVMode = verticalScrollbarMode();
909
910 if (m_firstLayout || (hMode != currentHMode || vMode != currentVMode)) {
911 if (m_firstLayout) {
912 setScrollbarsSuppressed(true);
913
914 m_firstLayout = false;
915 m_firstLayoutCallbackPending = true;
916 m_lastLayoutSize = IntSize(width(), height());
917 m_lastZoomFactor = root->style()->zoom();
918
919 // Set the initial vMode to AlwaysOn if we're auto.
920 if (vMode == ScrollbarAuto)
921 setVerticalScrollbarMode(ScrollbarAlwaysOn); // This causes a vertical scrollbar to appear.
922 // Set the initial hMode to AlwaysOff if we're auto.
923 if (hMode == ScrollbarAuto)
924 setHorizontalScrollbarMode(ScrollbarAlwaysOff); // This causes a horizontal scrollbar to disappear.
925
926 setScrollbarModes(hMode, vMode);
927 setScrollbarsSuppressed(false, true);
928 } else
929 setScrollbarModes(hMode, vMode);
930 }
931
932 IntSize oldSize = m_size;
933
934 m_size = IntSize(layoutWidth(), layoutHeight());
935
936 if (oldSize != m_size) {
937 m_doFullRepaint = true;
938 if (!m_firstLayout) {
939 RenderBox* rootRenderer = document->documentElement() ? document->documentElement()->renderBox() : 0;
940 RenderBox* bodyRenderer = rootRenderer && document->body() ? document->body()->renderBox() : 0;
941 if (bodyRenderer && bodyRenderer->stretchesToViewport())
942 bodyRenderer->setChildNeedsLayout(true);
943 else if (rootRenderer && rootRenderer->stretchesToViewport())
944 rootRenderer->setChildNeedsLayout(true);
945 }
946 }
947 }
948
949 RenderLayer* layer = root->enclosingLayer();
950
951 m_actionScheduler->pause();
952
953 bool disableLayoutState = false;
954 if (subtree) {
955 RenderView* view = root->view();
956 disableLayoutState = view->shouldDisableLayoutStateForSubtree(root);
957 view->pushLayoutState(root);
958 if (disableLayoutState)
959 view->disableLayoutState();
960 }
961
962 m_inLayout = true;
963 beginDeferredRepaints();
964 root->layout();
965 endDeferredRepaints();
966 m_inLayout = false;
967
968 if (subtree) {
969 RenderView* view = root->view();
970 view->popLayoutState(root);
971 if (disableLayoutState)
972 view->enableLayoutState();
973 }
974 m_layoutRoot = 0;
975
976 m_layoutSchedulingEnabled = true;
977
978 if (!subtree && !toRenderView(root)->printing())
979 adjustViewSize();
980
981 // Now update the positions of all layers.
982 beginDeferredRepaints();
983 IntPoint cachedOffset;
984 if (m_doFullRepaint)
985 root->view()->repaint(); // FIXME: This isn't really right, since the RenderView doesn't fully encompass the visibleContentRect(). It just happens
986 // to work out most of the time, since first layouts and printing don't have you scrolled anywhere.
987 layer->updateLayerPositions((m_doFullRepaint ? 0 : RenderLayer::CheckForRepaint)
988 | RenderLayer::IsCompositingUpdateRoot
989 | RenderLayer::UpdateCompositingLayers,
990 subtree ? 0 : &cachedOffset);
991 endDeferredRepaints();
992
993 #if USE(ACCELERATED_COMPOSITING)
994 updateCompositingLayers();
995 #endif
996
997 m_layoutCount++;
998
999 #if PLATFORM(MAC) || PLATFORM(CHROMIUM)
1000 if (AXObjectCache::accessibilityEnabled())
1001 root->document()->axObjectCache()->postNotification(root, AXObjectCache::AXLayoutComplete, true);
1002 #endif
1003 #if ENABLE(DASHBOARD_SUPPORT)
1004 updateDashboardRegions();
1005 #endif
1006
1007 ASSERT(!root->needsLayout());
1008
1009 updateCanBlitOnScrollRecursively();
1010
1011 if (document->hasListenerType(Document::OVERFLOWCHANGED_LISTENER))
1012 updateOverflowStatus(layoutWidth() < contentsWidth(),
1013 layoutHeight() < contentsHeight());
1014
1015 if (!m_hasPendingPostLayoutTasks) {
1016 if (!m_inSynchronousPostLayout) {
1017 if (inSubframeLayoutWithFrameFlattening)
1018 m_frame->contentRenderer()->updateWidgetPositions();
1019 else {
1020 m_inSynchronousPostLayout = true;
1021 // Calls resumeScheduledEvents()
1022 performPostLayoutTasks();
1023 m_inSynchronousPostLayout = false;
1024 }
1025 }
1026
1027 if (!m_hasPendingPostLayoutTasks && (needsLayout() || m_inSynchronousPostLayout || inSubframeLayoutWithFrameFlattening)) {
1028 // If we need layout or are already in a synchronous call to postLayoutTasks(),
1029 // defer widget updates and event dispatch until after we return. postLayoutTasks()
1030 // can make us need to update again, and we can get stuck in a nasty cycle unless
1031 // we call it through the timer here.
1032 m_hasPendingPostLayoutTasks = true;
1033 m_postLayoutTasksTimer.startOneShot(0);
1034 if (needsLayout()) {
1035 m_actionScheduler->pause();
1036 layout();
1037 }
1038 }
1039 } else {
1040 m_actionScheduler->resume();
1041 }
1042
1043 InspectorInstrumentation::didLayout(cookie);
1044
1045 m_nestedLayoutCount--;
1046 }
1047
addWidgetToUpdate(RenderEmbeddedObject * object)1048 void FrameView::addWidgetToUpdate(RenderEmbeddedObject* object)
1049 {
1050 if (!m_widgetUpdateSet)
1051 m_widgetUpdateSet = adoptPtr(new RenderEmbeddedObjectSet);
1052
1053 m_widgetUpdateSet->add(object);
1054 }
1055
removeWidgetToUpdate(RenderEmbeddedObject * object)1056 void FrameView::removeWidgetToUpdate(RenderEmbeddedObject* object)
1057 {
1058 if (!m_widgetUpdateSet)
1059 return;
1060
1061 m_widgetUpdateSet->remove(object);
1062 }
1063
setMediaType(const String & mediaType)1064 void FrameView::setMediaType(const String& mediaType)
1065 {
1066 m_mediaType = mediaType;
1067 }
1068
mediaType() const1069 String FrameView::mediaType() const
1070 {
1071 // See if we have an override type.
1072 String overrideType = m_frame->loader()->client()->overrideMediaType();
1073 if (!overrideType.isNull())
1074 return overrideType;
1075 return m_mediaType;
1076 }
1077
adjustMediaTypeForPrinting(bool printing)1078 void FrameView::adjustMediaTypeForPrinting(bool printing)
1079 {
1080 if (printing) {
1081 if (m_mediaTypeWhenNotPrinting.isNull())
1082 m_mediaTypeWhenNotPrinting = mediaType();
1083
1084 String mediaType = (m_frame && m_frame->settings())?m_frame->settings()->printingMediaType():"print";
1085 setMediaType(mediaType);
1086 } else {
1087 if (!m_mediaTypeWhenNotPrinting.isNull())
1088 setMediaType(m_mediaTypeWhenNotPrinting);
1089 m_mediaTypeWhenNotPrinting = String();
1090 }
1091 }
1092
useSlowRepaints() const1093 bool FrameView::useSlowRepaints() const
1094 {
1095 if (m_useSlowRepaints || m_slowRepaintObjectCount > 0 || (platformWidget() && m_fixedObjectCount > 0) || m_isOverlapped || !m_contentIsOpaque)
1096 return true;
1097
1098 if (FrameView* parentView = parentFrameView())
1099 return parentView->useSlowRepaints();
1100
1101 return false;
1102 }
1103
useSlowRepaintsIfNotOverlapped() const1104 bool FrameView::useSlowRepaintsIfNotOverlapped() const
1105 {
1106 if (m_useSlowRepaints || m_slowRepaintObjectCount > 0 || (platformWidget() && m_fixedObjectCount > 0) || !m_contentIsOpaque)
1107 return true;
1108
1109 if (FrameView* parentView = parentFrameView())
1110 return parentView->useSlowRepaintsIfNotOverlapped();
1111
1112 return false;
1113 }
1114
updateCanBlitOnScrollRecursively()1115 void FrameView::updateCanBlitOnScrollRecursively()
1116 {
1117 for (Frame* frame = m_frame.get(); frame; frame = frame->tree()->traverseNext(m_frame.get())) {
1118 if (FrameView* view = frame->view())
1119 view->setCanBlitOnScroll(!view->useSlowRepaints());
1120 }
1121 }
1122
setUseSlowRepaints()1123 void FrameView::setUseSlowRepaints()
1124 {
1125 m_useSlowRepaints = true;
1126 updateCanBlitOnScrollRecursively();
1127 }
1128
addSlowRepaintObject()1129 void FrameView::addSlowRepaintObject()
1130 {
1131 if (!m_slowRepaintObjectCount)
1132 updateCanBlitOnScrollRecursively();
1133 m_slowRepaintObjectCount++;
1134 }
1135
removeSlowRepaintObject()1136 void FrameView::removeSlowRepaintObject()
1137 {
1138 ASSERT(m_slowRepaintObjectCount > 0);
1139 m_slowRepaintObjectCount--;
1140 if (!m_slowRepaintObjectCount)
1141 updateCanBlitOnScrollRecursively();
1142 }
1143
addFixedObject()1144 void FrameView::addFixedObject()
1145 {
1146 if (!m_fixedObjectCount && platformWidget())
1147 updateCanBlitOnScrollRecursively();
1148 ++m_fixedObjectCount;
1149 }
1150
removeFixedObject()1151 void FrameView::removeFixedObject()
1152 {
1153 ASSERT(m_fixedObjectCount > 0);
1154 --m_fixedObjectCount;
1155 if (!m_fixedObjectCount)
1156 updateCanBlitOnScrollRecursively();
1157 }
1158
scrollXForFixedPosition() const1159 int FrameView::scrollXForFixedPosition() const
1160 {
1161 int visibleContentWidth = visibleContentRect().width();
1162 int maxX = contentsWidth() - visibleContentWidth;
1163
1164 if (maxX == 0)
1165 return 0;
1166
1167 int x = scrollX();
1168
1169 if (!ScrollView::scrollOrigin().x()) {
1170 if (x < 0)
1171 x = 0;
1172 else if (x > maxX)
1173 x = maxX;
1174 } else {
1175 if (x > 0)
1176 x = 0;
1177 else if (x < -maxX)
1178 x = -maxX;
1179 }
1180
1181 if (!m_frame)
1182 return x;
1183
1184 float pageScaleFactor = m_frame->pageScaleFactor();
1185
1186 // When the page is scaled, the scaled "viewport" with respect to which fixed object are positioned
1187 // doesn't move as fast as the content view, so that when the content is scrolled all the way to the
1188 // end, the bottom of the scaled "viewport" touches the bottom of the real viewport.
1189 float dragFactor = (contentsWidth() - visibleContentWidth * pageScaleFactor) / maxX;
1190
1191 return x * dragFactor / pageScaleFactor;
1192 }
1193
scrollYForFixedPosition() const1194 int FrameView::scrollYForFixedPosition() const
1195 {
1196 int visibleContentHeight = visibleContentRect().height();
1197
1198 int maxY = contentsHeight() - visibleContentHeight;
1199 if (maxY == 0)
1200 return 0;
1201
1202 int y = scrollY();
1203
1204 if (!ScrollView::scrollOrigin().y()) {
1205 if (y < 0)
1206 y = 0;
1207 else if (y > maxY)
1208 y = maxY;
1209 } else {
1210 if (y > 0)
1211 y = 0;
1212 else if (y < -maxY)
1213 y = -maxY;
1214 }
1215
1216 if (!m_frame)
1217 return y;
1218
1219 float pageScaleFactor = m_frame->pageScaleFactor();
1220 float dragFactor = (contentsHeight() - visibleContentHeight * pageScaleFactor) / maxY;
1221
1222 return y * dragFactor / pageScaleFactor;
1223 }
1224
scrollOffsetForFixedPosition() const1225 IntSize FrameView::scrollOffsetForFixedPosition() const
1226 {
1227 return IntSize(scrollXForFixedPosition(), scrollYForFixedPosition());
1228 }
1229
currentMousePosition() const1230 IntPoint FrameView::currentMousePosition() const
1231 {
1232 return m_frame ? m_frame->eventHandler()->currentMousePosition() : IntPoint();
1233 }
1234
scrollContentsFastPath(const IntSize & scrollDelta,const IntRect & rectToScroll,const IntRect & clipRect)1235 bool FrameView::scrollContentsFastPath(const IntSize& scrollDelta, const IntRect& rectToScroll, const IntRect& clipRect)
1236 {
1237 const size_t fixedObjectThreshold = 5;
1238
1239 RenderBlock::PositionedObjectsListHashSet* positionedObjects = 0;
1240 if (RenderView* root = m_frame->contentRenderer())
1241 positionedObjects = root->positionedObjects();
1242
1243 if (!positionedObjects || positionedObjects->isEmpty()) {
1244 hostWindow()->scroll(scrollDelta, rectToScroll, clipRect);
1245 return true;
1246 }
1247
1248 // Get the rects of the fixed objects visible in the rectToScroll
1249 Vector<IntRect, fixedObjectThreshold> subRectToUpdate;
1250 bool updateInvalidatedSubRect = true;
1251 RenderBlock::PositionedObjectsListHashSet::const_iterator end = positionedObjects->end();
1252 for (RenderBlock::PositionedObjectsListHashSet::const_iterator it = positionedObjects->begin(); it != end; ++it) {
1253 RenderBox* renderBox = *it;
1254 if (renderBox->style()->position() != FixedPosition)
1255 continue;
1256 IntRect updateRect = renderBox->layer()->repaintRectIncludingDescendants();
1257 updateRect = contentsToWindow(updateRect);
1258 if (clipsRepaints())
1259 updateRect.intersect(rectToScroll);
1260 if (!updateRect.isEmpty()) {
1261 if (subRectToUpdate.size() >= fixedObjectThreshold) {
1262 updateInvalidatedSubRect = false;
1263 break;
1264 }
1265 subRectToUpdate.append(updateRect);
1266 }
1267 }
1268
1269 // Scroll the view
1270 if (updateInvalidatedSubRect) {
1271 // 1) scroll
1272 hostWindow()->scroll(scrollDelta, rectToScroll, clipRect);
1273
1274 // 2) update the area of fixed objects that has been invalidated
1275 size_t fixObjectsCount = subRectToUpdate.size();
1276 for (size_t i = 0; i < fixObjectsCount; ++i) {
1277 IntRect updateRect = subRectToUpdate[i];
1278 IntRect scrolledRect = updateRect;
1279 scrolledRect.move(scrollDelta);
1280 updateRect.unite(scrolledRect);
1281 if (clipsRepaints())
1282 updateRect.intersect(rectToScroll);
1283 hostWindow()->invalidateContentsAndWindow(updateRect, false);
1284 }
1285 return true;
1286 }
1287
1288 // the number of fixed objects exceed the threshold, we cannot use the fast path
1289 return false;
1290 }
1291
scrollContentsSlowPath(const IntRect & updateRect)1292 void FrameView::scrollContentsSlowPath(const IntRect& updateRect)
1293 {
1294 #if USE(ACCELERATED_COMPOSITING)
1295 if (RenderPart* frameRenderer = m_frame->ownerRenderer()) {
1296 if (frameRenderer->containerForRepaint()) {
1297 IntRect rect(frameRenderer->borderLeft() + frameRenderer->paddingLeft(),
1298 frameRenderer->borderTop() + frameRenderer->paddingTop(),
1299 visibleWidth(), visibleHeight());
1300 frameRenderer->repaintRectangle(rect);
1301 return;
1302 }
1303 }
1304 #endif
1305
1306 ScrollView::scrollContentsSlowPath(updateRect);
1307 }
1308
1309 // Note that this gets called at painting time.
setIsOverlapped(bool isOverlapped)1310 void FrameView::setIsOverlapped(bool isOverlapped)
1311 {
1312 if (isOverlapped == m_isOverlapped)
1313 return;
1314
1315 m_isOverlapped = isOverlapped;
1316 updateCanBlitOnScrollRecursively();
1317
1318 #if USE(ACCELERATED_COMPOSITING)
1319 if (hasCompositedContentIncludingDescendants()) {
1320 // Overlap can affect compositing tests, so if it changes, we need to trigger
1321 // a layer update in the parent document.
1322 if (Frame* parentFrame = m_frame->tree()->parent()) {
1323 if (RenderView* parentView = parentFrame->contentRenderer()) {
1324 RenderLayerCompositor* compositor = parentView->compositor();
1325 compositor->setCompositingLayersNeedRebuild();
1326 compositor->scheduleCompositingLayerUpdate();
1327 }
1328 }
1329
1330 if (RenderLayerCompositor::allowsIndependentlyCompositedFrames(this)) {
1331 // We also need to trigger reevaluation for this and all descendant frames,
1332 // since a frame uses compositing if any ancestor is compositing.
1333 for (Frame* frame = m_frame.get(); frame; frame = frame->tree()->traverseNext(m_frame.get())) {
1334 if (RenderView* view = frame->contentRenderer()) {
1335 RenderLayerCompositor* compositor = view->compositor();
1336 compositor->setCompositingLayersNeedRebuild();
1337 compositor->scheduleCompositingLayerUpdate();
1338 }
1339 }
1340 }
1341 }
1342 #endif
1343 }
1344
isOverlappedIncludingAncestors() const1345 bool FrameView::isOverlappedIncludingAncestors() const
1346 {
1347 if (isOverlapped())
1348 return true;
1349
1350 if (FrameView* parentView = parentFrameView()) {
1351 if (parentView->isOverlapped())
1352 return true;
1353 }
1354
1355 return false;
1356 }
1357
setContentIsOpaque(bool contentIsOpaque)1358 void FrameView::setContentIsOpaque(bool contentIsOpaque)
1359 {
1360 if (contentIsOpaque == m_contentIsOpaque)
1361 return;
1362
1363 m_contentIsOpaque = contentIsOpaque;
1364 updateCanBlitOnScrollRecursively();
1365 }
1366
restoreScrollbar()1367 void FrameView::restoreScrollbar()
1368 {
1369 setScrollbarsSuppressed(false);
1370 }
1371
scrollToFragment(const KURL & url)1372 bool FrameView::scrollToFragment(const KURL& url)
1373 {
1374 // If our URL has no ref, then we have no place we need to jump to.
1375 // OTOH If CSS target was set previously, we want to set it to 0, recalc
1376 // and possibly repaint because :target pseudo class may have been
1377 // set (see bug 11321).
1378 if (!url.hasFragmentIdentifier() && !m_frame->document()->cssTarget())
1379 return false;
1380
1381 String fragmentIdentifier = url.fragmentIdentifier();
1382 if (scrollToAnchor(fragmentIdentifier))
1383 return true;
1384
1385 // Try again after decoding the ref, based on the document's encoding.
1386 if (TextResourceDecoder* decoder = m_frame->document()->decoder())
1387 return scrollToAnchor(decodeURLEscapeSequences(fragmentIdentifier, decoder->encoding()));
1388
1389 return false;
1390 }
1391
scrollToAnchor(const String & name)1392 bool FrameView::scrollToAnchor(const String& name)
1393 {
1394 ASSERT(m_frame->document());
1395
1396 if (!m_frame->document()->haveStylesheetsLoaded()) {
1397 m_frame->document()->setGotoAnchorNeededAfterStylesheetsLoad(true);
1398 return false;
1399 }
1400
1401 m_frame->document()->setGotoAnchorNeededAfterStylesheetsLoad(false);
1402
1403 Element* anchorNode = m_frame->document()->findAnchor(name);
1404
1405 #if ENABLE(SVG)
1406 if (m_frame->document()->isSVGDocument()) {
1407 if (name.startsWith("xpointer(")) {
1408 // We need to parse the xpointer reference here
1409 } else if (name.startsWith("svgView(")) {
1410 RefPtr<SVGSVGElement> svg = static_cast<SVGDocument*>(m_frame->document())->rootElement();
1411 if (!svg->currentView()->parseViewSpec(name))
1412 return false;
1413 svg->setUseCurrentView(true);
1414 } else {
1415 if (anchorNode && anchorNode->hasTagName(SVGNames::viewTag)) {
1416 RefPtr<SVGViewElement> viewElement = anchorNode->hasTagName(SVGNames::viewTag) ? static_cast<SVGViewElement*>(anchorNode) : 0;
1417 if (viewElement.get()) {
1418 SVGElement* element = SVGLocatable::nearestViewportElement(viewElement.get());
1419 if (element->hasTagName(SVGNames::svgTag)) {
1420 RefPtr<SVGSVGElement> svg = static_cast<SVGSVGElement*>(element);
1421 svg->inheritViewAttributes(viewElement.get());
1422 }
1423 }
1424 }
1425 }
1426 // FIXME: need to decide which <svg> to focus on, and zoom to that one
1427 // FIXME: need to actually "highlight" the viewTarget(s)
1428 }
1429 #endif
1430
1431 m_frame->document()->setCSSTarget(anchorNode); // Setting to null will clear the current target.
1432
1433 // Implement the rule that "" and "top" both mean top of page as in other browsers.
1434 if (!anchorNode && !(name.isEmpty() || equalIgnoringCase(name, "top")))
1435 return false;
1436
1437 maintainScrollPositionAtAnchor(anchorNode ? static_cast<Node*>(anchorNode) : m_frame->document());
1438 return true;
1439 }
1440
maintainScrollPositionAtAnchor(Node * anchorNode)1441 void FrameView::maintainScrollPositionAtAnchor(Node* anchorNode)
1442 {
1443 m_maintainScrollPositionAnchor = anchorNode;
1444 if (!m_maintainScrollPositionAnchor)
1445 return;
1446
1447 // We need to update the layout before scrolling, otherwise we could
1448 // really mess things up if an anchor scroll comes at a bad moment.
1449 m_frame->document()->updateStyleIfNeeded();
1450 // Only do a layout if changes have occurred that make it necessary.
1451 if (m_frame->contentRenderer() && m_frame->contentRenderer()->needsLayout())
1452 layout();
1453 else
1454 scrollToAnchor();
1455 }
1456
setScrollPosition(const IntPoint & scrollPoint)1457 void FrameView::setScrollPosition(const IntPoint& scrollPoint)
1458 {
1459 bool wasInProgrammaticScroll = m_inProgrammaticScroll;
1460 m_inProgrammaticScroll = true;
1461 m_maintainScrollPositionAnchor = 0;
1462 ScrollView::setScrollPosition(scrollPoint);
1463 m_inProgrammaticScroll = wasInProgrammaticScroll;
1464 }
1465
scrollPositionChangedViaPlatformWidget()1466 void FrameView::scrollPositionChangedViaPlatformWidget()
1467 {
1468 repaintFixedElementsAfterScrolling();
1469 scrollPositionChanged();
1470 }
1471
scrollPositionChanged()1472 void FrameView::scrollPositionChanged()
1473 {
1474 frame()->eventHandler()->sendScrollEvent();
1475
1476 #if USE(ACCELERATED_COMPOSITING)
1477 if (RenderView* root = m_frame->contentRenderer()) {
1478 if (root->usesCompositing())
1479 root->compositor()->frameViewDidScroll(scrollPosition());
1480 }
1481 #endif
1482 }
1483
repaintFixedElementsAfterScrolling()1484 void FrameView::repaintFixedElementsAfterScrolling()
1485 {
1486 // For fixed position elements, update widget positions and compositing layers after scrolling,
1487 // but only if we're not inside of layout.
1488 if (!m_nestedLayoutCount && hasFixedObjects()) {
1489 if (RenderView* root = m_frame->contentRenderer()) {
1490 root->updateWidgetPositions();
1491 root->layer()->updateRepaintRectsAfterScroll();
1492 #if USE(ACCELERATED_COMPOSITING)
1493 root->compositor()->updateCompositingLayers(CompositingUpdateOnScroll);
1494 #endif
1495 }
1496 }
1497 }
1498
hostWindow() const1499 HostWindow* FrameView::hostWindow() const
1500 {
1501 Page* page = frame() ? frame()->page() : 0;
1502 if (!page)
1503 return 0;
1504 return page->chrome();
1505 }
1506
1507 const unsigned cRepaintRectUnionThreshold = 25;
1508
repaintContentRectangle(const IntRect & r,bool immediate)1509 void FrameView::repaintContentRectangle(const IntRect& r, bool immediate)
1510 {
1511 ASSERT(!m_frame->ownerElement());
1512
1513 double delay = m_deferringRepaints ? 0 : adjustedDeferredRepaintDelay();
1514 if ((m_deferringRepaints || m_deferredRepaintTimer.isActive() || delay) && !immediate) {
1515 IntRect paintRect = r;
1516 if (clipsRepaints() && !paintsEntireContents())
1517 paintRect.intersect(visibleContentRect());
1518 if (paintRect.isEmpty())
1519 return;
1520 if (m_repaintCount == cRepaintRectUnionThreshold) {
1521 IntRect unionedRect;
1522 for (unsigned i = 0; i < cRepaintRectUnionThreshold; ++i)
1523 unionedRect.unite(m_repaintRects[i]);
1524 m_repaintRects.clear();
1525 m_repaintRects.append(unionedRect);
1526 }
1527 if (m_repaintCount < cRepaintRectUnionThreshold)
1528 m_repaintRects.append(paintRect);
1529 else
1530 m_repaintRects[0].unite(paintRect);
1531 m_repaintCount++;
1532
1533 if (!m_deferringRepaints && !m_deferredRepaintTimer.isActive())
1534 m_deferredRepaintTimer.startOneShot(delay);
1535 return;
1536 }
1537
1538 if (!shouldUpdate(immediate))
1539 return;
1540
1541 #if ENABLE(TILED_BACKING_STORE)
1542 if (frame()->tiledBackingStore()) {
1543 frame()->tiledBackingStore()->invalidate(r);
1544 return;
1545 }
1546 #endif
1547 ScrollView::repaintContentRectangle(r, immediate);
1548 }
1549
contentsResized()1550 void FrameView::contentsResized()
1551 {
1552 scrollAnimator()->contentsResized();
1553 setNeedsLayout();
1554 }
1555
visibleContentsResized()1556 void FrameView::visibleContentsResized()
1557 {
1558 // We check to make sure the view is attached to a frame() as this method can
1559 // be triggered before the view is attached by Frame::createView(...) setting
1560 // various values such as setScrollBarModes(...) for example. An ASSERT is
1561 // triggered when a view is layout before being attached to a frame().
1562 if (!frame()->view())
1563 return;
1564
1565 if (needsLayout())
1566 layout();
1567
1568 #if USE(ACCELERATED_COMPOSITING)
1569 if (RenderView* root = m_frame->contentRenderer()) {
1570 if (root->usesCompositing())
1571 root->compositor()->frameViewDidChangeSize();
1572 }
1573 #endif
1574 }
1575
beginDeferredRepaints()1576 void FrameView::beginDeferredRepaints()
1577 {
1578 Page* page = m_frame->page();
1579 if (page->mainFrame() != m_frame)
1580 return page->mainFrame()->view()->beginDeferredRepaints();
1581
1582 m_deferringRepaints++;
1583 }
1584
1585
endDeferredRepaints()1586 void FrameView::endDeferredRepaints()
1587 {
1588 Page* page = m_frame->page();
1589 if (page->mainFrame() != m_frame)
1590 return page->mainFrame()->view()->endDeferredRepaints();
1591
1592 ASSERT(m_deferringRepaints > 0);
1593
1594 if (--m_deferringRepaints)
1595 return;
1596
1597 if (m_deferredRepaintTimer.isActive())
1598 return;
1599
1600 if (double delay = adjustedDeferredRepaintDelay()) {
1601 m_deferredRepaintTimer.startOneShot(delay);
1602 return;
1603 }
1604
1605 doDeferredRepaints();
1606 }
1607
checkStopDelayingDeferredRepaints()1608 void FrameView::checkStopDelayingDeferredRepaints()
1609 {
1610 if (!m_deferredRepaintTimer.isActive())
1611 return;
1612
1613 Document* document = m_frame->document();
1614 if (document && (document->parsing() || document->cachedResourceLoader()->requestCount()))
1615 return;
1616
1617 m_deferredRepaintTimer.stop();
1618
1619 doDeferredRepaints();
1620 }
1621
doDeferredRepaints()1622 void FrameView::doDeferredRepaints()
1623 {
1624 ASSERT(!m_deferringRepaints);
1625 if (!shouldUpdate()) {
1626 m_repaintRects.clear();
1627 m_repaintCount = 0;
1628 return;
1629 }
1630 unsigned size = m_repaintRects.size();
1631 for (unsigned i = 0; i < size; i++) {
1632 #if ENABLE(TILED_BACKING_STORE)
1633 if (frame()->tiledBackingStore()) {
1634 frame()->tiledBackingStore()->invalidate(m_repaintRects[i]);
1635 continue;
1636 }
1637 #endif
1638 ScrollView::repaintContentRectangle(m_repaintRects[i], false);
1639 }
1640 m_repaintRects.clear();
1641 m_repaintCount = 0;
1642
1643 updateDeferredRepaintDelay();
1644 }
1645
updateDeferredRepaintDelay()1646 void FrameView::updateDeferredRepaintDelay()
1647 {
1648 Document* document = m_frame->document();
1649 if (!document || (!document->parsing() && !document->cachedResourceLoader()->requestCount())) {
1650 m_deferredRepaintDelay = s_deferredRepaintDelay;
1651 return;
1652 }
1653 if (m_deferredRepaintDelay < s_maxDeferredRepaintDelayDuringLoading) {
1654 m_deferredRepaintDelay += s_deferredRepaintDelayIncrementDuringLoading;
1655 if (m_deferredRepaintDelay > s_maxDeferredRepaintDelayDuringLoading)
1656 m_deferredRepaintDelay = s_maxDeferredRepaintDelayDuringLoading;
1657 }
1658 }
1659
resetDeferredRepaintDelay()1660 void FrameView::resetDeferredRepaintDelay()
1661 {
1662 m_deferredRepaintDelay = 0;
1663 if (m_deferredRepaintTimer.isActive()) {
1664 m_deferredRepaintTimer.stop();
1665 if (!m_deferringRepaints)
1666 doDeferredRepaints();
1667 }
1668 }
1669
adjustedDeferredRepaintDelay() const1670 double FrameView::adjustedDeferredRepaintDelay() const
1671 {
1672 ASSERT(!m_deferringRepaints);
1673 if (!m_deferredRepaintDelay)
1674 return 0;
1675 double timeSinceLastPaint = currentTime() - m_lastPaintTime;
1676 return max(0., m_deferredRepaintDelay - timeSinceLastPaint);
1677 }
1678
deferredRepaintTimerFired(Timer<FrameView> *)1679 void FrameView::deferredRepaintTimerFired(Timer<FrameView>*)
1680 {
1681 doDeferredRepaints();
1682 }
1683
layoutTimerFired(Timer<FrameView> *)1684 void FrameView::layoutTimerFired(Timer<FrameView>*)
1685 {
1686 #ifdef INSTRUMENT_LAYOUT_SCHEDULING
1687 if (!m_frame->document()->ownerElement())
1688 printf("Layout timer fired at %d\n", m_frame->document()->elapsedTime());
1689 #endif
1690 layout();
1691 }
1692
scheduleRelayout()1693 void FrameView::scheduleRelayout()
1694 {
1695 // FIXME: We should assert the page is not in the page cache, but that is causing
1696 // too many false assertions. See <rdar://problem/7218118>.
1697 ASSERT(m_frame->view() == this);
1698
1699 if (m_layoutRoot) {
1700 m_layoutRoot->markContainingBlocksForLayout(false);
1701 m_layoutRoot = 0;
1702 }
1703 if (!m_layoutSchedulingEnabled)
1704 return;
1705 if (!needsLayout())
1706 return;
1707 if (!m_frame->document()->shouldScheduleLayout())
1708 return;
1709
1710 // When frame flattening is enabled, the contents of the frame affects layout of the parent frames.
1711 // Also invalidate parent frame starting from the owner element of this frame.
1712 if (m_frame->settings() && m_frame->settings()->frameFlatteningEnabled() && m_frame->ownerRenderer()) {
1713 if (m_frame->ownerElement()->hasTagName(iframeTag) || m_frame->ownerElement()->hasTagName(frameTag))
1714 m_frame->ownerRenderer()->setNeedsLayout(true, true);
1715 }
1716
1717 int delay = m_frame->document()->minimumLayoutDelay();
1718 if (m_layoutTimer.isActive() && m_delayedLayout && !delay)
1719 unscheduleRelayout();
1720 if (m_layoutTimer.isActive())
1721 return;
1722
1723 m_delayedLayout = delay != 0;
1724
1725 #ifdef INSTRUMENT_LAYOUT_SCHEDULING
1726 if (!m_frame->document()->ownerElement())
1727 printf("Scheduling layout for %d\n", delay);
1728 #endif
1729
1730 m_layoutTimer.startOneShot(delay * 0.001);
1731 }
1732
isObjectAncestorContainerOf(RenderObject * ancestor,RenderObject * descendant)1733 static bool isObjectAncestorContainerOf(RenderObject* ancestor, RenderObject* descendant)
1734 {
1735 for (RenderObject* r = descendant; r; r = r->container()) {
1736 if (r == ancestor)
1737 return true;
1738 }
1739 return false;
1740 }
1741
scheduleRelayoutOfSubtree(RenderObject * relayoutRoot)1742 void FrameView::scheduleRelayoutOfSubtree(RenderObject* relayoutRoot)
1743 {
1744 ASSERT(m_frame->view() == this);
1745
1746 if (m_frame->contentRenderer() && m_frame->contentRenderer()->needsLayout()) {
1747 if (relayoutRoot)
1748 relayoutRoot->markContainingBlocksForLayout(false);
1749 return;
1750 }
1751
1752 if (layoutPending() || !m_layoutSchedulingEnabled) {
1753 if (m_layoutRoot != relayoutRoot) {
1754 if (isObjectAncestorContainerOf(m_layoutRoot, relayoutRoot)) {
1755 // Keep the current root
1756 relayoutRoot->markContainingBlocksForLayout(false, m_layoutRoot);
1757 ASSERT(!m_layoutRoot->container() || !m_layoutRoot->container()->needsLayout());
1758 } else if (m_layoutRoot && isObjectAncestorContainerOf(relayoutRoot, m_layoutRoot)) {
1759 // Re-root at relayoutRoot
1760 m_layoutRoot->markContainingBlocksForLayout(false, relayoutRoot);
1761 m_layoutRoot = relayoutRoot;
1762 ASSERT(!m_layoutRoot->container() || !m_layoutRoot->container()->needsLayout());
1763 } else {
1764 // Just do a full relayout
1765 if (m_layoutRoot)
1766 m_layoutRoot->markContainingBlocksForLayout(false);
1767 m_layoutRoot = 0;
1768 relayoutRoot->markContainingBlocksForLayout(false);
1769 }
1770 }
1771 } else if (m_layoutSchedulingEnabled) {
1772 int delay = m_frame->document()->minimumLayoutDelay();
1773 m_layoutRoot = relayoutRoot;
1774 ASSERT(!m_layoutRoot->container() || !m_layoutRoot->container()->needsLayout());
1775 m_delayedLayout = delay != 0;
1776 m_layoutTimer.startOneShot(delay * 0.001);
1777 }
1778 }
1779
layoutPending() const1780 bool FrameView::layoutPending() const
1781 {
1782 return m_layoutTimer.isActive();
1783 }
1784
needsLayout() const1785 bool FrameView::needsLayout() const
1786 {
1787 // This can return true in cases where the document does not have a body yet.
1788 // Document::shouldScheduleLayout takes care of preventing us from scheduling
1789 // layout in that case.
1790 if (!m_frame)
1791 return false;
1792 RenderView* root = m_frame->contentRenderer();
1793 return layoutPending()
1794 || (root && root->needsLayout())
1795 || m_layoutRoot
1796 || (m_deferSetNeedsLayouts && m_setNeedsLayoutWasDeferred);
1797 }
1798
setNeedsLayout()1799 void FrameView::setNeedsLayout()
1800 {
1801 if (m_deferSetNeedsLayouts) {
1802 m_setNeedsLayoutWasDeferred = true;
1803 return;
1804 }
1805 RenderView* root = m_frame->contentRenderer();
1806 if (root)
1807 root->setNeedsLayout(true);
1808 }
1809
unscheduleRelayout()1810 void FrameView::unscheduleRelayout()
1811 {
1812 m_postLayoutTasksTimer.stop();
1813
1814 if (!m_layoutTimer.isActive())
1815 return;
1816
1817 #ifdef INSTRUMENT_LAYOUT_SCHEDULING
1818 if (!m_frame->document()->ownerElement())
1819 printf("Layout timer unscheduled at %d\n", m_frame->document()->elapsedTime());
1820 #endif
1821
1822 m_layoutTimer.stop();
1823 m_delayedLayout = false;
1824 }
1825
1826 #if ENABLE(REQUEST_ANIMATION_FRAME)
serviceScriptedAnimations(DOMTimeStamp time)1827 void FrameView::serviceScriptedAnimations(DOMTimeStamp time)
1828 {
1829 for (Frame* frame = m_frame.get(); frame; frame = frame->tree()->traverseNext())
1830 frame->document()->serviceScriptedAnimations(time);
1831 }
1832 #endif
1833
isTransparent() const1834 bool FrameView::isTransparent() const
1835 {
1836 return m_isTransparent;
1837 }
1838
setTransparent(bool isTransparent)1839 void FrameView::setTransparent(bool isTransparent)
1840 {
1841 m_isTransparent = isTransparent;
1842 }
1843
baseBackgroundColor() const1844 Color FrameView::baseBackgroundColor() const
1845 {
1846 return m_baseBackgroundColor;
1847 }
1848
setBaseBackgroundColor(const Color & backgroundColor)1849 void FrameView::setBaseBackgroundColor(const Color& backgroundColor)
1850 {
1851 if (!backgroundColor.isValid())
1852 m_baseBackgroundColor = Color::white;
1853 else
1854 m_baseBackgroundColor = backgroundColor;
1855 }
1856
updateBackgroundRecursively(const Color & backgroundColor,bool transparent)1857 void FrameView::updateBackgroundRecursively(const Color& backgroundColor, bool transparent)
1858 {
1859 for (Frame* frame = m_frame.get(); frame; frame = frame->tree()->traverseNext(m_frame.get())) {
1860 if (FrameView* view = frame->view()) {
1861 view->setTransparent(transparent);
1862 view->setBaseBackgroundColor(backgroundColor);
1863 }
1864 }
1865 }
1866
shouldUpdateWhileOffscreen() const1867 bool FrameView::shouldUpdateWhileOffscreen() const
1868 {
1869 return m_shouldUpdateWhileOffscreen;
1870 }
1871
setShouldUpdateWhileOffscreen(bool shouldUpdateWhileOffscreen)1872 void FrameView::setShouldUpdateWhileOffscreen(bool shouldUpdateWhileOffscreen)
1873 {
1874 m_shouldUpdateWhileOffscreen = shouldUpdateWhileOffscreen;
1875 }
1876
shouldUpdate(bool immediateRequested) const1877 bool FrameView::shouldUpdate(bool immediateRequested) const
1878 {
1879 if (!immediateRequested && isOffscreen() && !shouldUpdateWhileOffscreen())
1880 return false;
1881 return true;
1882 }
1883
scheduleEvent(PassRefPtr<Event> event,PassRefPtr<Node> eventTarget)1884 void FrameView::scheduleEvent(PassRefPtr<Event> event, PassRefPtr<Node> eventTarget)
1885 {
1886 m_actionScheduler->scheduleEvent(event, eventTarget);
1887 }
1888
pauseScheduledEvents()1889 void FrameView::pauseScheduledEvents()
1890 {
1891 m_actionScheduler->pause();
1892 }
1893
resumeScheduledEvents()1894 void FrameView::resumeScheduledEvents()
1895 {
1896 m_actionScheduler->resume();
1897 }
1898
scrollToAnchor()1899 void FrameView::scrollToAnchor()
1900 {
1901 RefPtr<Node> anchorNode = m_maintainScrollPositionAnchor;
1902 if (!anchorNode)
1903 return;
1904
1905 if (!anchorNode->renderer())
1906 return;
1907
1908 IntRect rect;
1909 if (anchorNode != m_frame->document())
1910 rect = anchorNode->getRect();
1911
1912 // Scroll nested layers and frames to reveal the anchor.
1913 // Align to the top and to the closest side (this matches other browsers).
1914 anchorNode->renderer()->enclosingLayer()->scrollRectToVisible(rect, true, ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignTopAlways);
1915
1916 if (AXObjectCache::accessibilityEnabled())
1917 m_frame->document()->axObjectCache()->handleScrolledToAnchor(anchorNode.get());
1918
1919 // scrollRectToVisible can call into setScrollPosition(), which resets m_maintainScrollPositionAnchor.
1920 m_maintainScrollPositionAnchor = anchorNode;
1921 }
1922
updateWidget(RenderEmbeddedObject * object)1923 void FrameView::updateWidget(RenderEmbeddedObject* object)
1924 {
1925 ASSERT(!object->node() || object->node()->isElementNode());
1926 Element* ownerElement = static_cast<Element*>(object->node());
1927 // The object may have already been destroyed (thus node cleared),
1928 // but FrameView holds a manual ref, so it won't have been deleted.
1929 ASSERT(m_widgetUpdateSet->contains(object));
1930 if (!ownerElement)
1931 return;
1932
1933 // No need to update if it's already crashed or known to be missing.
1934 if (object->pluginCrashedOrWasMissing())
1935 return;
1936
1937 // FIXME: This could turn into a real virtual dispatch if we defined
1938 // updateWidget(bool) on HTMLElement.
1939 if (ownerElement->hasTagName(objectTag) || ownerElement->hasTagName(embedTag))
1940 static_cast<HTMLPlugInImageElement*>(ownerElement)->updateWidget(CreateAnyWidgetType);
1941 // FIXME: It is not clear that Media elements need or want this updateWidget() call.
1942 #if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
1943 else if (ownerElement->isMediaElement())
1944 static_cast<HTMLMediaElement*>(ownerElement)->updateWidget(CreateAnyWidgetType);
1945 #endif
1946 else
1947 ASSERT_NOT_REACHED();
1948
1949 // Caution: it's possible the object was destroyed again, since loading a
1950 // plugin may run any arbitrary javascript.
1951 object->updateWidgetPosition();
1952 }
1953
updateWidgets()1954 bool FrameView::updateWidgets()
1955 {
1956 if (m_nestedLayoutCount > 1 || !m_widgetUpdateSet || m_widgetUpdateSet->isEmpty())
1957 return true;
1958
1959 size_t size = m_widgetUpdateSet->size();
1960
1961 Vector<RenderEmbeddedObject*> objects;
1962 objects.reserveCapacity(size);
1963
1964 RenderEmbeddedObjectSet::const_iterator end = m_widgetUpdateSet->end();
1965 for (RenderEmbeddedObjectSet::const_iterator it = m_widgetUpdateSet->begin(); it != end; ++it) {
1966 objects.uncheckedAppend(*it);
1967 (*it)->ref();
1968 }
1969
1970 for (size_t i = 0; i < size; ++i) {
1971 RenderEmbeddedObject* object = objects[i];
1972 updateWidget(object);
1973 m_widgetUpdateSet->remove(object);
1974 }
1975
1976 RenderArena* arena = m_frame->document()->renderArena();
1977 for (size_t i = 0; i < size; ++i)
1978 objects[i]->deref(arena);
1979
1980 return m_widgetUpdateSet->isEmpty();
1981 }
1982
flushAnyPendingPostLayoutTasks()1983 void FrameView::flushAnyPendingPostLayoutTasks()
1984 {
1985 if (!m_hasPendingPostLayoutTasks)
1986 return;
1987
1988 m_postLayoutTasksTimer.stop();
1989 performPostLayoutTasks();
1990 }
1991
performPostLayoutTasks()1992 void FrameView::performPostLayoutTasks()
1993 {
1994 m_hasPendingPostLayoutTasks = false;
1995
1996 m_frame->selection()->setCaretRectNeedsUpdate();
1997 m_frame->selection()->updateAppearance();
1998
1999 if (m_nestedLayoutCount <= 1) {
2000 if (m_firstLayoutCallbackPending) {
2001 m_firstLayoutCallbackPending = false;
2002 m_frame->loader()->didFirstLayout();
2003 }
2004
2005 if (m_isVisuallyNonEmpty && m_firstVisuallyNonEmptyLayoutCallbackPending) {
2006 m_firstVisuallyNonEmptyLayoutCallbackPending = false;
2007 m_frame->loader()->didFirstVisuallyNonEmptyLayout();
2008 }
2009 }
2010
2011 RenderView* root = m_frame->contentRenderer();
2012
2013 root->updateWidgetPositions();
2014
2015 for (unsigned i = 0; i < maxUpdateWidgetsIterations; i++) {
2016 if (updateWidgets())
2017 break;
2018 }
2019
2020 scrollToAnchor();
2021
2022 m_actionScheduler->resume();
2023
2024 if (!root->printing()) {
2025 IntSize currentSize = IntSize(width(), height());
2026 float currentZoomFactor = root->style()->zoom();
2027 bool resized = !m_firstLayout && (currentSize != m_lastLayoutSize || currentZoomFactor != m_lastZoomFactor);
2028 m_lastLayoutSize = currentSize;
2029 m_lastZoomFactor = currentZoomFactor;
2030 if (resized)
2031 m_frame->eventHandler()->sendResizeEvent();
2032 }
2033 }
2034
postLayoutTimerFired(Timer<FrameView> *)2035 void FrameView::postLayoutTimerFired(Timer<FrameView>*)
2036 {
2037 performPostLayoutTasks();
2038 }
2039
updateOverflowStatus(bool horizontalOverflow,bool verticalOverflow)2040 void FrameView::updateOverflowStatus(bool horizontalOverflow, bool verticalOverflow)
2041 {
2042 if (!m_viewportRenderer)
2043 return;
2044
2045 if (m_overflowStatusDirty) {
2046 m_horizontalOverflow = horizontalOverflow;
2047 m_verticalOverflow = verticalOverflow;
2048 m_overflowStatusDirty = false;
2049 return;
2050 }
2051
2052 bool horizontalOverflowChanged = (m_horizontalOverflow != horizontalOverflow);
2053 bool verticalOverflowChanged = (m_verticalOverflow != verticalOverflow);
2054
2055 if (horizontalOverflowChanged || verticalOverflowChanged) {
2056 m_horizontalOverflow = horizontalOverflow;
2057 m_verticalOverflow = verticalOverflow;
2058
2059 m_actionScheduler->scheduleEvent(OverflowEvent::create(horizontalOverflowChanged, horizontalOverflow,
2060 verticalOverflowChanged, verticalOverflow),
2061 m_viewportRenderer->node());
2062 }
2063
2064 }
2065
windowClipRect(bool clipToContents) const2066 IntRect FrameView::windowClipRect(bool clipToContents) const
2067 {
2068 ASSERT(m_frame->view() == this);
2069
2070 if (paintsEntireContents())
2071 return IntRect(IntPoint(0, 0), contentsSize());
2072
2073 // Set our clip rect to be our contents.
2074 IntRect clipRect = contentsToWindow(visibleContentRect(!clipToContents));
2075 if (!m_frame || !m_frame->ownerElement())
2076 return clipRect;
2077
2078 // Take our owner element and get the clip rect from the enclosing layer.
2079 Element* elt = m_frame->ownerElement();
2080 // The renderer can sometimes be null when style="display:none" interacts
2081 // with external content and plugins.
2082 RenderLayer* layer = elt->renderer() ? elt->renderer()->enclosingLayer() : 0;
2083 if (!layer)
2084 return clipRect;
2085 FrameView* parentView = elt->document()->view();
2086 clipRect.intersect(parentView->windowClipRectForLayer(layer, true));
2087 return clipRect;
2088 }
2089
windowClipRectForLayer(const RenderLayer * layer,bool clipToLayerContents) const2090 IntRect FrameView::windowClipRectForLayer(const RenderLayer* layer, bool clipToLayerContents) const
2091 {
2092 // If we have no layer, just return our window clip rect.
2093 if (!layer)
2094 return windowClipRect();
2095
2096 // Apply the clip from the layer.
2097 IntRect clipRect;
2098 if (clipToLayerContents)
2099 clipRect = layer->childrenClipRect();
2100 else
2101 clipRect = layer->selfClipRect();
2102 clipRect = contentsToWindow(clipRect);
2103 return intersection(clipRect, windowClipRect());
2104 }
2105
isActive() const2106 bool FrameView::isActive() const
2107 {
2108 Page* page = frame()->page();
2109 return page && page->focusController()->isActive();
2110 }
2111
scrollTo(const IntSize & newOffset)2112 void FrameView::scrollTo(const IntSize& newOffset)
2113 {
2114 IntSize offset = scrollOffset();
2115 ScrollView::scrollTo(newOffset);
2116 if (offset != scrollOffset())
2117 scrollPositionChanged();
2118 frame()->loader()->client()->didChangeScrollOffset();
2119 }
2120
invalidateScrollbarRect(Scrollbar * scrollbar,const IntRect & rect)2121 void FrameView::invalidateScrollbarRect(Scrollbar* scrollbar, const IntRect& rect)
2122 {
2123 // Add in our offset within the FrameView.
2124 IntRect dirtyRect = rect;
2125 dirtyRect.move(scrollbar->x(), scrollbar->y());
2126 invalidateRect(dirtyRect);
2127 }
2128
getTickmarks(Vector<IntRect> & tickmarks) const2129 void FrameView::getTickmarks(Vector<IntRect>& tickmarks) const
2130 {
2131 tickmarks = frame()->document()->markers()->renderedRectsForMarkers(DocumentMarker::TextMatch);
2132 }
2133
windowResizerRect() const2134 IntRect FrameView::windowResizerRect() const
2135 {
2136 Page* page = frame() ? frame()->page() : 0;
2137 if (!page)
2138 return IntRect();
2139 return page->chrome()->windowResizerRect();
2140 }
2141
didCompleteRubberBand(const IntSize & initialOverhang) const2142 void FrameView::didCompleteRubberBand(const IntSize& initialOverhang) const
2143 {
2144 Page* page = m_frame->page();
2145 if (!page)
2146 return;
2147 if (page->mainFrame() != m_frame)
2148 return;
2149 return page->chrome()->client()->didCompleteRubberBandForMainFrame(initialOverhang);
2150 }
2151
scrollbarStyleChanged()2152 void FrameView::scrollbarStyleChanged()
2153 {
2154 Page* page = m_frame->page();
2155 if (!page)
2156 return;
2157 page->setNeedsRecalcStyleInAllFrames();
2158 }
2159
setVisibleScrollerThumbRect(const IntRect & scrollerThumb)2160 void FrameView::setVisibleScrollerThumbRect(const IntRect& scrollerThumb)
2161 {
2162 Page* page = m_frame->page();
2163 if (!page)
2164 return;
2165 if (page->mainFrame() != m_frame)
2166 return;
2167 return page->chrome()->client()->notifyScrollerThumbIsVisibleInRect(scrollerThumb);
2168 }
2169
shouldSuspendScrollAnimations() const2170 bool FrameView::shouldSuspendScrollAnimations() const
2171 {
2172 return m_frame->loader()->state() != FrameStateComplete;
2173 }
2174
notifyPageThatContentAreaWillPaint() const2175 void FrameView::notifyPageThatContentAreaWillPaint() const
2176 {
2177 Page* page = m_frame->page();
2178 const HashSet<ScrollableArea*>* scrollableAreas = page->scrollableAreaSet();
2179 if (!scrollableAreas)
2180 return;
2181
2182 HashSet<ScrollableArea*>::const_iterator end = scrollableAreas->end();
2183 for (HashSet<ScrollableArea*>::const_iterator it = scrollableAreas->begin(); it != end; ++it)
2184 (*it)->scrollAnimator()->contentAreaWillPaint();
2185 }
2186
2187 #if ENABLE(DASHBOARD_SUPPORT)
updateDashboardRegions()2188 void FrameView::updateDashboardRegions()
2189 {
2190 Document* document = m_frame->document();
2191 if (!document->hasDashboardRegions())
2192 return;
2193 Vector<DashboardRegionValue> newRegions;
2194 document->renderBox()->collectDashboardRegions(newRegions);
2195 if (newRegions == document->dashboardRegions())
2196 return;
2197 document->setDashboardRegions(newRegions);
2198 Page* page = m_frame->page();
2199 if (!page)
2200 return;
2201 page->chrome()->client()->dashboardRegionsChanged();
2202 }
2203 #endif
2204
updateScrollCorner()2205 void FrameView::updateScrollCorner()
2206 {
2207 RenderObject* renderer = 0;
2208 RefPtr<RenderStyle> cornerStyle;
2209
2210 if (!scrollCornerRect().isEmpty()) {
2211 // Try the <body> element first as a scroll corner source.
2212 Document* doc = m_frame->document();
2213 Element* body = doc ? doc->body() : 0;
2214 if (body && body->renderer()) {
2215 renderer = body->renderer();
2216 cornerStyle = renderer->getUncachedPseudoStyle(SCROLLBAR_CORNER, renderer->style());
2217 }
2218
2219 if (!cornerStyle) {
2220 // If the <body> didn't have a custom style, then the root element might.
2221 Element* docElement = doc ? doc->documentElement() : 0;
2222 if (docElement && docElement->renderer()) {
2223 renderer = docElement->renderer();
2224 cornerStyle = renderer->getUncachedPseudoStyle(SCROLLBAR_CORNER, renderer->style());
2225 }
2226 }
2227
2228 if (!cornerStyle) {
2229 // If we have an owning iframe/frame element, then it can set the custom scrollbar also.
2230 if (RenderPart* renderer = m_frame->ownerRenderer())
2231 cornerStyle = renderer->getUncachedPseudoStyle(SCROLLBAR_CORNER, renderer->style());
2232 }
2233 }
2234
2235 if (cornerStyle) {
2236 if (!m_scrollCorner)
2237 m_scrollCorner = new (renderer->renderArena()) RenderScrollbarPart(renderer->document());
2238 m_scrollCorner->setStyle(cornerStyle.release());
2239 invalidateScrollCorner();
2240 } else if (m_scrollCorner) {
2241 m_scrollCorner->destroy();
2242 m_scrollCorner = 0;
2243 }
2244
2245 ScrollView::updateScrollCorner();
2246 }
2247
paintScrollCorner(GraphicsContext * context,const IntRect & cornerRect)2248 void FrameView::paintScrollCorner(GraphicsContext* context, const IntRect& cornerRect)
2249 {
2250 if (context->updatingControlTints()) {
2251 updateScrollCorner();
2252 return;
2253 }
2254
2255 if (m_scrollCorner) {
2256 m_scrollCorner->paintIntoRect(context, cornerRect.x(), cornerRect.y(), cornerRect);
2257 return;
2258 }
2259
2260 ScrollView::paintScrollCorner(context, cornerRect);
2261 }
2262
hasCustomScrollbars() const2263 bool FrameView::hasCustomScrollbars() const
2264 {
2265 const HashSet<RefPtr<Widget> >* viewChildren = children();
2266 HashSet<RefPtr<Widget> >::const_iterator end = viewChildren->end();
2267 for (HashSet<RefPtr<Widget> >::const_iterator current = viewChildren->begin(); current != end; ++current) {
2268 Widget* widget = current->get();
2269 if (widget->isFrameView()) {
2270 if (static_cast<FrameView*>(widget)->hasCustomScrollbars())
2271 return true;
2272 } else if (widget->isScrollbar()) {
2273 Scrollbar* scrollbar = static_cast<Scrollbar*>(widget);
2274 if (scrollbar->isCustomScrollbar())
2275 return true;
2276 }
2277 }
2278
2279 return false;
2280 }
2281
clearOwningRendererForCustomScrollbars(RenderBox * box)2282 void FrameView::clearOwningRendererForCustomScrollbars(RenderBox* box)
2283 {
2284 const HashSet<RefPtr<Widget> >* viewChildren = children();
2285 HashSet<RefPtr<Widget> >::const_iterator end = viewChildren->end();
2286 for (HashSet<RefPtr<Widget> >::const_iterator current = viewChildren->begin(); current != end; ++current) {
2287 Widget* widget = current->get();
2288 if (widget->isScrollbar()) {
2289 Scrollbar* scrollbar = static_cast<Scrollbar*>(widget);
2290 if (scrollbar->isCustomScrollbar()) {
2291 RenderScrollbar* customScrollbar = toRenderScrollbar(scrollbar);
2292 if (customScrollbar->owningRenderer() == box)
2293 customScrollbar->clearOwningRenderer();
2294 }
2295 }
2296 }
2297 }
2298
parentFrameView() const2299 FrameView* FrameView::parentFrameView() const
2300 {
2301 if (Widget* parentView = parent()) {
2302 if (parentView->isFrameView())
2303 return static_cast<FrameView*>(parentView);
2304 }
2305 return 0;
2306 }
2307
updateControlTints()2308 void FrameView::updateControlTints()
2309 {
2310 // This is called when control tints are changed from aqua/graphite to clear and vice versa.
2311 // We do a "fake" paint, and when the theme gets a paint call, it can then do an invalidate.
2312 // This is only done if the theme supports control tinting. It's up to the theme and platform
2313 // to define when controls get the tint and to call this function when that changes.
2314
2315 // Optimize the common case where we bring a window to the front while it's still empty.
2316 if (!m_frame || m_frame->document()->url().isEmpty())
2317 return;
2318
2319 if ((m_frame->contentRenderer() && m_frame->contentRenderer()->theme()->supportsControlTints()) || hasCustomScrollbars()) {
2320 if (needsLayout())
2321 layout();
2322 PlatformGraphicsContext* const noContext = 0;
2323 GraphicsContext context(noContext);
2324 context.setUpdatingControlTints(true);
2325 if (platformWidget())
2326 paintContents(&context, visibleContentRect());
2327 else
2328 paint(&context, frameRect());
2329 }
2330 }
2331
wasScrolledByUser() const2332 bool FrameView::wasScrolledByUser() const
2333 {
2334 return m_wasScrolledByUser;
2335 }
2336
setWasScrolledByUser(bool wasScrolledByUser)2337 void FrameView::setWasScrolledByUser(bool wasScrolledByUser)
2338 {
2339 if (m_inProgrammaticScroll)
2340 return;
2341 m_maintainScrollPositionAnchor = 0;
2342 m_wasScrolledByUser = wasScrolledByUser;
2343 }
2344
paintContents(GraphicsContext * p,const IntRect & rect)2345 void FrameView::paintContents(GraphicsContext* p, const IntRect& rect)
2346 {
2347 if (!frame())
2348 return;
2349
2350 InspectorInstrumentationCookie cookie = InspectorInstrumentation::willPaint(m_frame.get(), rect);
2351
2352 Document* document = m_frame->document();
2353
2354 #ifndef NDEBUG
2355 bool fillWithRed;
2356 if (document->printing())
2357 fillWithRed = false; // Printing, don't fill with red (can't remember why).
2358 else if (m_frame->ownerElement())
2359 fillWithRed = false; // Subframe, don't fill with red.
2360 else if (isTransparent())
2361 fillWithRed = false; // Transparent, don't fill with red.
2362 else if (m_paintBehavior & PaintBehaviorSelectionOnly)
2363 fillWithRed = false; // Selections are transparent, don't fill with red.
2364 else if (m_nodeToDraw)
2365 fillWithRed = false; // Element images are transparent, don't fill with red.
2366 else
2367 fillWithRed = true;
2368
2369 if (fillWithRed)
2370 p->fillRect(rect, Color(0xFF, 0, 0), ColorSpaceDeviceRGB);
2371 #endif
2372
2373 bool isTopLevelPainter = !sCurrentPaintTimeStamp;
2374 if (isTopLevelPainter)
2375 sCurrentPaintTimeStamp = currentTime();
2376
2377 RenderView* contentRenderer = frame()->contentRenderer();
2378 if (!contentRenderer) {
2379 LOG_ERROR("called FrameView::paint with nil renderer");
2380 return;
2381 }
2382
2383 ASSERT(!needsLayout());
2384 if (needsLayout())
2385 return;
2386
2387 #if USE(ACCELERATED_COMPOSITING)
2388 if (!p->paintingDisabled())
2389 syncCompositingStateForThisFrame();
2390 #endif
2391
2392 PaintBehavior oldPaintBehavior = m_paintBehavior;
2393
2394 if (FrameView* parentView = parentFrameView()) {
2395 if (parentView->paintBehavior() & PaintBehaviorFlattenCompositingLayers)
2396 m_paintBehavior |= PaintBehaviorFlattenCompositingLayers;
2397 }
2398
2399 if (m_paintBehavior == PaintBehaviorNormal)
2400 document->markers()->invalidateRenderedRectsForMarkersInRect(rect);
2401
2402 if (document->printing())
2403 m_paintBehavior |= PaintBehaviorFlattenCompositingLayers;
2404
2405 bool flatteningPaint = m_paintBehavior & PaintBehaviorFlattenCompositingLayers;
2406 bool isRootFrame = !m_frame->ownerElement();
2407 if (flatteningPaint && isRootFrame)
2408 notifyWidgetsInAllFrames(WillPaintFlattened);
2409
2410 ASSERT(!m_isPainting);
2411 m_isPainting = true;
2412
2413 // m_nodeToDraw is used to draw only one element (and its descendants)
2414 RenderObject* eltRenderer = m_nodeToDraw ? m_nodeToDraw->renderer() : 0;
2415 RenderLayer* rootLayer = contentRenderer->layer();
2416
2417 rootLayer->paint(p, rect, m_paintBehavior, eltRenderer);
2418
2419 if (rootLayer->containsDirtyOverlayScrollbars())
2420 rootLayer->paintOverlayScrollbars(p, rect, m_paintBehavior, eltRenderer);
2421
2422 m_isPainting = false;
2423
2424 if (flatteningPaint && isRootFrame)
2425 notifyWidgetsInAllFrames(DidPaintFlattened);
2426
2427 m_paintBehavior = oldPaintBehavior;
2428 m_lastPaintTime = currentTime();
2429
2430 #if ENABLE(DASHBOARD_SUPPORT)
2431 // Regions may have changed as a result of the visibility/z-index of element changing.
2432 if (document->dashboardRegionsDirty())
2433 updateDashboardRegions();
2434 #endif
2435
2436 if (isTopLevelPainter)
2437 sCurrentPaintTimeStamp = 0;
2438
2439 InspectorInstrumentation::didPaint(cookie);
2440 }
2441
setPaintBehavior(PaintBehavior behavior)2442 void FrameView::setPaintBehavior(PaintBehavior behavior)
2443 {
2444 m_paintBehavior = behavior;
2445 }
2446
paintBehavior() const2447 PaintBehavior FrameView::paintBehavior() const
2448 {
2449 return m_paintBehavior;
2450 }
2451
isPainting() const2452 bool FrameView::isPainting() const
2453 {
2454 return m_isPainting;
2455 }
2456
setNodeToDraw(Node * node)2457 void FrameView::setNodeToDraw(Node* node)
2458 {
2459 m_nodeToDraw = node;
2460 }
2461
paintOverhangAreas(GraphicsContext * context,const IntRect & horizontalOverhangArea,const IntRect & verticalOverhangArea,const IntRect & dirtyRect)2462 void FrameView::paintOverhangAreas(GraphicsContext* context, const IntRect& horizontalOverhangArea, const IntRect& verticalOverhangArea, const IntRect& dirtyRect)
2463 {
2464 if (context->paintingDisabled())
2465 return;
2466
2467 if (m_frame->document()->printing())
2468 return;
2469
2470 Page* page = m_frame->page();
2471 if (page->mainFrame() == m_frame) {
2472 if (page->chrome()->client()->paintCustomOverhangArea(context, horizontalOverhangArea, verticalOverhangArea, dirtyRect))
2473 return;
2474 }
2475
2476 return ScrollView::paintOverhangAreas(context, horizontalOverhangArea, verticalOverhangArea, dirtyRect);
2477 }
2478
updateLayoutAndStyleIfNeededRecursive()2479 void FrameView::updateLayoutAndStyleIfNeededRecursive()
2480 {
2481 // We have to crawl our entire tree looking for any FrameViews that need
2482 // layout and make sure they are up to date.
2483 // Mac actually tests for intersection with the dirty region and tries not to
2484 // update layout for frames that are outside the dirty region. Not only does this seem
2485 // pointless (since those frames will have set a zero timer to layout anyway), but
2486 // it is also incorrect, since if two frames overlap, the first could be excluded from the dirty
2487 // region but then become included later by the second frame adding rects to the dirty region
2488 // when it lays out.
2489
2490 m_frame->document()->updateStyleIfNeeded();
2491
2492 if (needsLayout())
2493 layout();
2494
2495 const HashSet<RefPtr<Widget> >* viewChildren = children();
2496 HashSet<RefPtr<Widget> >::const_iterator end = viewChildren->end();
2497 for (HashSet<RefPtr<Widget> >::const_iterator current = viewChildren->begin(); current != end; ++current) {
2498 Widget* widget = (*current).get();
2499 if (widget->isFrameView())
2500 static_cast<FrameView*>(widget)->updateLayoutAndStyleIfNeededRecursive();
2501 }
2502
2503 // updateLayoutAndStyleIfNeededRecursive is called when we need to make sure style and layout are up-to-date before
2504 // painting, so we need to flush out any deferred repaints too.
2505 flushDeferredRepaints();
2506 }
2507
flushDeferredRepaints()2508 void FrameView::flushDeferredRepaints()
2509 {
2510 if (!m_deferredRepaintTimer.isActive())
2511 return;
2512 m_deferredRepaintTimer.stop();
2513 doDeferredRepaints();
2514 }
2515
forceLayout(bool allowSubtree)2516 void FrameView::forceLayout(bool allowSubtree)
2517 {
2518 layout(allowSubtree);
2519 }
2520
forceLayoutForPagination(const FloatSize & pageSize,float maximumShrinkFactor,Frame::AdjustViewSizeOrNot shouldAdjustViewSize)2521 void FrameView::forceLayoutForPagination(const FloatSize& pageSize, float maximumShrinkFactor, Frame::AdjustViewSizeOrNot shouldAdjustViewSize)
2522 {
2523 // Dumping externalRepresentation(m_frame->renderer()).ascii() is a good trick to see
2524 // the state of things before and after the layout
2525 RenderView *root = toRenderView(m_frame->document()->renderer());
2526 if (root) {
2527 float pageLogicalWidth = root->style()->isHorizontalWritingMode() ? pageSize.width() : pageSize.height();
2528 float pageLogicalHeight = root->style()->isHorizontalWritingMode() ? pageSize.height() : pageSize.width();
2529
2530 int flooredPageLogicalWidth = static_cast<int>(pageLogicalWidth);
2531 root->setLogicalWidth(flooredPageLogicalWidth);
2532 root->setPageLogicalHeight(pageLogicalHeight);
2533 root->setNeedsLayoutAndPrefWidthsRecalc();
2534 forceLayout();
2535
2536 // If we don't fit in the given page width, we'll lay out again. If we don't fit in the
2537 // page width when shrunk, we will lay out at maximum shrink and clip extra content.
2538 // FIXME: We are assuming a shrink-to-fit printing implementation. A cropping
2539 // implementation should not do this!
2540 int docLogicalWidth = root->style()->isHorizontalWritingMode() ? root->docWidth() : root->docHeight();
2541 if (docLogicalWidth > pageLogicalWidth) {
2542 flooredPageLogicalWidth = std::min<int>(docLogicalWidth, pageLogicalWidth * maximumShrinkFactor);
2543 if (pageLogicalHeight)
2544 root->setPageLogicalHeight(flooredPageLogicalWidth / pageSize.width() * pageSize.height());
2545 root->setLogicalWidth(flooredPageLogicalWidth);
2546 root->setNeedsLayoutAndPrefWidthsRecalc();
2547 forceLayout();
2548 int docLogicalHeight = root->style()->isHorizontalWritingMode() ? root->docHeight() : root->docWidth();
2549 int docLogicalTop = root->style()->isHorizontalWritingMode() ? root->docTop() : root->docLeft();
2550 int docLogicalRight = root->style()->isHorizontalWritingMode() ? root->docRight() : root->docBottom();
2551 int clippedLogicalLeft = 0;
2552 if (!root->style()->isLeftToRightDirection())
2553 clippedLogicalLeft = docLogicalRight - flooredPageLogicalWidth;
2554 IntRect overflow(clippedLogicalLeft, docLogicalTop, flooredPageLogicalWidth, docLogicalHeight);
2555 if (!root->style()->isHorizontalWritingMode())
2556 overflow = overflow.transposedRect();
2557 root->clearLayoutOverflow();
2558 root->addLayoutOverflow(overflow); // This is how we clip in case we overflow again.
2559 }
2560 }
2561
2562 if (shouldAdjustViewSize)
2563 adjustViewSize();
2564 }
2565
adjustPageHeightDeprecated(float * newBottom,float oldTop,float oldBottom,float)2566 void FrameView::adjustPageHeightDeprecated(float *newBottom, float oldTop, float oldBottom, float /*bottomLimit*/)
2567 {
2568 RenderView* root = m_frame->contentRenderer();
2569 if (root) {
2570 // Use a context with painting disabled.
2571 GraphicsContext context((PlatformGraphicsContext*)0);
2572 root->setTruncatedAt((int)floorf(oldBottom));
2573 IntRect dirtyRect(0, (int)floorf(oldTop), root->maxXLayoutOverflow(), (int)ceilf(oldBottom - oldTop));
2574 root->setPrintRect(dirtyRect);
2575 root->layer()->paint(&context, dirtyRect);
2576 *newBottom = root->bestTruncatedAt();
2577 if (*newBottom == 0)
2578 *newBottom = oldBottom;
2579 root->setPrintRect(IntRect());
2580 } else
2581 *newBottom = oldBottom;
2582 }
2583
convertFromRenderer(const RenderObject * renderer,const IntRect & rendererRect) const2584 IntRect FrameView::convertFromRenderer(const RenderObject* renderer, const IntRect& rendererRect) const
2585 {
2586 IntRect rect = renderer->localToAbsoluteQuad(FloatRect(rendererRect)).enclosingBoundingBox();
2587
2588 // Convert from page ("absolute") to FrameView coordinates.
2589 rect.move(-scrollX(), -scrollY());
2590
2591 return rect;
2592 }
2593
convertToRenderer(const RenderObject * renderer,const IntRect & viewRect) const2594 IntRect FrameView::convertToRenderer(const RenderObject* renderer, const IntRect& viewRect) const
2595 {
2596 IntRect rect = viewRect;
2597
2598 // Convert from FrameView coords into page ("absolute") coordinates.
2599 rect.move(scrollX(), scrollY());
2600
2601 // FIXME: we don't have a way to map an absolute rect down to a local quad, so just
2602 // move the rect for now.
2603 rect.setLocation(roundedIntPoint(renderer->absoluteToLocal(rect.location(), false, true /* use transforms */)));
2604 return rect;
2605 }
2606
convertFromRenderer(const RenderObject * renderer,const IntPoint & rendererPoint) const2607 IntPoint FrameView::convertFromRenderer(const RenderObject* renderer, const IntPoint& rendererPoint) const
2608 {
2609 IntPoint point = roundedIntPoint(renderer->localToAbsolute(rendererPoint, false, true /* use transforms */));
2610
2611 // Convert from page ("absolute") to FrameView coordinates.
2612 point.move(-scrollX(), -scrollY());
2613 return point;
2614 }
2615
convertToRenderer(const RenderObject * renderer,const IntPoint & viewPoint) const2616 IntPoint FrameView::convertToRenderer(const RenderObject* renderer, const IntPoint& viewPoint) const
2617 {
2618 IntPoint point = viewPoint;
2619
2620 // Convert from FrameView coords into page ("absolute") coordinates.
2621 point += IntSize(scrollX(), scrollY());
2622
2623 return roundedIntPoint(renderer->absoluteToLocal(point, false, true /* use transforms */));
2624 }
2625
convertToContainingView(const IntRect & localRect) const2626 IntRect FrameView::convertToContainingView(const IntRect& localRect) const
2627 {
2628 if (const ScrollView* parentScrollView = parent()) {
2629 if (parentScrollView->isFrameView()) {
2630 const FrameView* parentView = static_cast<const FrameView*>(parentScrollView);
2631 // Get our renderer in the parent view
2632 RenderPart* renderer = m_frame->ownerRenderer();
2633 if (!renderer)
2634 return localRect;
2635
2636 IntRect rect(localRect);
2637 // Add borders and padding??
2638 rect.move(renderer->borderLeft() + renderer->paddingLeft(),
2639 renderer->borderTop() + renderer->paddingTop());
2640 return parentView->convertFromRenderer(renderer, rect);
2641 }
2642
2643 return Widget::convertToContainingView(localRect);
2644 }
2645
2646 return localRect;
2647 }
2648
convertFromContainingView(const IntRect & parentRect) const2649 IntRect FrameView::convertFromContainingView(const IntRect& parentRect) const
2650 {
2651 if (const ScrollView* parentScrollView = parent()) {
2652 if (parentScrollView->isFrameView()) {
2653 const FrameView* parentView = static_cast<const FrameView*>(parentScrollView);
2654
2655 // Get our renderer in the parent view
2656 RenderPart* renderer = m_frame->ownerRenderer();
2657 if (!renderer)
2658 return parentRect;
2659
2660 IntRect rect = parentView->convertToRenderer(renderer, parentRect);
2661 // Subtract borders and padding
2662 rect.move(-renderer->borderLeft() - renderer->paddingLeft(),
2663 -renderer->borderTop() - renderer->paddingTop());
2664 return rect;
2665 }
2666
2667 return Widget::convertFromContainingView(parentRect);
2668 }
2669
2670 return parentRect;
2671 }
2672
convertToContainingView(const IntPoint & localPoint) const2673 IntPoint FrameView::convertToContainingView(const IntPoint& localPoint) const
2674 {
2675 if (const ScrollView* parentScrollView = parent()) {
2676 if (parentScrollView->isFrameView()) {
2677 const FrameView* parentView = static_cast<const FrameView*>(parentScrollView);
2678
2679 // Get our renderer in the parent view
2680 RenderPart* renderer = m_frame->ownerRenderer();
2681 if (!renderer)
2682 return localPoint;
2683
2684 IntPoint point(localPoint);
2685
2686 // Add borders and padding
2687 point.move(renderer->borderLeft() + renderer->paddingLeft(),
2688 renderer->borderTop() + renderer->paddingTop());
2689 return parentView->convertFromRenderer(renderer, point);
2690 }
2691
2692 return Widget::convertToContainingView(localPoint);
2693 }
2694
2695 return localPoint;
2696 }
2697
convertFromContainingView(const IntPoint & parentPoint) const2698 IntPoint FrameView::convertFromContainingView(const IntPoint& parentPoint) const
2699 {
2700 if (const ScrollView* parentScrollView = parent()) {
2701 if (parentScrollView->isFrameView()) {
2702 const FrameView* parentView = static_cast<const FrameView*>(parentScrollView);
2703
2704 // Get our renderer in the parent view
2705 RenderPart* renderer = m_frame->ownerRenderer();
2706 if (!renderer)
2707 return parentPoint;
2708
2709 IntPoint point = parentView->convertToRenderer(renderer, parentPoint);
2710 // Subtract borders and padding
2711 point.move(-renderer->borderLeft() - renderer->paddingLeft(),
2712 -renderer->borderTop() - renderer->paddingTop());
2713 return point;
2714 }
2715
2716 return Widget::convertFromContainingView(parentPoint);
2717 }
2718
2719 return parentPoint;
2720 }
2721
2722 // Normal delay
setRepaintThrottlingDeferredRepaintDelay(double p)2723 void FrameView::setRepaintThrottlingDeferredRepaintDelay(double p)
2724 {
2725 s_deferredRepaintDelay = p;
2726 }
2727
2728 // Negative value would mean that first few repaints happen without a delay
setRepaintThrottlingnInitialDeferredRepaintDelayDuringLoading(double p)2729 void FrameView::setRepaintThrottlingnInitialDeferredRepaintDelayDuringLoading(double p)
2730 {
2731 s_initialDeferredRepaintDelayDuringLoading = p;
2732 }
2733
2734 // The delay grows on each repaint to this maximum value
setRepaintThrottlingMaxDeferredRepaintDelayDuringLoading(double p)2735 void FrameView::setRepaintThrottlingMaxDeferredRepaintDelayDuringLoading(double p)
2736 {
2737 s_maxDeferredRepaintDelayDuringLoading = p;
2738 }
2739
2740 // On each repaint the delay increases by this amount
setRepaintThrottlingDeferredRepaintDelayIncrementDuringLoading(double p)2741 void FrameView::setRepaintThrottlingDeferredRepaintDelayIncrementDuringLoading(double p)
2742 {
2743 s_deferredRepaintDelayIncrementDuringLoading = p;
2744 }
2745
isVerticalDocument() const2746 bool FrameView::isVerticalDocument() const
2747 {
2748 if (!m_frame)
2749 return true;
2750 Document* doc = m_frame->document();
2751 if (!doc)
2752 return true;
2753 RenderObject* renderView = doc->renderer();
2754 if (!renderView)
2755 return true;
2756 return renderView->style()->isHorizontalWritingMode();
2757 }
2758
isFlippedDocument() const2759 bool FrameView::isFlippedDocument() const
2760 {
2761 if (!m_frame)
2762 return false;
2763 Document* doc = m_frame->document();
2764 if (!doc)
2765 return false;
2766 RenderObject* renderView = doc->renderer();
2767 if (!renderView)
2768 return false;
2769 return renderView->style()->isFlippedBlocksWritingMode();
2770 }
2771
notifyWidgetsInAllFrames(WidgetNotification notification)2772 void FrameView::notifyWidgetsInAllFrames(WidgetNotification notification)
2773 {
2774 for (Frame* frame = m_frame.get(); frame; frame = frame->tree()->traverseNext(m_frame.get())) {
2775 if (RenderView* root = frame->contentRenderer())
2776 root->notifyWidgets(notification);
2777 }
2778 }
2779
axObjectCache() const2780 AXObjectCache* FrameView::axObjectCache() const
2781 {
2782 if (frame() && frame()->document() && frame()->document()->axObjectCacheExists())
2783 return frame()->document()->axObjectCache();
2784 return 0;
2785 }
2786
2787 } // namespace WebCore
2788