FrameView.cpp 31.1 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>
darin's avatar
darin committed
6
 * Copyright (C) 2004, 2005, 2006, 2007 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)
kocienda's avatar
kocienda committed
9 10 11 12 13 14 15 16 17 18 19 20 21
 *
 * 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
22 23
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
kocienda's avatar
kocienda committed
24
 */
darin's avatar
darin committed
25

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

29
#include "AXObjectCache.h"
darin's avatar
darin committed
30
#include "EventHandler.h"
31
#include "FloatRect.h"
mjs's avatar
mjs committed
32
#include "Frame.h"
darin's avatar
darin committed
33
#include "FrameLoader.h"
lars's avatar
lars committed
34
#include "FrameLoaderClient.h"
darin's avatar
darin committed
35
#include "GraphicsContext.h"
weinig's avatar
 
weinig committed
36
#include "HTMLDocument.h"
37
#include "HTMLFrameSetElement.h"
weinig's avatar
 
weinig committed
38
#include "HTMLNames.h"
andersca's avatar
andersca committed
39
#include "OverflowEvent.h"
40
#include "RenderPart.h"
bdakin's avatar
bdakin committed
41
#include "RenderPartObject.h"
darin's avatar
darin committed
42
#include "RenderTheme.h"
weinig's avatar
 
weinig committed
43
#include "RenderView.h"
rwlbuis's avatar
rwlbuis committed
44

darin's avatar
darin committed
45 46
namespace WebCore {

47
using namespace HTMLNames;
darin's avatar
darin committed
48

andersca's avatar
andersca committed
49 50 51 52 53 54
struct ScheduledEvent {
    RefPtr<Event> m_event;
    RefPtr<EventTargetNode> m_eventTarget;
    bool m_tempEvent;
};

55
class FrameViewPrivate {
kocienda's avatar
kocienda committed
56
public:
darin's avatar
darin committed
57
    FrameViewPrivate(FrameView* view)
58 59
        : m_slowRepaintObjectCount(0)
        , layoutTimer(view, &FrameView::layoutTimerFired)
mitz@apple.com's avatar
mitz@apple.com committed
60
        , layoutRoot(0)
mitz@apple.com's avatar
mitz@apple.com committed
61
        , postLayoutTasksTimer(view, &FrameView::postLayoutTimerFired)
62
        , m_mediaType("screen")
aroben's avatar
aroben committed
63
        , m_enqueueEvents(0)
andersca's avatar
andersca committed
64 65
        , m_overflowStatusDirty(true)
        , m_viewportRenderer(0)
darin's avatar
darin committed
66 67
        , m_wasScrolledByUser(false)
        , m_inProgrammaticScroll(false)
kocienda's avatar
kocienda committed
68
    {
darin's avatar
darin committed
69
        isTransparent = false;
thatcher's avatar
thatcher committed
70
        baseBackgroundColor = Color::white;
ggaren's avatar
ggaren committed
71 72
        vmode = hmode = ScrollbarAuto;
        needToInitScrollbars = true;
darin's avatar
darin committed
73
        reset();
kocienda's avatar
kocienda committed
74 75 76 77
    }
    void reset()
    {
        useSlowRepaints = false;
78 79
        borderX = 30;
        borderY = 30;
darin's avatar
darin committed
80
        layoutTimer.stop();
adele's avatar
adele committed
81
        layoutRoot = 0;
82
        delayedLayout = false;
83
        doFullRepaint = true;
84
        layoutSchedulingEnabled = true;
bdakin's avatar
bdakin committed
85
        midLayout = false;
86
        layoutCount = 0;
bdakin's avatar
bdakin committed
87
        nestedLayoutCount = 0;
mitz@apple.com's avatar
mitz@apple.com committed
88
        postLayoutTasksTimer.stop();
89
        firstLayout = true;
darin's avatar
darin committed
90
        repaintRects.clear();
darin's avatar
darin committed
91
        m_wasScrolledByUser = false;
mitz@apple.com's avatar
mitz@apple.com committed
92
        lastLayoutSize = IntSize();
kocienda's avatar
kocienda committed
93 94
    }

darin's avatar
darin committed
95
    bool doFullRepaint;
96
    
ggaren's avatar
ggaren committed
97 98
    ScrollbarMode vmode;
    ScrollbarMode hmode;
kocienda's avatar
kocienda committed
99
    bool useSlowRepaints;
100
    unsigned m_slowRepaintObjectCount;
kocienda's avatar
kocienda committed
101 102 103

