FrameView.cpp 27.7 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 22 23 24
 *
 * 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
 * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 */
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"
darin's avatar
darin committed
41
#include "RenderTheme.h"
weinig's avatar
 
weinig committed
42
#include "RenderView.h"
rwlbuis's avatar
rwlbuis committed
43

darin's avatar
darin committed
44 45
namespace WebCore {

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

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

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

darin's avatar
darin committed
89
    bool doFullRepaint;
90
    
ggaren's avatar
ggaren committed
91 92
    ScrollbarMode vmode;
    ScrollbarMode hmode;
kocienda's avatar
kocienda committed
93
    bool useSlowRepaints;
94
    unsigned m_slowRepaintObjectCount;
kocienda's avatar
kocienda committed
95 96 97

    int borderX, borderY;

darin's avatar
darin committed
98
    Timer<FrameView> layoutTimer;
99
    bool delayedLayout;
adele's avatar
adele committed
100
    RefPtr<Node> layoutRoot;
hyatt's avatar
hyatt committed
101
    
102
    bool layoutSchedulingEnabled;
bdakin's avatar
bdakin committed
103
    bool midLayout;
104 105
    int layoutCount;

106
    bool firstLayout;
ggaren's avatar
ggaren committed
107
    bool needToInitScrollbars;
darin's avatar
darin committed
108
    bool isTransparent;
thatcher's avatar
thatcher committed
109 110
    Color baseBackgroundColor;

111 112
    // 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
113
    Vector<RenderObject::RepaintInfo> repaintRects;
114 115
    
    String m_mediaType;
andersca's avatar
andersca committed
116
    
aroben's avatar
aroben committed
117
    unsigned m_enqueueEvents;
darin's avatar
darin committed
118
    Vector<ScheduledEvent*> m_scheduledEvents;
andersca's avatar
andersca committed
119 120 121 122 123
    
    bool m_overflowStatusDirty;
    bool horizontalOverflow;
    bool m_verticalOverflow;    
    RenderObject* m_viewportRenderer;
darin's avatar
darin committed
124 125 126

    bool m_wasScrolledByUser;
    bool m_inProgrammaticScroll;
kocienda's avatar
kocienda committed
127 128
};

darin's avatar
darin committed
129
FrameView::FrameView(Frame* frame)
130
    : m_refCount(1)
darin's avatar
darin committed
131 132
    , m_frame(frame)
    , d(new FrameViewPrivate(this))
kocienda's avatar
kocienda committed
133 134
{
    init();
darin's avatar
darin committed
135
    show();
kocienda's avatar
kocienda committed
136 137
}

138
FrameView::~FrameView()
kocienda's avatar
kocienda committed
139
{
ggaren's avatar
ggaren committed
140
    resetScrollbars();
141

142
    ASSERT(m_refCount == 0);
143
    ASSERT(d->m_scheduledEvents.isEmpty() && !d->m_enqueueEvents);
mjs's avatar
mjs committed
144

darin's avatar
darin committed
145
    if (m_frame) {
146 147 148
        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
149
            renderer->setWidget(0);
150
    }
151

darin's avatar
darin committed
152 153
    delete d;
    d = 0;
kocienda's avatar
kocienda committed
154 155
}

ggaren's avatar
ggaren committed
156 157 158 159 160
bool FrameView::isFrameView() const 
{ 
    return true; 
}

darin's avatar
darin committed
161
void FrameView::clearFrame()
rjw's avatar
rjw committed
162
{
darin's avatar
darin committed
163
    m_frame = 0;
rjw's avatar
rjw committed
164 165
}

ggaren's avatar
ggaren committed
166
void FrameView::resetScrollbars()
167 168
{
    // Reset the document's scrollbars back to our defaults before we yield the floor.
169
    d->firstLayout = true;
ggaren's avatar
ggaren committed
170 171 172 173
    suppressScrollbars(true);
    ScrollView::setVScrollbarMode(d->vmode);
    ScrollView::setHScrollbarMode(d->hmode);
    suppressScrollbars(false);
174 175
}

