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 #if PLATFORM(ANDROID)
84 #include "WebCoreFrameBridge.h"
85 #endif
86
87 namespace WebCore {
88
89 using namespace HTMLNames;
90
91 double FrameView::sCurrentPaintTimeStamp = 0.0;
92
93 // REPAINT_THROTTLING now chooses default values for throttling parameters.
94 // Should be removed when applications start using runtime configuration.
95 #if ENABLE(REPAINT_THROTTLING)
96 // Normal delay
97 double FrameView::s_deferredRepaintDelay = 0.025;
98 // Negative value would mean that first few repaints happen without a delay
99 double FrameView::s_initialDeferredRepaintDelayDuringLoading = 0;
100 // The delay grows on each repaint to this maximum value
101 double FrameView::s_maxDeferredRepaintDelayDuringLoading = 2.5;
102 // On each repaint the delay increses by this amount
103 double FrameView::s_deferredRepaintDelayIncrementDuringLoading = 0.5;
104 #else
105 // FIXME: Repaint throttling could be good to have on all platform.
106 // The balance between CPU use and repaint frequency will need some tuning for desktop.
107 // More hooks may be needed to reset the delay on things like GIF and CSS animations.
108 double FrameView::s_deferredRepaintDelay = 0;
109 double FrameView::s_initialDeferredRepaintDelayDuringLoading = 0;
110 double FrameView::s_maxDeferredRepaintDelayDuringLoading = 0;
111 double FrameView::s_deferredRepaintDelayIncrementDuringLoading = 0;
112 #endif
113
114 // The maximum number of updateWidgets iterations that should be done before returning.
115 static const unsigned maxUpdateWidgetsIterations = 2;
116
FrameView(Frame * frame)117 FrameView::FrameView(Frame* frame)
118 : m_frame(frame)
119 , m_canHaveScrollbars(true)
120 , m_slowRepaintObjectCount(0)
121 , m_fixedObjectCount(0)
122 , m_layoutTimer(this, &FrameView::layoutTimerFired)
123 , m_layoutRoot(0)
124 , m_hasPendingPostLayoutTasks(false)
125 , m_inSynchronousPostLayout(false)
126 , m_postLayoutTasksTimer(this, &FrameView::postLayoutTimerFired)
127 , m_isTransparent(false)
128 , m_baseBackgroundColor(Color::white)
129 , m_mediaType("screen")
130 , m_actionScheduler(new FrameActionScheduler())
131 , m_overflowStatusDirty(true)
132 , m_viewportRenderer(0)
133 , m_wasScrolledByUser(false)
134 , m_inProgrammaticScroll(false)
135 , m_deferredRepaintTimer(this, &FrameView::deferredRepaintTimerFired)
136 , m_shouldUpdateWhileOffscreen(true)
137 , m_deferSetNeedsLayouts(0)
138 , m_setNeedsLayoutWasDeferred(false)
139 , m_scrollCorner(0)
140 #if ENABLE(ANDROID_OVERFLOW_SCROLL)
141 , m_hasOverflowScroll(false)
142 #endif
143 {
144 init();
145
146 if (m_frame) {
147 if (Page* page = m_frame->page()) {
148 m_page = page;
149 m_page->addScrollableArea(this);
150
151 if (m_frame == m_page->mainFrame()) {
152 ScrollableArea::setVerticalScrollElasticity(ScrollElasticityAllowed);
153 ScrollableArea::setHorizontalScrollElasticity(ScrollElasticityAllowed);
154 }
155 }
156 }
157 }
158
create(Frame * frame)159 PassRefPtr<FrameView> FrameView::create(Frame* frame)
160 {
161 RefPtr<FrameView> view = adoptRef(new FrameView(frame));
162 view->show();
163 return view.release();
164 }
165
create(Frame * frame,const IntSize & initialSize)166 PassRefPtr<FrameView> FrameView::create(Frame* frame, const IntSize& initialSize)
167 {
168 RefPtr<FrameView> view = adoptRef(new FrameView(frame));
169 view->Widget::setFrameRect(IntRect(view->pos(), initialSize));
170 view->setInitialBoundsSize(initialSize);
171 view->show();
172 return view.release();
173 }
174
~FrameView()175 FrameView::~FrameView()
176 {
177 if (m_hasPendingPostLayoutTasks) {
178 m_postLayoutTasksTimer.stop();
179 m_actionScheduler->clear();
180 }
181
182 if (AXObjectCache::accessibilityEnabled() && axObjectCache())
183 axObjectCache()->remove(this);
184
185 resetScrollbars();
186
187 // Custom scrollbars should already be destroyed at this point
188 ASSERT(!horizontalScrollbar() || !horizontalScrollbar()->isCustomScrollbar());
189 ASSERT(!verticalScrollbar() || !verticalScrollbar()->isCustomScrollbar());
190
191 setHasHorizontalScrollbar(false); // Remove native scrollbars now before we lose the connection to the HostWindow.
192 setHasVerticalScrollbar(false);
193
194 ASSERT(!m_scrollCorner);
195 ASSERT(m_actionScheduler->isEmpty());
196
197 if (m_page)
198 m_page->removeScrollableArea(this);
199
200 if (m_frame) {
201 ASSERT(m_frame->view() != this || !m_frame->contentRenderer());
202 RenderPart* renderer = m_frame->ownerRenderer();
203 if (renderer && renderer->widget() == this)
204 renderer->setWidget(0);
205 }
206 }
207
reset()208 void FrameView::reset()
209 {
210 m_useSlowRepaints = false;
211 m_isOverlapped = false;
212 m_contentIsOpaque = false;
213 m_borderX = 30;
214 m_borderY = 30;
215 m_layoutTimer.stop();
216 m_layoutRoot = 0;
217 m_delayedLayout = false;
218 m_doFullRepaint = true;
219 m_layoutSchedulingEnabled = true;
220 m_inLayout = false;
221 m_inSynchronousPostLayout = false;
222 m_hasPendingPostLayoutTasks = false;
223 m_layoutCount = 0;
224 m_nestedLayoutCount = 0;
225 m_postLayoutTasksTimer.stop();
226 m_firstLayout = true;
227 m_firstLayoutCallbackPending = false;
228 m_wasScrolledByUser = false;
229 m_lastLayoutSize = IntSize();
230 m_lastZoomFactor = 1.0f;
231 m_deferringRepaints = 0;
232 m_repaintCount = 0;
233 m_repaintRects.clear();
234 m_deferredRepaintDelay = s_initialDeferredRepaintDelayDuringLoading;
235 m_deferredRepaintTimer.stop();
236 m_lastPaintTime = 0;
237 m_paintBehavior = PaintBehaviorNormal;
238 m_isPainting = false;
239 m_isVisuallyNonEmpty = false;
240 m_firstVisuallyNonEmptyLayoutCallbackPending = true;
241 m_maintainScrollPositionAnchor = 0;
242 }
243
isFrameView() const244 bool FrameView::isFrameView() const
245 {
246 return true;
247 }
248
clearFrame()249 void FrameView::clearFrame()
250 {
251 m_frame = 0;
252 }
253
resetScrollbars()254 void FrameView::resetScrollbars()
255 {
256 // Reset the document's scrollbars back to our defaults before we yield the floor.
257 m_firstLayout = true;
258 setScrollbarsSuppressed(true);
259 if (m_canHaveScrollbars)
260 setScrollbarModes(ScrollbarAuto, ScrollbarAuto);
261 else
262 setScrollbarModes(ScrollbarAlwaysOff, ScrollbarAlwaysOff);
263 setScrollbarsSuppressed(false);
264 }
265
resetScrollbarsAndClearContentsSize()266 void FrameView::resetScrollbarsAndClearContentsSize()
267 {
268 // Since the contents size is being cleared, the scroll position will lost as a consequence.
269 // Cache the scroll position so it can be restored by the page cache if necessary.
270 cacheCurrentScrollPosition();
271
272 resetScrollbars();
273
274 setScrollbarsSuppressed(true);
275 setContentsSize(IntSize());
276 setScrollbarsSuppressed(false);
277 }
278
init()279 void FrameView::init()
280 {
281 reset();
282
283 m_margins = IntSize(-1, -1); // undefined
284 m_size = IntSize();
285
286 // Propagate the marginwidth/height and scrolling modes to the view.
287 Element* ownerElement = m_frame ? m_frame->ownerElement() : 0;
288 if (ownerElement && (ownerElement->hasTagName(frameTag) || ownerElement->hasTagName(iframeTag))) {
289 HTMLFrameElement* frameElt = static_cast<HTMLFrameElement*>(ownerElement);
290 if (frameElt->scrollingMode() == ScrollbarAlwaysOff)
291 setCanHaveScrollbars(false);
292 int marginWidth = frameElt->marginWidth();
293 int marginHeight = frameElt->marginHeight();
294 if (marginWidth != -1)
295 setMarginWidth(marginWidth);
296 if (marginHeight != -1)
297 setMarginHeight(marginHeight);
298 }
299 }
300
detachCustomScrollbars()301 void FrameView::detachCustomScrollbars()
302 {
303 if (!m_frame)
304 return;
305
306 Scrollbar* horizontalBar = horizontalScrollbar();
307 if (horizontalBar && horizontalBar->isCustomScrollbar())
308 setHasHorizontalScrollbar(false);
309
310 Scrollbar* verticalBar = verticalScrollbar();
311 if (verticalBar && verticalBar->isCustomScrollbar())
312 setHasVerticalScrollbar(false);
313
314 if (m_scrollCorner) {
315 m_scrollCorner->destroy();
316 m_scrollCorner = 0;
317 }
318 }
319
clear()320 void FrameView::clear()
321 {
322 setCanBlitOnScroll(true);
323
324 reset();
325
326 if (m_frame) {
327 if (RenderPart* renderer = m_frame->ownerRenderer())
328 renderer->viewCleared();
329 }
330
331 setScrollbarsSuppressed(true);
332 }
333
didFirstLayout() const334 bool FrameView::didFirstLayout() const
335 {
336 return !m_firstLayout;
337 }
338
invalidateRect(const IntRect & rect)339 void FrameView::invalidateRect(const IntRect& rect)
340 {
341 if (!parent()) {
342 if (hostWindow())
343 hostWindow()->invalidateContentsAndWindow(rect, false /*immediate*/);
344 return;
345 }
346
347 if (!m_frame)
348 return;
349
350 RenderPart* renderer = m_frame->ownerRenderer();
351 if (!renderer)
352 return;
353
354 IntRect repaintRect = rect;
355 repaintRect.move(renderer->borderLeft() + renderer->paddingLeft(),
356 renderer->borderTop() + renderer->paddingTop());
357 renderer->repaintRectangle(repaintRect);
358 }
359
setFrameRect(const IntRect & newRect)360 void FrameView::setFrameRect(const IntRect& newRect)
361 {
362 IntRect oldRect = frameRect();
363 if (newRect == oldRect)
364 return;
365
366 ScrollView::setFrameRect(newRect);
367
368 #if USE(ACCELERATED_COMPOSITING)
369 if (RenderView* root = m_frame->contentRenderer()) {
370 if (root->usesCompositing())
371 root->compositor()->frameViewDidChangeSize();
372 }
373 #endif
374 }
375
376 #if ENABLE(REQUEST_ANIMATION_FRAME)
scheduleAnimation()377 void FrameView::scheduleAnimation()
378 {
379 if (hostWindow())
380 hostWindow()->scheduleAnimation();
381 }
382 #endif
383
setMarginWidth(int w)384 void FrameView::setMarginWidth(int w)
385 {
386 // make it update the rendering area when set
387 m_margins.setWidth(w);
388 }
389
setMarginHeight(int h)390 void FrameView::setMarginHeight(int h)
391 {
392 // make it update the rendering area when set
393 m_margins.setHeight(h);
394 }
395
avoidScrollbarCreation() const396 bool FrameView::avoidScrollbarCreation() const
397 {
398 ASSERT(m_frame);
399
400 // with frame flattening no subframe can have scrollbars
401 // but we also cannot turn scrollbars of as we determine
402 // our flattening policy using that.
403
404 if (!m_frame->ownerElement())
405 return false;
406
407 if (!m_frame->settings() || m_frame->settings()->frameFlatteningEnabled())
408 return true;
409
410 return false;
411 }
412
setCanHaveScrollbars(bool canHaveScrollbars)413 void FrameView::setCanHaveScrollbars(bool canHaveScrollbars)
414 {
415 m_canHaveScrollbars = canHaveScrollbars;
416 ScrollView::setCanHaveScrollbars(canHaveScrollbars);
417 }
418
updateCanHaveScrollbars()419 void FrameView::updateCanHaveScrollbars()
420 {
421 ScrollbarMode hMode;
422 ScrollbarMode vMode;
423 scrollbarModes(hMode, vMode);
424 if (hMode == ScrollbarAlwaysOff && vMode == ScrollbarAlwaysOff)
425 setCanHaveScrollbars(false);
426 else
427 setCanHaveScrollbars(true);
428 }
429
createScrollbar(ScrollbarOrientation orientation)430 PassRefPtr<Scrollbar> FrameView::createScrollbar(ScrollbarOrientation orientation)
431 {
432 // FIXME: We need to update the scrollbar dynamically as documents change (or as doc elements and bodies get discovered that have custom styles).
433 Document* doc = m_frame->document();
434
435 // Try the <body> element first as a scrollbar source.
436 Element* body = doc ? doc->body() : 0;
437 if (body && body->renderer() && body->renderer()->style()->hasPseudoStyle(SCROLLBAR))
438 return RenderScrollbar::createCustomScrollbar(this, orientation, body->renderer()->enclosingBox());
439
440 // If the <body> didn't have a custom style, then the root element might.
441 Element* docElement = doc ? doc->documentElement() : 0;
442 if (docElement && docElement->renderer() && docElement->renderer()->style()->hasPseudoStyle(SCROLLBAR))
443 return RenderScrollbar::createCustomScrollbar(this, orientation, docElement->renderBox());
444
445 // If we have an owning iframe/frame element, then it can set the custom scrollbar also.
446 RenderPart* frameRenderer = m_frame->ownerRenderer();
447 if (frameRenderer && frameRenderer->style()->hasPseudoStyle(SCROLLBAR))
448 return RenderScrollbar::createCustomScrollbar(this, orientation, 0, m_frame.get());
449
450 // Nobody set a custom style, so we just use a native scrollbar.
451 return ScrollView::createScrollbar(orientation);
452 }
453
setContentsSize(const IntSize & size)454 void FrameView::setContentsSize(const IntSize& size)
455 {
456 if (size == contentsSize())
457 return;
458
459 m_deferSetNeedsLayouts++;
460
461 ScrollView::setContentsSize(size);
462 scrollAnimator()->contentsResized();
463
464 Page* page = frame() ? frame()->page() : 0;
465 if (!page)
466 return;
467
468 page->chrome()->contentsSizeChanged(frame(), size); //notify only
469
470 m_deferSetNeedsLayouts--;
471
472 if (!m_deferSetNeedsLayouts)
473 m_setNeedsLayoutWasDeferred = false; // FIXME: Find a way to make the deferred layout actually happen.
474 }
475
adjustViewSize()476 void FrameView::adjustViewSize()
477 {
478 ASSERT(m_frame->view() == this);
479 RenderView* root = m_frame->contentRenderer();
480 if (!root)
481 return;
482
483 IntSize size = IntSize(root->docWidth(), root->docHeight());
484
485 ScrollView::setScrollOrigin(IntPoint(-root->docLeft(), -root->docTop()), !m_frame->document()->printing(), size == contentsSize());
486
487 setContentsSize(size);
488 }
489
applyOverflowToViewport(RenderObject * o,ScrollbarMode & hMode,ScrollbarMode & vMode)490 void FrameView::applyOverflowToViewport(RenderObject* o, ScrollbarMode& hMode, ScrollbarMode& vMode)
491 {
492 // Handle the overflow:hidden/scroll case for the body/html elements. WinIE treats
493 // overflow:hidden and overflow:scroll on <body> as applying to the document's
494 // scrollbars. The CSS2.1 draft states that HTML UAs should use the <html> or <body> element and XML/XHTML UAs should
495 // use the root element.
496 switch (o->style()->overflowX()) {
497 case OHIDDEN:
498 hMode = ScrollbarAlwaysOff;
499 break;
500 case OSCROLL:
501 hMode = ScrollbarAlwaysOn;
502 break;
503 case OAUTO:
504 hMode = ScrollbarAuto;
505 break;
506 default:
507 // Don't set it at all.
508 ;
509 }
510
511 switch (o->style()->overflowY()) {
512 case OHIDDEN:
513 vMode = ScrollbarAlwaysOff;
514 break;
515 case OSCROLL:
516 vMode = ScrollbarAlwaysOn;
517 break;
518 case OAUTO:
519 vMode = ScrollbarAuto;
520 break;
521 default:
522 // Don't set it at all.
523 ;
524 }
525
526 m_viewportRenderer = o;
527 }
528
calculateScrollbarModesForLayout(ScrollbarMode & hMode,ScrollbarMode & vMode)529 void FrameView::calculateScrollbarModesForLayout(ScrollbarMode& hMode, ScrollbarMode& vMode)
530 {
531 m_viewportRenderer = 0;
532
533 const HTMLFrameOwnerElement* owner = m_frame->ownerElement();
534 if (owner && (owner->scrollingMode() == ScrollbarAlwaysOff)) {
535 hMode = ScrollbarAlwaysOff;
536 vMode = ScrollbarAlwaysOff;
537 return;
538 }
539
540 if (m_canHaveScrollbars) {
541 hMode = ScrollbarAuto;
542 vMode = ScrollbarAuto;
543 } else {
544 hMode = ScrollbarAlwaysOff;
545 vMode = ScrollbarAlwaysOff;
546 }
547
548 if (!m_layoutRoot) {
549 Document* document = m_frame->document();
550 Node* documentElement = document->documentElement();
551 RenderObject* rootRenderer = documentElement ? documentElement->renderer() : 0;
552 Node* body = document->body();
553 if (body && body->renderer()) {
554 if (body->hasTagName(framesetTag) && m_frame->settings() && !m_frame->settings()->frameFlatteningEnabled()) {
555 vMode = ScrollbarAlwaysOff;
556 hMode = ScrollbarAlwaysOff;
557 } else if (body->hasTagName(bodyTag)) {
558 // It's sufficient to just check the X overflow,
559 // since it's illegal to have visible in only one direction.
560 RenderObject* o = rootRenderer->style()->overflowX() == OVISIBLE && document->documentElement()->hasTagName(htmlTag) ? body->renderer() : rootRenderer;
561 applyOverflowToViewport(o, hMode, vMode);
562 }
563 } else if (rootRenderer) {
564 #if ENABLE(SVG)
565 if (!documentElement->isSVGElement())
566 applyOverflowToViewport(rootRenderer, hMode, vMode);
567 #else
568 applyOverflowToViewport(rootRenderer, hMode, vMode);
569 #endif
570 }
571 }
572 }
573
574 #if ENABLE(FULLSCREEN_API) && USE(ACCELERATED_COMPOSITING)
isDocumentRunningFullScreenAnimation(Document * document)575 static bool isDocumentRunningFullScreenAnimation(Document* document)
576 {
577 return document->webkitIsFullScreen() && document->fullScreenRenderer() && document->fullScreenRenderer()->isAnimating();
578 }
579 #endif
580
581 #if USE(ACCELERATED_COMPOSITING)
updateCompositingLayers()582 void FrameView::updateCompositingLayers()
583 {
584 RenderView* view = m_frame->contentRenderer();
585 if (!view)
586 return;
587
588 // This call will make sure the cached hasAcceleratedCompositing is updated from the pref
589 view->compositor()->cacheAcceleratedCompositingFlags();
590 view->compositor()->updateCompositingLayers(CompositingUpdateAfterLayoutOrStyleChange);
591
592 #if ENABLE(FULLSCREEN_API)
593 Document* document = m_frame->document();
594 if (isDocumentRunningFullScreenAnimation(document))
595 view->compositor()->updateCompositingLayers(CompositingUpdateAfterLayoutOrStyleChange, document->fullScreenRenderer()->layer());
596 #endif
597 }
598
layerForHorizontalScrollbar() const599 GraphicsLayer* FrameView::layerForHorizontalScrollbar() const
600 {
601 RenderView* view = m_frame->contentRenderer();
602 if (!view)
603 return 0;
604 return view->compositor()->layerForHorizontalScrollbar();
605 }
606
layerForVerticalScrollbar() const607 GraphicsLayer* FrameView::layerForVerticalScrollbar() const
608 {
609 RenderView* view = m_frame->contentRenderer();
610 if (!view)
611 return 0;
612 return view->compositor()->layerForVerticalScrollbar();
613 }
614
layerForScrollCorner() const615 GraphicsLayer* FrameView::layerForScrollCorner() const
616 {
617 RenderView* view = m_frame->contentRenderer();
618 if (!view)
619 return 0;
620 return view->compositor()->layerForScrollCorner();
621 }
622
syncCompositingStateForThisFrame()623 bool FrameView::syncCompositingStateForThisFrame()
624 {
625 ASSERT(m_frame->view() == this);
626 RenderView* view = m_frame->contentRenderer();
627 if (!view)
628 return true; // We don't want to keep trying to update layers if we have no renderer.
629
630 // If we sync compositing layers when a layout is pending, we may cause painting of compositing
631 // layer content to occur before layout has happened, which will cause paintContents() to bail.
632 if (needsLayout())
633 return false;
634
635 if (GraphicsLayer* graphicsLayer = view->compositor()->layerForHorizontalScrollbar())
636 graphicsLayer->syncCompositingStateForThisLayerOnly();
637 if (GraphicsLayer* graphicsLayer = view->compositor()->layerForVerticalScrollbar())
638 graphicsLayer->syncCompositingStateForThisLayerOnly();
639 if (GraphicsLayer* graphicsLayer = view->compositor()->layerForScrollCorner())
640 graphicsLayer->syncCompositingStateForThisLayerOnly();
641
642 view->compositor()->flushPendingLayerChanges();
643
644 #if ENABLE(FULLSCREEN_API)
645 // The fullScreenRenderer's graphicsLayer has been re-parented, and the above recursive syncCompositingState
646 // call will not cause the subtree under it to repaint. Explicitly call the syncCompositingState on
647 // the fullScreenRenderer's graphicsLayer here:
648 Document* document = m_frame->document();
649 if (isDocumentRunningFullScreenAnimation(document)) {
650 #if PLATFORM(ANDROID)
651 // We don't create an extra layer for the full screen video.
652 if (!document->fullScreenRenderer()->layer()
653 || !document->fullScreenRenderer()->layer()->backing())
654 return true;
655 #endif
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 && !inSubframeLayoutWithFrameFlattening) {
1017 m_inSynchronousPostLayout = true;
1018 // Calls resumeScheduledEvents()
1019 performPostLayoutTasks();
1020 m_inSynchronousPostLayout = false;
1021 }
1022
1023 if (!m_hasPendingPostLayoutTasks && (needsLayout() || m_inSynchronousPostLayout || inSubframeLayoutWithFrameFlattening)) {
1024 // If we need layout or are already in a synchronous call to postLayoutTasks(),
1025 // defer widget updates and event dispatch until after we return. postLayoutTasks()
1026 // can make us need to update again, and we can get stuck in a nasty cycle unless
1027 // we call it through the timer here.
1028 m_hasPendingPostLayoutTasks = true;
1029 m_postLayoutTasksTimer.startOneShot(0);
1030 if (needsLayout()) {
1031 m_actionScheduler->pause();
1032 layout();
1033 }
1034 }
1035 } else {
1036 m_actionScheduler->resume();
1037 }
1038
1039 InspectorInstrumentation::didLayout(cookie);
1040
1041 m_nestedLayoutCount--;
1042 #if ENABLE(ANDROID_OVERFLOW_SCROLL)
1043 // Reset to false each time we layout in case the overflow status changed.
1044 bool hasOverflowScroll = false;
1045 RenderObject* ownerRenderer = m_frame->ownerRenderer();
1046 if (ownerRenderer && ownerRenderer->isRenderIFrame()) {
1047 RenderLayer* layer = ownerRenderer->enclosingLayer();
1048 if (layer) {
1049 // Some sites use tiny iframes for loading so don't composite those.
1050 if (canHaveScrollbars() && layoutWidth() > 1 && layoutHeight() > 1)
1051 hasOverflowScroll = layoutWidth() < contentsWidth() || layoutHeight() < contentsHeight();
1052 }
1053 }
1054 if (RenderView* view = m_frame->contentRenderer()) {
1055 if (hasOverflowScroll != m_hasOverflowScroll) {
1056 if (hasOverflowScroll)
1057 enterCompositingMode();
1058 else
1059 // We are leaving overflow mode so we need to update the layer
1060 // tree in case that is the reason we were composited.
1061 view->compositor()->scheduleCompositingLayerUpdate();
1062 }
1063 }
1064 m_hasOverflowScroll = hasOverflowScroll;
1065 #endif
1066 }
1067
addWidgetToUpdate(RenderEmbeddedObject * object)1068 void FrameView::addWidgetToUpdate(RenderEmbeddedObject* object)
1069 {
1070 if (!m_widgetUpdateSet)
1071 m_widgetUpdateSet.set(new RenderEmbeddedObjectSet);
1072
1073 m_widgetUpdateSet->add(object);
1074 }
1075
removeWidgetToUpdate(RenderEmbeddedObject * object)1076 void FrameView::removeWidgetToUpdate(RenderEmbeddedObject* object)
1077 {
1078 if (!m_widgetUpdateSet)
1079 return;
1080
1081 m_widgetUpdateSet->remove(object);
1082 }
1083
setMediaType(const String & mediaType)1084 void FrameView::setMediaType(const String& mediaType)
1085 {
1086 m_mediaType = mediaType;
1087 }
1088
mediaType() const1089 String FrameView::mediaType() const
1090 {
1091 // See if we have an override type.
1092 String overrideType = m_frame->loader()->client()->overrideMediaType();
1093 if (!overrideType.isNull())
1094 return overrideType;
1095 return m_mediaType;
1096 }
1097
adjustMediaTypeForPrinting(bool printing)1098 void FrameView::adjustMediaTypeForPrinting(bool printing)
1099 {
1100 if (printing) {
1101 if (m_mediaTypeWhenNotPrinting.isNull())
1102 m_mediaTypeWhenNotPrinting = mediaType();
1103 setMediaType("print");
1104 } else {
1105 if (!m_mediaTypeWhenNotPrinting.isNull())
1106 setMediaType(m_mediaTypeWhenNotPrinting);
1107 m_mediaTypeWhenNotPrinting = String();
1108 }
1109 }
1110
useSlowRepaints() const1111 bool FrameView::useSlowRepaints() const
1112 {
1113 if (m_useSlowRepaints || m_slowRepaintObjectCount > 0 || (platformWidget() && m_fixedObjectCount > 0) || m_isOverlapped || !m_contentIsOpaque)
1114 return true;
1115
1116 if (FrameView* parentView = parentFrameView())
1117 return parentView->useSlowRepaints();
1118
1119 return false;
1120 }
1121
useSlowRepaintsIfNotOverlapped() const1122 bool FrameView::useSlowRepaintsIfNotOverlapped() const
1123 {
1124 if (m_useSlowRepaints || m_slowRepaintObjectCount > 0 || (platformWidget() && m_fixedObjectCount > 0) || !m_contentIsOpaque)
1125 return true;
1126
1127 if (FrameView* parentView = parentFrameView())
1128 return parentView->useSlowRepaintsIfNotOverlapped();
1129
1130 return false;
1131 }
1132
updateCanBlitOnScrollRecursively()1133 void FrameView::updateCanBlitOnScrollRecursively()
1134 {
1135 for (Frame* frame = m_frame.get(); frame; frame = frame->tree()->traverseNext(m_frame.get())) {
1136 if (FrameView* view = frame->view())
1137 view->setCanBlitOnScroll(!view->useSlowRepaints());
1138 }
1139 }
1140
setUseSlowRepaints()1141 void FrameView::setUseSlowRepaints()
1142 {
1143 m_useSlowRepaints = true;
1144 updateCanBlitOnScrollRecursively();
1145 }
1146
addSlowRepaintObject()1147 void FrameView::addSlowRepaintObject()
1148 {
1149 if (!m_slowRepaintObjectCount)
1150 updateCanBlitOnScrollRecursively();
1151 m_slowRepaintObjectCount++;
1152 }
1153
removeSlowRepaintObject()1154 void FrameView::removeSlowRepaintObject()
1155 {
1156 ASSERT(m_slowRepaintObjectCount > 0);
1157 m_slowRepaintObjectCount--;
1158 if (!m_slowRepaintObjectCount)
1159 updateCanBlitOnScrollRecursively();
1160 }
1161
addFixedObject()1162 void FrameView::addFixedObject()
1163 {
1164 if (!m_fixedObjectCount && platformWidget())
1165 updateCanBlitOnScrollRecursively();
1166 ++m_fixedObjectCount;
1167 }
1168
removeFixedObject()1169 void FrameView::removeFixedObject()
1170 {
1171 ASSERT(m_fixedObjectCount > 0);
1172 --m_fixedObjectCount;
1173 if (!m_fixedObjectCount)
1174 updateCanBlitOnScrollRecursively();
1175 }
1176
1177 #if PLATFORM(ANDROID)
1178 // When the screen size change, fixed positioned element should be updated.
updatePositionedObjects()1179 void FrameView::updatePositionedObjects()
1180 {
1181 RenderBlock::PositionedObjectsListHashSet* positionedObjects = 0;
1182 if (RenderView* root = m_frame->contentRenderer())
1183 positionedObjects = root->positionedObjects();
1184
1185 if (!positionedObjects || positionedObjects->isEmpty())
1186 return;
1187
1188 RenderBlock::PositionedObjectsListHashSet::const_iterator end = positionedObjects->end();
1189 for (RenderBlock::PositionedObjectsListHashSet::const_iterator it = positionedObjects->begin(); it != end; ++it) {
1190 RenderBox* renderBox = *it;
1191 if (renderBox->style()->position() != FixedPosition)
1192 continue;
1193
1194 renderBox->computeLogicalWidth();
1195 renderBox->computeLogicalHeight();
1196 }
1197 }
1198 #endif
1199
scrollXForFixedPosition() const1200 int FrameView::scrollXForFixedPosition() const
1201 {
1202 int visibleContentWidth = visibleContentRect().width();
1203 int maxX = contentsWidth() - visibleContentWidth;
1204
1205 if (maxX == 0)
1206 return 0;
1207
1208 int x = scrollX();
1209
1210 if (x < 0)
1211 x = 0;
1212 else if (x > maxX)
1213 x = maxX;
1214
1215 if (!m_frame)
1216 return x;
1217
1218 float pageScaleFactor = m_frame->pageScaleFactor();
1219
1220 // When the page is scaled, the scaled "viewport" with respect to which fixed object are positioned
1221 // doesn't move as fast as the content view, so that when the content is scrolled all the way to the
1222 // end, the bottom of the scaled "viewport" touches the bottom of the real viewport.
1223 float dragFactor = (contentsWidth() - visibleContentWidth * pageScaleFactor) / maxX;
1224
1225 return x * dragFactor / pageScaleFactor;
1226 }
1227
scrollYForFixedPosition() const1228 int FrameView::scrollYForFixedPosition() const
1229 {
1230 int visibleContentHeight = visibleContentRect().height();
1231
1232 int maxY = contentsHeight() - visibleContentHeight;
1233 if (maxY == 0)
1234 return 0;
1235
1236 int y = scrollY();
1237
1238 if (y < 0)
1239 y = 0;
1240 else if (y > maxY)
1241 y = maxY;
1242
1243 if (!m_frame)
1244 return y;
1245
1246 float pageScaleFactor = m_frame->pageScaleFactor();
1247 float dragFactor = (contentsHeight() - visibleContentHeight * pageScaleFactor) / maxY;
1248
1249 return y * dragFactor / pageScaleFactor;
1250 }
1251
scrollOffsetForFixedPosition() const1252 IntSize FrameView::scrollOffsetForFixedPosition() const
1253 {
1254 return IntSize(scrollXForFixedPosition(), scrollYForFixedPosition());
1255 }
1256
currentMousePosition() const1257 IntPoint FrameView::currentMousePosition() const
1258 {
1259 return m_frame ? m_frame->eventHandler()->currentMousePosition() : IntPoint();
1260 }
1261
scrollContentsFastPath(const IntSize & scrollDelta,const IntRect & rectToScroll,const IntRect & clipRect)1262 bool FrameView::scrollContentsFastPath(const IntSize& scrollDelta, const IntRect& rectToScroll, const IntRect& clipRect)
1263 {
1264 const size_t fixedObjectThreshold = 5;
1265
1266 RenderBlock::PositionedObjectsListHashSet* positionedObjects = 0;
1267 if (RenderView* root = m_frame->contentRenderer())
1268 positionedObjects = root->positionedObjects();
1269
1270 if (!positionedObjects || positionedObjects->isEmpty()) {
1271 hostWindow()->scroll(scrollDelta, rectToScroll, clipRect);
1272 return true;
1273 }
1274
1275 // Get the rects of the fixed objects visible in the rectToScroll
1276 Vector<IntRect, fixedObjectThreshold> subRectToUpdate;
1277 bool updateInvalidatedSubRect = true;
1278 RenderBlock::PositionedObjectsListHashSet::const_iterator end = positionedObjects->end();
1279 for (RenderBlock::PositionedObjectsListHashSet::const_iterator it = positionedObjects->begin(); it != end; ++it) {
1280 RenderBox* renderBox = *it;
1281 if (renderBox->style()->position() != FixedPosition)
1282 continue;
1283 IntRect updateRect = renderBox->layer()->repaintRectIncludingDescendants();
1284 updateRect = contentsToWindow(updateRect);
1285 if (clipsRepaints())
1286 updateRect.intersect(rectToScroll);
1287 if (!updateRect.isEmpty()) {
1288 if (subRectToUpdate.size() >= fixedObjectThreshold) {
1289 updateInvalidatedSubRect = false;
1290 break;
1291 }
1292 subRectToUpdate.append(updateRect);
1293 }
1294 }
1295
1296 // Scroll the view
1297 if (updateInvalidatedSubRect) {
1298 // 1) scroll
1299 hostWindow()->scroll(scrollDelta, rectToScroll, clipRect);
1300
1301 // 2) update the area of fixed objects that has been invalidated
1302 size_t fixObjectsCount = subRectToUpdate.size();
1303 for (size_t i = 0; i < fixObjectsCount; ++i) {
1304 IntRect updateRect = subRectToUpdate[i];
1305 IntRect scrolledRect = updateRect;
1306 scrolledRect.move(scrollDelta);
1307 updateRect.unite(scrolledRect);
1308 if (clipsRepaints())
1309 updateRect.intersect(rectToScroll);
1310 hostWindow()->invalidateContentsAndWindow(updateRect, false);
1311 }
1312 return true;
1313 }
1314
1315 // the number of fixed objects exceed the threshold, we cannot use the fast path
1316 return false;
1317 }
1318
scrollContentsSlowPath(const IntRect & updateRect)1319 void FrameView::scrollContentsSlowPath(const IntRect& updateRect)
1320 {
1321 #if USE(ACCELERATED_COMPOSITING)
1322 if (RenderPart* frameRenderer = m_frame->ownerRenderer()) {
1323 if (frameRenderer->containerForRepaint()) {
1324 IntRect rect(frameRenderer->borderLeft() + frameRenderer->paddingLeft(),
1325 frameRenderer->borderTop() + frameRenderer->paddingTop(),
1326 visibleWidth(), visibleHeight());
1327 frameRenderer->repaintRectangle(rect);
1328 return;
1329 }
1330 }
1331 #endif
1332
1333 ScrollView::scrollContentsSlowPath(updateRect);
1334 }
1335
1336 // Note that this gets called at painting time.
setIsOverlapped(bool isOverlapped)1337 void FrameView::setIsOverlapped(bool isOverlapped)
1338 {
1339 if (isOverlapped == m_isOverlapped)
1340 return;
1341
1342 m_isOverlapped = isOverlapped;
1343 updateCanBlitOnScrollRecursively();
1344
1345 #if USE(ACCELERATED_COMPOSITING)
1346 if (hasCompositedContentIncludingDescendants()) {
1347 // Overlap can affect compositing tests, so if it changes, we need to trigger
1348 // a layer update in the parent document.
1349 if (Frame* parentFrame = m_frame->tree()->parent()) {
1350 if (RenderView* parentView = parentFrame->contentRenderer()) {
1351 RenderLayerCompositor* compositor = parentView->compositor();
1352 compositor->setCompositingLayersNeedRebuild();
1353 compositor->scheduleCompositingLayerUpdate();
1354 }
1355 }
1356
1357 if (RenderLayerCompositor::allowsIndependentlyCompositedFrames(this)) {
1358 // We also need to trigger reevaluation for this and all descendant frames,
1359 // since a frame uses compositing if any ancestor is compositing.
1360 for (Frame* frame = m_frame.get(); frame; frame = frame->tree()->traverseNext(m_frame.get())) {
1361 if (RenderView* view = frame->contentRenderer()) {
1362 RenderLayerCompositor* compositor = view->compositor();
1363 compositor->setCompositingLayersNeedRebuild();
1364 compositor->scheduleCompositingLayerUpdate();
1365 }
1366 }
1367 }
1368 }
1369 #endif
1370 }
1371
isOverlappedIncludingAncestors() const1372 bool FrameView::isOverlappedIncludingAncestors() const
1373 {
1374 if (isOverlapped())
1375 return true;
1376
1377 if (FrameView* parentView = parentFrameView()) {
1378 if (parentView->isOverlapped())
1379 return true;
1380 }
1381
1382 return false;
1383 }
1384
setContentIsOpaque(bool contentIsOpaque)1385 void FrameView::setContentIsOpaque(bool contentIsOpaque)
1386 {
1387 if (contentIsOpaque == m_contentIsOpaque)
1388 return;
1389
1390 m_contentIsOpaque = contentIsOpaque;
1391 updateCanBlitOnScrollRecursively();
1392 }
1393
restoreScrollbar()1394 void FrameView::restoreScrollbar()
1395 {
1396 setScrollbarsSuppressed(false);
1397 }
1398
scrollToFragment(const KURL & url)1399 bool FrameView::scrollToFragment(const KURL& url)
1400 {
1401 // If our URL has no ref, then we have no place we need to jump to.
1402 // OTOH If CSS target was set previously, we want to set it to 0, recalc
1403 // and possibly repaint because :target pseudo class may have been
1404 // set (see bug 11321).
1405 if (!url.hasFragmentIdentifier() && !m_frame->document()->cssTarget())
1406 return false;
1407
1408 String fragmentIdentifier = url.fragmentIdentifier();
1409 if (scrollToAnchor(fragmentIdentifier))
1410 return true;
1411
1412 // Try again after decoding the ref, based on the document's encoding.
1413 if (TextResourceDecoder* decoder = m_frame->document()->decoder())
1414 return scrollToAnchor(decodeURLEscapeSequences(fragmentIdentifier, decoder->encoding()));
1415
1416 return false;
1417 }
1418
scrollToAnchor(const String & name)1419 bool FrameView::scrollToAnchor(const String& name)
1420 {
1421 ASSERT(m_frame->document());
1422
1423 if (!m_frame->document()->haveStylesheetsLoaded()) {
1424 m_frame->document()->setGotoAnchorNeededAfterStylesheetsLoad(true);
1425 return false;
1426 }
1427
1428 m_frame->document()->setGotoAnchorNeededAfterStylesheetsLoad(false);
1429
1430 Element* anchorNode = m_frame->document()->findAnchor(name);
1431
1432 #if ENABLE(SVG)
1433 if (m_frame->document()->isSVGDocument()) {
1434 if (name.startsWith("xpointer(")) {
1435 // We need to parse the xpointer reference here
1436 } else if (name.startsWith("svgView(")) {
1437 RefPtr<SVGSVGElement> svg = static_cast<SVGDocument*>(m_frame->document())->rootElement();
1438 if (!svg->currentView()->parseViewSpec(name))
1439 return false;
1440 svg->setUseCurrentView(true);
1441 } else {
1442 if (anchorNode && anchorNode->hasTagName(SVGNames::viewTag)) {
1443 RefPtr<SVGViewElement> viewElement = anchorNode->hasTagName(SVGNames::viewTag) ? static_cast<SVGViewElement*>(anchorNode) : 0;
1444 if (viewElement.get()) {
1445 SVGElement* element = SVGLocatable::nearestViewportElement(viewElement.get());
1446 if (element->hasTagName(SVGNames::svgTag)) {
1447 RefPtr<SVGSVGElement> svg = static_cast<SVGSVGElement*>(element);
1448 svg->inheritViewAttributes(viewElement.get());
1449 }
1450 }
1451 }
1452 }
1453 // FIXME: need to decide which <svg> to focus on, and zoom to that one
1454 // FIXME: need to actually "highlight" the viewTarget(s)
1455 }
1456 #endif
1457
1458 m_frame->document()->setCSSTarget(anchorNode); // Setting to null will clear the current target.
1459
1460 // Implement the rule that "" and "top" both mean top of page as in other browsers.
1461 if (!anchorNode && !(name.isEmpty() || equalIgnoringCase(name, "top")))
1462 return false;
1463
1464 maintainScrollPositionAtAnchor(anchorNode ? static_cast<Node*>(anchorNode) : m_frame->document());
1465 return true;
1466 }
1467
maintainScrollPositionAtAnchor(Node * anchorNode)1468 void FrameView::maintainScrollPositionAtAnchor(Node* anchorNode)
1469 {
1470 m_maintainScrollPositionAnchor = anchorNode;
1471 if (!m_maintainScrollPositionAnchor)
1472 return;
1473
1474 // We need to update the layout before scrolling, otherwise we could
1475 // really mess things up if an anchor scroll comes at a bad moment.
1476 m_frame->document()->updateStyleIfNeeded();
1477 // Only do a layout if changes have occurred that make it necessary.
1478 if (m_frame->contentRenderer() && m_frame->contentRenderer()->needsLayout())
1479 layout();
1480 else
1481 scrollToAnchor();
1482 }
1483
setScrollPosition(const IntPoint & scrollPoint)1484 void FrameView::setScrollPosition(const IntPoint& scrollPoint)
1485 {
1486 bool wasInProgrammaticScroll = m_inProgrammaticScroll;
1487 m_inProgrammaticScroll = true;
1488 m_maintainScrollPositionAnchor = 0;
1489 ScrollView::setScrollPosition(scrollPoint);
1490 m_inProgrammaticScroll = wasInProgrammaticScroll;
1491 }
1492
scrollPositionChangedViaPlatformWidget()1493 void FrameView::scrollPositionChangedViaPlatformWidget()
1494 {
1495 repaintFixedElementsAfterScrolling();
1496 scrollPositionChanged();
1497 }
1498
scrollPositionChanged()1499 void FrameView::scrollPositionChanged()
1500 {
1501 frame()->eventHandler()->sendScrollEvent();
1502
1503 #if USE(ACCELERATED_COMPOSITING)
1504 if (RenderView* root = m_frame->contentRenderer()) {
1505 if (root->usesCompositing())
1506 root->compositor()->frameViewDidScroll(scrollPosition());
1507 }
1508 #endif
1509 }
1510
repaintFixedElementsAfterScrolling()1511 void FrameView::repaintFixedElementsAfterScrolling()
1512 {
1513 // For fixed position elements, update widget positions and compositing layers after scrolling,
1514 // but only if we're not inside of layout.
1515 if (!m_nestedLayoutCount && hasFixedObjects()) {
1516 if (RenderView* root = m_frame->contentRenderer()) {
1517 root->updateWidgetPositions();
1518 root->layer()->updateRepaintRectsAfterScroll();
1519 #if USE(ACCELERATED_COMPOSITING)
1520 root->compositor()->updateCompositingLayers(CompositingUpdateOnScroll);
1521 #endif
1522 }
1523 }
1524 }
1525
hostWindow() const1526 HostWindow* FrameView::hostWindow() const
1527 {
1528 Page* page = frame() ? frame()->page() : 0;
1529 if (!page)
1530 return 0;
1531 return page->chrome();
1532 }
1533
1534 const unsigned cRepaintRectUnionThreshold = 25;
1535
repaintContentRectangle(const IntRect & r,bool immediate)1536 void FrameView::repaintContentRectangle(const IntRect& r, bool immediate)
1537 {
1538 ASSERT(!m_frame->ownerElement());
1539
1540 double delay = m_deferringRepaints ? 0 : adjustedDeferredRepaintDelay();
1541 if ((m_deferringRepaints || m_deferredRepaintTimer.isActive() || delay) && !immediate) {
1542 IntRect paintRect = r;
1543 if (clipsRepaints() && !paintsEntireContents())
1544 paintRect.intersect(visibleContentRect());
1545 #ifdef ANDROID_CAPTURE_OFFSCREEN_PAINTS
1546 if (r != paintRect)
1547 ScrollView::platformOffscreenContentRectangle(visibleContentRect(), r);
1548 #endif
1549 if (paintRect.isEmpty())
1550 return;
1551 if (m_repaintCount == cRepaintRectUnionThreshold) {
1552 IntRect unionedRect;
1553 for (unsigned i = 0; i < cRepaintRectUnionThreshold; ++i)
1554 unionedRect.unite(m_repaintRects[i]);
1555 m_repaintRects.clear();
1556 m_repaintRects.append(unionedRect);
1557 }
1558 if (m_repaintCount < cRepaintRectUnionThreshold)
1559 m_repaintRects.append(paintRect);
1560 else
1561 m_repaintRects[0].unite(paintRect);
1562 m_repaintCount++;
1563
1564 if (!m_deferringRepaints && !m_deferredRepaintTimer.isActive())
1565 m_deferredRepaintTimer.startOneShot(delay);
1566 return;
1567 }
1568
1569 if (!shouldUpdate(immediate))
1570 return;
1571
1572 #if ENABLE(TILED_BACKING_STORE)
1573 if (frame()->tiledBackingStore()) {
1574 frame()->tiledBackingStore()->invalidate(r);
1575 return;
1576 }
1577 #endif
1578 ScrollView::repaintContentRectangle(r, immediate);
1579 }
1580
contentsResized()1581 void FrameView::contentsResized()
1582 {
1583 scrollAnimator()->contentsResized();
1584 setNeedsLayout();
1585 }
1586
visibleContentsResized()1587 void FrameView::visibleContentsResized()
1588 {
1589 // We check to make sure the view is attached to a frame() as this method can
1590 // be triggered before the view is attached by Frame::createView(...) setting
1591 // various values such as setScrollBarModes(...) for example. An ASSERT is
1592 // triggered when a view is layout before being attached to a frame().
1593 if (!frame()->view())
1594 return;
1595
1596 if (needsLayout())
1597 layout();
1598
1599 #if USE(ACCELERATED_COMPOSITING)
1600 if (RenderView* root = m_frame->contentRenderer()) {
1601 if (root->usesCompositing())
1602 root->compositor()->frameViewDidChangeSize();
1603 }
1604 #endif
1605 }
1606
beginDeferredRepaints()1607 void FrameView::beginDeferredRepaints()
1608 {
1609 Page* page = m_frame->page();
1610 if (page->mainFrame() != m_frame)
1611 return page->mainFrame()->view()->beginDeferredRepaints();
1612
1613 m_deferringRepaints++;
1614 }
1615
1616
endDeferredRepaints()1617 void FrameView::endDeferredRepaints()
1618 {
1619 Page* page = m_frame->page();
1620 if (page->mainFrame() != m_frame)
1621 return page->mainFrame()->view()->endDeferredRepaints();
1622
1623 ASSERT(m_deferringRepaints > 0);
1624
1625 if (--m_deferringRepaints)
1626 return;
1627
1628 if (m_deferredRepaintTimer.isActive())
1629 return;
1630
1631 if (double delay = adjustedDeferredRepaintDelay()) {
1632 m_deferredRepaintTimer.startOneShot(delay);
1633 return;
1634 }
1635
1636 doDeferredRepaints();
1637 }
1638
checkStopDelayingDeferredRepaints()1639 void FrameView::checkStopDelayingDeferredRepaints()
1640 {
1641 if (!m_deferredRepaintTimer.isActive())
1642 return;
1643
1644 Document* document = m_frame->document();
1645 if (document && (document->parsing() || document->cachedResourceLoader()->requestCount()))
1646 return;
1647
1648 m_deferredRepaintTimer.stop();
1649
1650 doDeferredRepaints();
1651 }
1652
doDeferredRepaints()1653 void FrameView::doDeferredRepaints()
1654 {
1655 ASSERT(!m_deferringRepaints);
1656 if (!shouldUpdate()) {
1657 m_repaintRects.clear();
1658 m_repaintCount = 0;
1659 return;
1660 }
1661 unsigned size = m_repaintRects.size();
1662 for (unsigned i = 0; i < size; i++) {
1663 #if ENABLE(TILED_BACKING_STORE)
1664 if (frame()->tiledBackingStore()) {
1665 frame()->tiledBackingStore()->invalidate(m_repaintRects[i]);
1666 continue;
1667 }
1668 #endif
1669 ScrollView::repaintContentRectangle(m_repaintRects[i], false);
1670 }
1671 m_repaintRects.clear();
1672 m_repaintCount = 0;
1673
1674 updateDeferredRepaintDelay();
1675 }
1676
updateDeferredRepaintDelay()1677 void FrameView::updateDeferredRepaintDelay()
1678 {
1679 Document* document = m_frame->document();
1680 if (!document || (!document->parsing() && !document->cachedResourceLoader()->requestCount())) {
1681 m_deferredRepaintDelay = s_deferredRepaintDelay;
1682 return;
1683 }
1684 if (m_deferredRepaintDelay < s_maxDeferredRepaintDelayDuringLoading) {
1685 m_deferredRepaintDelay += s_deferredRepaintDelayIncrementDuringLoading;
1686 if (m_deferredRepaintDelay > s_maxDeferredRepaintDelayDuringLoading)
1687 m_deferredRepaintDelay = s_maxDeferredRepaintDelayDuringLoading;
1688 }
1689 }
1690
resetDeferredRepaintDelay()1691 void FrameView::resetDeferredRepaintDelay()
1692 {
1693 m_deferredRepaintDelay = 0;
1694 if (m_deferredRepaintTimer.isActive()) {
1695 m_deferredRepaintTimer.stop();
1696 if (!m_deferringRepaints)
1697 doDeferredRepaints();
1698 }
1699 }
1700
adjustedDeferredRepaintDelay() const1701 double FrameView::adjustedDeferredRepaintDelay() const
1702 {
1703 ASSERT(!m_deferringRepaints);
1704 if (!m_deferredRepaintDelay)
1705 return 0;
1706 double timeSinceLastPaint = currentTime() - m_lastPaintTime;
1707 return max(0., m_deferredRepaintDelay - timeSinceLastPaint);
1708 }
1709
deferredRepaintTimerFired(Timer<FrameView> *)1710 void FrameView::deferredRepaintTimerFired(Timer<FrameView>*)
1711 {
1712 doDeferredRepaints();
1713 }
1714
layoutTimerFired(Timer<FrameView> *)1715 void FrameView::layoutTimerFired(Timer<FrameView>*)
1716 {
1717 #ifdef INSTRUMENT_LAYOUT_SCHEDULING
1718 if (!m_frame->document()->ownerElement())
1719 printf("Layout timer fired at %d\n", m_frame->document()->elapsedTime());
1720 #endif
1721 layout();
1722 }
1723
scheduleRelayout()1724 void FrameView::scheduleRelayout()
1725 {
1726 // FIXME: We should assert the page is not in the page cache, but that is causing
1727 // too many false assertions. See <rdar://problem/7218118>.
1728 ASSERT(m_frame->view() == this);
1729
1730 if (m_layoutRoot) {
1731 m_layoutRoot->markContainingBlocksForLayout(false);
1732 m_layoutRoot = 0;
1733 }
1734 if (!m_layoutSchedulingEnabled)
1735 return;
1736 if (!needsLayout())
1737 return;
1738 if (!m_frame->document()->shouldScheduleLayout())
1739 return;
1740
1741 // When frame flattening is enabled, the contents of the frame affects layout of the parent frames.
1742 // Also invalidate parent frame starting from the owner element of this frame.
1743 if (m_frame->settings() && m_frame->settings()->frameFlatteningEnabled() && m_frame->ownerRenderer()) {
1744 if (m_frame->ownerElement()->hasTagName(iframeTag) || m_frame->ownerElement()->hasTagName(frameTag))
1745 m_frame->ownerRenderer()->setNeedsLayout(true, true);
1746 }
1747
1748 #ifdef ANDROID_FLATTEN_FRAMESET
1749 if (m_frame->ownerRenderer() && m_frame->ownerElement()->hasTagName(frameTag))
1750 m_frame->ownerRenderer()->setNeedsLayoutAndPrefWidthsRecalc();
1751 #endif
1752
1753 int delay = m_frame->document()->minimumLayoutDelay();
1754 if (m_layoutTimer.isActive() && m_delayedLayout && !delay)
1755 unscheduleRelayout();
1756 if (m_layoutTimer.isActive())
1757 return;
1758
1759 m_delayedLayout = delay != 0;
1760
1761 #ifdef INSTRUMENT_LAYOUT_SCHEDULING
1762 if (!m_frame->document()->ownerElement())
1763 printf("Scheduling layout for %d\n", delay);
1764 #endif
1765
1766 m_layoutTimer.startOneShot(delay * 0.001);
1767 }
1768
isObjectAncestorContainerOf(RenderObject * ancestor,RenderObject * descendant)1769 static bool isObjectAncestorContainerOf(RenderObject* ancestor, RenderObject* descendant)
1770 {
1771 for (RenderObject* r = descendant; r; r = r->container()) {
1772 if (r == ancestor)
1773 return true;
1774 }
1775 return false;
1776 }
1777
scheduleRelayoutOfSubtree(RenderObject * relayoutRoot)1778 void FrameView::scheduleRelayoutOfSubtree(RenderObject* relayoutRoot)
1779 {
1780 ASSERT(m_frame->view() == this);
1781
1782 if (m_frame->contentRenderer() && m_frame->contentRenderer()->needsLayout()) {
1783 if (relayoutRoot)
1784 relayoutRoot->markContainingBlocksForLayout(false);
1785 return;
1786 }
1787
1788 if (layoutPending() || !m_layoutSchedulingEnabled) {
1789 if (m_layoutRoot != relayoutRoot) {
1790 if (isObjectAncestorContainerOf(m_layoutRoot, relayoutRoot)) {
1791 // Keep the current root
1792 relayoutRoot->markContainingBlocksForLayout(false, m_layoutRoot);
1793 ASSERT(!m_layoutRoot->container() || !m_layoutRoot->container()->needsLayout());
1794 } else if (m_layoutRoot && isObjectAncestorContainerOf(relayoutRoot, m_layoutRoot)) {
1795 // Re-root at relayoutRoot
1796 m_layoutRoot->markContainingBlocksForLayout(false, relayoutRoot);
1797 m_layoutRoot = relayoutRoot;
1798 ASSERT(!m_layoutRoot->container() || !m_layoutRoot->container()->needsLayout());
1799 } else {
1800 // Just do a full relayout
1801 if (m_layoutRoot)
1802 m_layoutRoot->markContainingBlocksForLayout(false);
1803 m_layoutRoot = 0;
1804 relayoutRoot->markContainingBlocksForLayout(false);
1805 }
1806 }
1807 } else if (m_layoutSchedulingEnabled) {
1808 int delay = m_frame->document()->minimumLayoutDelay();
1809 m_layoutRoot = relayoutRoot;
1810 ASSERT(!m_layoutRoot->container() || !m_layoutRoot->container()->needsLayout());
1811 m_delayedLayout = delay != 0;
1812 m_layoutTimer.startOneShot(delay * 0.001);
1813 }
1814 }
1815
layoutPending() const1816 bool FrameView::layoutPending() const
1817 {
1818 return m_layoutTimer.isActive();
1819 }
1820
needsLayout() const1821 bool FrameView::needsLayout() const
1822 {
1823 // This can return true in cases where the document does not have a body yet.
1824 // Document::shouldScheduleLayout takes care of preventing us from scheduling
1825 // layout in that case.
1826 if (!m_frame)
1827 return false;
1828 RenderView* root = m_frame->contentRenderer();
1829 return layoutPending()
1830 || (root && root->needsLayout())
1831 || m_layoutRoot
1832 || (m_deferSetNeedsLayouts && m_setNeedsLayoutWasDeferred);
1833 }
1834
setNeedsLayout()1835 void FrameView::setNeedsLayout()
1836 {
1837 if (m_deferSetNeedsLayouts) {
1838 m_setNeedsLayoutWasDeferred = true;
1839 return;
1840 }
1841 RenderView* root = m_frame->contentRenderer();
1842 if (root)
1843 root->setNeedsLayout(true);
1844 }
1845
unscheduleRelayout()1846 void FrameView::unscheduleRelayout()
1847 {
1848 m_postLayoutTasksTimer.stop();
1849
1850 if (!m_layoutTimer.isActive())
1851 return;
1852
1853 #ifdef INSTRUMENT_LAYOUT_SCHEDULING
1854 if (!m_frame->document()->ownerElement())
1855 printf("Layout timer unscheduled at %d\n", m_frame->document()->elapsedTime());
1856 #endif
1857
1858 m_layoutTimer.stop();
1859 m_delayedLayout = false;
1860 }
1861
1862 #if ENABLE(REQUEST_ANIMATION_FRAME)
serviceScriptedAnimations(DOMTimeStamp time)1863 void FrameView::serviceScriptedAnimations(DOMTimeStamp time)
1864 {
1865 for (Frame* frame = m_frame.get(); frame; frame = frame->tree()->traverseNext())
1866 frame->document()->serviceScriptedAnimations(time);
1867 }
1868 #endif
1869
isTransparent() const1870 bool FrameView::isTransparent() const
1871 {
1872 return m_isTransparent;
1873 }
1874
setTransparent(bool isTransparent)1875 void FrameView::setTransparent(bool isTransparent)
1876 {
1877 m_isTransparent = isTransparent;
1878 }
1879
baseBackgroundColor() const1880 Color FrameView::baseBackgroundColor() const
1881 {
1882 return m_baseBackgroundColor;
1883 }
1884
setBaseBackgroundColor(const Color & backgroundColor)1885 void FrameView::setBaseBackgroundColor(const Color& backgroundColor)
1886 {
1887 if (!backgroundColor.isValid())
1888 m_baseBackgroundColor = Color::white;
1889 else
1890 m_baseBackgroundColor = backgroundColor;
1891 }
1892
updateBackgroundRecursively(const Color & backgroundColor,bool transparent)1893 void FrameView::updateBackgroundRecursively(const Color& backgroundColor, bool transparent)
1894 {
1895 for (Frame* frame = m_frame.get(); frame; frame = frame->tree()->traverseNext(m_frame.get())) {
1896 if (FrameView* view = frame->view()) {
1897 view->setTransparent(transparent);
1898 view->setBaseBackgroundColor(backgroundColor);
1899 }
1900 }
1901 }
1902
shouldUpdateWhileOffscreen() const1903 bool FrameView::shouldUpdateWhileOffscreen() const
1904 {
1905 return m_shouldUpdateWhileOffscreen;
1906 }
1907
setShouldUpdateWhileOffscreen(bool shouldUpdateWhileOffscreen)1908 void FrameView::setShouldUpdateWhileOffscreen(bool shouldUpdateWhileOffscreen)
1909 {
1910 m_shouldUpdateWhileOffscreen = shouldUpdateWhileOffscreen;
1911 }
1912
shouldUpdate(bool immediateRequested) const1913 bool FrameView::shouldUpdate(bool immediateRequested) const
1914 {
1915 if (!immediateRequested && isOffscreen() && !shouldUpdateWhileOffscreen())
1916 return false;
1917 return true;
1918 }
1919
scheduleEvent(PassRefPtr<Event> event,PassRefPtr<Node> eventTarget)1920 void FrameView::scheduleEvent(PassRefPtr<Event> event, PassRefPtr<Node> eventTarget)
1921 {
1922 m_actionScheduler->scheduleEvent(event, eventTarget);
1923 }
1924
pauseScheduledEvents()1925 void FrameView::pauseScheduledEvents()
1926 {
1927 m_actionScheduler->pause();
1928 }
1929
resumeScheduledEvents()1930 void FrameView::resumeScheduledEvents()
1931 {
1932 m_actionScheduler->resume();
1933 }
1934
scrollToAnchor()1935 void FrameView::scrollToAnchor()
1936 {
1937 RefPtr<Node> anchorNode = m_maintainScrollPositionAnchor;
1938 if (!anchorNode)
1939 return;
1940
1941 if (!anchorNode->renderer())
1942 return;
1943
1944 IntRect rect;
1945 if (anchorNode != m_frame->document())
1946 rect = anchorNode->getRect();
1947
1948 // Scroll nested layers and frames to reveal the anchor.
1949 // Align to the top and to the closest side (this matches other browsers).
1950 anchorNode->renderer()->enclosingLayer()->scrollRectToVisible(rect, true, ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignTopAlways);
1951
1952 if (AXObjectCache::accessibilityEnabled())
1953 m_frame->document()->axObjectCache()->handleScrolledToAnchor(anchorNode.get());
1954
1955 // scrollRectToVisible can call into setScrollPosition(), which resets m_maintainScrollPositionAnchor.
1956 m_maintainScrollPositionAnchor = anchorNode;
1957 }
1958
updateWidget(RenderEmbeddedObject * object)1959 void FrameView::updateWidget(RenderEmbeddedObject* object)
1960 {
1961 ASSERT(!object->node() || object->node()->isElementNode());
1962 Element* ownerElement = static_cast<Element*>(object->node());
1963 // The object may have already been destroyed (thus node cleared),
1964 // but FrameView holds a manual ref, so it won't have been deleted.
1965 ASSERT(m_widgetUpdateSet->contains(object));
1966 if (!ownerElement)
1967 return;
1968
1969 // No need to update if it's already crashed or known to be missing.
1970 if (object->pluginCrashedOrWasMissing())
1971 return;
1972
1973 // FIXME: This could turn into a real virtual dispatch if we defined
1974 // updateWidget(bool) on HTMLElement.
1975 if (ownerElement->hasTagName(objectTag) || ownerElement->hasTagName(embedTag))
1976 static_cast<HTMLPlugInImageElement*>(ownerElement)->updateWidget(CreateAnyWidgetType);
1977 // FIXME: It is not clear that Media elements need or want this updateWidget() call.
1978 #if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
1979 else if (ownerElement->hasTagName(videoTag) || ownerElement->hasTagName(audioTag))
1980 static_cast<HTMLMediaElement*>(ownerElement)->updateWidget(CreateAnyWidgetType);
1981 #endif
1982 else
1983 ASSERT_NOT_REACHED();
1984
1985 // Caution: it's possible the object was destroyed again, since loading a
1986 // plugin may run any arbitrary javascript.
1987 object->updateWidgetPosition();
1988 }
1989
updateWidgets()1990 bool FrameView::updateWidgets()
1991 {
1992 if (m_nestedLayoutCount > 1 || !m_widgetUpdateSet || m_widgetUpdateSet->isEmpty())
1993 return true;
1994
1995 size_t size = m_widgetUpdateSet->size();
1996
1997 Vector<RenderEmbeddedObject*> objects;
1998 objects.reserveCapacity(size);
1999
2000 RenderEmbeddedObjectSet::const_iterator end = m_widgetUpdateSet->end();
2001 for (RenderEmbeddedObjectSet::const_iterator it = m_widgetUpdateSet->begin(); it != end; ++it) {
2002 objects.uncheckedAppend(*it);
2003 (*it)->ref();
2004 }
2005
2006 for (size_t i = 0; i < size; ++i) {
2007 RenderEmbeddedObject* object = objects[i];
2008 updateWidget(object);
2009 m_widgetUpdateSet->remove(object);
2010 }
2011
2012 RenderArena* arena = m_frame->document()->renderArena();
2013 for (size_t i = 0; i < size; ++i)
2014 objects[i]->deref(arena);
2015
2016 return m_widgetUpdateSet->isEmpty();
2017 }
2018
flushAnyPendingPostLayoutTasks()2019 void FrameView::flushAnyPendingPostLayoutTasks()
2020 {
2021 if (!m_hasPendingPostLayoutTasks)
2022 return;
2023
2024 m_postLayoutTasksTimer.stop();
2025 performPostLayoutTasks();
2026 }
2027
performPostLayoutTasks()2028 void FrameView::performPostLayoutTasks()
2029 {
2030 m_hasPendingPostLayoutTasks = false;
2031
2032 m_frame->selection()->setCaretRectNeedsUpdate();
2033 m_frame->selection()->updateAppearance();
2034
2035 if (m_nestedLayoutCount <= 1) {
2036 if (m_firstLayoutCallbackPending) {
2037 m_firstLayoutCallbackPending = false;
2038 m_frame->loader()->didFirstLayout();
2039 }
2040
2041 if (m_isVisuallyNonEmpty && m_firstVisuallyNonEmptyLayoutCallbackPending) {
2042 m_firstVisuallyNonEmptyLayoutCallbackPending = false;
2043 m_frame->loader()->didFirstVisuallyNonEmptyLayout();
2044 }
2045 }
2046
2047 RenderView* root = m_frame->contentRenderer();
2048
2049 root->updateWidgetPositions();
2050
2051 for (unsigned i = 0; i < maxUpdateWidgetsIterations; i++) {
2052 if (updateWidgets())
2053 break;
2054 }
2055
2056 scrollToAnchor();
2057
2058 m_actionScheduler->resume();
2059
2060 if (!root->printing()) {
2061 IntSize currentSize = IntSize(width(), height());
2062 float currentZoomFactor = root->style()->zoom();
2063 bool resized = !m_firstLayout && (currentSize != m_lastLayoutSize || currentZoomFactor != m_lastZoomFactor);
2064 m_lastLayoutSize = currentSize;
2065 m_lastZoomFactor = currentZoomFactor;
2066 if (resized)
2067 m_frame->eventHandler()->sendResizeEvent();
2068 }
2069 }
2070
postLayoutTimerFired(Timer<FrameView> *)2071 void FrameView::postLayoutTimerFired(Timer<FrameView>*)
2072 {
2073 performPostLayoutTasks();
2074 }
2075
updateOverflowStatus(bool horizontalOverflow,bool verticalOverflow)2076 void FrameView::updateOverflowStatus(bool horizontalOverflow, bool verticalOverflow)
2077 {
2078 if (!m_viewportRenderer)
2079 return;
2080
2081 if (m_overflowStatusDirty) {
2082 m_horizontalOverflow = horizontalOverflow;
2083 m_verticalOverflow = verticalOverflow;
2084 m_overflowStatusDirty = false;
2085 return;
2086 }
2087
2088 bool horizontalOverflowChanged = (m_horizontalOverflow != horizontalOverflow);
2089 bool verticalOverflowChanged = (m_verticalOverflow != verticalOverflow);
2090
2091 if (horizontalOverflowChanged || verticalOverflowChanged) {
2092 m_horizontalOverflow = horizontalOverflow;
2093 m_verticalOverflow = verticalOverflow;
2094
2095 m_actionScheduler->scheduleEvent(OverflowEvent::create(horizontalOverflowChanged, horizontalOverflow,
2096 verticalOverflowChanged, verticalOverflow),
2097 m_viewportRenderer->node());
2098 }
2099
2100 }
2101
windowClipRect(bool clipToContents) const2102 IntRect FrameView::windowClipRect(bool clipToContents) const
2103 {
2104 ASSERT(m_frame->view() == this);
2105
2106 if (paintsEntireContents())
2107 return IntRect(IntPoint(0, 0), contentsSize());
2108
2109 // Set our clip rect to be our contents.
2110 IntRect clipRect = contentsToWindow(visibleContentRect(!clipToContents));
2111 if (!m_frame || !m_frame->ownerElement())
2112 return clipRect;
2113
2114 // Take our owner element and get the clip rect from the enclosing layer.
2115 Element* elt = m_frame->ownerElement();
2116 RenderLayer* layer = elt->renderer()->enclosingLayer();
2117 // FIXME: layer should never be null, but sometimes seems to be anyway.
2118 if (!layer)
2119 return clipRect;
2120 FrameView* parentView = elt->document()->view();
2121 clipRect.intersect(parentView->windowClipRectForLayer(layer, true));
2122 return clipRect;
2123 }
2124
windowClipRectForLayer(const RenderLayer * layer,bool clipToLayerContents) const2125 IntRect FrameView::windowClipRectForLayer(const RenderLayer* layer, bool clipToLayerContents) const
2126 {
2127 // If we have no layer, just return our window clip rect.
2128 if (!layer)
2129 return windowClipRect();
2130
2131 // Apply the clip from the layer.
2132 IntRect clipRect;
2133 if (clipToLayerContents)
2134 clipRect = layer->childrenClipRect();
2135 else
2136 clipRect = layer->selfClipRect();
2137 clipRect = contentsToWindow(clipRect);
2138 return intersection(clipRect, windowClipRect());
2139 }
2140
isActive() const2141 bool FrameView::isActive() const
2142 {
2143 Page* page = frame()->page();
2144 return page && page->focusController()->isActive();
2145 }
2146
scrollTo(const IntSize & newOffset)2147 void FrameView::scrollTo(const IntSize& newOffset)
2148 {
2149 IntSize offset = scrollOffset();
2150 ScrollView::scrollTo(newOffset);
2151 if (offset != scrollOffset())
2152 scrollPositionChanged();
2153 frame()->loader()->client()->didChangeScrollOffset();
2154 }
2155
invalidateScrollbarRect(Scrollbar * scrollbar,const IntRect & rect)2156 void FrameView::invalidateScrollbarRect(Scrollbar* scrollbar, const IntRect& rect)
2157 {
2158 // Add in our offset within the FrameView.
2159 IntRect dirtyRect = rect;
2160 dirtyRect.move(scrollbar->x(), scrollbar->y());
2161 invalidateRect(dirtyRect);
2162 }
2163
getTickmarks(Vector<IntRect> & tickmarks) const2164 void FrameView::getTickmarks(Vector<IntRect>& tickmarks) const
2165 {
2166 tickmarks = frame()->document()->markers()->renderedRectsForMarkers(DocumentMarker::TextMatch);
2167 }
2168
windowResizerRect() const2169 IntRect FrameView::windowResizerRect() const
2170 {
2171 Page* page = frame() ? frame()->page() : 0;
2172 if (!page)
2173 return IntRect();
2174 return page->chrome()->windowResizerRect();
2175 }
2176
didCompleteRubberBand(const IntSize & initialOverhang) const2177 void FrameView::didCompleteRubberBand(const IntSize& initialOverhang) const
2178 {
2179 Page* page = m_frame->page();
2180 if (page->mainFrame() != m_frame)
2181 return;
2182 return page->chrome()->client()->didCompleteRubberBandForMainFrame(initialOverhang);
2183 }
2184
scrollbarStyleChanged()2185 void FrameView::scrollbarStyleChanged()
2186 {
2187 Page* page = m_frame->page();
2188 ASSERT(page);
2189 if (!page)
2190 return;
2191 page->setNeedsRecalcStyleInAllFrames();
2192 }
2193
shouldSuspendScrollAnimations() const2194 bool FrameView::shouldSuspendScrollAnimations() const
2195 {
2196 return m_frame->loader()->state() != FrameStateComplete;
2197 }
2198
notifyPageThatContentAreaWillPaint() const2199 void FrameView::notifyPageThatContentAreaWillPaint() const
2200 {
2201 Page* page = m_frame->page();
2202 const HashSet<ScrollableArea*>* scrollableAreas = page->scrollableAreaSet();
2203 if (!scrollableAreas)
2204 return;
2205
2206 HashSet<ScrollableArea*>::const_iterator end = scrollableAreas->end();
2207 for (HashSet<ScrollableArea*>::const_iterator it = scrollableAreas->begin(); it != end; ++it)
2208 (*it)->scrollAnimator()->contentAreaWillPaint();
2209 }
2210
2211 #if ENABLE(DASHBOARD_SUPPORT)
updateDashboardRegions()2212 void FrameView::updateDashboardRegions()
2213 {
2214 Document* document = m_frame->document();
2215 if (!document->hasDashboardRegions())
2216 return;
2217 Vector<DashboardRegionValue> newRegions;
2218 document->renderBox()->collectDashboardRegions(newRegions);
2219 if (newRegions == document->dashboardRegions())
2220 return;
2221 document->setDashboardRegions(newRegions);
2222 Page* page = m_frame->page();
2223 if (!page)
2224 return;
2225 page->chrome()->client()->dashboardRegionsChanged();
2226 }
2227 #endif
2228
updateScrollCorner()2229 void FrameView::updateScrollCorner()
2230 {
2231 RenderObject* renderer = 0;
2232 RefPtr<RenderStyle> cornerStyle;
2233
2234 if (!scrollCornerRect().isEmpty()) {
2235 // Try the <body> element first as a scroll corner source.
2236 Document* doc = m_frame->document();
2237 Element* body = doc ? doc->body() : 0;
2238 if (body && body->renderer()) {
2239 renderer = body->renderer();
2240 cornerStyle = renderer->getUncachedPseudoStyle(SCROLLBAR_CORNER, renderer->style());
2241 }
2242
2243 if (!cornerStyle) {
2244 // If the <body> didn't have a custom style, then the root element might.
2245 Element* docElement = doc ? doc->documentElement() : 0;
2246 if (docElement && docElement->renderer()) {
2247 renderer = docElement->renderer();
2248 cornerStyle = renderer->getUncachedPseudoStyle(SCROLLBAR_CORNER, renderer->style());
2249 }
2250 }
2251
2252 if (!cornerStyle) {
2253 // If we have an owning iframe/frame element, then it can set the custom scrollbar also.
2254 if (RenderPart* renderer = m_frame->ownerRenderer())
2255 cornerStyle = renderer->getUncachedPseudoStyle(SCROLLBAR_CORNER, renderer->style());
2256 }
2257 }
2258
2259 if (cornerStyle) {
2260 if (!m_scrollCorner)
2261 m_scrollCorner = new (renderer->renderArena()) RenderScrollbarPart(renderer->document());
2262 m_scrollCorner->setStyle(cornerStyle.release());
2263 invalidateScrollCorner();
2264 } else if (m_scrollCorner) {
2265 m_scrollCorner->destroy();
2266 m_scrollCorner = 0;
2267 }
2268
2269 ScrollView::updateScrollCorner();
2270 }
2271
paintScrollCorner(GraphicsContext * context,const IntRect & cornerRect)2272 void FrameView::paintScrollCorner(GraphicsContext* context, const IntRect& cornerRect)
2273 {
2274 if (context->updatingControlTints()) {
2275 updateScrollCorner();
2276 return;
2277 }
2278
2279 if (m_scrollCorner) {
2280 m_scrollCorner->paintIntoRect(context, cornerRect.x(), cornerRect.y(), cornerRect);
2281 return;
2282 }
2283
2284 ScrollView::paintScrollCorner(context, cornerRect);
2285 }
2286
hasCustomScrollbars() const2287 bool FrameView::hasCustomScrollbars() const
2288 {
2289 const HashSet<RefPtr<Widget> >* viewChildren = children();
2290 HashSet<RefPtr<Widget> >::const_iterator end = viewChildren->end();
2291 for (HashSet<RefPtr<Widget> >::const_iterator current = viewChildren->begin(); current != end; ++current) {
2292 Widget* widget = current->get();
2293 if (widget->isFrameView()) {
2294 if (static_cast<FrameView*>(widget)->hasCustomScrollbars())
2295 return true;
2296 } else if (widget->isScrollbar()) {
2297 Scrollbar* scrollbar = static_cast<Scrollbar*>(widget);
2298 if (scrollbar->isCustomScrollbar())
2299 return true;
2300 }
2301 }
2302
2303 return false;
2304 }
2305
parentFrameView() const2306 FrameView* FrameView::parentFrameView() const
2307 {
2308 if (Widget* parentView = parent()) {
2309 if (parentView->isFrameView())
2310 return static_cast<FrameView*>(parentView);
2311 }
2312 return 0;
2313 }
2314
updateControlTints()2315 void FrameView::updateControlTints()
2316 {
2317 // This is called when control tints are changed from aqua/graphite to clear and vice versa.
2318 // We do a "fake" paint, and when the theme gets a paint call, it can then do an invalidate.
2319 // This is only done if the theme supports control tinting. It's up to the theme and platform
2320 // to define when controls get the tint and to call this function when that changes.
2321
2322 // Optimize the common case where we bring a window to the front while it's still empty.
2323 if (!m_frame || m_frame->document()->url().isEmpty())
2324 return;
2325
2326 if ((m_frame->contentRenderer() && m_frame->contentRenderer()->theme()->supportsControlTints()) || hasCustomScrollbars()) {
2327 if (needsLayout())
2328 layout();
2329 PlatformGraphicsContext* const noContext = 0;
2330 GraphicsContext context(noContext);
2331 context.setUpdatingControlTints(true);
2332 if (platformWidget())
2333 paintContents(&context, visibleContentRect());
2334 else
2335 paint(&context, frameRect());
2336 }
2337 }
2338
wasScrolledByUser() const2339 bool FrameView::wasScrolledByUser() const
2340 {
2341 return m_wasScrolledByUser;
2342 }
2343
setWasScrolledByUser(bool wasScrolledByUser)2344 void FrameView::setWasScrolledByUser(bool wasScrolledByUser)
2345 {
2346 if (m_inProgrammaticScroll)
2347 return;
2348 m_maintainScrollPositionAnchor = 0;
2349 m_wasScrolledByUser = wasScrolledByUser;
2350 }
2351
paintContents(GraphicsContext * p,const IntRect & rect)2352 void FrameView::paintContents(GraphicsContext* p, const IntRect& rect)
2353 {
2354 if (!frame())
2355 return;
2356
2357 InspectorInstrumentationCookie cookie = InspectorInstrumentation::willPaint(m_frame.get(), rect);
2358
2359 Document* document = m_frame->document();
2360
2361 #ifndef NDEBUG
2362 bool fillWithRed;
2363 if (document->printing())
2364 fillWithRed = false; // Printing, don't fill with red (can't remember why).
2365 else if (m_frame->ownerElement())
2366 fillWithRed = false; // Subframe, don't fill with red.
2367 else if (isTransparent())
2368 fillWithRed = false; // Transparent, don't fill with red.
2369 else if (m_paintBehavior & PaintBehaviorSelectionOnly)
2370 fillWithRed = false; // Selections are transparent, don't fill with red.
2371 else if (m_nodeToDraw)
2372 fillWithRed = false; // Element images are transparent, don't fill with red.
2373 else
2374 fillWithRed = true;
2375
2376 if (fillWithRed)
2377 p->fillRect(rect, Color(0xFF, 0, 0), ColorSpaceDeviceRGB);
2378 #endif
2379
2380 bool isTopLevelPainter = !sCurrentPaintTimeStamp;
2381 if (isTopLevelPainter)
2382 sCurrentPaintTimeStamp = currentTime();
2383
2384 RenderView* contentRenderer = frame()->contentRenderer();
2385 if (!contentRenderer) {
2386 LOG_ERROR("called FrameView::paint with nil renderer");
2387 return;
2388 }
2389
2390 ASSERT(!needsLayout());
2391 if (needsLayout())
2392 return;
2393
2394 #if USE(ACCELERATED_COMPOSITING)
2395 if (!p->paintingDisabled())
2396 syncCompositingStateForThisFrame();
2397 #endif
2398
2399 PaintBehavior oldPaintBehavior = m_paintBehavior;
2400
2401 if (FrameView* parentView = parentFrameView()) {
2402 if (parentView->paintBehavior() & PaintBehaviorFlattenCompositingLayers)
2403 m_paintBehavior |= PaintBehaviorFlattenCompositingLayers;
2404 }
2405
2406 if (m_paintBehavior == PaintBehaviorNormal)
2407 document->markers()->invalidateRenderedRectsForMarkersInRect(rect);
2408
2409 if (document->printing())
2410 m_paintBehavior |= PaintBehaviorFlattenCompositingLayers;
2411
2412 bool flatteningPaint = m_paintBehavior & PaintBehaviorFlattenCompositingLayers;
2413 bool isRootFrame = !m_frame->ownerElement();
2414 if (flatteningPaint && isRootFrame)
2415 notifyWidgetsInAllFrames(WillPaintFlattened);
2416
2417 ASSERT(!m_isPainting);
2418 m_isPainting = true;
2419
2420 // m_nodeToDraw is used to draw only one element (and its descendants)
2421 RenderObject* eltRenderer = m_nodeToDraw ? m_nodeToDraw->renderer() : 0;
2422 RenderLayer* rootLayer = contentRenderer->layer();
2423
2424 rootLayer->paint(p, rect, m_paintBehavior, eltRenderer);
2425
2426 if (rootLayer->containsDirtyOverlayScrollbars())
2427 rootLayer->paintOverlayScrollbars(p, rect, m_paintBehavior, eltRenderer);
2428
2429 m_isPainting = false;
2430
2431 if (flatteningPaint && isRootFrame)
2432 notifyWidgetsInAllFrames(DidPaintFlattened);
2433
2434 m_paintBehavior = oldPaintBehavior;
2435 m_lastPaintTime = currentTime();
2436
2437 #if ENABLE(DASHBOARD_SUPPORT)
2438 // Regions may have changed as a result of the visibility/z-index of element changing.
2439 if (document->dashboardRegionsDirty())
2440 updateDashboardRegions();
2441 #endif
2442
2443 if (isTopLevelPainter)
2444 sCurrentPaintTimeStamp = 0;
2445
2446 InspectorInstrumentation::didPaint(cookie);
2447 }
2448
setPaintBehavior(PaintBehavior behavior)2449 void FrameView::setPaintBehavior(PaintBehavior behavior)
2450 {
2451 m_paintBehavior = behavior;
2452 }
2453
paintBehavior() const2454 PaintBehavior FrameView::paintBehavior() const
2455 {
2456 return m_paintBehavior;
2457 }
2458
isPainting() const2459 bool FrameView::isPainting() const
2460 {
2461 return m_isPainting;
2462 }
2463
setNodeToDraw(Node * node)2464 void FrameView::setNodeToDraw(Node* node)
2465 {
2466 m_nodeToDraw = node;
2467 }
2468
paintOverhangAreas(GraphicsContext * context,const IntRect & horizontalOverhangArea,const IntRect & verticalOverhangArea,const IntRect & dirtyRect)2469 void FrameView::paintOverhangAreas(GraphicsContext* context, const IntRect& horizontalOverhangArea, const IntRect& verticalOverhangArea, const IntRect& dirtyRect)
2470 {
2471 if (context->paintingDisabled())
2472 return;
2473
2474 if (m_frame->document()->printing())
2475 return;
2476
2477 Page* page = m_frame->page();
2478 if (page->mainFrame() == m_frame) {
2479 if (page->chrome()->client()->paintCustomOverhangArea(context, horizontalOverhangArea, verticalOverhangArea, dirtyRect))
2480 return;
2481 }
2482
2483 return ScrollView::paintOverhangAreas(context, horizontalOverhangArea, verticalOverhangArea, dirtyRect);
2484 }
2485
updateLayoutAndStyleIfNeededRecursive()2486 void FrameView::updateLayoutAndStyleIfNeededRecursive()
2487 {
2488 // We have to crawl our entire tree looking for any FrameViews that need
2489 // layout and make sure they are up to date.
2490 // Mac actually tests for intersection with the dirty region and tries not to
2491 // update layout for frames that are outside the dirty region. Not only does this seem
2492 // pointless (since those frames will have set a zero timer to layout anyway), but
2493 // it is also incorrect, since if two frames overlap, the first could be excluded from the dirty
2494 // region but then become included later by the second frame adding rects to the dirty region
2495 // when it lays out.
2496
2497 m_frame->document()->updateStyleIfNeeded();
2498
2499 if (needsLayout())
2500 layout();
2501
2502 const HashSet<RefPtr<Widget> >* viewChildren = children();
2503 HashSet<RefPtr<Widget> >::const_iterator end = viewChildren->end();
2504 for (HashSet<RefPtr<Widget> >::const_iterator current = viewChildren->begin(); current != end; ++current) {
2505 Widget* widget = (*current).get();
2506 if (widget->isFrameView())
2507 static_cast<FrameView*>(widget)->updateLayoutAndStyleIfNeededRecursive();
2508 }
2509
2510 // updateLayoutAndStyleIfNeededRecursive is called when we need to make sure style and layout are up-to-date before
2511 // painting, so we need to flush out any deferred repaints too.
2512 flushDeferredRepaints();
2513 }
2514
flushDeferredRepaints()2515 void FrameView::flushDeferredRepaints()
2516 {
2517 if (!m_deferredRepaintTimer.isActive())
2518 return;
2519 m_deferredRepaintTimer.stop();
2520 doDeferredRepaints();
2521 }
2522
forceLayout(bool allowSubtree)2523 void FrameView::forceLayout(bool allowSubtree)
2524 {
2525 layout(allowSubtree);
2526 }
2527
forceLayoutForPagination(const FloatSize & pageSize,float maximumShrinkFactor,Frame::AdjustViewSizeOrNot shouldAdjustViewSize)2528 void FrameView::forceLayoutForPagination(const FloatSize& pageSize, float maximumShrinkFactor, Frame::AdjustViewSizeOrNot shouldAdjustViewSize)
2529 {
2530 // Dumping externalRepresentation(m_frame->renderer()).ascii() is a good trick to see
2531 // the state of things before and after the layout
2532 RenderView *root = toRenderView(m_frame->document()->renderer());
2533 if (root) {
2534 float pageLogicalWidth = root->style()->isHorizontalWritingMode() ? pageSize.width() : pageSize.height();
2535 float pageLogicalHeight = root->style()->isHorizontalWritingMode() ? pageSize.height() : pageSize.width();
2536
2537 int flooredPageLogicalWidth = static_cast<int>(pageLogicalWidth);
2538 root->setLogicalWidth(flooredPageLogicalWidth);
2539 root->setPageLogicalHeight(pageLogicalHeight);
2540 root->setNeedsLayoutAndPrefWidthsRecalc();
2541 forceLayout();
2542
2543 // If we don't fit in the given page width, we'll lay out again. If we don't fit in the
2544 // page width when shrunk, we will lay out at maximum shrink and clip extra content.
2545 // FIXME: We are assuming a shrink-to-fit printing implementation. A cropping
2546 // implementation should not do this!
2547 int docLogicalWidth = root->style()->isHorizontalWritingMode() ? root->docWidth() : root->docHeight();
2548 if (docLogicalWidth > pageLogicalWidth) {
2549 flooredPageLogicalWidth = std::min<int>(docLogicalWidth, pageLogicalWidth * maximumShrinkFactor);
2550 if (pageLogicalHeight)
2551 root->setPageLogicalHeight(flooredPageLogicalWidth / pageSize.width() * pageSize.height());
2552 root->setLogicalWidth(flooredPageLogicalWidth);
2553 root->setNeedsLayoutAndPrefWidthsRecalc();
2554 forceLayout();
2555 int docLogicalHeight = root->style()->isHorizontalWritingMode() ? root->docHeight() : root->docWidth();
2556 int docLogicalTop = root->style()->isHorizontalWritingMode() ? root->docTop() : root->docLeft();
2557 int docLogicalRight = root->style()->isHorizontalWritingMode() ? root->docRight() : root->docBottom();
2558 int clippedLogicalLeft = 0;
2559 if (!root->style()->isLeftToRightDirection())
2560 clippedLogicalLeft = docLogicalRight - flooredPageLogicalWidth;
2561 IntRect overflow(clippedLogicalLeft, docLogicalTop, flooredPageLogicalWidth, docLogicalHeight);
2562 if (!root->style()->isHorizontalWritingMode())
2563 overflow = overflow.transposedRect();
2564 root->clearLayoutOverflow();
2565 root->addLayoutOverflow(overflow); // This is how we clip in case we overflow again.
2566 }
2567 }
2568
2569 if (shouldAdjustViewSize)
2570 adjustViewSize();
2571 }
2572
adjustPageHeightDeprecated(float * newBottom,float oldTop,float oldBottom,float)2573 void FrameView::adjustPageHeightDeprecated(float *newBottom, float oldTop, float oldBottom, float /*bottomLimit*/)
2574 {
2575 RenderView* root = m_frame->contentRenderer();
2576 if (root) {
2577 // Use a context with painting disabled.
2578 GraphicsContext context((PlatformGraphicsContext*)0);
2579 root->setTruncatedAt((int)floorf(oldBottom));
2580 IntRect dirtyRect(0, (int)floorf(oldTop), root->maxXLayoutOverflow(), (int)ceilf(oldBottom - oldTop));
2581 root->setPrintRect(dirtyRect);
2582 root->layer()->paint(&context, dirtyRect);
2583 *newBottom = root->bestTruncatedAt();
2584 if (*newBottom == 0)
2585 *newBottom = oldBottom;
2586 root->setPrintRect(IntRect());
2587 } else
2588 *newBottom = oldBottom;
2589 }
2590
convertFromRenderer(const RenderObject * renderer,const IntRect & rendererRect) const2591 IntRect FrameView::convertFromRenderer(const RenderObject* renderer, const IntRect& rendererRect) const
2592 {
2593 IntRect rect = renderer->localToAbsoluteQuad(FloatRect(rendererRect)).enclosingBoundingBox();
2594
2595 // Convert from page ("absolute") to FrameView coordinates.
2596 rect.move(-scrollX(), -scrollY());
2597
2598 return rect;
2599 }
2600
convertToRenderer(const RenderObject * renderer,const IntRect & viewRect) const2601 IntRect FrameView::convertToRenderer(const RenderObject* renderer, const IntRect& viewRect) const
2602 {
2603 IntRect rect = viewRect;
2604
2605 // Convert from FrameView coords into page ("absolute") coordinates.
2606 rect.move(scrollX(), scrollY());
2607
2608 // FIXME: we don't have a way to map an absolute rect down to a local quad, so just
2609 // move the rect for now.
2610 rect.setLocation(roundedIntPoint(renderer->absoluteToLocal(rect.location(), false, true /* use transforms */)));
2611 return rect;
2612 }
2613
convertFromRenderer(const RenderObject * renderer,const IntPoint & rendererPoint) const2614 IntPoint FrameView::convertFromRenderer(const RenderObject* renderer, const IntPoint& rendererPoint) const
2615 {
2616 IntPoint point = roundedIntPoint(renderer->localToAbsolute(rendererPoint, false, true /* use transforms */));
2617
2618 // Convert from page ("absolute") to FrameView coordinates.
2619 point.move(-scrollX(), -scrollY());
2620 return point;
2621 }
2622
convertToRenderer(const RenderObject * renderer,const IntPoint & viewPoint) const2623 IntPoint FrameView::convertToRenderer(const RenderObject* renderer, const IntPoint& viewPoint) const
2624 {
2625 IntPoint point = viewPoint;
2626
2627 // Convert from FrameView coords into page ("absolute") coordinates.
2628 point += IntSize(scrollX(), scrollY());
2629
2630 return roundedIntPoint(renderer->absoluteToLocal(point, false, true /* use transforms */));
2631 }
2632
convertToContainingView(const IntRect & localRect) const2633 IntRect FrameView::convertToContainingView(const IntRect& localRect) const
2634 {
2635 if (const ScrollView* parentScrollView = parent()) {
2636 if (parentScrollView->isFrameView()) {
2637 const FrameView* parentView = static_cast<const FrameView*>(parentScrollView);
2638 // Get our renderer in the parent view
2639 RenderPart* renderer = m_frame->ownerRenderer();
2640 if (!renderer)
2641 return localRect;
2642
2643 IntRect rect(localRect);
2644 // Add borders and padding??
2645 rect.move(renderer->borderLeft() + renderer->paddingLeft(),
2646 renderer->borderTop() + renderer->paddingTop());
2647 return parentView->convertFromRenderer(renderer, rect);
2648 }
2649
2650 return Widget::convertToContainingView(localRect);
2651 }
2652
2653 return localRect;
2654 }
2655
convertFromContainingView(const IntRect & parentRect) const2656 IntRect FrameView::convertFromContainingView(const IntRect& parentRect) const
2657 {
2658 if (const ScrollView* parentScrollView = parent()) {
2659 if (parentScrollView->isFrameView()) {
2660 const FrameView* parentView = static_cast<const FrameView*>(parentScrollView);
2661
2662 // Get our renderer in the parent view
2663 RenderPart* renderer = m_frame->ownerRenderer();
2664 if (!renderer)
2665 return parentRect;
2666
2667 IntRect rect = parentView->convertToRenderer(renderer, parentRect);
2668 // Subtract borders and padding
2669 rect.move(-renderer->borderLeft() - renderer->paddingLeft(),
2670 -renderer->borderTop() - renderer->paddingTop());
2671 return rect;
2672 }
2673
2674 return Widget::convertFromContainingView(parentRect);
2675 }
2676
2677 return parentRect;
2678 }
2679
convertToContainingView(const IntPoint & localPoint) const2680 IntPoint FrameView::convertToContainingView(const IntPoint& localPoint) const
2681 {
2682 if (const ScrollView* parentScrollView = parent()) {
2683 if (parentScrollView->isFrameView()) {
2684 const FrameView* parentView = static_cast<const FrameView*>(parentScrollView);
2685
2686 // Get our renderer in the parent view
2687 RenderPart* renderer = m_frame->ownerRenderer();
2688 if (!renderer)
2689 return localPoint;
2690
2691 IntPoint point(localPoint);
2692
2693 // Add borders and padding
2694 point.move(renderer->borderLeft() + renderer->paddingLeft(),
2695 renderer->borderTop() + renderer->paddingTop());
2696 return parentView->convertFromRenderer(renderer, point);
2697 }
2698
2699 return Widget::convertToContainingView(localPoint);
2700 }
2701
2702 return localPoint;
2703 }
2704
convertFromContainingView(const IntPoint & parentPoint) const2705 IntPoint FrameView::convertFromContainingView(const IntPoint& parentPoint) const
2706 {
2707 if (const ScrollView* parentScrollView = parent()) {
2708 if (parentScrollView->isFrameView()) {
2709 const FrameView* parentView = static_cast<const FrameView*>(parentScrollView);
2710
2711 // Get our renderer in the parent view
2712 RenderPart* renderer = m_frame->ownerRenderer();
2713 if (!renderer)
2714 return parentPoint;
2715
2716 IntPoint point = parentView->convertToRenderer(renderer, parentPoint);
2717 // Subtract borders and padding
2718 point.move(-renderer->borderLeft() - renderer->paddingLeft(),
2719 -renderer->borderTop() - renderer->paddingTop());
2720 return point;
2721 }
2722
2723 return Widget::convertFromContainingView(parentPoint);
2724 }
2725
2726 return parentPoint;
2727 }
2728
2729 // Normal delay
setRepaintThrottlingDeferredRepaintDelay(double p)2730 void FrameView::setRepaintThrottlingDeferredRepaintDelay(double p)
2731 {
2732 s_deferredRepaintDelay = p;
2733 }
2734
2735 // Negative value would mean that first few repaints happen without a delay
setRepaintThrottlingnInitialDeferredRepaintDelayDuringLoading(double p)2736 void FrameView::setRepaintThrottlingnInitialDeferredRepaintDelayDuringLoading(double p)
2737 {
2738 s_initialDeferredRepaintDelayDuringLoading = p;
2739 }
2740
2741 // The delay grows on each repaint to this maximum value
setRepaintThrottlingMaxDeferredRepaintDelayDuringLoading(double p)2742 void FrameView::setRepaintThrottlingMaxDeferredRepaintDelayDuringLoading(double p)
2743 {
2744 s_maxDeferredRepaintDelayDuringLoading = p;
2745 }
2746
2747 // On each repaint the delay increases by this amount
setRepaintThrottlingDeferredRepaintDelayIncrementDuringLoading(double p)2748 void FrameView::setRepaintThrottlingDeferredRepaintDelayIncrementDuringLoading(double p)
2749 {
2750 s_deferredRepaintDelayIncrementDuringLoading = p;
2751 }
2752
isVerticalDocument() const2753 bool FrameView::isVerticalDocument() const
2754 {
2755 if (!m_frame)
2756 return true;
2757 Document* doc = m_frame->document();
2758 if (!doc)
2759 return true;
2760 RenderObject* renderView = doc->renderer();
2761 if (!renderView)
2762 return true;
2763 return renderView->style()->isHorizontalWritingMode();
2764 }
2765
isFlippedDocument() const2766 bool FrameView::isFlippedDocument() const
2767 {
2768 if (!m_frame)
2769 return false;
2770 Document* doc = m_frame->document();
2771 if (!doc)
2772 return false;
2773 RenderObject* renderView = doc->renderer();
2774 if (!renderView)
2775 return false;
2776 return renderView->style()->isFlippedBlocksWritingMode();
2777 }
2778
notifyWidgetsInAllFrames(WidgetNotification notification)2779 void FrameView::notifyWidgetsInAllFrames(WidgetNotification notification)
2780 {
2781 for (Frame* frame = m_frame.get(); frame; frame = frame->tree()->traverseNext(m_frame.get())) {
2782 if (RenderView* root = frame->contentRenderer())
2783 root->notifyWidgets(notification);
2784 }
2785 }
2786
axObjectCache() const2787 AXObjectCache* FrameView::axObjectCache() const
2788 {
2789 if (frame() && frame()->document() && frame()->document()->axObjectCacheExists())
2790 return frame()->document()->axObjectCache();
2791 return 0;
2792 }
2793
2794 } // namespace WebCore
2795