    int borderX, borderY;

darin's avatar
darin committed
104
    Timer<FrameView> layoutTimer;
105
    bool delayedLayout;
mitz@apple.com's avatar
mitz@apple.com committed
106
    RenderObject* layoutRoot;
hyatt's avatar
hyatt committed
107
    
108
    bool layoutSchedulingEnabled;
bdakin's avatar
bdakin committed
109
    bool midLayout;
110
    int layoutCount;
bdakin's avatar
bdakin committed
111
    unsigned nestedLayoutCount;
mitz@apple.com's avatar
mitz@apple.com committed
112
    Timer<FrameView> postLayoutTasksTimer;
113

114
    bool firstLayout;
ggaren's avatar
ggaren committed
115
    bool needToInitScrollbars;
darin's avatar
darin committed
116
    bool isTransparent;
thatcher's avatar
thatcher committed
117
    Color baseBackgroundColor;
mitz@apple.com's avatar
mitz@apple.com committed
118
    IntSize lastLayoutSize;
thatcher's avatar
thatcher committed
119

120 121
    // Used by objects during layout to communicate repaints that need to take place only
    // after all layout has been completed.
darin's avatar
darin committed
122
    Vector<RenderObject::RepaintInfo> repaintRects;
123 124
    
    String m_mediaType;
andersca's avatar
andersca committed
125
    
aroben's avatar
aroben committed
126
    unsigned m_enqueueEvents;
darin's avatar
darin committed
127
    Vector<ScheduledEvent*> m_scheduledEvents;
andersca's avatar
andersca committed
128 129 130 131 132
    
    bool m_overflowStatusDirty;
    bool horizontalOverflow;
    bool m_verticalOverflow;    
    RenderObject* m_viewportRenderer;
darin's avatar
darin committed
133 134 135