176
void FrameView::init()
kocienda's avatar
kocienda committed
177
{
178 179
    m_margins = IntSize(-1, -1); // undefined
    m_size = IntSize();
kocienda's avatar
kocienda committed
180 181
}

182
void FrameView::clear()
kocienda's avatar
kocienda committed
183
{
184
    setStaticBackground(false);
kocienda's avatar
kocienda committed
185
    
kocienda's avatar
kocienda committed
186
    d->reset();
187

darin's avatar
darin committed
188 189 190
    if (m_frame)
        if (RenderPart* renderer = m_frame->ownerRenderer())
            renderer->viewCleared();
kocienda's avatar
kocienda committed
191

ggaren's avatar
ggaren committed
192
    suppressScrollbars(true);
kocienda's avatar
kocienda committed
193 194
}

195 196 197 198 199
bool FrameView::didFirstLayout() const
{
    return !d->firstLayout;
}

ggaren's avatar
ggaren committed
200
void FrameView::initScrollbars()
201
{
ggaren's avatar
ggaren committed
202
    if (!d->needToInitScrollbars)
203
        return;
ggaren's avatar
ggaren committed
204 205
    d->needToInitScrollbars = false;
    setScrollbarsMode(hScrollbarMode());
206
}
207

208
void FrameView::setMarginWidth(int w)
209 210
{
    // make it update the rendering area when set
211
    m_margins.setWidth(w);
212 213
}

214
void FrameView::setMarginHeight(int h)
215 216
{
    // make it update the rendering area when set
217
    m_margins.setHeight(h);
kocienda's avatar
kocienda committed
218 219
}

220
void FrameView::adjustViewSize()
rjw's avatar
WebKit:  
rjw committed
221
{
222
    ASSERT(m_frame->view() == this);
223 224 225 226
    RenderView* root = static_cast<RenderView*>(m_frame->renderer());
    if (!root)
        return;
    resizeContents(root->overflowWidth(), root->overflowHeight());
rjw's avatar
WebKit:  
rjw committed
227 228
}

ggaren's avatar
ggaren committed
229
void FrameView::applyOverflowToViewport(RenderObject* o, ScrollbarMode& hMode, ScrollbarMode& vMode)
230
{
231
    // Handle the overflow:hidden/scroll case for the body/html elements.  WinIE treats
232
    // overflow:hidden and overflow:scroll on <body> as applying to the document's
233 234
    // 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.
235
    switch (o->style()->overflowX()) {
236
        case OHIDDEN:
ggaren's avatar
ggaren committed
237
            hMode = ScrollbarAlwaysOff;
238 239
            break;
        case OSCROLL:
ggaren's avatar
ggaren committed
240
            hMode = ScrollbarAlwaysOn;
241 242
            break;
        case OAUTO:
ggaren's avatar
ggaren committed
243
            hMode = ScrollbarAuto;
244 245 246 247 248 249 250 251
            break;
        default:
            // Don't set it at all.
            ;
    }
    
     switch (o->style()->overflowY()) {
        case OHIDDEN:
ggaren's avatar
ggaren committed
252
            vMode = ScrollbarAlwaysOff;
253 254
            break;
        case OSCROLL:
ggaren's avatar
ggaren committed
255
            vMode = ScrollbarAlwaysOn;
256 257
            break;
        case OAUTO:
ggaren's avatar
ggaren committed
258
            vMode = ScrollbarAuto;
259 260 261 262 263
            break;
        default:
            // Don't set it at all.
            ;
    }
andersca's avatar
andersca committed
264 265

    d->m_viewportRenderer = o;
266 267
}

268
int FrameView::layoutCount() const
269 270 271 272
{
    return d->layoutCount;
}

