FrameView.cpp 101 KB
Newer Older
darin's avatar
darin committed
1
/*
kocienda's avatar
kocienda committed
2 3 4 5
 * Copyright (C) 1998, 1999 Torben Weis <weis@kde.org>
 *                     1999 Lars Knoll <knoll@kde.org>
 *                     1999 Antti Koivisto <koivisto@kde.org>
 *                     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)
ap's avatar
ap committed
8
 *           (C) 2006 Alexey Proskuryakov (ap@nypop.com)
levin@chromium.org's avatar
levin@chromium.org committed
9
 * Copyright (C) 2009 Google Inc. All rights reserved.
kocienda's avatar
kocienda committed
10 11 12 13 14 15 16 17 18 19 20 21 22
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB.  If not, write to
ddkilzer's avatar
ddkilzer committed
23 24
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
kocienda's avatar
kocienda committed
25
 */
darin's avatar
darin committed
26

mjs's avatar
mjs committed
27
#include "config.h"
mjs's avatar
mjs committed
28
#include "FrameView.h"
darin's avatar
darin committed
29

30
#include "AXObjectCache.h"
31
#include "BackForwardController.h"
32
#include "CSSStyleSelector.h"
33
#include "CachedResourceLoader.h"
34
#include "Chrome.h"
darin@apple.com's avatar
darin@apple.com committed
35
#include "ChromeClient.h"
36
#include "DocumentMarkerController.h"
darin's avatar
darin committed
37
#include "EventHandler.h"
38
#include "FloatRect.h"
hyatt@apple.com's avatar
hyatt@apple.com committed
39
#include "FocusController.h"
40
#include "FontCache.h"
mjs's avatar
mjs committed
41
#include "Frame.h"
42
#include "FrameActionScheduler.h"
darin's avatar
darin committed
43
#include "FrameLoader.h"
lars's avatar
lars committed
44
#include "FrameLoaderClient.h"
45
#include "FrameTree.h"
darin's avatar
darin committed
46
#include "GraphicsContext.h"
weinig's avatar
 
weinig committed
47
#include "HTMLDocument.h"
hyatt@apple.com's avatar
hyatt@apple.com committed
48
#include "HTMLFrameElement.h"
49
#include "HTMLFrameSetElement.h"
weinig's avatar
 
weinig committed
50
#include "HTMLNames.h"
51
#include "HTMLPlugInImageElement.h"
52
#include "InspectorInstrumentation.h"
andersca's avatar
andersca committed
53
#include "OverflowEvent.h"
54
#include "RenderArena.h"
55
#include "RenderEmbeddedObject.h"
56
#include "RenderFullScreen.h"
57
#include "RenderLayer.h"
58
#include "RenderPart.h"
59
#include "RenderScrollbar.h"
60
#include "RenderScrollbarPart.h"
darin's avatar
darin committed
61
#include "RenderTheme.h"
weinig's avatar
 
weinig committed
62
#include "RenderView.h"
63
#include "ScrollAnimator.h"
mitz@apple.com's avatar
mitz@apple.com committed
64
#include "Settings.h"
65
#include "TextResourceDecoder.h"
ap@webkit.org's avatar
ap@webkit.org committed
66
#include <wtf/CurrentTime.h>
rwlbuis's avatar
rwlbuis committed
67

68 69 70 71
#if USE(ACCELERATED_COMPOSITING)
#include "RenderLayerCompositor.h"
#endif

72
#if ENABLE(SVG)
73
#include "RenderSVGRoot.h"
74 75 76 77
#include "SVGDocument.h"
#include "SVGSVGElement.h"
#endif

78 79 80
#if ENABLE(TILED_BACKING_STORE)
#include "TiledBackingStore.h"
#endif
81