    bool m_wasScrolledByUser;
    bool m_inProgrammaticScroll;
kocienda's avatar
kocienda committed
136 137
};

darin's avatar
darin committed
138
FrameView::FrameView(Frame* frame)
139
    : m_refCount(1)
darin's avatar
darin committed
140 141
    , m_frame(frame)
    , d(new FrameViewPrivate(this))
kocienda's avatar
kocienda committed
142 143
{
    init();
darin's avatar
darin committed
144
    show();
kocienda's avatar
kocienda committed
145 146
}

147
FrameView::~FrameView()
kocienda's avatar
kocienda committed
148
{
mitz@apple.com's avatar
mitz@apple.com committed
149 150 151 152 153 154
    if (d->postLayoutTasksTimer.isActive()) {
        d->postLayoutTasksTimer.stop();
        d->m_scheduledEvents.clear();
        d->m_enqueueEvents = 0;
    }

ggaren's avatar
ggaren committed
155
    resetScrollbars();
156

157
    ASSERT(m_refCount == 0);
158
    ASSERT(d->m_scheduledEvents.isEmpty() && !d->m_enqueueEvents);
mjs's avatar
mjs committed
159

darin's avatar
darin committed
160
    if (m_frame) {
161 162 163
        ASSERT(m_frame->view() != this || !m_frame->document() || !m_frame->document()->renderer());
        RenderPart* renderer = m_frame->ownerRenderer();
        if (renderer && renderer->widget() == this)
darin's avatar
darin committed
164
            renderer->setWidget(0);
165
    }
166

darin's avatar
darin committed
167 168
    delete d;
    d = 0;
kocienda's avatar
kocienda committed
169 170
}

ggaren's avatar
ggaren committed
171 172 173 174 175
bool FrameView::isFrameView() const 
{ 
    return true; 
}

darin's avatar
darin committed
176
void FrameView::clearFrame()
rjw's avatar
rjw committed
177
{
darin's avatar
darin committed
178
    m_frame = 0;
rjw's avatar
rjw committed
179 180
}

ggaren's avatar
ggaren committed
181
void FrameView::resetScrollbars()
182 183
{
    // Reset the document's scrollbars back to our defaults before we yield the floor.
184
    d->firstLayout = true;
ggaren's avatar
ggaren committed
185 186 187 188
    suppressScrollbars(true);
    ScrollView::setVScrollbarMode(d->vmode);
    ScrollView::setHScrollbarMode(d->hmode);
    suppressScrollbars(false);
189 190
}

191
void FrameView::init()
kocienda's avatar
kocienda committed
192
{
193 194
    m_margins = IntSize(-1, -1); // undefined
    m_size = IntSize();
kocienda's avatar
kocienda committed
195 196
}

197
void FrameView::clear()
kocienda's avatar
kocienda committed
198
{
199
    setStaticBackground(false);
kocienda's avatar
kocienda committed
200
    
kocienda's avatar
kocienda committed
201
    d->reset();
202

darin's avatar
darin committed
203 204 205
    if (m_frame)
        if (RenderPart* renderer = m_frame->ownerRenderer())
            renderer->viewCleared();
kocienda's avatar
kocienda committed
206

ggaren's avatar
ggaren committed
207
    suppressScrollbars(true);
kocienda's avatar
kocienda committed
208 209
}

210 211 212 213 214
bool FrameView::didFirstLayout() const
{
    return !d->firstLayout;
}

ggaren's avatar
ggaren committed
215
void FrameView::initScrollbars()
216
{
ggaren's avatar
ggaren committed
217
    if (!d->needToInitScrollbars)
218
        return;
ggaren's avatar
ggaren committed
219 220
    d->needToInitScrollbars = false;
    setScrollbarsMode(hScrollbarMode());
221
}
222

223
void FrameView::setMarginWidth(int w)
224 225
{
    // make it update the rendering area when set
226
    m_margins.setWidth(w);
227 228
}

229
void FrameView::setMarginHeight(int h)
230 231
{
    // make it update the rendering area when set
232
    m_margins.setHeight(h);
kocienda's avatar
kocienda committed
233 234
}

235
void FrameView::adjustViewSize()
rjw's avatar
WebKit:  
rjw committed
236
{
237
    ASSERT(m_frame->view() == this);
238 239 240 241
    RenderView* root = static_cast<RenderView*>(m_frame->renderer());
    if (!root)
        return;
    resizeContents(root->overflowWidth(), root->overflowHeight());
rjw's avatar
WebKit:  
rjw committed
242 243
}

ggaren's avatar
ggaren committed
244
void FrameView::applyOverflowToViewport(RenderObject* o, ScrollbarMode& hMode, ScrollbarMode& vMode)
245
{
246
    // Handle the overflow:hidden/scroll case for the body/html elements.  WinIE treats
247
    // overflow:hidden and overflow:scroll on <body> as applying to the document's
248 249
    // 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.
250
    switch (o->style()->overflowX()) {
251
        case OHIDDEN:
ggaren's avatar
ggaren committed
252
            hMode = ScrollbarAlwaysOff;
253 254
            break;
        case OSCROLL:
ggaren's avatar
ggaren committed
255
            hMode = ScrollbarAlwaysOn;
256 257
            break;
        case OAUTO:
ggaren's avatar
ggaren committed
258
            hMode = ScrollbarAuto;
259 260 261 262 263 264 265 266
            break;
        default:
            // Don't set it at all.
            ;
    }
    
     switch (o->style()->overflowY()) {
        case OHIDDEN:
ggaren's avatar
ggaren committed
267
            vMode = ScrollbarAlwaysOff;
268 269
            break;
        case OSCROLL:
ggaren's avatar
ggaren committed
270
            vMode = ScrollbarAlwaysOn;
271 272
            break;
        case OAUTO:
ggaren's avatar
ggaren committed
273
            vMode = ScrollbarAuto;
274 275 276 277 278
            break;
        default:
            // Don't set it at all.
            ;
    }
andersca's avatar
andersca committed
279 280

    d->m_viewportRenderer = o;
281 282
}

283
int FrameView::layoutCount() const
284 285 286 287
{
    return d->layoutCount;
}

288
bool FrameView::needsFullRepaint() const
289 290 291 292
{
    return d->doFullRepaint;
}

293
void FrameView::addRepaintInfo(RenderObject* o, const IntRect& r)
294
{
darin's avatar
darin committed
295
    d->repaintRects.append(RenderObject::RepaintInfo(o, r));
296 297
}

mitz@apple.com's avatar
mitz@apple.com committed
298
RenderObject* FrameView::layoutRoot(bool onlyDuringLayout) const
ap's avatar
ap committed
299
{
mitz@apple.com's avatar
mitz@apple.com committed
300
    return onlyDuringLayout && layoutPending() ? 0 : d->layoutRoot;
ap's avatar
ap committed
301 302
}

adele's avatar
adele committed
303
void FrameView::layout(bool allowSubtree)
kocienda's avatar
kocienda committed
304
{
bdakin's avatar
bdakin committed
305 306 307
    if (d->midLayout)
        return;

darin's avatar
darin committed
308
    d->layoutTimer.stop();
309
    d->delayedLayout = false;
310

adele's avatar
adele committed
311 312 313
    // Protect the view from being deleted during layout (in recalcStyle)
    RefPtr<FrameView> protector(this);

mjs's avatar
mjs committed
314
    if (!m_frame) {
315 316 317
        // FIXME: Do we need to set m_size.width here?
        // FIXME: Should we set m_size.height here too?
        m_size.setWidth(visibleWidth());
darin's avatar
darin committed
318 319
        return;
    }
antti's avatar
antti committed
320 321 322 323 324
    
    // we shouldn't enter layout() while painting
    ASSERT(!m_frame->isPainting());
    if (m_frame->isPainting())
        return;
darin's avatar
darin committed
325

adele's avatar
adele committed
326
    if (!allowSubtree && d->layoutRoot) {
mitz@apple.com's avatar
mitz@apple.com committed
327
        d->layoutRoot->markContainingBlocksForLayout(false);
adele's avatar
adele committed
328 329 330
        d->layoutRoot = 0;
    }

331 332
    ASSERT(m_frame->view() == this);

darin's avatar
darin committed
333
    Document* document = m_frame->document();
334
    if (!document) {
335 336
        // FIXME: Should we set m_size.height here too?
        m_size.setWidth(visibleWidth());
337 338
        return;
    }
kocienda's avatar
kocienda committed
339

justing's avatar
justing committed
340 341
    d->layoutSchedulingEnabled = false;

mitz@apple.com's avatar
mitz@apple.com committed
342 343 344 345 346 347 348
    if (!d->nestedLayoutCount && d->postLayoutTasksTimer.isActive()) {
        // This is a new top-level layout. If there are any remaining tasks from the previous
        // layout, finish them now.
        d->postLayoutTasksTimer.stop();
        performPostLayoutTasks();
    }

349 350
    // Always ensure our style info is up-to-date.  This can happen in situations where
    // the layout beats any sort of style recalc update that needs to occur.
351 352 353
    if (m_frame->needsReapplyStyles())
        m_frame->reapplyStyles();
    else if (document->hasChangedChild())
354
        document->recalcStyle();
adele's avatar
adele committed
355
    
ddkilzer's avatar
ddkilzer committed
356 357
    bool subtree = d->layoutRoot;

adele's avatar
adele committed
358
    // If there is only one ref to this view left, then its going to be destroyed as soon as we exit, 
mitz@apple.com's avatar
mitz@apple.com committed
359
    // so there's no point to continuing to layout
adele's avatar
adele committed
360 361
    if (protector->hasOneRef())
        return;
362

mitz@apple.com's avatar
mitz@apple.com committed
363
    RenderObject* root = subtree ? d->layoutRoot : document->renderer();
darin's avatar
darin committed
364
    if (!root) {
365
        // FIXME: Do we need to set m_size here?
justing's avatar
justing committed
366
        d->layoutSchedulingEnabled = true;
367
        return;
darin's avatar
darin committed
368
    }
kocienda's avatar
kocienda committed
369

bdakin's avatar
bdakin committed
370 371
    d->nestedLayoutCount++;

ggaren's avatar
ggaren committed
372 373
    ScrollbarMode hMode = d->hmode;
    ScrollbarMode vMode = d->vmode;
mitz@apple.com's avatar
mitz@apple.com committed
374

adele's avatar
adele committed
375 376 377
    if (!subtree) {
        RenderObject* rootRenderer = document->documentElement() ? document->documentElement()->renderer() : 0;
        if (document->isHTMLDocument()) {
darin's avatar
darin committed
378
            Node* body = static_cast<HTMLDocument*>(document)->body();
adele's avatar
adele committed
379 380
            if (body && body->renderer()) {
                if (body->hasTagName(framesetTag)) {
weinig's avatar
weinig committed
381
                    body->renderer()->setChildNeedsLayout(true);
ggaren's avatar
ggaren committed
382 383
                    vMode = ScrollbarAlwaysOff;
                    hMode = ScrollbarAlwaysOff;
adele's avatar
adele committed
384
                } else if (body->hasTagName(bodyTag)) {
darin's avatar
darin committed
385 386
                    if (!d->firstLayout && m_size.height() != visibleHeight()
                            && static_cast<RenderBox*>(body->renderer())->stretchesToViewHeight())
ddkilzer's avatar
ddkilzer committed
387
                        body->renderer()->setChildNeedsLayout(true);
darin's avatar
darin committed
388 389 390 391
                    // 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 
                        ? body->renderer() : rootRenderer;
adele's avatar
adele committed
392 393
                    applyOverflowToViewport(o, hMode, vMode); // Only applies to HTML UAs, not to XML/XHTML UAs
                }
394
            }
adele's avatar
adele committed
395 396
        } else if (rootRenderer)
            applyOverflowToViewport(rootRenderer, hMode, vMode); // XML/XHTML UAs use the root element.
weinig's avatar
weinig committed
397
#ifdef INSTRUMENT_LAYOUT_SCHEDULING
adele's avatar
adele committed
398 399
        if (d->firstLayout && !document->ownerElement())
            printf("Elapsed time before first layout: %d\n", document->elapsedTime());
hyatt's avatar
hyatt committed
400
#endif
adele's avatar
adele committed
401
    }
hyatt's avatar
hyatt committed
402

403
    d->doFullRepaint = !subtree && (d->firstLayout || static_cast<RenderView*>(root)->printing());
mitz@apple.com's avatar
mitz@apple.com committed
404
    ASSERT(d->nestedLayoutCount > 1 || d->repaintRects.isEmpty());
405

cblu's avatar
cblu committed
406
    bool didFirstLayout = false;
adele's avatar
adele committed
407 408
    if (!subtree) {
        // Now set our scrollbar state for the layout.
ggaren's avatar
ggaren committed
409 410
        ScrollbarMode currentHMode = hScrollbarMode();
        ScrollbarMode currentVMode = vScrollbarMode();
adele's avatar
adele committed
411 412

        if (d->firstLayout || (hMode != currentHMode || vMode != currentVMode)) {
ggaren's avatar
ggaren committed
413
            suppressScrollbars(true);
adele's avatar
adele committed
414 415 416
            if (d->firstLayout) {
                d->firstLayout = false;
                didFirstLayout = true;
mitz@apple.com's avatar
mitz@apple.com committed
417
                d->lastLayoutSize = IntSize(width(), height());
adele's avatar
adele committed
418 419
                
                // Set the initial vMode to AlwaysOn if we're auto.
ggaren's avatar
ggaren committed
420 421
                if (vMode == ScrollbarAuto)
                    ScrollView::setVScrollbarMode(ScrollbarAlwaysOn); // This causes a vertical scrollbar to appear.
adele's avatar
adele committed
422
                // Set the initial hMode to AlwaysOff if we're auto.
ggaren's avatar
ggaren committed
423 424
                if (hMode == ScrollbarAuto)
                    ScrollView::setHScrollbarMode(ScrollbarAlwaysOff); // This causes a horizontal scrollbar to disappear.
adele's avatar
adele committed
425
            }
426
            
adele's avatar
adele committed
427
            if (hMode == vMode)
ggaren's avatar
ggaren committed
428
                ScrollView::setScrollbarsMode(hMode);
adele's avatar
adele committed
429
            else {
ggaren's avatar
ggaren committed
430 431
                ScrollView::setHScrollbarMode(hMode);
                ScrollView::setVScrollbarMode(vMode);
adele's avatar
adele committed
432
            }
433

ggaren's avatar
ggaren committed
434
            suppressScrollbars(false, true);
adele's avatar
adele committed
435
        }
436

adele's avatar
adele committed
437
        IntSize oldSize = m_size;
438

adele's avatar
adele committed
439
        m_size = IntSize(visibleWidth(), visibleHeight());
440

adele's avatar
adele committed
441 442 443
        if (oldSize != m_size)
            d->doFullRepaint = true;
    }
444
    
adele's avatar
adele committed
445
    RenderLayer* layer = root->enclosingLayer();
mitz@apple.com's avatar
mitz@apple.com committed
446 447 448

    if (!d->postLayoutTasksTimer.isActive())
        pauseScheduledEvents();
weinig's avatar
weinig committed
449 450 451

    if (subtree)
        root->view()->pushLayoutState(root);
bdakin's avatar
bdakin committed
452
    d->midLayout = true;
453
    root->layout();
bdakin's avatar
bdakin committed
454
    d->midLayout = false;
weinig's avatar
weinig committed
455 456
    if (subtree)
        root->view()->popLayoutState();
adele's avatar
adele committed
457
    d->layoutRoot = 0;
458

mjs's avatar
mjs committed
459
    m_frame->invalidateSelection();
460
   
mitz@apple.com's avatar
mitz@apple.com committed
461
    d->layoutSchedulingEnabled = true;
462

463
    if (!subtree && !static_cast<RenderView*>(root)->printing())
464
        adjustViewSize();
465 466

    // Now update the positions of all layers.
467
    layer->updateLayerPositions(d->doFullRepaint);
468

darin's avatar
darin committed
469 470 471 472 473 474
    // FIXME: Could optimize this and have objects removed from this list
    // if they ever do full repaints.
    Vector<RenderObject::RepaintInfo>::iterator end = d->repaintRects.end();
    for (Vector<RenderObject::RepaintInfo>::iterator it = d->repaintRects.begin(); it != end; ++it)
        it->m_object->repaintRectangle(it->m_repaintRect);
    d->repaintRects.clear();
475
    
476
    d->layoutCount++;
darin's avatar
darin committed
477

darin's avatar
darin committed
478
#if PLATFORM(MAC)
479
    if (AXObjectCache::accessibilityEnabled())
harrison's avatar
harrison committed
480
        root->document()->axObjectCache()->postNotificationToElement(root, "AXLayoutComplete");
481
#endif
aroben's avatar
aroben committed
482
    updateDashboardRegions();
rjw's avatar
rjw committed
483

484
    if (didFirstLayout)
darin's avatar
darin committed
485
        m_frame->loader()->didFirstLayout();
486
    
weinig's avatar
weinig committed
487 488
    ASSERT(!root->needsLayout());

489
    setStaticBackground(useSlowRepaints());
cblu's avatar
cblu committed
490

491 492 493
    if (document->hasListenerType(Document::OVERFLOWCHANGED_LISTENER))
        updateOverflowStatus(visibleWidth() < contentsWidth(),
                             visibleHeight() < contentsHeight());
andersca's avatar
andersca committed
494

mitz@apple.com's avatar
mitz@apple.com committed
495 496 497 498 499 500 501 502 503 504 505
    if (!d->postLayoutTasksTimer.isActive()) {
        // Calls resumeScheduledEvents()
        performPostLayoutTasks();

        if (needsLayout()) {
            // Post-layout widget updates or an event handler made us need layout again.
            // Lay out again, but this time defer widget updates and event dispatch until after
            // we return.
            d->postLayoutTasksTimer.startOneShot(0);
            pauseScheduledEvents();
            layout();
bdakin's avatar
bdakin committed
506
        }
bdakin's avatar
bdakin committed
507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525
    }

    d->nestedLayoutCount--;
}

void FrameView::addWidgetToUpdate(RenderPartObject* object)
{
    if (!m_widgetUpdateSet)
        m_widgetUpdateSet.set(new HashSet<RenderPartObject*>);

    m_widgetUpdateSet->add(object);
}

void FrameView::removeWidgetToUpdate(RenderPartObject* object)
{
    if (!m_widgetUpdateSet)
        return;

    m_widgetUpdateSet->remove(object);
kocienda's avatar
kocienda committed
526 527 528 529 530 531 532
}

//
// Event Handling
//
/////////////////

533
bool FrameView::scrollTo(const IntRect& bounds)
kocienda's avatar
kocienda committed
534 535
{
    int x, y, xe, ye;
darin's avatar
darin committed
536 537 538 539
    x = bounds.x();
    y = bounds.y();
    xe = bounds.right() - 1;
    ye = bounds.bottom() - 1;
eseidel's avatar
eseidel committed
540
    
kocienda's avatar
kocienda committed
541 542 543 544 545 546
    int deltax;
    int deltay;

    int curHeight = visibleHeight();
    int curWidth = visibleWidth();

darin's avatar
darin committed
547 548
    if (ye - y>curHeight-d->borderY)
        ye = y + curHeight - d->borderY;
kocienda's avatar
kocienda committed
549

darin's avatar
darin committed
550
    if (xe - x>curWidth-d->borderX)
551
        xe = x + curWidth - d->borderX;
kocienda's avatar
kocienda committed
552 553

    // is xpos of target left of the view's border?
554
    if (x < contentsX() + d->borderX)
darin's avatar
darin committed
555
        deltax = x - contentsX() - d->borderX;
kocienda's avatar
kocienda committed
556 557
    // is xpos of target right of the view's right border?
    else if (xe + d->borderX > contentsX() + curWidth)
558
        deltax = xe + d->borderX - (contentsX() + curWidth);
kocienda's avatar
kocienda committed
559 560 561 562 563
    else
        deltax = 0;

    // is ypos of target above upper border?
    if (y < contentsY() + d->borderY)
darin's avatar
darin committed
564
        deltay = y - contentsY() - d->borderY;
kocienda's avatar
kocienda committed
565 566
    // is ypos of target below lower border?
    else if (ye + d->borderY > contentsY() + curHeight)
567
        deltay = ye + d->borderY - (contentsY() + curHeight);
kocienda's avatar
kocienda committed
568 569 570
    else
        deltay = 0;

darin's avatar
darin committed
571 572
    int maxx = curWidth - d->borderX;
    int maxy = curHeight - d->borderY;
kocienda's avatar
kocienda committed
573

darin's avatar
darin committed
574 575
    int scrollX = deltax > 0 ? (deltax > maxx ? maxx : deltax) : deltax == 0 ? 0 : (deltax > -maxx ? deltax : -maxx);
    int scrollY = deltay > 0 ? (deltay > maxy ? maxy : deltay) : deltay == 0 ? 0 : (deltay > -maxy ? deltay : -maxy);
kocienda's avatar
kocienda committed
576 577

    if (contentsX() + scrollX < 0)
578
        scrollX = -contentsX();
kocienda's avatar
kocienda committed
579
    else if (contentsWidth() - visibleWidth() - contentsX() < scrollX)
580
        scrollX = contentsWidth() - visibleWidth() - contentsX();
kocienda's avatar
kocienda committed
581 582

    if (contentsY() + scrollY < 0)
583
        scrollY = -contentsY();
kocienda's avatar
kocienda committed
584
    else if (contentsHeight() - visibleHeight() - contentsY() < scrollY)
585
        scrollY = contentsHeight() - visibleHeight() - contentsY();
kocienda's avatar
kocienda committed
586 587 588 589

    scrollBy(scrollX, scrollY);

    // generate abs(scroll.)
darin's avatar
darin committed
590 591 592 593
    if (scrollX < 0)
        scrollX = -scrollX;
    if (scrollY < 0)
        scrollY = -scrollY;
kocienda's avatar
kocienda committed
594

darin's avatar
darin committed
595
    return scrollX != maxx && scrollY != maxy;
kocienda's avatar
kocienda committed
596 597
}

598
void FrameView::setMediaType(const String& mediaType)
599
{
600
    d->m_mediaType = mediaType;
601
}
kocienda's avatar
kocienda committed
602

603
String FrameView::mediaType() const
604
{
rjw's avatar
rjw committed
605
    // See if we have an override type.
lars's avatar
lars committed
606
    String overrideType = m_frame->loader()->client()->overrideMediaType();
rjw's avatar
rjw committed
607 608
    if (!overrideType.isNull())
        return overrideType;
609
    return d->m_mediaType;
610
}
kocienda's avatar
kocienda committed
611

612 613
bool FrameView::useSlowRepaints() const
{
614
    return d->useSlowRepaints || d->m_slowRepaintObjectCount > 0;
615 616 617
}

void FrameView::setUseSlowRepaints()
kocienda's avatar
kocienda committed
618 619 620 621 622
{
    d->useSlowRepaints = true;
    setStaticBackground(true);
}

623 624
void FrameView::addSlowRepaintObject()
{
625
    if (!d->m_slowRepaintObjectCount)
626
        setStaticBackground(true);
627
    d->m_slowRepaintObjectCount++;
628 629 630 631
}

void FrameView::removeSlowRepaintObject()
{
632 633 634
    ASSERT(d->m_slowRepaintObjectCount > 0);
    d->m_slowRepaintObjectCount--;
    if (!d->m_slowRepaintObjectCount)
635 636 637
        setStaticBackground(d->useSlowRepaints);
}

ggaren's avatar
ggaren committed
638
void FrameView::setScrollbarsMode(ScrollbarMode mode)
639 640 641 642
{
    d->vmode = mode;
    d->hmode = mode;
    
ggaren's avatar
ggaren committed
643
    ScrollView::setScrollbarsMode(mode);
644
}
kocienda's avatar
kocienda committed
645

ggaren's avatar
ggaren committed
646
void FrameView::setVScrollbarMode(ScrollbarMode mode)
kocienda's avatar
kocienda committed
647 648
{
    d->vmode = mode;
ggaren's avatar
ggaren committed
649
    ScrollView::setVScrollbarMode(mode);
kocienda's avatar
kocienda committed
650 651
}

ggaren's avatar
ggaren committed
652
void FrameView::setHScrollbarMode(ScrollbarMode mode)
kocienda's avatar
kocienda committed
653 654
{
    d->hmode = mode;
ggaren's avatar
ggaren committed
655
    ScrollView::setHScrollbarMode(mode);
kocienda's avatar
kocienda committed
656 657
}

ggaren's avatar
ggaren committed
658
void FrameView::restoreScrollbar()
kocienda's avatar
kocienda committed
659
{
ggaren's avatar
ggaren committed
660
    suppressScrollbars(false);
kocienda's avatar
kocienda committed
661 662
}

mjs's avatar
mjs committed
663
void FrameView::scrollRectIntoViewRecursively(const IntRect& r)
tomernic's avatar
tomernic committed
664 665 666
{
    if (frame()->prohibitsScrolling())
        return;
darin's avatar
darin committed
667 668
    bool wasInProgrammaticScroll = d->m_inProgrammaticScroll;
    d->m_inProgrammaticScroll = true;
mjs's avatar
mjs committed
669
    ScrollView::scrollRectIntoViewRecursively(r);
darin's avatar
darin committed
670
    d->m_inProgrammaticScroll = wasInProgrammaticScroll;
tomernic's avatar
tomernic committed
671 672 673 674 675 676
}

void FrameView::setContentsPos(int x, int y)
{
    if (frame()->prohibitsScrolling())
        return;
darin's avatar
darin committed
677 678
    bool wasInProgrammaticScroll = d->m_inProgrammaticScroll;
    d->m_inProgrammaticScroll = true;
tomernic's avatar
tomernic committed
679
    ScrollView::setContentsPos(x, y);
darin's avatar
darin committed
680
    d->m_inProgrammaticScroll = wasInProgrammaticScroll;
tomernic's avatar
tomernic committed
681 682
}

683
void FrameView::repaintRectangle(const IntRect& r, bool immediate)
684 685 686 687
{
    updateContents(r, immediate);
}

darin's avatar
darin committed
688
void FrameView::layoutTimerFired(Timer<FrameView>*)
689
{
weinig's avatar
weinig committed
690
#ifdef INSTRUMENT_LAYOUT_SCHEDULING
darin's avatar
darin committed
691 692
    if (m_frame->document() && !m_frame->document()->ownerElement())
        printf("Layout timer fired at %d\n", m_frame->document()->elapsedTime());
693
#endif
darin's avatar
darin committed
694
    layout();
695 696
}

697
void FrameView::scheduleRelayout()
698
{
699 700
    ASSERT(m_frame->view() == this);

adele's avatar
adele committed
701
    if (d->layoutRoot) {
mitz@apple.com's avatar
mitz@apple.com committed
702
        d->layoutRoot->markContainingBlocksForLayout(false);
adele's avatar
adele committed
703 704
        d->layoutRoot = 0;
    }
705 706
    if (!d->layoutSchedulingEnabled)
        return;
707

708
    if (!m_frame->document() || !m_frame->document()->shouldScheduleLayout())
709 710
        return;

711
    int delay = m_frame->document()->minimumLayoutDelay();
darin's avatar
darin committed
712
    if (d->layoutTimer.isActive() && d->delayedLayout && !delay)
713
        unscheduleRelayout();
darin's avatar
darin committed
714
    if (d->layoutTimer.isActive())
715 716 717
        return;

    d->delayedLayout = delay != 0;
hyatt's avatar
hyatt committed
718

weinig's avatar
weinig committed
719
#ifdef INSTRUMENT_LAYOUT_SCHEDULING
720
    if (!m_frame->document()->ownerElement())
721
        printf("Scheduling layout for %d\n", delay);
hyatt's avatar
hyatt committed
722 723
#endif

darin's avatar
darin committed
724
    d->layoutTimer.startOneShot(delay * 0.001);
725 726
}

mitz@apple.com's avatar
mitz@apple.com committed
727 728 729 730 731 732 733 734 735 736
static bool isObjectAncestorContainerOf(RenderObject* ancestor, RenderObject* descendant)
{
    for (RenderObject* r = descendant; r; r = r->container()) {
        if (r == ancestor)
            return true;
    }
    return false;
}

void FrameView::scheduleRelayoutOfSubtree(RenderObject* o)
adele's avatar
adele committed
737
{
738 739
    ASSERT(m_frame->view() == this);

darin's avatar
darin committed
740 741 742
    if (!d->layoutSchedulingEnabled || (m_frame->document()
            && m_frame->document()->renderer()
            && m_frame->document()->renderer()->needsLayout())) {
mitz@apple.com's avatar
mitz@apple.com committed
743 744
        if (o)
            o->markContainingBlocksForLayout(false);
adele's avatar
adele committed
745 746 747 748
        return;
    }

    if (layoutPending()) {
mitz@apple.com's avatar
mitz@apple.com committed
749 750
        if (d->layoutRoot != o) {
            if (isObjectAncestorContainerOf(d->layoutRoot, o)) {
mitz's avatar
mitz committed
751
                // Keep the current root
mitz@apple.com's avatar
mitz@apple.com committed
752
                o->markContainingBlocksForLayout(false, d->layoutRoot);
mitz@apple.com's avatar
mitz@apple.com committed
753 754
            } else if (d->layoutRoot && isObjectAncestorContainerOf(o, d->layoutRoot)) {
                // Re-root at o
mitz@apple.com's avatar
mitz@apple.com committed
755
                d->layoutRoot->markContainingBlocksForLayout(false, o);
mitz@apple.com's avatar
mitz@apple.com committed
756
                d->layoutRoot = o;
mitz's avatar
mitz committed
757 758
            } else {
                // Just do a full relayout
mitz@apple.com's avatar
mitz@apple.com committed
759 760
                if (d->layoutRoot)
                    d->layoutRoot->markContainingBlocksForLayout(false);
mitz's avatar
mitz committed
761
                d->layoutRoot = 0;
mitz@apple.com's avatar
mitz@apple.com committed
762
                o->markContainingBlocksForLayout(false);
mitz's avatar
mitz committed
763
            }