273
bool FrameView::needsFullRepaint() const
274 275 276 277
{
    return d->doFullRepaint;
}

278
void FrameView::addRepaintInfo(RenderObject* o, const IntRect& r)
279
{
darin's avatar
darin committed
280
    d->repaintRects.append(RenderObject::RepaintInfo(o, r));
281 282
}

ap's avatar
ap committed
283 284 285 286 287
Node* FrameView::layoutRoot() const
{
    return layoutPending() ? 0 : d->layoutRoot.get();
}

adele's avatar
adele committed
288
void FrameView::layout(bool allowSubtree)
kocienda's avatar
kocienda committed
289
{
bdakin's avatar
bdakin committed
290 291 292
    if (d->midLayout)
        return;

darin's avatar
darin committed
293
    d->layoutTimer.stop();
294
    d->delayedLayout = false;
295

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

mjs's avatar
mjs committed
299
    if (!m_frame) {
300 301 302
        // 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
303 304
        return;
    }
antti's avatar
antti committed
305 306 307 308 309
    
    // we shouldn't enter layout() while painting
    ASSERT(!m_frame->isPainting());
    if (m_frame->isPainting())
        return;
darin's avatar
darin committed
310

adele's avatar
adele committed
311 312 313 314 315 316
    if (!allowSubtree && d->layoutRoot) {
        if (d->layoutRoot->renderer())
            d->layoutRoot->renderer()->markContainingBlocksForLayout(false);
        d->layoutRoot = 0;
    }

317 318 319

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

darin's avatar
darin committed
320
    Document* document = m_frame->document();
321
    if (!document) {
322 323
        // FIXME: Should we set m_size.height here too?
        m_size.setWidth(visibleWidth());
324 325
        return;
    }
kocienda's avatar
kocienda committed
326

justing's avatar
justing committed
327 328
    d->layoutSchedulingEnabled = false;

329 330 331 332
    // 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.
    if (document->hasChangedChild())
        document->recalcStyle();
adele's avatar
adele committed
333
    
ddkilzer's avatar
ddkilzer committed
334 335 336
    bool subtree = d->layoutRoot;
    Node* rootNode = subtree ? d->layoutRoot.get() : document;

adele's avatar
adele committed
337 338 339 340
    // If there is only one ref to this view left, then its going to be destroyed as soon as we exit, 
    // so there's no point to continuiing to layout
    if (protector->hasOneRef())
        return;
341

adele's avatar
adele committed
342
    RenderObject* root = rootNode->renderer();
darin's avatar
darin committed
343
    if (!root) {
344
        // FIXME: Do we need to set m_size here?
justing's avatar
justing committed
345
        d->layoutSchedulingEnabled = true;
346
        return;
darin's avatar
darin committed
347
    }
kocienda's avatar
kocienda committed
348

ggaren's avatar
ggaren committed
349 350
    ScrollbarMode hMode = d->hmode;
    ScrollbarMode vMode = d->vmode;
351
    
adele's avatar
adele committed
352 353 354 355
    if (!subtree) {
        Document* document = static_cast<Document*>(rootNode);
        RenderObject* rootRenderer = document->documentElement() ? document->documentElement()->renderer() : 0;
        if (document->isHTMLDocument()) {
darin's avatar
darin committed
356
            Node* body = static_cast<HTMLDocument*>(document)->body();
adele's avatar
adele committed
357 358
            if (body && body->renderer()) {
                if (body->hasTagName(framesetTag)) {
weinig's avatar
weinig committed
359
                    body->renderer()->setChildNeedsLayout(true);
ggaren's avatar
ggaren committed
360 361
                    vMode = ScrollbarAlwaysOff;
                    hMode = ScrollbarAlwaysOff;
adele's avatar
adele committed
362
                } else if (body->hasTagName(bodyTag)) {
darin's avatar
darin committed
363 364
                    if (!d->firstLayout && m_size.height() != visibleHeight()
                            && static_cast<RenderBox*>(body->renderer())->stretchesToViewHeight())
ddkilzer's avatar
ddkilzer committed
365
                        body->renderer()->setChildNeedsLayout(true);
darin's avatar
darin committed
366 367 368 369
                    // 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
370 371
                    applyOverflowToViewport(o, hMode, vMode); // Only applies to HTML UAs, not to XML/XHTML UAs
                }
372
            }
adele's avatar
adele committed
373 374
        } else if (rootRenderer)
            applyOverflowToViewport(rootRenderer, hMode, vMode); // XML/XHTML UAs use the root element.
weinig's avatar
weinig committed
375
#ifdef INSTRUMENT_LAYOUT_SCHEDULING
adele's avatar
adele committed
376 377
        if (d->firstLayout && !document->ownerElement())
            printf("Elapsed time before first layout: %d\n", document->elapsedTime());
hyatt's avatar
hyatt committed
378
#endif
adele's avatar
adele committed
379
    }
hyatt's avatar
hyatt committed
380

381
    d->doFullRepaint = !subtree && (d->firstLayout || static_cast<RenderView*>(root)->printing());
darin's avatar
darin committed
382
    d->repaintRects.clear();
383

cblu's avatar
cblu committed
384
    bool didFirstLayout = false;
adele's avatar
adele committed
385 386
    if (!subtree) {
        // Now set our scrollbar state for the layout.
ggaren's avatar
ggaren committed
387 388
        ScrollbarMode currentHMode = hScrollbarMode();
        ScrollbarMode currentVMode = vScrollbarMode();
adele's avatar
adele committed
389 390

        if (d->firstLayout || (hMode != currentHMode || vMode != currentVMode)) {
ggaren's avatar
ggaren committed
391
            suppressScrollbars(true);
adele's avatar
adele committed
392 393 394 395 396
            if (d->firstLayout) {
                d->firstLayout = false;
                didFirstLayout = true;
                
                // Set the initial vMode to AlwaysOn if we're auto.
ggaren's avatar
ggaren committed
397 398
                if (vMode == ScrollbarAuto)
                    ScrollView::setVScrollbarMode(ScrollbarAlwaysOn); // This causes a vertical scrollbar to appear.
adele's avatar
adele committed
399
                // Set the initial hMode to AlwaysOff if we're auto.
ggaren's avatar
ggaren committed
400 401
                if (hMode == ScrollbarAuto)
                    ScrollView::setHScrollbarMode(ScrollbarAlwaysOff); // This causes a horizontal scrollbar to disappear.
adele's avatar
adele committed
402
            }
403
            
adele's avatar
adele committed
404
            if (hMode == vMode)
ggaren's avatar
ggaren committed
405
                ScrollView::setScrollbarsMode(hMode);
adele's avatar
adele committed
406
            else {
ggaren's avatar
ggaren committed
407 408
                ScrollView::setHScrollbarMode(hMode);
                ScrollView::setVScrollbarMode(vMode);
adele's avatar
adele committed
409
            }
410

ggaren's avatar
ggaren committed
411
            suppressScrollbars(false, true);
adele's avatar
adele committed
412
        }
413

adele's avatar
adele committed
414
        IntSize oldSize = m_size;
415

adele's avatar
adele committed
416
        m_size = IntSize(visibleWidth(), visibleHeight());
417

adele's avatar
adele committed
418 419 420
        if (oldSize != m_size)
            d->doFullRepaint = true;
    }
421
    
adele's avatar
adele committed
422
    RenderLayer* layer = root->enclosingLayer();
423
     
424
    pauseScheduledEvents();
weinig's avatar
weinig committed
425 426 427

    if (subtree)
        root->view()->pushLayoutState(root);
bdakin's avatar
bdakin committed
428
    d->midLayout = true;
429
    root->layout();
bdakin's avatar
bdakin committed
430
    d->midLayout = false;
weinig's avatar
weinig committed
431 432
    if (subtree)
        root->view()->popLayoutState();
adele's avatar
adele committed
433
    d->layoutRoot = 0;
434

mjs's avatar
mjs committed
435
    m_frame->invalidateSelection();
436
   
437 438
    d->layoutSchedulingEnabled=true;

439
    if (!subtree && !static_cast<RenderView*>(root)->printing())
440
        adjustViewSize();
441 442

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

445
    // We update our widget positions right after doing a layout.
weinig's avatar
weinig committed
446
    if (!subtree)
adele's avatar
adele committed
447
        static_cast<RenderView*>(root)->updateWidgetPositions();
448
    
darin's avatar
darin committed
449 450 451 452 453 454
    // 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();
455
    
456
    d->layoutCount++;
darin's avatar
darin committed
457

darin's avatar
darin committed
458
#if PLATFORM(MAC)
459
    if (AXObjectCache::accessibilityEnabled())
harrison's avatar
harrison committed
460
        root->document()->axObjectCache()->postNotificationToElement(root, "AXLayoutComplete");
461
#endif
aroben's avatar
aroben committed
462
    updateDashboardRegions();
rjw's avatar
rjw committed
463

464
    if (didFirstLayout)
darin's avatar
darin committed
465
        m_frame->loader()->didFirstLayout();
466
    
weinig's avatar
weinig committed
467 468
    ASSERT(!root->needsLayout());

469
    setStaticBackground(useSlowRepaints());
cblu's avatar
cblu committed
470

471 472 473
    if (document->hasListenerType(Document::OVERFLOWCHANGED_LISTENER))
        updateOverflowStatus(visibleWidth() < contentsWidth(),
                             visibleHeight() < contentsHeight());
andersca's avatar
andersca committed
474

475 476
    // Allow events scheduled during layout to fire
    resumeScheduledEvents();
kocienda's avatar
kocienda committed
477 478 479 480 481 482 483
}

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