darin's avatar
darin committed
82 83
namespace WebCore {

84
using namespace HTMLNames;
darin's avatar
darin committed
85

86 87
double FrameView::sCurrentPaintTimeStamp = 0.0;

88 89
// REPAINT_THROTTLING now chooses default values for throttling parameters.
// Should be removed when applications start using runtime configuration.
antti@apple.com's avatar
antti@apple.com committed
90 91
#if ENABLE(REPAINT_THROTTLING)
// Normal delay
92
double FrameView::s_deferredRepaintDelay = 0.025;
antti@apple.com's avatar
antti@apple.com committed
93
// Negative value would mean that first few repaints happen without a delay
94
double FrameView::s_initialDeferredRepaintDelayDuringLoading = 0;
antti@apple.com's avatar
antti@apple.com committed
95
// The delay grows on each repaint to this maximum value
96
double FrameView::s_maxDeferredRepaintDelayDuringLoading = 2.5;
antti@apple.com's avatar
antti@apple.com committed
97
// On each repaint the delay increses by this amount
98
double FrameView::s_deferredRepaintDelayIncrementDuringLoading = 0.5;
antti@apple.com's avatar
antti@apple.com committed
99 100 101 102
#else
// FIXME: Repaint throttling could be good to have on all platform.
// The balance between CPU use and repaint frequency will need some tuning for desktop.
// More hooks may be needed to reset the delay on things like GIF and CSS animations.
103 104 105 106
double FrameView::s_deferredRepaintDelay = 0;
double FrameView::s_initialDeferredRepaintDelayDuringLoading = 0;
double FrameView::s_maxDeferredRepaintDelayDuringLoading = 0;
double FrameView::s_deferredRepaintDelayIncrementDuringLoading = 0;
antti@apple.com's avatar
antti@apple.com committed
107 108
#endif

109 110 111
// The maximum number of updateWidgets iterations that should be done before returning.
static const unsigned maxUpdateWidgetsIterations = 2;

darin's avatar
darin committed
112
FrameView::FrameView(Frame* frame)
darin@apple.com's avatar
darin@apple.com committed
113
    : m_frame(frame)
114
    , m_canHaveScrollbars(true)
115
    , m_slowRepaintObjectCount(0)
116
    , m_fixedObjectCount(0)
117 118
    , m_layoutTimer(this, &FrameView::layoutTimerFired)
    , m_layoutRoot(0)
119 120 121
#if ENABLE(SVG)
    , m_inLayoutParentView(false)
#endif
122
    , m_hasPendingPostLayoutTasks(false)
123
    , m_inSynchronousPostLayout(false)
124 125 126 127
    , m_postLayoutTasksTimer(this, &FrameView::postLayoutTimerFired)
    , m_isTransparent(false)
    , m_baseBackgroundColor(Color::white)
    , m_mediaType("screen")
128
    , m_actionScheduler(adoptPtr(new FrameActionScheduler))
129 130 131 132
    , m_overflowStatusDirty(true)
    , m_viewportRenderer(0)
    , m_wasScrolledByUser(false)
    , m_inProgrammaticScroll(false)
antti@apple.com's avatar
antti@apple.com committed
133
    , m_deferredRepaintTimer(this, &FrameView::deferredRepaintTimerFired)
134
    , m_shouldUpdateWhileOffscreen(true)
135 136
    , m_deferSetNeedsLayouts(0)
    , m_setNeedsLayoutWasDeferred(false)
137
    , m_scrollCorner(0)
kocienda's avatar
kocienda committed
138 139
{
    init();
140 141 142 143 144

    if (m_frame) {
        if (Page* page = m_frame->page()) {
            m_page = page;
            m_page->addScrollableArea(this);
145 146 147 148 149

            if (m_frame == m_page->mainFrame()) {
                ScrollableArea::setVerticalScrollElasticity(ScrollElasticityAllowed);
                ScrollableArea::setHorizontalScrollElasticity(ScrollElasticityAllowed);
            }
150 151
        }
    }
kocienda's avatar
kocienda committed
152 153
}

darin@apple.com's avatar
darin@apple.com committed
154
PassRefPtr<FrameView> FrameView::create(Frame* frame)
155
{
darin@apple.com's avatar
darin@apple.com committed
156 157 158 159 160 161 162 163
    RefPtr<FrameView> view = adoptRef(new FrameView(frame));
    view->show();
    return view.release();
}

PassRefPtr<FrameView> FrameView::create(Frame* frame, const IntSize& initialSize)
{
    RefPtr<FrameView> view = adoptRef(new FrameView(frame));
164
    view->Widget::setFrameRect(LayoutRect(view->location(), initialSize));
darin@apple.com's avatar
darin@apple.com committed
165 166
    view->show();
    return view.release();
167 168
}

169
FrameView::~FrameView()
kocienda's avatar
kocienda committed
170
{
171
    if (m_hasPendingPostLayoutTasks) {
172
        m_postLayoutTasksTimer.stop();
173
        m_actionScheduler->clear();
mitz@apple.com's avatar
mitz@apple.com committed
174
    }
175 176 177 178
    
    if (AXObjectCache::accessibilityEnabled() && axObjectCache())
        axObjectCache()->remove(this);
    
ggaren's avatar
ggaren committed
179
    resetScrollbars();
180 181 182 183 184

    // Custom scrollbars should already be destroyed at this point
    ASSERT(!horizontalScrollbar() || !horizontalScrollbar()->isCustomScrollbar());
    ASSERT(!verticalScrollbar() || !verticalScrollbar()->isCustomScrollbar());

185 186 187
    setHasHorizontalScrollbar(false); // Remove native scrollbars now before we lose the connection to the HostWindow.
    setHasVerticalScrollbar(false);
    
188
    ASSERT(!m_scrollCorner);
189
    ASSERT(m_actionScheduler->isEmpty());
mjs's avatar
mjs committed
190

191 192 193
    if (m_page)
        m_page->removeScrollableArea(this);

darin's avatar
darin committed
194
    if (m_frame) {
ap@webkit.org's avatar
ap@webkit.org committed
195
        ASSERT(m_frame->view() != this || !m_frame->contentRenderer());
196
        RenderPart* renderer = m_frame->ownerRenderer();
197
        if (renderer && renderer->widget() == this)
darin's avatar
darin committed
198
            renderer->setWidget(0);
199
    }
200
}
201

202 203
void FrameView::reset()
{
204
    m_cannotBlitToWindow = false;
mitz@apple.com's avatar
mitz@apple.com committed
205
    m_isOverlapped = false;
mitz@apple.com's avatar
mitz@apple.com committed
206
    m_contentIsOpaque = false;
207 208 209 210 211 212 213
    m_borderX = 30;
    m_borderY = 30;
    m_layoutTimer.stop();
    m_layoutRoot = 0;
    m_delayedLayout = false;
    m_doFullRepaint = true;
    m_layoutSchedulingEnabled = true;
214
    m_inLayout = false;
215
    m_inSynchronousPostLayout = false;
216
    m_hasPendingPostLayoutTasks = false;
217 218 219 220 221 222
    m_layoutCount = 0;
    m_nestedLayoutCount = 0;
    m_postLayoutTasksTimer.stop();
    m_firstLayout = true;
    m_firstLayoutCallbackPending = false;
    m_wasScrolledByUser = false;
223
    m_lastLayoutSize = LayoutSize();
224 225 226 227
    m_lastZoomFactor = 1.0f;
    m_deferringRepaints = 0;
    m_repaintCount = 0;
    m_repaintRects.clear();
228
    m_deferredRepaintDelay = s_initialDeferredRepaintDelayDuringLoading;
antti@apple.com's avatar
antti@apple.com committed
229 230
    m_deferredRepaintTimer.stop();
    m_lastPaintTime = 0;
231
    m_paintBehavior = PaintBehaviorNormal;
232
    m_isPainting = false;
233 234
    m_visuallyNonEmptyCharacterCount = 0;
    m_visuallyNonEmptyPixelCount = 0;
235 236
    m_isVisuallyNonEmpty = false;
    m_firstVisuallyNonEmptyLayoutCallbackPending = true;
mitz@apple.com's avatar
mitz@apple.com committed
237
    m_maintainScrollPositionAnchor = 0;
kocienda's avatar
kocienda committed
238 239
}

ggaren's avatar
ggaren committed
240 241 242 243 244
bool FrameView::isFrameView() const 
{ 
    return true; 
}

darin's avatar
darin committed
245
void FrameView::clearFrame()
rjw's avatar
rjw committed
246
{
darin's avatar
darin committed
247
    m_frame = 0;
rjw's avatar
rjw committed
248 249
}

ggaren's avatar
ggaren committed
250
void FrameView::resetScrollbars()
251 252
{
    // Reset the document's scrollbars back to our defaults before we yield the floor.
253
    m_firstLayout = true;
254
    setScrollbarsSuppressed(true);
255 256 257 258
    if (m_canHaveScrollbars)
        setScrollbarModes(ScrollbarAuto, ScrollbarAuto);
    else
        setScrollbarModes(ScrollbarAlwaysOff, ScrollbarAlwaysOff);
259
    setScrollbarsSuppressed(false);
260 261
}

262 263 264 265 266 267 268 269 270
void FrameView::resetScrollbarsAndClearContentsSize()
{
    resetScrollbars();

    setScrollbarsSuppressed(true);
    setContentsSize(IntSize());
    setScrollbarsSuppressed(false);
}

271
void FrameView::init()
kocienda's avatar
kocienda committed
272
{
273 274
    reset();

275 276
    m_margins = LayoutSize(-1, -1); // undefined
    m_size = LayoutSize();
hyatt@apple.com's avatar
hyatt@apple.com committed
277 278

    // Propagate the marginwidth/height and scrolling modes to the view.
279
    Element* ownerElement = m_frame ? m_frame->ownerElement() : 0;
hyatt@apple.com's avatar
hyatt@apple.com committed
280 281 282 283
    if (ownerElement && (ownerElement->hasTagName(frameTag) || ownerElement->hasTagName(iframeTag))) {
        HTMLFrameElement* frameElt = static_cast<HTMLFrameElement*>(ownerElement);
        if (frameElt->scrollingMode() == ScrollbarAlwaysOff)
            setCanHaveScrollbars(false);
284 285 286 287
        LayoutUnit marginWidth = frameElt->marginWidth();
        LayoutUnit marginHeight = frameElt->marginHeight();
        // FIXME: Change to roughlyEquals or >= 0 when we move to floats. 
        // See https://bugs.webkit.org/show_bug.cgi?id=66148
hyatt@apple.com's avatar
hyatt@apple.com committed
288 289 290 291 292
        if (marginWidth != -1)
            setMarginWidth(marginWidth);
        if (marginHeight != -1)
            setMarginHeight(marginHeight);
    }
levin@chromium.org's avatar
levin@chromium.org committed
293 294 295 296 297 298 299 300
}

void FrameView::detachCustomScrollbars()
{
    if (!m_frame)
        return;

    Scrollbar* horizontalBar = horizontalScrollbar();
301
    if (horizontalBar && horizontalBar->isCustomScrollbar())
levin@chromium.org's avatar
levin@chromium.org committed
302 303 304
        setHasHorizontalScrollbar(false);

    Scrollbar* verticalBar = verticalScrollbar();
305
    if (verticalBar && verticalBar->isCustomScrollbar())
levin@chromium.org's avatar
levin@chromium.org committed
306
        setHasVerticalScrollbar(false);
307 308 309 310 311

    if (m_scrollCorner) {
        m_scrollCorner->destroy();
        m_scrollCorner = 0;
    }
kocienda's avatar
kocienda committed
312 313
}

314 315
void FrameView::didAddHorizontalScrollbar(Scrollbar* scrollbar)
{
316
    if (m_frame && m_frame->document())
317 318 319 320 321 322 323 324
        m_frame->document()->didAddWheelEventHandler();
    ScrollView::didAddHorizontalScrollbar(scrollbar);
}

void FrameView::willRemoveHorizontalScrollbar(Scrollbar* scrollbar)
{
    ScrollView::willRemoveHorizontalScrollbar(scrollbar);
    // FIXME: maybe need a separate ScrollableArea::didRemoveHorizontalScrollbar callback?
325
    if (m_frame && m_frame->document())
326 327 328
        m_frame->document()->didRemoveWheelEventHandler();
}

329
void FrameView::recalculateScrollbarOverlayStyle()
330
{
331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346
    ScrollbarOverlayStyle oldOverlayStyle = scrollbarOverlayStyle();
    ScrollbarOverlayStyle overlayStyle = ScrollbarOverlayStyleDefault;

    Color backgroundColor = documentBackgroundColor();
    if (backgroundColor.isValid()) {
        // Reduce the background color from RGB to a lightness value
        // and determine which scrollbar style to use based on a lightness
        // heuristic.
        double hue, saturation, lightness;
        backgroundColor.getHSL(hue, saturation, lightness);
        if (lightness <= .5)
            overlayStyle = ScrollbarOverlayStyleLight;
    }

    if (oldOverlayStyle != overlayStyle)
        setScrollbarOverlayStyle(overlayStyle);
347 348
}

349
void FrameView::clear()
kocienda's avatar
kocienda committed
350
{
351
    setCanBlitOnScroll(true);
kocienda's avatar
kocienda committed
352
    
353
    reset();
354

355
    if (m_frame) {
356
        if (RenderPart* renderer = m_frame->ownerRenderer())
darin's avatar
darin committed
357
            renderer->viewCleared();
358
    }
kocienda's avatar
kocienda committed
359

360
    setScrollbarsSuppressed(true);
kocienda's avatar
kocienda committed
361 362
}

363 364
bool FrameView::didFirstLayout() const
{
365
    return !m_firstLayout;
366 367
}

368
void FrameView::invalidateRect(const IntRect& rect)
hyatt@apple.com's avatar
hyatt@apple.com committed
369 370
{
    if (!parent()) {
371
        if (hostWindow())
372
            hostWindow()->invalidateContentsAndWindow(rect, false /*immediate*/);
hyatt@apple.com's avatar
hyatt@apple.com committed
373 374 375 376 377 378
        return;
    }

    if (!m_frame)
        return;

379
    RenderPart* renderer = m_frame->ownerRenderer();
hyatt@apple.com's avatar
hyatt@apple.com committed
380 381 382
    if (!renderer)
        return;

383
    LayoutRect repaintRect = rect;
hyatt@apple.com's avatar
hyatt@apple.com committed
384 385 386 387 388
    repaintRect.move(renderer->borderLeft() + renderer->paddingLeft(),
                     renderer->borderTop() + renderer->paddingTop());
    renderer->repaintRectangle(repaintRect);
}

389
void FrameView::setFrameRect(const IntRect& newRect)
390
{
391
    IntRect oldRect = frameRect();
392 393 394 395 396 397 398 399 400 401 402 403 404
    if (newRect == oldRect)
        return;

    ScrollView::setFrameRect(newRect);

#if USE(ACCELERATED_COMPOSITING)
    if (RenderView* root = m_frame->contentRenderer()) {
        if (root->usesCompositing())
            root->compositor()->frameViewDidChangeSize();
    }
#endif
}

405 406 407 408 409 410 411 412
#if ENABLE(REQUEST_ANIMATION_FRAME)
void FrameView::scheduleAnimation()
{
    if (hostWindow())
        hostWindow()->scheduleAnimation();
}
#endif

413
void FrameView::setMarginWidth(LayoutUnit w)
414 415
{
    // make it update the rendering area when set
416
    m_margins.setWidth(w);
417 418
}

419
void FrameView::setMarginHeight(LayoutUnit h)
420 421
{
    // make it update the rendering area when set
422
    m_margins.setHeight(h);
kocienda's avatar
kocienda committed
423 424
}

425
bool FrameView::avoidScrollbarCreation() const
426
{
kenneth@webkit.org's avatar
kenneth@webkit.org committed
427 428
    ASSERT(m_frame);

429 430 431 432 433 434 435 436 437 438 439 440 441
    // with frame flattening no subframe can have scrollbars
    // but we also cannot turn scrollbars of as we determine
    // our flattening policy using that.

    if (!m_frame->ownerElement())
        return false;

    if (!m_frame->settings() || m_frame->settings()->frameFlatteningEnabled())
        return true;

    return false;
}

442 443 444 445 446 447 448 449 450 451 452 453
void FrameView::setCanHaveScrollbars(bool canHaveScrollbars)
{
    m_canHaveScrollbars = canHaveScrollbars;
    ScrollView::setCanHaveScrollbars(canHaveScrollbars);
}

void FrameView::updateCanHaveScrollbars()
{
    ScrollbarMode hMode;
    ScrollbarMode vMode;
    scrollbarModes(hMode, vMode);
    if (hMode == ScrollbarAlwaysOff && vMode == ScrollbarAlwaysOff)
454
        setCanHaveScrollbars(false);
455
    else
456
        setCanHaveScrollbars(true);
457 458
}

459 460
PassRefPtr<Scrollbar> FrameView::createScrollbar(ScrollbarOrientation orientation)
{
461 462 463 464
    // FIXME: We need to update the scrollbar dynamically as documents change (or as doc elements and bodies get discovered that have custom styles).
    Document* doc = m_frame->document();

    // Try the <body> element first as a scrollbar source.
hyatt@apple.com's avatar
hyatt@apple.com committed
465
    Element* body = doc ? doc->body() : 0;
466
    if (body && body->renderer() && body->renderer()->style()->hasPseudoStyle(SCROLLBAR))
467
        return RenderScrollbar::createCustomScrollbar(this, orientation, body->renderer()->enclosingBox());
468 469
    
    // If the <body> didn't have a custom style, then the root element might.
hyatt@apple.com's avatar
hyatt@apple.com committed
470
    Element* docElement = doc ? doc->documentElement() : 0;
471
    if (docElement && docElement->renderer() && docElement->renderer()->style()->hasPseudoStyle(SCROLLBAR))
hyatt@apple.com's avatar
hyatt@apple.com committed
472
        return RenderScrollbar::createCustomScrollbar(this, orientation, docElement->renderBox());
473 474
        
    // If we have an owning iframe/frame element, then it can set the custom scrollbar also.
475
    RenderPart* frameRenderer = m_frame->ownerRenderer();
476
    if (frameRenderer && frameRenderer->style()->hasPseudoStyle(SCROLLBAR))
477
        return RenderScrollbar::createCustomScrollbar(this, orientation, 0, m_frame.get());
478 479
    
    // Nobody set a custom style, so we just use a native scrollbar.
480 481 482
    return ScrollView::createScrollbar(orientation);
}

483
void FrameView::setContentsSize(const LayoutSize& size)
484
{
485 486
    if (size == contentsSize())
        return;
487

488
    m_deferSetNeedsLayouts++;
489

490 491 492 493 494 495
    ScrollView::setContentsSize(size);
    scrollAnimator()->contentsResized();
    
    Page* page = frame() ? frame()->page() : 0;
    if (!page)
        return;
496

497
    page->chrome()->contentsSizeChanged(frame(), size); //notify only
498

499 500 501 502
    m_deferSetNeedsLayouts--;
    
    if (!m_deferSetNeedsLayouts)
        m_setNeedsLayoutWasDeferred = false; // FIXME: Find a way to make the deferred layout actually happen.
503 504
}

505
void FrameView::adjustViewSize()
rjw's avatar
WebKit:  
rjw committed
506
{
507
    ASSERT(m_frame->view() == this);
eric@webkit.org's avatar
eric@webkit.org committed
508
    RenderView* root = m_frame->contentRenderer();
509 510
    if (!root)
        return;
511

512 513 514
    const LayoutRect& rect = root->documentRect();
    const LayoutSize& size = rect.size();
    ScrollView::setScrollOrigin(LayoutPoint(-rect.x(), -rect.y()), !m_frame->document()->printing(), size == contentsSize());
515
    
516
    setContentsSize(size);
rjw's avatar
WebKit:  
rjw committed
517 518
}

ggaren's avatar
ggaren committed
519
void FrameView::applyOverflowToViewport(RenderObject* o, ScrollbarMode& hMode, ScrollbarMode& vMode)
520
{
521
    // Handle the overflow:hidden/scroll case for the body/html elements.  WinIE treats
522
    // overflow:hidden and overflow:scroll on <body> as applying to the document's
523 524
    // scrollbars.  The CSS2.1 draft states that HTML UAs should use the <html> or <body> element and XML/XHTML UAs should
    // use the root element.
525 526

    // To combat the inability to scroll on a page with overflow:hidden on the root when scaled, disregard hidden when
527
    // there is a frameScaleFactor that is greater than one on the main frame.
528

529
    bool overrideHidden = m_frame->page() && m_frame->page()->mainFrame() == m_frame && m_frame->frameScaleFactor() > 1;
530

531
    switch (o->style()->overflowX()) {
532
        case OHIDDEN:
533 534 535 536
            if (overrideHidden)
                hMode = ScrollbarAuto;
            else
                hMode = ScrollbarAlwaysOff;
537 538
            break;
        case OSCROLL:
ggaren's avatar
ggaren committed
539
            hMode = ScrollbarAlwaysOn;
540 541
            break;
        case OAUTO:
ggaren's avatar
ggaren committed
542
            hMode = ScrollbarAuto;
543 544 545 546 547 548 549 550
            break;
        default:
            // Don't set it at all.
            ;
    }
    
     switch (o->style()->overflowY()) {
        case OHIDDEN:
551 552 553 554
            if (overrideHidden)
                vMode = ScrollbarAuto;
            else
                vMode = ScrollbarAlwaysOff;
555 556
            break;
        case OSCROLL:
ggaren's avatar
ggaren committed
557
            vMode = ScrollbarAlwaysOn;
558 559
            break;
        case OAUTO:
ggaren's avatar
ggaren committed
560
            vMode = ScrollbarAuto;
561 562 563 564 565
            break;
        default:
            // Don't set it at all.
            ;
    }
andersca's avatar
andersca committed
566

567
    m_viewportRenderer = o;
568 569
}

570 571
void FrameView::calculateScrollbarModesForLayout(ScrollbarMode& hMode, ScrollbarMode& vMode)
{
572 573
    m_viewportRenderer = 0;

574 575 576 577 578 579 580
    const HTMLFrameOwnerElement* owner = m_frame->ownerElement();
    if (owner && (owner->scrollingMode() == ScrollbarAlwaysOff)) {
        hMode = ScrollbarAlwaysOff;
        vMode = ScrollbarAlwaysOff;
        return;
    }  
    
581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605
    if (m_canHaveScrollbars) {
        hMode = ScrollbarAuto;
        vMode = ScrollbarAuto;
    } else {
        hMode = ScrollbarAlwaysOff;
        vMode = ScrollbarAlwaysOff;
    }
    
    if (!m_layoutRoot) {
        Document* document = m_frame->document();
        Node* documentElement = document->documentElement();
        RenderObject* rootRenderer = documentElement ? documentElement->renderer() : 0;
        Node* body = document->body();
        if (body && body->renderer()) {
            if (body->hasTagName(framesetTag) && m_frame->settings() && !m_frame->settings()->frameFlatteningEnabled()) {
                vMode = ScrollbarAlwaysOff;
                hMode = ScrollbarAlwaysOff;
            } else if (body->hasTagName(bodyTag)) {
                // It's sufficient to just check the X overflow,
                // since it's illegal to have visible in only one direction.
                RenderObject* o = rootRenderer->style()->overflowX() == OVISIBLE && document->documentElement()->hasTagName(htmlTag) ? body->renderer() : rootRenderer;
                applyOverflowToViewport(o, hMode, vMode);
            }
        } else if (rootRenderer) {
#if ENABLE(SVG)
606
            if (!documentElement->isSVGElement())
607 608 609 610 611
                applyOverflowToViewport(rootRenderer, hMode, vMode);
#else
            applyOverflowToViewport(rootRenderer, hMode, vMode);
#endif
        }
612 613
    }    
}
614

615
#if ENABLE(FULLSCREEN_API) && USE(ACCELERATED_COMPOSITING)
616 617
static bool isDocumentRunningFullScreenAnimation(Document* document)
{
618
    return document->webkitIsFullScreen() && document->fullScreenRenderer() && document->isAnimatingFullScreen();
619 620
}
#endif
621
    
622
#if USE(ACCELERATED_COMPOSITING)
623
void FrameView::updateCompositingLayers()
624 625
{
    RenderView* view = m_frame->contentRenderer();
626
    if (!view)
627 628
        return;

629
    // This call will make sure the cached hasAcceleratedCompositing is updated from the pref
630
    view->compositor()->cacheAcceleratedCompositingFlags();
631
    view->compositor()->updateCompositingLayers(CompositingUpdateAfterLayoutOrStyleChange);
632 633 634 635
    
#if ENABLE(FULLSCREEN_API)
    Document* document = m_frame->document();
    if (isDocumentRunningFullScreenAnimation(document))
636
        view->compositor()->updateCompositingLayers(CompositingUpdateAfterLayoutOrStyleChange, document->fullScreenRenderer()->layer());
637
#endif
638 639
}

640 641 642 643 644 645 646 647 648
void FrameView::clearBackingStores()
{
    RenderView* root = m_frame->contentRenderer();
    if (!root)
        return;

    RenderLayerCompositor* compositor = root->compositor();
    ASSERT(compositor->inCompositingMode());
    compositor->enableCompositingMode(false);
649
    compositor->clearBackingForAllLayers();
650 651 652 653 654 655 656 657 658 659
}

void FrameView::restoreBackingStores()
{
    RenderView* root = m_frame->contentRenderer();
    if (!root)
        return;

    RenderLayerCompositor* compositor = root->compositor();
    compositor->enableCompositingMode(true);
660
    compositor->updateCompositingLayers();
661 662
}

663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686
GraphicsLayer* FrameView::layerForHorizontalScrollbar() const
{
    RenderView* view = m_frame->contentRenderer();
    if (!view)
        return 0;
    return view->compositor()->layerForHorizontalScrollbar();
}

GraphicsLayer* FrameView::layerForVerticalScrollbar() const
{
    RenderView* view = m_frame->contentRenderer();
    if (!view)
        return 0;
    return view->compositor()->layerForVerticalScrollbar();
}

GraphicsLayer* FrameView::layerForScrollCorner() const
{
    RenderView* view = m_frame->contentRenderer();
    if (!view)
        return 0;
    return view->compositor()->layerForScrollCorner();
}

687 688 689 690 691 692 693 694 695 696
#if PLATFORM(CHROMIUM) && ENABLE(RUBBER_BANDING)
GraphicsLayer* FrameView::layerForOverhangAreas() const
{
    RenderView* view = m_frame->contentRenderer();
    if (!view)
        return 0;
    return view->compositor()->layerForOverhangAreas();
}
#endif

697
bool FrameView::syncCompositingStateForThisFrame(Frame* rootFrameForSync)
698
{
699 700 701 702 703 704 705 706 707 708
    ASSERT(m_frame->view() == this);
    RenderView* view = m_frame->contentRenderer();
    if (!view)
        return true; // We don't want to keep trying to update layers if we have no renderer.

    // If we sync compositing layers when a layout is pending, we may cause painting of compositing
    // layer content to occur before layout has happened, which will cause paintContents() to bail.
    if (needsLayout())
        return false;

709
    view->compositor()->flushPendingLayerChanges(rootFrameForSync == m_frame);
710 711 712 713 714 715 716 717

#if ENABLE(FULLSCREEN_API)
    // The fullScreenRenderer's graphicsLayer  has been re-parented, and the above recursive syncCompositingState
    // call will not cause the subtree under it to repaint.  Explicitly call the syncCompositingState on 
    // the fullScreenRenderer's graphicsLayer here:
    Document* document = m_frame->document();
    if (isDocumentRunningFullScreenAnimation(document)) {
        RenderLayerBacking* backing = document->fullScreenRenderer()->layer()->backing();
718 719 720 721 722
        if (GraphicsLayer* fullScreenLayer = backing->graphicsLayer()) {
            // FIXME: Passing frameRect() is correct only when RenderLayerCompositor uses a ScrollLayer (as in WebKit2)
            // otherwise, the passed clip rect needs to take scrolling into account
            fullScreenLayer->syncCompositingState(frameRect());
        }
723
    }
724 725
#endif
    return true;
726 727
}

728 729 730 731 732 733
void FrameView::setNeedsOneShotDrawingSynchronization()
{
    Page* page = frame() ? frame()->page() : 0;
    if (page)
        page->chrome()->client()->setNeedsOneShotDrawingSynchronization();
}
734

735 736
#endif // USE(ACCELERATED_COMPOSITING)

737 738 739 740 741 742 743 744 745
bool FrameView::hasCompositedContent() const
{
#if USE(ACCELERATED_COMPOSITING)
    if (RenderView* view = m_frame->contentRenderer())
        return view->compositor()->inCompositingMode();
#endif
    return false;
}

746 747 748 749 750 751 752 753 754 755
bool FrameView::hasCompositedContentIncludingDescendants() const
{
#if USE(ACCELERATED_COMPOSITING)
    for (Frame* frame = m_frame.get(); frame; frame = frame->tree()->traverseNext(m_frame.get())) {
        RenderView* renderView = frame->contentRenderer();
        RenderLayerCompositor* compositor = renderView ? renderView->compositor() : 0;
        if (compositor) {
            if (compositor->inCompositingMode())
                return true;

756
            if (!RenderLayerCompositor::allowsIndependentlyCompositedFrames(this))
757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776
                break;
        }
    }
#endif
    return false;
}

bool FrameView::hasCompositingAncestor() const
{
#if USE(ACCELERATED_COMPOSITING)
    for (Frame* frame = m_frame->tree()->parent(); frame; frame = frame->tree()->parent()) {
        if (FrameView* view = frame->view()) {
            if (view->hasCompositedContent())
                return true;
        }
    }
#endif
    return false;
}

777 778 779 780
// Sometimes (for plug-ins) we need to eagerly go into compositing mode.
void FrameView::enterCompositingMode()
{
#if USE(ACCELERATED_COMPOSITING)
781
    if (RenderView* view = m_frame->contentRenderer()) {
782
        view->compositor()->enableCompositingMode();
783 784 785
        if (!needsLayout())
            view->compositor()->scheduleCompositingLayerUpdate();
    }
786 787 788
#endif
}

789 790
bool FrameView::isEnclosedInCompositingLayer() const
{
791
#if USE(ACCELERATED_COMPOSITING)
792
    RenderObject* frameOwnerRenderer = m_frame->ownerRenderer();
793 794 795
    if (frameOwnerRenderer && frameOwnerRenderer->containerForRepaint())
        return true;

796 797
    if (FrameView* parentView = parentFrameView())
        return parentView->isEnclosedInCompositingLayer();
798
#endif
799
    return false;
800
}
801
    
802
bool FrameView::syncCompositingStateIncludingSubframes()
803 804
{
#if USE(ACCELERATED_COMPOSITING)
805
    bool allFramesSynced = syncCompositingStateForThisFrame(m_frame.get());
806
    
807
    for (Frame* child = m_frame->tree()->firstChild(); child; child = child->tree()->traverseNext(m_frame.get())) {
808
        bool synced = child->view()->syncCompositingStateForThisFrame(m_frame.get());
809
        allFramesSynced &= synced;
810
    }
811
    return allFramesSynced;
812
#else // USE(ACCELERATED_COMPOSITING)
813
    return true;
814
#endif
815 816
}

817 818 819 820 821 822 823 824 825 826 827 828 829
bool FrameView::isSoftwareRenderable() const
{
#if USE(ACCELERATED_COMPOSITING)
    RenderView* view = m_frame->contentRenderer();
    if (!view)
        return true;

    return !view->compositor()->has3DContent();
#else
    return true;
#endif
}

830 831 832 833 834
void FrameView::didMoveOnscreen()
{
    RenderView* view = m_frame->contentRenderer();
    if (view)
        view->didMoveOnscreen();
835
    scrollAnimator()->contentAreaDidShow();
836 837 838 839 840 841 842
}

void FrameView::willMoveOffscreen()
{
    RenderView* view = m_frame->contentRenderer();
    if (view)
        view->willMoveOffscreen();
843
    scrollAnimator()->contentAreaDidHide();
844 845
}

mitz@apple.com's avatar
mitz@apple.com committed
846
RenderObject* FrameView::layoutRoot(bool onlyDuringLayout) const
ap's avatar
ap committed
847
{
848
    return onlyDuringLayout && layoutPending() ? 0 : m_layoutRoot;
ap's avatar
ap committed
849 850
}

851 852 853 854 855 856 857 858 859 860 861 862 863
static inline void collectFrameViewChildren(FrameView* frameView, Vector<RefPtr<FrameView> >& frameViews)
{
    const HashSet<RefPtr<Widget> >* viewChildren = frameView->children();
    ASSERT(viewChildren);

    const HashSet<RefPtr<Widget> >::iterator end = viewChildren->end();
    for (HashSet<RefPtr<Widget> >::iterator current = viewChildren->begin(); current != end; ++current) {
        Widget* widget = (*current).get();
        if (widget->isFrameView())
            frameViews.append(static_cast<FrameView*>(widget));
    }
}

864 865 866
inline void FrameView::forceLayoutParentViewIfNeeded()
{
#if ENABLE(SVG)
867 868 869
    if (m_inLayoutParentView)
        return;

870 871 872 873 874 875 876 877 878 879 880 881
    RenderPart* ownerRenderer = m_frame->ownerRenderer();
    if (!ownerRenderer || !ownerRenderer->frame())
        return;

    RenderBox* contentBox = embeddedContentBox();
    if (!contentBox)
        return;

    RenderSVGRoot* svgRoot = toRenderSVGRoot(contentBox);
    if (!svgRoot->needsSizeNegotiationWithHostDocument())
        return;

882 883
    m_inLayoutParentView = true;

884 885 886 887 888 889 890 891
    // Clear needs-size-negotiation flag in RenderSVGRoot, so the next call to our
    // layout() method won't fire the size negotiation logic again.
    svgRoot->scheduledSizeNegotiationWithHostDocument();
    ASSERT(!svgRoot->needsSizeNegotiationWithHostDocument());

    // Mark the owner renderer as needing layout.
    ownerRenderer->setNeedsLayoutAndPrefWidthsRecalc();

892 893 894 895 896 897 898
    // Immediately relayout the child widgets, which can now calculate the SVG documents
    // intrinsic size, negotiating with the parent object/embed/iframe.
    RenderView* rootView = ownerRenderer->frame()->contentRenderer();
    ASSERT(rootView);
    rootView->updateWidgetPositions();

    // Synchronously enter layout, to layout the view containing the host object/embed/iframe.
899 900 901
    FrameView* frameView = ownerRenderer->frame()->view();
    ASSERT(frameView);
    frameView->layout();
902 903

    m_inLayoutParentView = false;
904 905 906
#endif
}

adele's avatar
adele committed
907
void FrameView::layout(bool allowSubtree)
kocienda's avatar
kocienda committed
908
{
909
    if (m_inLayout)
bdakin's avatar
bdakin committed
910 911
        return;

912 913 914 915 916 917 918 919 920 921 922 923 924 925
    bool inSubframeLayoutWithFrameFlattening = parent() && m_frame->settings() && m_frame->settings()->frameFlatteningEnabled();

    if (inSubframeLayoutWithFrameFlattening) {
        if (parent()->isFrameView()) {
            FrameView* parentView =   static_cast<FrameView*>(parent());
            if (!parentView->m_nestedLayoutCount) {
                while (parentView->parent() && parentView->parent()->isFrameView())
                    parentView = static_cast<FrameView*>(parentView->parent());
                parentView->layout(allowSubtree);
                return;
            }
        }
    }

926 927
    m_layoutTimer.stop();
    m_delayedLayout = false;
928
    m_setNeedsLayoutWasDeferred = false;