webengine/osswebengine/WebCore/page/FrameView.cpp
changeset 0 dd21522fd290
child 71 4bd5176e1bc8
equal deleted inserted replaced
-1:000000000000 0:dd21522fd290
       
     1 /*
       
     2  * Copyright (C) 1998, 1999 Torben Weis <weis@kde.org>
       
     3  *                     1999 Lars Knoll <knoll@kde.org>
       
     4  *                     1999 Antti Koivisto <koivisto@kde.org>
       
     5  *                     2000 Dirk Mueller <mueller@kde.org>
       
     6  * Copyright (C) 2004, 2005, 2006, 2007 Apple Inc. All rights reserved.
       
     7  *           (C) 2006 Graham Dennis (graham.dennis@gmail.com)
       
     8  *           (C) 2006 Alexey Proskuryakov (ap@nypop.com)
       
     9  *
       
    10  * This library is free software; you can redistribute it and/or
       
    11  * modify it under the terms of the GNU Library General Public
       
    12  * License as published by the Free Software Foundation; either
       
    13  * version 2 of the License, or (at your option) any later version.
       
    14  *
       
    15  * This library is distributed in the hope that it will be useful,
       
    16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
       
    18  * Library General Public License for more details.
       
    19  *
       
    20  * You should have received a copy of the GNU Library General Public License
       
    21  * along with this library; see the file COPYING.LIB.  If not, write to
       
    22  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
       
    23  * Boston, MA 02110-1301, USA.
       
    24  */
       
    25 
       
    26 #include "config.h"
       
    27 #include "FrameView.h"
       
    28 #include "Settings.h"
       
    29 
       
    30 #include "AXObjectCache.h"
       
    31 #include "EventHandler.h"
       
    32 #include "FloatRect.h"
       
    33 #include "Frame.h"
       
    34 #include "FrameLoader.h"
       
    35 #include "FrameLoaderClient.h"
       
    36 #include "GraphicsContext.h"
       
    37 #include "HTMLDocument.h"
       
    38 #include "HTMLFrameSetElement.h"
       
    39 #include "HTMLNames.h"
       
    40 #include "OverflowEvent.h"
       
    41 #include "RenderPart.h"
       
    42 #include "RenderPartObject.h"
       
    43 #include "RenderTheme.h"
       
    44 #include "RenderView.h"
       
    45 
       
    46 #if PLATFORM(SYMBIAN)
       
    47 #include "WebCoreFrameBridge.h"
       
    48 #include "FrameTree.h"
       
    49 #include "oom.h"
       
    50 #endif
       
    51 
       
    52 namespace WebCore {
       
    53 
       
    54 using namespace HTMLNames;
       
    55 
       
    56 struct ScheduledEvent {
       
    57     RefPtr<Event> m_event;
       
    58     RefPtr<EventTargetNode> m_eventTarget;
       
    59     bool m_tempEvent;
       
    60 };
       
    61 
       
    62 class FrameViewPrivate {
       
    63 public:
       
    64     FrameViewPrivate(FrameView* view)
       
    65         : m_slowRepaintObjectCount(0)
       
    66         , layoutTimer(view, &FrameView::layoutTimerFired)
       
    67         , m_mediaType("screen")
       
    68         , m_enqueueEvents(0)
       
    69         , m_overflowStatusDirty(true)
       
    70         , m_viewportRenderer(0)
       
    71         , m_wasScrolledByUser(false)
       
    72         , m_inProgrammaticScroll(false)
       
    73     {
       
    74         isTransparent = false;
       
    75         baseBackgroundColor = Color::white;
       
    76         vmode = hmode = ScrollbarAuto;
       
    77         needToInitScrollbars = true;
       
    78         reset();
       
    79     }
       
    80     void reset()
       
    81     {
       
    82         useSlowRepaints = false;
       
    83         borderX = 30;
       
    84         borderY = 30;
       
    85         layoutTimer.stop();
       
    86         layoutRoot = 0;
       
    87         delayedLayout = false;
       
    88         doFullRepaint = true;
       
    89         layoutSchedulingEnabled = true;
       
    90         midLayout = false;
       
    91         layoutCount = 0;
       
    92         nestedLayoutCount = 0;
       
    93         firstLayout = true;
       
    94         repaintRects.clear();
       
    95         m_wasScrolledByUser = false;
       
    96     }
       
    97 
       
    98     bool doFullRepaint;
       
    99     
       
   100     ScrollbarMode vmode;
       
   101     ScrollbarMode hmode;
       
   102     bool useSlowRepaints;
       
   103     unsigned m_slowRepaintObjectCount;
       
   104 
       
   105     int borderX, borderY;
       
   106 
       
   107     Timer<FrameView> layoutTimer;
       
   108     bool delayedLayout;
       
   109     RefPtr<Node> layoutRoot;
       
   110     
       
   111     bool layoutSchedulingEnabled;
       
   112     bool midLayout;
       
   113     int layoutCount;
       
   114     unsigned nestedLayoutCount;
       
   115 
       
   116     bool firstLayout;
       
   117     bool needToInitScrollbars;
       
   118     bool isTransparent;
       
   119     Color baseBackgroundColor;
       
   120 
       
   121     // Used by objects during layout to communicate repaints that need to take place only
       
   122     // after all layout has been completed.
       
   123     Vector<RenderObject::RepaintInfo> repaintRects;
       
   124     
       
   125     String m_mediaType;
       
   126     
       
   127     unsigned m_enqueueEvents;
       
   128     Vector<ScheduledEvent*> m_scheduledEvents;
       
   129     
       
   130     bool m_overflowStatusDirty;
       
   131     bool horizontalOverflow;
       
   132     bool m_verticalOverflow;    
       
   133     RenderObject* m_viewportRenderer;
       
   134 
       
   135     bool m_wasScrolledByUser;
       
   136     bool m_inProgrammaticScroll;
       
   137 };
       
   138 
       
   139 FrameView::FrameView(Frame* frame)
       
   140     : m_refCount(1)
       
   141     , m_frame(frame)
       
   142     , d(new FrameViewPrivate(this))
       
   143 {
       
   144     init();
       
   145     show();
       
   146 }
       
   147 
       
   148 FrameView::~FrameView()
       
   149 {
       
   150     resetScrollbars();
       
   151 
       
   152     ASSERT(m_refCount == 0);
       
   153     ASSERT(d->m_scheduledEvents.isEmpty() && !d->m_enqueueEvents);
       
   154 
       
   155     if (m_frame) {
       
   156         ASSERT(m_frame->view() != this || !m_frame->document() || !m_frame->document()->renderer());
       
   157         RenderPart* renderer = m_frame->ownerRenderer();
       
   158         if (renderer && renderer->widget() == this)
       
   159             renderer->setWidget(0);
       
   160     }
       
   161 
       
   162     delete d;
       
   163     d = 0;
       
   164 }
       
   165 
       
   166 bool FrameView::isFrameView() const 
       
   167 { 
       
   168     return true; 
       
   169 }
       
   170 
       
   171 void FrameView::clearFrame()
       
   172 {
       
   173     m_frame = 0;
       
   174 }
       
   175 
       
   176 void FrameView::resetScrollbars()
       
   177 {
       
   178     // Reset the document's scrollbars back to our defaults before we yield the floor.
       
   179     d->firstLayout = true;
       
   180     suppressScrollbars(true);
       
   181     ScrollView::setVScrollbarMode(d->vmode);
       
   182     ScrollView::setHScrollbarMode(d->hmode);
       
   183     suppressScrollbars(false);
       
   184 }
       
   185 
       
   186 void FrameView::init()
       
   187 {
       
   188     m_margins = IntSize(-1, -1); // undefined
       
   189     m_size = IntSize();
       
   190 }
       
   191 
       
   192 void FrameView::clear()
       
   193 {
       
   194     setStaticBackground(false);
       
   195     
       
   196     d->reset();
       
   197 
       
   198     if (m_frame)
       
   199         if (RenderPart* renderer = m_frame->ownerRenderer())
       
   200             renderer->viewCleared();
       
   201 
       
   202     suppressScrollbars(true);
       
   203 }
       
   204 
       
   205 bool FrameView::didFirstLayout() const
       
   206 {
       
   207     return !d->firstLayout;
       
   208 }
       
   209 
       
   210 void FrameView::initScrollbars()
       
   211 {
       
   212     if (!d->needToInitScrollbars)
       
   213         return;
       
   214     d->needToInitScrollbars = false;
       
   215     setScrollbarsMode(hScrollbarMode());
       
   216 }
       
   217 
       
   218 void FrameView::setMarginWidth(int w)
       
   219 {
       
   220     // make it update the rendering area when set
       
   221     m_margins.setWidth(w);
       
   222 }
       
   223 
       
   224 void FrameView::setMarginHeight(int h)
       
   225 {
       
   226     // make it update the rendering area when set
       
   227     m_margins.setHeight(h);
       
   228 }
       
   229 
       
   230 void FrameView::adjustViewSize()
       
   231 {
       
   232     ASSERT(m_frame->view() == this);
       
   233     RenderView* root = static_cast<RenderView*>(m_frame->renderer());
       
   234     if (!root)
       
   235         return;
       
   236     resizeContents(root->overflowWidth(), root->overflowHeight());
       
   237 }
       
   238 
       
   239 void FrameView::applyOverflowToViewport(RenderObject* o, ScrollbarMode& hMode, ScrollbarMode& vMode)
       
   240 {
       
   241     // Handle the overflow:hidden/scroll case for the body/html elements.  WinIE treats
       
   242     // overflow:hidden and overflow:scroll on <body> as applying to the document's
       
   243     // scrollbars.  The CSS2.1 draft states that HTML UAs should use the <html> or <body> element and XML/XHTML UAs should
       
   244     // use the root element.
       
   245     switch (o->style()->overflowX()) {
       
   246         case OHIDDEN:
       
   247             hMode = ScrollbarAlwaysOff;
       
   248             break;
       
   249         case OSCROLL:
       
   250             hMode = ScrollbarAlwaysOn;
       
   251             break;
       
   252         case OAUTO:
       
   253             hMode = ScrollbarAuto;
       
   254             break;
       
   255         default:
       
   256             // Don't set it at all.
       
   257             ;
       
   258     }
       
   259     
       
   260      switch (o->style()->overflowY()) {
       
   261         case OHIDDEN:
       
   262             vMode = ScrollbarAlwaysOff;
       
   263             break;
       
   264         case OSCROLL:
       
   265             vMode = ScrollbarAlwaysOn;
       
   266             break;
       
   267         case OAUTO:
       
   268             vMode = ScrollbarAuto;
       
   269             break;
       
   270         default:
       
   271             // Don't set it at all.
       
   272             ;
       
   273     }
       
   274 
       
   275     d->m_viewportRenderer = o;
       
   276 }
       
   277 
       
   278 int FrameView::layoutCount() const
       
   279 {
       
   280     return d->layoutCount;
       
   281 }
       
   282 
       
   283 bool FrameView::needsFullRepaint() const
       
   284 {
       
   285     return d->doFullRepaint;
       
   286 }
       
   287 
       
   288 void FrameView::addRepaintInfo(RenderObject* o, const IntRect& r)
       
   289 {
       
   290     d->repaintRects.append(RenderObject::RepaintInfo(o, r));
       
   291 }
       
   292 
       
   293 Node* FrameView::layoutRoot() const
       
   294 {
       
   295     return layoutPending() ? 0 : d->layoutRoot.get();
       
   296 }
       
   297 
       
   298 void FrameView::layout(bool allowSubtree)
       
   299 {
       
   300 #if PLATFORM(SYMBIAN)
       
   301     OOM_PRE_CHECK(1024*1024*2, 0, "FrameView::layout")
       
   302 #endif
       
   303     if (d->midLayout)
       
   304         return;
       
   305 
       
   306     d->layoutTimer.stop();
       
   307     d->delayedLayout = false;
       
   308 
       
   309     // Protect the view from being deleted during layout (in recalcStyle)
       
   310     RefPtr<FrameView> protector(this);
       
   311 
       
   312     if (!m_frame) {
       
   313         // FIXME: Do we need to set m_size.width here?
       
   314         // FIXME: Should we set m_size.height here too?
       
   315         m_size.setWidth(visibleWidth());
       
   316         return;
       
   317     }
       
   318     
       
   319     // we shouldn't enter layout() while painting
       
   320     ASSERT(!m_frame->isPainting());
       
   321     if (m_frame->isPainting())
       
   322         return;
       
   323 
       
   324     if (!allowSubtree && d->layoutRoot) {
       
   325         if (d->layoutRoot->renderer())
       
   326             d->layoutRoot->renderer()->markContainingBlocksForLayout(false);
       
   327         d->layoutRoot = 0;
       
   328     }
       
   329 
       
   330 
       
   331     ASSERT(m_frame->view() == this);
       
   332 
       
   333     Document* document = m_frame->document();
       
   334     if (!document) {
       
   335         // FIXME: Should we set m_size.height here too?
       
   336         m_size.setWidth(visibleWidth());
       
   337         return;
       
   338     }
       
   339 
       
   340     d->layoutSchedulingEnabled = false;
       
   341 
       
   342     // Always ensure our style info is up-to-date.  This can happen in situations where
       
   343     // the layout beats any sort of style recalc update that needs to occur.
       
   344     if (document->hasChangedChild())
       
   345         document->recalcStyle();
       
   346     
       
   347     bool subtree = d->layoutRoot;
       
   348     Node* rootNode = subtree ? d->layoutRoot.get() : document;
       
   349 
       
   350     // If there is only one ref to this view left, then its going to be destroyed as soon as we exit, 
       
   351     // so there's no point to continuiing to layout
       
   352     if (protector->hasOneRef())
       
   353         return;
       
   354 
       
   355     RenderObject* root = rootNode->renderer();
       
   356     if (!root) {
       
   357         // FIXME: Do we need to set m_size here?
       
   358         d->layoutSchedulingEnabled = true;
       
   359         return;
       
   360     }
       
   361 
       
   362     d->nestedLayoutCount++;
       
   363 
       
   364     ScrollbarMode hMode = d->hmode;
       
   365     ScrollbarMode vMode = d->vmode;
       
   366     
       
   367     if (!subtree) {
       
   368         Document* document = static_cast<Document*>(rootNode);
       
   369         RenderObject* rootRenderer = document->documentElement() ? document->documentElement()->renderer() : 0;
       
   370         if (document->isHTMLDocument()) {
       
   371             Node* body = static_cast<HTMLDocument*>(document)->body();
       
   372             if (body && body->renderer()) {
       
   373                 if (body->hasTagName(framesetTag) && !m_frame->settings()->flatFrameSetLayoutEnabled()) {
       
   374                     body->renderer()->setChildNeedsLayout(true);
       
   375                     vMode = ScrollbarAlwaysOff;
       
   376                     hMode = ScrollbarAlwaysOff;
       
   377                 } else if (body->hasTagName(bodyTag)) {
       
   378                     if (!d->firstLayout && m_size.height() != visibleHeight()
       
   379                             && static_cast<RenderBox*>(body->renderer())->stretchesToViewHeight())
       
   380                         body->renderer()->setChildNeedsLayout(true);
       
   381                     // It's sufficient to just check the X overflow,
       
   382                     // since it's illegal to have visible in only one direction.
       
   383                     RenderObject* o = rootRenderer->style()->overflowX() == OVISIBLE 
       
   384                         ? body->renderer() : rootRenderer;
       
   385                     applyOverflowToViewport(o, hMode, vMode); // Only applies to HTML UAs, not to XML/XHTML UAs
       
   386                 }
       
   387             }
       
   388         } else if (rootRenderer)
       
   389             applyOverflowToViewport(rootRenderer, hMode, vMode); // XML/XHTML UAs use the root element.
       
   390 #ifdef INSTRUMENT_LAYOUT_SCHEDULING
       
   391         if (d->firstLayout && !document->ownerElement())
       
   392             printf("Elapsed time before first layout: %d\n", document->elapsedTime());
       
   393 #endif
       
   394     }
       
   395 
       
   396     d->doFullRepaint = !subtree && (d->firstLayout || static_cast<RenderView*>(root)->printing());
       
   397     d->repaintRects.clear();
       
   398 
       
   399     bool didFirstLayout = false;
       
   400     if (!subtree) {
       
   401         // Now set our scrollbar state for the layout.
       
   402         ScrollbarMode currentHMode = hScrollbarMode();
       
   403         ScrollbarMode currentVMode = vScrollbarMode();
       
   404 
       
   405         if (d->firstLayout || (hMode != currentHMode || vMode != currentVMode)) {
       
   406             suppressScrollbars(true);
       
   407             if (d->firstLayout) {
       
   408                 d->firstLayout = false;
       
   409                 didFirstLayout = true;
       
   410                 
       
   411                 // Set the initial vMode to AlwaysOn if we're auto.
       
   412                 if (vMode == ScrollbarAuto)
       
   413                     ScrollView::setVScrollbarMode(ScrollbarAlwaysOn); // This causes a vertical scrollbar to appear.
       
   414                 // Set the initial hMode to AlwaysOff if we're auto.
       
   415                 if (hMode == ScrollbarAuto)
       
   416                     ScrollView::setHScrollbarMode(ScrollbarAlwaysOff); // This causes a horizontal scrollbar to disappear.
       
   417             }
       
   418             
       
   419             if (hMode == vMode)
       
   420                 ScrollView::setScrollbarsMode(hMode);
       
   421             else {
       
   422                 ScrollView::setHScrollbarMode(hMode);
       
   423                 ScrollView::setVScrollbarMode(vMode);
       
   424             }
       
   425 
       
   426             suppressScrollbars(false, true);
       
   427         }
       
   428 
       
   429         IntSize oldSize = m_size;
       
   430 
       
   431         m_size = IntSize(visibleWidth(), visibleHeight());
       
   432 
       
   433         if (oldSize != m_size)
       
   434             d->doFullRepaint = true;
       
   435     }
       
   436     
       
   437     RenderLayer* layer = root->enclosingLayer();
       
   438      
       
   439     pauseScheduledEvents();
       
   440 
       
   441     if (subtree)
       
   442         root->view()->pushLayoutState(root);
       
   443     d->midLayout = true;
       
   444     root->layout();
       
   445     d->midLayout = false;
       
   446     if (subtree)
       
   447         root->view()->popLayoutState();
       
   448     d->layoutRoot = 0;
       
   449 
       
   450     m_frame->invalidateSelection();
       
   451    
       
   452     d->layoutSchedulingEnabled=true;
       
   453 
       
   454     if (!subtree && !static_cast<RenderView*>(root)->printing())
       
   455         adjustViewSize();
       
   456 
       
   457     // Now update the positions of all layers.
       
   458     layer->updateLayerPositions(d->doFullRepaint);
       
   459 
       
   460     // We update our widget positions right after doing a layout.
       
   461     if (!subtree)
       
   462         static_cast<RenderView*>(root)->updateWidgetPositions();
       
   463     
       
   464     // FIXME: Could optimize this and have objects removed from this list
       
   465     // if they ever do full repaints.
       
   466     Vector<RenderObject::RepaintInfo>::iterator end = d->repaintRects.end();
       
   467     for (Vector<RenderObject::RepaintInfo>::iterator it = d->repaintRects.begin(); it != end; ++it)
       
   468         it->m_object->repaintRectangle(it->m_repaintRect);
       
   469     d->repaintRects.clear();
       
   470     
       
   471     d->layoutCount++;
       
   472 
       
   473 #if PLATFORM(MAC)
       
   474     if (AXObjectCache::accessibilityEnabled())
       
   475         root->document()->axObjectCache()->postNotificationToElement(root, "AXLayoutComplete");
       
   476 #endif
       
   477     updateDashboardRegions();
       
   478 #if PLATFORM(SYMBIAN)
       
   479     // Update focusable rect lists in main frame
       
   480     if (m_frame.get()->bridge()) {
       
   481         m_frame.get()->bridge()->updateFocusableRectList();
       
   482         m_frame.get()->bridge()->updateThumbnail();
       
   483     }
       
   484 #endif
       
   485 
       
   486     if (didFirstLayout)
       
   487         m_frame->loader()->didFirstLayout();
       
   488     
       
   489     ASSERT(!root->needsLayout());
       
   490 
       
   491     setStaticBackground(useSlowRepaints());
       
   492 
       
   493     if (document->hasListenerType(Document::OVERFLOWCHANGED_LISTENER))
       
   494         updateOverflowStatus(visibleWidth() < contentsWidth(),
       
   495                              visibleHeight() < contentsHeight());
       
   496 
       
   497     if (m_widgetUpdateSet && d->nestedLayoutCount == 1) {
       
   498         Vector<RenderPartObject*> objectVector;
       
   499         copyToVector(*m_widgetUpdateSet, objectVector);
       
   500         size_t size = objectVector.size();
       
   501         for (size_t i = 0; i < size; ++i) {
       
   502             RenderPartObject* object = objectVector[i];
       
   503             object->updateWidget(false);
       
   504 
       
   505             // updateWidget() can destroy the RenderPartObject, so we need to make sure it's
       
   506             // alive by checking if it's still in m_widgetUpdateSet.
       
   507             if (m_widgetUpdateSet->contains(object))
       
   508                 object->updateWidgetPosition();
       
   509         }
       
   510         m_widgetUpdateSet->clear();
       
   511     }
       
   512 
       
   513     // Allow events scheduled during layout to fire
       
   514     resumeScheduledEvents();
       
   515 
       
   516     d->nestedLayoutCount--;
       
   517 #if PLATFORM(SYMBIAN)
       
   518     OOM_POST_CHECK_FAILED(unscheduleRelayout(); return;)
       
   519 #endif
       
   520 }
       
   521 
       
   522 void FrameView::addWidgetToUpdate(RenderPartObject* object)
       
   523 {
       
   524     if (!m_widgetUpdateSet)
       
   525         m_widgetUpdateSet.set(new HashSet<RenderPartObject*>);
       
   526 
       
   527     m_widgetUpdateSet->add(object);
       
   528 }
       
   529 
       
   530 void FrameView::removeWidgetToUpdate(RenderPartObject* object)
       
   531 {
       
   532     if (!m_widgetUpdateSet)
       
   533         return;
       
   534 
       
   535     m_widgetUpdateSet->remove(object);
       
   536 }
       
   537 
       
   538 //
       
   539 // Event Handling
       
   540 //
       
   541 /////////////////
       
   542 
       
   543 bool FrameView::scrollTo(const IntRect& bounds)
       
   544 {
       
   545     int x, y, xe, ye;
       
   546     x = bounds.x();
       
   547     y = bounds.y();
       
   548     xe = bounds.right() - 1;
       
   549     ye = bounds.bottom() - 1;
       
   550     
       
   551     int deltax;
       
   552     int deltay;
       
   553 
       
   554     int curHeight = visibleHeight();
       
   555     int curWidth = visibleWidth();
       
   556 
       
   557     if (ye - y>curHeight-d->borderY)
       
   558         ye = y + curHeight - d->borderY;
       
   559 
       
   560     if (xe - x>curWidth-d->borderX)
       
   561         xe = x + curWidth - d->borderX;
       
   562 
       
   563     // is xpos of target left of the view's border?
       
   564     if (x < contentsX() + d->borderX)
       
   565         deltax = x - contentsX() - d->borderX;
       
   566     // is xpos of target right of the view's right border?
       
   567     else if (xe + d->borderX > contentsX() + curWidth)
       
   568         deltax = xe + d->borderX - (contentsX() + curWidth);
       
   569     else
       
   570         deltax = 0;
       
   571 
       
   572     // is ypos of target above upper border?
       
   573     if (y < contentsY() + d->borderY)
       
   574         deltay = y - contentsY() - d->borderY;
       
   575     // is ypos of target below lower border?
       
   576     else if (ye + d->borderY > contentsY() + curHeight)
       
   577         deltay = ye + d->borderY - (contentsY() + curHeight);
       
   578     else
       
   579         deltay = 0;
       
   580 
       
   581     int maxx = curWidth - d->borderX;
       
   582     int maxy = curHeight - d->borderY;
       
   583 
       
   584     int scrollX = deltax > 0 ? (deltax > maxx ? maxx : deltax) : deltax == 0 ? 0 : (deltax > -maxx ? deltax : -maxx);
       
   585     int scrollY = deltay > 0 ? (deltay > maxy ? maxy : deltay) : deltay == 0 ? 0 : (deltay > -maxy ? deltay : -maxy);
       
   586 
       
   587     if (contentsX() + scrollX < 0)
       
   588         scrollX = -contentsX();
       
   589     else if (contentsWidth() - visibleWidth() - contentsX() < scrollX)
       
   590         scrollX = contentsWidth() - visibleWidth() - contentsX();
       
   591 
       
   592     if (contentsY() + scrollY < 0)
       
   593         scrollY = -contentsY();
       
   594     else if (contentsHeight() - visibleHeight() - contentsY() < scrollY)
       
   595         scrollY = contentsHeight() - visibleHeight() - contentsY();
       
   596 
       
   597     scrollBy(scrollX, scrollY);
       
   598 
       
   599     // generate abs(scroll.)
       
   600     if (scrollX < 0)
       
   601         scrollX = -scrollX;
       
   602     if (scrollY < 0)
       
   603         scrollY = -scrollY;
       
   604 
       
   605     return scrollX != maxx && scrollY != maxy;
       
   606 }
       
   607 
       
   608 void FrameView::setMediaType(const String& mediaType)
       
   609 {
       
   610     d->m_mediaType = mediaType;
       
   611 }
       
   612 
       
   613 String FrameView::mediaType() const
       
   614 {
       
   615     // See if we have an override type.
       
   616     String overrideType = m_frame->loader()->client()->overrideMediaType();
       
   617     if (!overrideType.isNull())
       
   618         return overrideType;
       
   619     return d->m_mediaType;
       
   620 }
       
   621 
       
   622 bool FrameView::useSlowRepaints() const
       
   623 {
       
   624     return d->useSlowRepaints || d->m_slowRepaintObjectCount > 0;
       
   625 }
       
   626 
       
   627 void FrameView::setUseSlowRepaints()
       
   628 {
       
   629     d->useSlowRepaints = true;
       
   630     setStaticBackground(true);
       
   631 }
       
   632 
       
   633 void FrameView::addSlowRepaintObject()
       
   634 {
       
   635     if (!d->m_slowRepaintObjectCount)
       
   636         setStaticBackground(true);
       
   637     d->m_slowRepaintObjectCount++;
       
   638 }
       
   639 
       
   640 void FrameView::removeSlowRepaintObject()
       
   641 {
       
   642     ASSERT(d->m_slowRepaintObjectCount > 0);
       
   643     d->m_slowRepaintObjectCount--;
       
   644     if (!d->m_slowRepaintObjectCount)
       
   645         setStaticBackground(d->useSlowRepaints);
       
   646 }
       
   647 
       
   648 void FrameView::setScrollbarsMode(ScrollbarMode mode)
       
   649 {
       
   650     d->vmode = mode;
       
   651     d->hmode = mode;
       
   652     
       
   653     ScrollView::setScrollbarsMode(mode);
       
   654 }
       
   655 
       
   656 void FrameView::setVScrollbarMode(ScrollbarMode mode)
       
   657 {
       
   658     d->vmode = mode;
       
   659     ScrollView::setVScrollbarMode(mode);
       
   660 }
       
   661 
       
   662 void FrameView::setHScrollbarMode(ScrollbarMode mode)
       
   663 {
       
   664     d->hmode = mode;
       
   665     ScrollView::setHScrollbarMode(mode);
       
   666 }
       
   667 
       
   668 void FrameView::restoreScrollbar()
       
   669 {
       
   670     suppressScrollbars(false);
       
   671 }
       
   672 
       
   673 void FrameView::scrollRectIntoViewRecursively(const IntRect& r)
       
   674 {
       
   675     if (frame()->prohibitsScrolling())
       
   676         return;
       
   677     bool wasInProgrammaticScroll = d->m_inProgrammaticScroll;
       
   678     d->m_inProgrammaticScroll = true;
       
   679     ScrollView::scrollRectIntoViewRecursively(r);
       
   680     d->m_inProgrammaticScroll = wasInProgrammaticScroll;
       
   681 }
       
   682 
       
   683 void FrameView::setContentsPos(int x, int y)
       
   684 {
       
   685     if (frame()->prohibitsScrolling())
       
   686         return;
       
   687     bool wasInProgrammaticScroll = d->m_inProgrammaticScroll;
       
   688     d->m_inProgrammaticScroll = true;
       
   689     ScrollView::setContentsPos(x, y);
       
   690     d->m_inProgrammaticScroll = wasInProgrammaticScroll;
       
   691 }
       
   692 
       
   693 void FrameView::repaintRectangle(const IntRect& r, bool immediate)
       
   694 {
       
   695     updateContents(r, immediate);
       
   696 }
       
   697 
       
   698 void FrameView::layoutTimerFired(Timer<FrameView>*)
       
   699 {
       
   700 #ifdef INSTRUMENT_LAYOUT_SCHEDULING
       
   701     if (m_frame->document() && !m_frame->document()->ownerElement())
       
   702         printf("Layout timer fired at %d\n", m_frame->document()->elapsedTime());
       
   703 #endif
       
   704     layout();
       
   705 }
       
   706 
       
   707 void FrameView::scheduleRelayout()
       
   708 {
       
   709     ASSERT(m_frame->view() == this);
       
   710 
       
   711     if (d->layoutRoot) {
       
   712         if (d->layoutRoot->renderer())
       
   713             d->layoutRoot->renderer()->markContainingBlocksForLayout(false);
       
   714         d->layoutRoot = 0;
       
   715     }
       
   716     if (!d->layoutSchedulingEnabled)
       
   717         return;
       
   718 
       
   719     if (!m_frame->document() || !m_frame->document()->shouldScheduleLayout())
       
   720         return;
       
   721 
       
   722     // In flat frame layout mode the content of frame affects layout of the parent frames.
       
   723     // Invalidate also parent frame starting from the owner element of this frame.
       
   724 #if PLATFORM(SYMBIAN)
       
   725     if (m_frame->settings()->flatFrameSetLayoutEnabled() && m_frame->ownerRenderer() && m_frame->tree()->parent()->isFrameSet())
       
   726 #else
       
   727     if (m_frame->settings()->flatFrameSetLayoutEnabled() && m_frame->ownerRenderer())
       
   728 #endif
       
   729         m_frame->ownerRenderer()->setNeedsLayout(true, true);
       
   730 
       
   731     int delay = m_frame->document()->minimumLayoutDelay();
       
   732     if (d->layoutTimer.isActive() && d->delayedLayout && !delay)
       
   733         unscheduleRelayout();
       
   734     if (d->layoutTimer.isActive())
       
   735         return;
       
   736 
       
   737     d->delayedLayout = delay != 0;
       
   738 
       
   739 #ifdef INSTRUMENT_LAYOUT_SCHEDULING
       
   740     if (!m_frame->document()->ownerElement())
       
   741         printf("Scheduling layout for %d\n", delay);
       
   742 #endif
       
   743 
       
   744     d->layoutTimer.startOneShot(delay * 0.001);
       
   745 }
       
   746 
       
   747 void FrameView::scheduleRelayoutOfSubtree(Node* n)
       
   748 {
       
   749     ASSERT(m_frame->view() == this);
       
   750 
       
   751     if (!d->layoutSchedulingEnabled || (m_frame->document()
       
   752             && m_frame->document()->renderer()
       
   753             && m_frame->document()->renderer()->needsLayout())) {
       
   754         if (n->renderer())
       
   755             n->renderer()->markContainingBlocksForLayout(false);
       
   756         return;
       
   757     }
       
   758 
       
   759     if (layoutPending()) {
       
   760         if (d->layoutRoot != n) {
       
   761             // Just do a full relayout
       
   762             if (d->layoutRoot && d->layoutRoot->renderer())
       
   763                 d->layoutRoot->renderer()->markContainingBlocksForLayout(false);
       
   764             d->layoutRoot = 0;
       
   765             if (n->renderer())
       
   766                 n->renderer()->markContainingBlocksForLayout(false);
       
   767         }
       
   768     } else {
       
   769         int delay = m_frame->document()->minimumLayoutDelay();
       
   770         d->layoutRoot = n;
       
   771         d->delayedLayout = delay != 0;
       
   772         d->layoutTimer.startOneShot(delay * 0.001);
       
   773     }
       
   774 }
       
   775 
       
   776 bool FrameView::layoutPending() const
       
   777 {
       
   778     return d->layoutTimer.isActive();
       
   779 }
       
   780 
       
   781 bool FrameView::needsLayout() const
       
   782 {
       
   783     // It is possible that our document will not have a body yet. If this is the case, 
       
   784     // then we are not allowed to schedule layouts yet, so we won't be pending layout.
       
   785     if (!m_frame)
       
   786         return false;
       
   787     RenderView* root = static_cast<RenderView*>(m_frame->renderer());
       
   788     Document * doc = m_frame->document();
       
   789     // doc->hasChangedChild() condition can occur when using WebKit ObjC interface
       
   790     return layoutPending() || (root && root->needsLayout()) || d->layoutRoot || (doc && doc->hasChangedChild());
       
   791 }
       
   792 
       
   793 void FrameView::setNeedsLayout()
       
   794 {
       
   795     if (m_frame->renderer())
       
   796         m_frame->renderer()->setNeedsLayout(true);
       
   797 }
       
   798 
       
   799 void FrameView::unscheduleRelayout()
       
   800 {
       
   801     if (!d->layoutTimer.isActive())
       
   802         return;
       
   803 
       
   804 #ifdef INSTRUMENT_LAYOUT_SCHEDULING
       
   805     if (m_frame->document() && !m_frame->document()->ownerElement())
       
   806         printf("Layout timer unscheduled at %d\n", m_frame->document()->elapsedTime());
       
   807 #endif
       
   808     
       
   809     d->layoutTimer.stop();
       
   810     d->delayedLayout = false;
       
   811 }
       
   812 
       
   813 bool FrameView::isTransparent() const
       
   814 {
       
   815     return d->isTransparent;
       
   816 }
       
   817 
       
   818 void FrameView::setTransparent(bool isTransparent)
       
   819 {
       
   820     d->isTransparent = isTransparent;
       
   821 }
       
   822 
       
   823 Color FrameView::baseBackgroundColor() const
       
   824 {
       
   825     return d->baseBackgroundColor;
       
   826 }
       
   827 
       
   828 void FrameView::setBaseBackgroundColor(Color bc)
       
   829 {
       
   830     if (!bc.isValid())
       
   831         bc = Color::white;
       
   832     d->baseBackgroundColor = bc;
       
   833 }
       
   834 
       
   835 void FrameView::scheduleEvent(PassRefPtr<Event> event, PassRefPtr<EventTargetNode> eventTarget, bool tempEvent)
       
   836 {
       
   837     if (!d->m_enqueueEvents) {
       
   838         ExceptionCode ec = 0;
       
   839         eventTarget->dispatchEvent(event, ec, tempEvent);
       
   840         return;
       
   841     }
       
   842 
       
   843     ScheduledEvent* scheduledEvent = new ScheduledEvent;
       
   844     scheduledEvent->m_event = event;
       
   845     scheduledEvent->m_eventTarget = eventTarget;
       
   846     scheduledEvent->m_tempEvent = tempEvent;
       
   847     d->m_scheduledEvents.append(scheduledEvent);
       
   848 }
       
   849 
       
   850 void FrameView::pauseScheduledEvents()
       
   851 {
       
   852     ASSERT(d->m_scheduledEvents.isEmpty() || d->m_enqueueEvents);
       
   853     d->m_enqueueEvents++;
       
   854 }
       
   855 
       
   856 void FrameView::resumeScheduledEvents()
       
   857 {
       
   858     d->m_enqueueEvents--;
       
   859     if (!d->m_enqueueEvents)
       
   860         dispatchScheduledEvents();
       
   861     ASSERT(d->m_scheduledEvents.isEmpty() || d->m_enqueueEvents);
       
   862 }
       
   863 
       
   864 void FrameView::updateOverflowStatus(bool horizontalOverflow, bool verticalOverflow)
       
   865 {
       
   866     if (!d->m_viewportRenderer)
       
   867         return;
       
   868     
       
   869     if (d->m_overflowStatusDirty) {
       
   870         d->horizontalOverflow = horizontalOverflow;
       
   871         d->m_verticalOverflow = verticalOverflow;
       
   872         d->m_overflowStatusDirty = false;
       
   873         return;
       
   874     }
       
   875     
       
   876     bool horizontalOverflowChanged = (d->horizontalOverflow != horizontalOverflow);
       
   877     bool verticalOverflowChanged = (d->m_verticalOverflow != verticalOverflow);
       
   878     
       
   879     if (horizontalOverflowChanged || verticalOverflowChanged) {
       
   880         d->horizontalOverflow = horizontalOverflow;
       
   881         d->m_verticalOverflow = verticalOverflow;
       
   882         
       
   883         scheduleEvent(new OverflowEvent(horizontalOverflowChanged, horizontalOverflow,
       
   884             verticalOverflowChanged, verticalOverflow),
       
   885             EventTargetNodeCast(d->m_viewportRenderer->element()), true);
       
   886     }
       
   887     
       
   888 }
       
   889 
       
   890 void FrameView::dispatchScheduledEvents()
       
   891 {
       
   892     if (d->m_scheduledEvents.isEmpty())
       
   893         return;
       
   894     
       
   895     Vector<ScheduledEvent*> scheduledEventsCopy = d->m_scheduledEvents;
       
   896     d->m_scheduledEvents.clear();
       
   897     
       
   898     Vector<ScheduledEvent*>::iterator end = scheduledEventsCopy.end();
       
   899     for (Vector<ScheduledEvent*>::iterator it = scheduledEventsCopy.begin(); it != end; ++it) {
       
   900         ScheduledEvent* scheduledEvent = *it;
       
   901         
       
   902         ExceptionCode ec = 0;
       
   903         
       
   904         // Only dispatch events to nodes that are in the document
       
   905         if (scheduledEvent->m_eventTarget->inDocument())
       
   906             scheduledEvent->m_eventTarget->dispatchEvent(scheduledEvent->m_event,
       
   907                 ec, scheduledEvent->m_tempEvent);
       
   908         
       
   909         delete scheduledEvent;
       
   910     }    
       
   911 }
       
   912 
       
   913 IntRect FrameView::windowClipRect() const
       
   914 {
       
   915     return windowClipRect(true);
       
   916 }
       
   917 
       
   918 IntRect FrameView::windowClipRect(bool clipToContents) const
       
   919 {
       
   920     ASSERT(m_frame->view() == this);
       
   921 
       
   922     // Set our clip rect to be our contents.
       
   923     IntRect clipRect;
       
   924     if (clipToContents)
       
   925         clipRect = enclosingIntRect(visibleContentRect());
       
   926     else
       
   927         clipRect = IntRect(contentsX(), contentsY(), width(), height());
       
   928     clipRect = contentsToWindow(clipRect);
       
   929 
       
   930     if (!m_frame || !m_frame->document() || !m_frame->document()->ownerElement())
       
   931         return clipRect;
       
   932 
       
   933     // Take our owner element and get the clip rect from the enclosing layer.
       
   934     Element* elt = m_frame->document()->ownerElement();
       
   935     RenderLayer* layer = elt->renderer()->enclosingLayer();
       
   936     // FIXME: layer should never be null, but sometimes seems to be anyway.
       
   937     if (!layer)
       
   938         return clipRect;
       
   939     FrameView* parentView = elt->document()->view();
       
   940     clipRect.intersect(parentView->windowClipRectForLayer(layer, true));
       
   941     return clipRect;
       
   942 }
       
   943 
       
   944 IntRect FrameView::windowClipRectForLayer(const RenderLayer* layer, bool clipToLayerContents) const
       
   945 {
       
   946     // If we have no layer, just return our window clip rect.
       
   947     if (!layer)
       
   948         return windowClipRect();
       
   949 
       
   950     // Apply the clip from the layer.
       
   951     IntRect clipRect;
       
   952     if (clipToLayerContents)
       
   953         clipRect = layer->childrenClipRect();
       
   954     else
       
   955         clipRect = layer->selfClipRect();
       
   956     clipRect = contentsToWindow(clipRect); 
       
   957     return intersection(clipRect, windowClipRect());
       
   958 }
       
   959 
       
   960 void FrameView::updateDashboardRegions()
       
   961 {
       
   962     Document* doc = m_frame->document();
       
   963     if (doc->hasDashboardRegions()) {
       
   964         Vector<DashboardRegionValue> newRegions;
       
   965         doc->renderer()->collectDashboardRegions(newRegions);
       
   966         doc->setDashboardRegions(newRegions);
       
   967         m_frame.get()->dashboardRegionsChanged();
       
   968     }
       
   969 }
       
   970 
       
   971 void FrameView::updateControlTints()
       
   972 {
       
   973     // This is called when control tints are changed from aqua/graphite to clear and vice versa.
       
   974     // We do a "fake" paint, and when the theme gets a paint call, it can then do an invalidate.
       
   975     // This is only done if the theme supports control tinting. It's up to the theme and platform
       
   976     // to define when controls get the tint and to call this function when that changes.
       
   977     
       
   978     // Optimize the common case where we bring a window to the front while it's still empty.
       
   979     if (!m_frame || m_frame->loader()->url().isEmpty()) 
       
   980         return;
       
   981     
       
   982     Document* doc = m_frame->document();
       
   983     if (doc && theme()->supportsControlTints() && m_frame->renderer()) {
       
   984         doc->updateLayout(); // Ensure layout is up to date.
       
   985         PlatformGraphicsContext* const noContext = 0;
       
   986         GraphicsContext context(noContext);
       
   987         context.setUpdatingControlTints(true);
       
   988         m_frame->paint(&context, enclosingIntRect(visibleContentRect()));
       
   989     }
       
   990 }
       
   991 
       
   992 bool FrameView::wasScrolledByUser() const
       
   993 {
       
   994     return d->m_wasScrolledByUser;
       
   995 }
       
   996 
       
   997 void FrameView::setWasScrolledByUser(bool wasScrolledByUser)
       
   998 {
       
   999     if (d->m_inProgrammaticScroll)
       
  1000         return;
       
  1001     d->m_wasScrolledByUser = wasScrolledByUser;
       
  1002 }
       
  1003 
       
  1004 #if PLATFORM(WIN) || PLATFORM(GTK)
       
  1005 void FrameView::layoutIfNeededRecursive()
       
  1006 {
       
  1007     // We have to crawl our entire tree looking for any FrameViews that need
       
  1008     // layout and make sure they are up to date.
       
  1009     // Mac actually tests for intersection with the dirty region and tries not to
       
  1010     // update layout for frames that are outside the dirty region.  Not only does this seem
       
  1011     // pointless (since those frames will have set a zero timer to layout anyway), but
       
  1012     // it is also incorrect, since if two frames overlap, the first could be excluded from the dirty
       
  1013     // region but then become included later by the second frame adding rects to the dirty region
       
  1014     // when it lays out.
       
  1015 
       
  1016     if (needsLayout())
       
  1017         layout();
       
  1018 
       
  1019     HashSet<Widget*>* viewChildren = children();
       
  1020     HashSet<Widget*>::iterator end = viewChildren->end();
       
  1021     for (HashSet<Widget*>::iterator current = viewChildren->begin(); current != end; ++current)
       
  1022         if ((*current)->isFrameView())
       
  1023             static_cast<FrameView*>(*current)->layoutIfNeededRecursive();
       
  1024 }
       
  1025 #endif
       
  1026 
       
  1027 }