484
bool FrameView::scrollTo(const IntRect& bounds)
kocienda's avatar
kocienda committed
485 486
{
    int x, y, xe, ye;
darin's avatar
darin committed
487 488 489 490
    x = bounds.x();
    y = bounds.y();
    xe = bounds.right() - 1;
    ye = bounds.bottom() - 1;
eseidel's avatar
eseidel committed
491
    
kocienda's avatar
kocienda committed
492 493 494 495 496 497
    int deltax;
    int deltay;

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

darin's avatar
darin committed
498 499
    if (ye - y>curHeight-d->borderY)
        ye = y + curHeight - d->borderY;
kocienda's avatar
kocienda committed
500

darin's avatar
darin committed
501
    if (xe - x>curWidth-d->borderX)
502
        xe = x + curWidth - d->borderX;
kocienda's avatar
kocienda committed
503 504

    // is xpos of target left of the view's border?
505
    if (x < contentsX() + d->borderX)
darin's avatar
darin committed
506
        deltax = x - contentsX() - d->borderX;
kocienda's avatar
kocienda committed
507 508
    // is xpos of target right of the view's right border?
    else if (xe + d->borderX > contentsX() + curWidth)
509
        deltax = xe + d->borderX - (contentsX() + curWidth);
kocienda's avatar
kocienda committed
510 511 512 513 514
    else
        deltax = 0;

    // is ypos of target above upper border?
    if (y < contentsY() + d->borderY)
darin's avatar
darin committed
515
        deltay = y - contentsY() - d->borderY;
kocienda's avatar
kocienda committed
516 517
    // is ypos of target below lower border?
    else if (ye + d->borderY > contentsY() + curHeight)
518
        deltay = ye + d->borderY - (contentsY() + curHeight);
kocienda's avatar
kocienda committed
519 520 521
    else
        deltay = 0;

darin's avatar
darin committed
522 523
    int maxx = curWidth - d->borderX;
    int maxy = curHeight - d->borderY;
kocienda's avatar
kocienda committed
524

darin's avatar
darin committed
525 526
    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
527 528

    if (contentsX() + scrollX < 0)
529
        scrollX = -contentsX();
kocienda's avatar
kocienda committed
530
    else if (contentsWidth() - visibleWidth() - contentsX() < scrollX)
531
        scrollX = contentsWidth() - visibleWidth() - contentsX();
kocienda's avatar
kocienda committed
532 533

    if (contentsY() + scrollY < 0)
534
        scrollY = -contentsY();
kocienda's avatar
kocienda committed
535
    else if (contentsHeight() - visibleHeight() - contentsY() < scrollY)
536
        scrollY = contentsHeight() - visibleHeight() - contentsY();
kocienda's avatar
kocienda committed
537 538 539 540

    scrollBy(scrollX, scrollY);

    // generate abs(scroll.)
darin's avatar
darin committed
541 542 543 544
    if (scrollX < 0)
        scrollX = -scrollX;
    if (scrollY < 0)
        scrollY = -scrollY;
kocienda's avatar
kocienda committed
545

darin's avatar
darin committed
546
    return scrollX != maxx && scrollY != maxy;
kocienda's avatar
kocienda committed
547 548
}

549
void FrameView::setMediaType(const String& mediaType)
550
{
551
    d->m_mediaType = mediaType;
552
}
kocienda's avatar
kocienda committed
553

554
String FrameView::mediaType() const
555
{
rjw's avatar
rjw committed
556
    // See if we have an override type.
lars's avatar
lars committed
557
    String overrideType = m_frame->loader()->client()->overrideMediaType();
rjw's avatar
rjw committed
558 559
    if (!overrideType.isNull())
        return overrideType;
560
    return d->m_mediaType;
561
}
kocienda's avatar
kocienda committed
562

563 564
bool FrameView::useSlowRepaints() const
{
565
    return d->useSlowRepaints || d->m_slowRepaintObjectCount > 0;
566 567 568
}

void FrameView::setUseSlowRepaints()
kocienda's avatar
kocienda committed
569 570 571 572 573
{
    d->useSlowRepaints = true;
    setStaticBackground(true);
}

574 575
void FrameView::addSlowRepaintObject()
{
576
    if (!d->m_slowRepaintObjectCount)
577
        setStaticBackground(true);
578
    d->m_slowRepaintObjectCount++;
579 580 581 582
}

void FrameView::removeSlowRepaintObject()
{
583 584 585
    ASSERT(d->m_slowRepaintObjectCount > 0);
    d->m_slowRepaintObjectCount--;
    if (!d->m_slowRepaintObjectCount)
586 587 588
        setStaticBackground(d->useSlowRepaints);
}

ggaren's avatar
ggaren committed
589
void FrameView::setScrollbarsMode(ScrollbarMode mode)
590 591 592 593
{
    d->vmode = mode;
    d->hmode = mode;
    
ggaren's avatar
ggaren committed
594
    ScrollView::setScrollbarsMode(mode);
595
}
kocienda's avatar
kocienda committed
596

ggaren's avatar
ggaren committed
597
void FrameView::setVScrollbarMode(ScrollbarMode mode)
kocienda's avatar
kocienda committed
598 599
{
    d->vmode = mode;
ggaren's avatar
ggaren committed
600
    ScrollView::setVScrollbarMode(mode);
kocienda's avatar
kocienda committed
601 602
}

ggaren's avatar
ggaren committed
603
void FrameView::setHScrollbarMode(ScrollbarMode mode)
kocienda's avatar
kocienda committed
604 605
{
    d->hmode = mode;
ggaren's avatar
ggaren committed
606
    ScrollView::setHScrollbarMode(mode);
kocienda's avatar
kocienda committed
607 608
}

ggaren's avatar
ggaren committed
609
void FrameView::restoreScrollbar()
kocienda's avatar
kocienda committed
610
{
ggaren's avatar
ggaren committed
611
    suppressScrollbars(false);
kocienda's avatar
kocienda committed
612 613
}

mjs's avatar
mjs committed
614
void FrameView::scrollRectIntoViewRecursively(const IntRect& r)
tomernic's avatar
tomernic committed
615 616 617
{
    if (frame()->prohibitsScrolling())
        return;
darin's avatar
darin committed
618 619
    bool wasInProgrammaticScroll = d->m_inProgrammaticScroll;
    d->m_inProgrammaticScroll = true;
mjs's avatar
mjs committed
620
    ScrollView::scrollRectIntoViewRecursively(r);
darin's avatar
darin committed
621
    d->m_inProgrammaticScroll = wasInProgrammaticScroll;
tomernic's avatar
tomernic committed
622 623 624 625 626 627
}

void FrameView::setContentsPos(int x, int y)
{
    if (frame()->prohibitsScrolling())
        return;
darin's avatar
darin committed
628 629
    bool wasInProgrammaticScroll = d->m_inProgrammaticScroll;
    d->m_inProgrammaticScroll = true;
tomernic's avatar
tomernic committed
630
    ScrollView::setContentsPos(x, y);
darin's avatar
darin committed
631
    d->m_inProgrammaticScroll = wasInProgrammaticScroll;
tomernic's avatar
tomernic committed
632 633
}

634
void FrameView::repaintRectangle(const IntRect& r, bool immediate)
635 636 637 638
{
    updateContents(r, immediate);
}

darin's avatar
darin committed
639
void FrameView::layoutTimerFired(Timer<FrameView>*)
640
{
weinig's avatar
weinig committed
641
#ifdef INSTRUMENT_LAYOUT_SCHEDULING
darin's avatar
darin committed
642 643
    if (m_frame->document() && !m_frame->document()->ownerElement())
        printf("Layout timer fired at %d\n", m_frame->document()->elapsedTime());
644
#endif
darin's avatar
darin committed
645
    layout();
646 647
}

648
void FrameView::scheduleRelayout()
649
{
650 651
    ASSERT(m_frame->view() == this);

adele's avatar
adele committed
652 653 654 655 656
    if (d->layoutRoot) {
        if (d->layoutRoot->renderer())
            d->layoutRoot->renderer()->markContainingBlocksForLayout(false);
        d->layoutRoot = 0;
    }
657 658
    if (!d->layoutSchedulingEnabled)
        return;
659

660
    if (!m_frame->document() || !m_frame->document()->shouldScheduleLayout())
661 662
        return;

663
    int delay = m_frame->document()->minimumLayoutDelay();
darin's avatar
darin committed
664
    if (d->layoutTimer.isActive() && d->delayedLayout && !delay)
665
        unscheduleRelayout();
darin's avatar
darin committed
666
    if (d->layoutTimer.isActive())
667 668 669
        return;

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

weinig's avatar
weinig committed
671
#ifdef INSTRUMENT_LAYOUT_SCHEDULING
672
    if (!m_frame->document()->ownerElement())
673
        printf("Scheduling layout for %d\n", delay);
hyatt's avatar
hyatt committed
674 675
#endif

darin's avatar
darin committed
676
    d->layoutTimer.startOneShot(delay * 0.001);
677 678
}

adele's avatar
adele committed
679 680
void FrameView::scheduleRelayoutOfSubtree(Node* n)
{
681 682
    ASSERT(m_frame->view() == this);

darin's avatar
darin committed
683 684 685
    if (!d->layoutSchedulingEnabled || (m_frame->document()
            && m_frame->document()->renderer()
            && m_frame->document()->renderer()->needsLayout())) {
adele's avatar
adele committed
686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707
        if (n->renderer())
            n->renderer()->markContainingBlocksForLayout(false);
        return;
    }

    if (layoutPending()) {
        if (d->layoutRoot != n) {
            // Just do a full relayout
            if (d->layoutRoot && d->layoutRoot->renderer())
                d->layoutRoot->renderer()->markContainingBlocksForLayout(false);
            d->layoutRoot = 0;
            if (n->renderer())
                n->renderer()->markContainingBlocksForLayout(false);
        }
    } else {
        int delay = m_frame->document()->minimumLayoutDelay();
        d->layoutRoot = n;
        d->delayedLayout = delay != 0;
        d->layoutTimer.startOneShot(delay * 0.001);
    }
}

ap's avatar
ap committed
708
bool FrameView::layoutPending() const
709
{
710
    return d->layoutTimer.isActive();
711 712
}

713 714
bool FrameView::needsLayout() const
{
715 716
    // It is possible that our document will not have a body yet. If this is the case, 
    // then we are not allowed to schedule layouts yet, so we won't be pending layout.
antti's avatar
antti committed
717 718
    if (!m_frame)
        return false;
719
    RenderView* root = static_cast<RenderView*>(m_frame->renderer());
antti's avatar
antti committed
720 721 722
    Document * doc = m_frame->document();
    // doc->hasChangedChild() condition can occur when using WebKit ObjC interface
    return layoutPending() || (root && root->needsLayout()) || d->layoutRoot || (doc && doc->hasChangedChild());
723 724 725 726 727 728 729 730
}

void FrameView::setNeedsLayout()
{
    if (m_frame->renderer())
        m_frame->renderer()->setNeedsLayout(true);
}

731
void FrameView::unscheduleRelayout()
darin's avatar
darin committed
732
{
darin's avatar
darin committed
733
    if (!d->layoutTimer.isActive())
darin's avatar
darin committed
734 735
        return;

weinig's avatar
weinig committed
736
#ifdef INSTRUMENT_LAYOUT_SCHEDULING
737 738
    if (m_frame->document() && !m_frame->document()->ownerElement())
        printf("Layout timer unscheduled at %d\n", m_frame->document()->elapsedTime());
739 740
#endif
    
darin's avatar
darin committed
741
    d->layoutTimer.stop();
742
    d->delayedLayout = false;
743
}
kocienda's avatar
kocienda committed
744

745
bool FrameView::isTransparent() const
darin's avatar
darin committed
746 747 748 749
{
    return d->isTransparent;
}

750
void FrameView::setTransparent(bool isTransparent)
darin's avatar
darin committed
751 752 753
{
    d->isTransparent = isTransparent;
}
darin's avatar
darin committed
754

thatcher's avatar
thatcher committed
755 756 757 758 759 760 761 762 763 764 765 766
Color FrameView::baseBackgroundColor() const
{
    return d->baseBackgroundColor;
}

void FrameView::setBaseBackgroundColor(Color bc)
{
    if (!bc.isValid())
        bc = Color::white;
    d->baseBackgroundColor = bc;
}

andersca's avatar
andersca committed
767 768
void FrameView::scheduleEvent(PassRefPtr<Event> event, PassRefPtr<EventTargetNode> eventTarget, bool tempEvent)
{
aroben's avatar
aroben committed
769 770 771 772 773 774
    if (!d->m_enqueueEvents) {
        ExceptionCode ec = 0;
        eventTarget->dispatchEvent(event, ec, tempEvent);
        return;
    }

darin's avatar
darin committed
775
    ScheduledEvent* scheduledEvent = new ScheduledEvent;
andersca's avatar
andersca committed
776 777 778
    scheduledEvent->m_event = event;
    scheduledEvent->m_eventTarget = eventTarget;
    scheduledEvent->m_tempEvent = tempEvent;
darin's avatar
darin committed
779
    d->m_scheduledEvents.append(scheduledEvent);
andersca's avatar
andersca committed
780