#include "config.h"
#include "FrameView.h"
#include "AXObjectCache.h"
#include "CachedImage.h"
#include "Cursor.h"
#include "EventNames.h"
#include "Frame.h"
#include "FrameTree.h"
#include "HTMLDocument.h"
#include "HTMLFrameSetElement.h"
#include "HTMLInputElement.h"
#include "HTMLNames.h"
#include "Image.h"
#include "MouseEvent.h"
#include "MouseEventWithHitTestResults.h"
#include "OverflowEvent.h"
#include "PlatformKeyboardEvent.h"
#include "PlatformWheelEvent.h"
#include "RenderArena.h"
#include "RenderPart.h"
#include "RenderText.h"
#include "RenderView.h"
#include "Settings.h"
#include "SelectionController.h"
#include "cssstyleselector.h"
#include "XMLTokenizer.h"
#include "SystemTime.h"
namespace WebCore {
using namespace EventNames;
using namespace HTMLNames;
struct ScheduledEvent {
RefPtr<Event> m_event;
RefPtr<EventTargetNode> m_eventTarget;
bool m_tempEvent;
};
class FrameViewPrivate {
public:
FrameViewPrivate(FrameView* view)
: m_hasBorder(false)
, layoutTimer(view, &FrameView::layoutTimerFired)
, hoverTimer(view, &FrameView::hoverTimerFired)
, m_resizeLayer(0)
, m_mediaType("screen")
, m_scheduledEvents(0)
, m_overflowStatusDirty(true)
, m_viewportRenderer(0)
{
repaintRects = 0;
isTransparent = false;
vmode = hmode = ScrollBarAuto;
needToInitScrollBars = true;
reset();
}
~FrameViewPrivate()
{
delete repaintRects;
delete m_scheduledEvents;
}
void reset()
{
underMouse = 0;
oldUnder = 0;
oldSubframe = 0;
linkPressed = false;
useSlowRepaints = false;
dragTarget = 0;
borderTouched = false;
scrollBarMoved = false;
ignoreWheelEvents = false;
borderX = 30;
borderY = 30;
clickCount = 0;
clickNode = 0;
scrollingSelf = false;
layoutTimer.stop();
layoutRoot = 0;
delayedLayout = false;
mousePressed = false;
doFullRepaint = true;
layoutSchedulingEnabled = true;
layoutCount = 0;
firstLayout = true;
allowRepaints = false;
hoverTimer.stop();
if (repaintRects)
repaintRects->clear();
resizingFrameSet = 0;
m_resizeLayer = 0;
}
RefPtr<Node> underMouse;
RefPtr<Node> oldUnder;
RefPtr<Frame> oldSubframe;
bool borderTouched : 1;
bool borderStart : 1;
bool scrollBarMoved : 1;
bool doFullRepaint : 1;
bool m_hasBorder : 1;
ScrollBarMode vmode;
ScrollBarMode hmode;
bool linkPressed;
bool useSlowRepaints;
bool ignoreWheelEvents;
int borderX, borderY;
int clickCount;
RefPtr<Node> clickNode;
bool scrollingSelf;
Timer<FrameView> layoutTimer;
bool delayedLayout;
RefPtr<Node> layoutRoot;
bool layoutSchedulingEnabled;
int layoutCount;
bool allowRepaints;
bool firstLayout;
bool needToInitScrollBars;
bool mousePressed;
bool isTransparent;
Timer<FrameView> hoverTimer;
RenderLayer* m_resizeLayer;
IntSize offsetFromResizeCorner;
DeprecatedPtrList<RenderObject::RepaintInfo>* repaintRects;
RefPtr<Node> dragTarget;
RefPtr<HTMLFrameSetElement> resizingFrameSet;
String m_mediaType;
Vector<ScheduledEvent*>* m_scheduledEvents;
bool m_overflowStatusDirty;
bool horizontalOverflow;
bool m_verticalOverflow;
RenderObject* m_viewportRenderer;
};
FrameView::FrameView(Frame *frame)
: m_refCount(1)
, m_frame(frame)
, d(new FrameViewPrivate(this))
{
init();
show();
}
FrameView::~FrameView()
{
resetScrollBars();
ASSERT(m_refCount == 0);
if (d->hoverTimer.isActive())
d->hoverTimer.stop();
if (m_frame) {
if (Document* doc = m_frame->document())
doc->detach();
if (RenderPart* renderer = m_frame->ownerRenderer())
renderer->setWidget(0);
}
delete d;
d = 0;
}
void FrameView::clearPart()
{
m_frame = 0;
}
void FrameView::resetScrollBars()
{
d->firstLayout = true;
suppressScrollBars(true);
ScrollView::setVScrollBarMode(d->vmode);
ScrollView::setHScrollBarMode(d->hmode);
suppressScrollBars(false);
}
void FrameView::init()
{
m_margins = IntSize(-1, -1); m_size = IntSize();
}
void FrameView::clear()
{
setStaticBackground(false);
m_frame->setSelection(SelectionController());
d->reset();
#if INSTRUMENT_LAYOUT_SCHEDULING
if (d->layoutTimer.isActive() && m_frame->document() && !m_frame->document()->ownerElement())
printf("Killing the layout timer from a clear at %d\n", m_frame->document()->elapsedTime());
#endif
d->layoutTimer.stop();
cleared();
suppressScrollBars(true);
}
void FrameView::initScrollBars()
{
if (!d->needToInitScrollBars)
return;
d->needToInitScrollBars = false;
setScrollBarsMode(hScrollBarMode());
}
void FrameView::setMarginWidth(int w)
{
m_margins.setWidth(w);
}
void FrameView::setMarginHeight(int h)
{
m_margins.setHeight(h);
}
void FrameView::adjustViewSize()
{
if (m_frame->document()) {
Document *document = m_frame->document();
RenderView* root = static_cast<RenderView *>(document->renderer());
if (!root)
return;
int docw = root->docWidth();
int doch = root->docHeight();
resizeContents(docw, doch);
}
}
void FrameView::applyOverflowToViewport(RenderObject* o, ScrollBarMode& hMode, ScrollBarMode& vMode)
{
switch (o->style()->overflowX()) {
case OHIDDEN:
hMode = ScrollBarAlwaysOff;
break;
case OSCROLL:
hMode = ScrollBarAlwaysOn;
break;
case OAUTO:
hMode = ScrollBarAuto;
break;
default:
;
}
switch (o->style()->overflowY()) {
case OHIDDEN:
vMode = ScrollBarAlwaysOff;
break;
case OSCROLL:
vMode = ScrollBarAlwaysOn;
break;
case OAUTO:
vMode = ScrollBarAuto;
break;
default:
;
}
d->m_viewportRenderer = o;
}
int FrameView::layoutCount() const
{
return d->layoutCount;
}
bool FrameView::needsFullRepaint() const
{
return d->doFullRepaint;
}
void FrameView::addRepaintInfo(RenderObject* o, const IntRect& r)
{
if (!d->repaintRects) {
d->repaintRects = new DeprecatedPtrList<RenderObject::RepaintInfo>;
d->repaintRects->setAutoDelete(true);
}
d->repaintRects->append(new RenderObject::RepaintInfo(o, r));
}
Node* FrameView::layoutRoot() const
{
return layoutPending() ? 0 : d->layoutRoot.get();
}
void FrameView::layout(bool allowSubtree)
{
bool didFirstLayout = false;
setVisibleSizeOverrideEnabled(true);
d->layoutTimer.stop();
d->delayedLayout = false;
RefPtr<FrameView> protector(this);
if (!m_frame) {
m_size.setWidth(visibleWidth());
goto abort;
}
if (!allowSubtree && d->layoutRoot) {
if (d->layoutRoot->renderer())
d->layoutRoot->renderer()->markContainingBlocksForLayout(false);
d->layoutRoot = 0;
}
bool subtree = d->layoutRoot;
Document* document = m_frame->document();
if (!document) {
m_size.setWidth(visibleWidth());
goto abort;
}
Node* rootNode = subtree ? d->layoutRoot.get() : document;
d->layoutSchedulingEnabled = false;
if (document->hasChangedChild())
document->recalcStyle();
if (protector->hasOneRef())
goto abort;
RenderObject* root = rootNode->renderer();
if (!root) {
d->layoutSchedulingEnabled = true;
goto abort;
}
d->allowRepaints = true;
double startTime = currentTime();
ScrollBarMode hMode = d->hmode;
ScrollBarMode vMode = d->vmode;
if (!subtree) {
Document* document = static_cast<Document*>(rootNode);
RenderObject* rootRenderer = document->documentElement() ? document->documentElement()->renderer() : 0;
if (document->isHTMLDocument()) {
Node* body = static_cast<HTMLDocument*>(document)->body();
if (body && body->renderer()) {
if (body->hasTagName(framesetTag) && !m_frame->settings()->flatFrameSetLayoutEnabled()) {
body->renderer()->setChildNeedsLayout(true);
vMode = ScrollBarAlwaysOff;
hMode = ScrollBarAlwaysOff;
} else if (body->hasTagName(bodyTag)) {
if (!d->firstLayout && m_size.height() != visibleHeight()
&& static_cast<RenderBox*>(body->renderer())->stretchesToViewHeight())
body->renderer()->setChildNeedsLayout(true);
RenderObject* o = rootRenderer->style()->overflowX() == OVISIBLE
? body->renderer() : rootRenderer;
applyOverflowToViewport(o, hMode, vMode); }
}
} else if (rootRenderer)
applyOverflowToViewport(rootRenderer, hMode, vMode); #if INSTRUMENT_LAYOUT_SCHEDULING
if (d->firstLayout && !document->ownerElement())
printf("Elapsed time before first layout: %d\n", document->elapsedTime());
#endif
}
d->doFullRepaint = !subtree && (d->firstLayout || static_cast<RenderView*>(root)->printingMode());
if (d->repaintRects)
d->repaintRects->clear();
if (!subtree) {
ScrollBarMode currentHMode = hScrollBarMode();
ScrollBarMode currentVMode = vScrollBarMode();
if (d->firstLayout || (hMode != currentHMode || vMode != currentVMode)) {
suppressScrollBars(true);
if (d->firstLayout) {
d->firstLayout = false;
didFirstLayout = true;
if (vMode == ScrollBarAuto)
ScrollView::setVScrollBarMode(ScrollBarAlwaysOn); if (hMode == ScrollBarAuto)
ScrollView::setHScrollBarMode(ScrollBarAlwaysOff); }
if (hMode == vMode)
ScrollView::setScrollBarsMode(hMode);
else {
ScrollView::setHScrollBarMode(hMode);
ScrollView::setVScrollBarMode(vMode);
}
suppressScrollBars(false, true);
}
IntSize oldSize = m_size;
m_size = IntSize(visibleWidth(), visibleHeight());
if (oldSize != m_size)
d->doFullRepaint = true;
}
RenderLayer* layer = root->enclosingLayer();
if (!d->doFullRepaint) {
layer->checkForRepaintOnResize();
root->repaintObjectsBeforeLayout();
}
if (subtree) {
if (root->recalcMinMax())
root->recalcMinMaxWidths();
}
root->layout();
d->layoutRoot = 0;
float minZoomFontSize = minimumZoomFontSize();
float visWidth = visibleSize().width;
if (minZoomFontSize != 0 && visWidth != 0) {
root->adjustComputedFontSizesOnBlocks(minZoomFontSize, visWidth);
bool needsLayout = root->needsLayout();
if (needsLayout)
root->layout();
}
m_frame->invalidateSelection();
d->layoutSchedulingEnabled=true;
if (!subtree && !static_cast<RenderView*>(root)->printingMode())
resizeContents(layer->width(), layer->height());
layer->updateLayerPositions(d->doFullRepaint);
if (!subtree)
static_cast<RenderView*>(root)->updateWidgetPositions();
if (d->repaintRects && !d->repaintRects->isEmpty()) {
RenderObject::RepaintInfo* r;
DeprecatedPtrListIterator<RenderObject::RepaintInfo> it(*d->repaintRects);
for (; (r = it.current()); ++it)
r->m_object->repaintRectangle(r->m_repaintRect);
d->repaintRects->clear();
}
d->layoutCount++;
#if __APPLE__
updateDashboardRegions();
d->allowRepaints = false;
double endTime = currentTime();
m_frame->didLayout(didFirstLayout, endTime - startTime);
#endif
if (root->needsLayout()) {
scheduleRelayout();
goto abort;
}
setStaticBackground(d->useSlowRepaints);
if (document->hasListenerType(Document::OVERFLOWCHANGED_LISTENER))
updateOverflowStatus(visibleWidth() < contentsWidth(),
visibleHeight() < contentsHeight());
dispatchScheduledEvents();
abort:
setVisibleSizeOverrideEnabled(false);
}
static Frame* subframeForEvent(const MouseEventWithHitTestResults& mev)
{
if (!mev.targetNode())
return 0;
RenderObject* renderer = mev.targetNode()->renderer();
if (!renderer || !renderer->isWidget())
return 0;
Widget* widget = static_cast<RenderWidget*>(renderer)->widget();
if (!widget || !widget->isFrameView())
return 0;
return static_cast<FrameView*>(widget)->frame();
}
void FrameView::handleMousePressEvent(const PlatformMouseEvent& mouseEvent)
{
if (!m_frame->document())
return;
RefPtr<FrameView> protector(this);
d->mousePressed = true;
MouseEventWithHitTestResults mev = prepareMouseEvent(false, true, false, mouseEvent);
if (m_frame->passSubframeEventToSubframe(mev)) {
invalidateClick();
return;
}
d->clickCount = mouseEvent.clickCount();
d->clickNode = mev.targetNode();
if (!d->clickNode) return invalidateClick();
RenderLayer* layer = d->clickNode->renderer()? d->clickNode->renderer()->enclosingLayer() : 0;
IntPoint p = viewportToContents(mouseEvent.pos());
if (layer && layer->isPointInResizeControl(p)) {
layer->setInResizeMode(true);
d->m_resizeLayer = layer;
d->offsetFromResizeCorner = layer->offsetFromResizeCorner(p);
invalidateClick();
return;
}
bool swallowEvent = dispatchMouseEvent(mousedownEvent, mev.targetNode(), true, d->clickCount, mouseEvent, true);
if (!swallowEvent) {
if (mev.targetNode()->isShadowNode() && mev.targetNode()->shadowParentNode()->hasTagName(inputTag))
mev = prepareMouseEvent(true, true, false, mouseEvent);
m_frame->handleMousePressEvent(mev);
if (m_frame->lastEventIsMouseUp())
d->mousePressed = false;
}
m_frame->passEventToScrollView();
}
void FrameView::handleMouseDoubleClickEvent(const PlatformMouseEvent& mouseEvent)
{
if (!m_frame->document())
return;
RefPtr<FrameView> protector(this);
d->mousePressed = false;
MouseEventWithHitTestResults mev = prepareMouseEvent(false, true, false, mouseEvent);
if (m_frame->passSubframeEventToSubframe(mev))
return;
d->clickCount = mouseEvent.clickCount();
bool swallowEvent = dispatchMouseEvent(mouseupEvent, mev.targetNode(), true, d->clickCount, mouseEvent, false);
if (mev.targetNode() == d->clickNode)
dispatchMouseEvent(clickEvent, mev.targetNode(), true, d->clickCount, mouseEvent, true);
if (!swallowEvent) {
m_frame->handleMouseReleaseEvent(mev);
m_frame->handleMouseReleaseDoubleClickEvent(mev);
}
invalidateClick();
}
void FrameView::handleMouseMoveEvent(const PlatformMouseEvent& mouseEvent)
{
ASSERT(m_frame);
if (!m_frame || !m_frame->document())
return;
RefPtr<FrameView> protector(this);
if (d->hoverTimer.isActive())
d->hoverTimer.stop();
if (d->resizingFrameSet) {
dispatchMouseEvent(mousemoveEvent, d->resizingFrameSet.get(), false, 0, mouseEvent, false);
return;
}
MouseEventWithHitTestResults mev = prepareMouseEvent(d->mousePressed && m_frame->mouseDownMayStartSelect(),
d->mousePressed, true, mouseEvent);
bool subFrameHandledEvent = false;
if (d->oldSubframe && d->oldSubframe->tree()->isDescendantOf(m_frame.get()))
subFrameHandledEvent = m_frame->passSubframeEventToSubframe(mev, d->oldSubframe.get());
bool swallowEvent = dispatchMouseEvent(mousemoveEvent, mev.targetNode(), false, 0, mouseEvent, true);
if (d->m_resizeLayer && d->m_resizeLayer->inResizeMode())
d->m_resizeLayer->resize(mouseEvent, d->offsetFromResizeCorner);
if (!swallowEvent)
m_frame->handleMouseMoveEvent(mev);
RefPtr<Frame> newSubframe = subframeForEvent(mev);
if (newSubframe && d->oldSubframe != newSubframe)
subFrameHandledEvent = m_frame->passSubframeEventToSubframe(mev, newSubframe.get());
d->oldSubframe = newSubframe;
if (!subFrameHandledEvent)
m_frame->passEventToScrollView();
}
void FrameView::invalidateClick()
{
d->clickCount = 0;
d->clickNode = 0;
}
bool FrameView::mousePressed()
{
return d->mousePressed;
}
void FrameView::handleMouseReleaseEvent(const PlatformMouseEvent& mouseEvent)
{
if (!m_frame->document())
return;
RefPtr<FrameView> protector(this);
d->mousePressed = false;
if (d->resizingFrameSet) {
dispatchMouseEvent(mouseupEvent, d->resizingFrameSet.get(), true, d->clickCount, mouseEvent, false);
return;
}
MouseEventWithHitTestResults mev = prepareMouseEvent(false, false, false, mouseEvent);
if (m_frame->passSubframeEventToSubframe(mev))
return;
bool swallowEvent = dispatchMouseEvent(mouseupEvent, mev.targetNode(), true, d->clickCount, mouseEvent, false);
if (d->clickCount > 0 && mev.targetNode() == d->clickNode)
dispatchMouseEvent(clickEvent, mev.targetNode(), true, d->clickCount, mouseEvent, true);
if (d->m_resizeLayer) {
d->m_resizeLayer->setInResizeMode(false);
d->m_resizeLayer = 0;
}
if (!swallowEvent)
m_frame->handleMouseReleaseEvent(mev);
invalidateClick();
m_frame->passEventToScrollView();
}
bool FrameView::dispatchDragEvent(const AtomicString& eventType, Node *dragTarget, const PlatformMouseEvent& event, Clipboard* clipboard)
{
IntPoint contentsPos = viewportToContents(event.pos());
RefPtr<MouseEvent> me = new MouseEvent(eventType,
true, true, m_frame->document()->defaultView(),
0, event.globalX(), event.globalY(), contentsPos.x(), contentsPos.y(),
event.ctrlKey(), event.altKey(), event.shiftKey(), event.metaKey(),
0, 0, clipboard);
ExceptionCode ec = 0;
EventTargetNodeCast(dragTarget)->dispatchEvent(me.get(), ec, true);
return me->defaultPrevented();
}
bool FrameView::updateDragAndDrop(const PlatformMouseEvent& event, Clipboard* clipboard)
{
bool accept = false;
MouseEventWithHitTestResults mev = prepareMouseEvent(true, false, false, event);
Node* newTarget = mev.targetNode();
if (newTarget && newTarget->isTextNode())
newTarget = newTarget->parentNode();
if (newTarget)
newTarget = newTarget->shadowAncestorNode();
if (d->dragTarget != newTarget) {
if (newTarget)
accept = dispatchDragEvent(dragenterEvent, newTarget, event, clipboard);
if (d->dragTarget)
dispatchDragEvent(dragleaveEvent, d->dragTarget.get(), event, clipboard);
} else {
if (newTarget)
accept = dispatchDragEvent(dragoverEvent, newTarget, event, clipboard);
}
d->dragTarget = newTarget;
return accept;
}
void FrameView::cancelDragAndDrop(const PlatformMouseEvent& event, Clipboard* clipboard)
{
if (d->dragTarget)
dispatchDragEvent(dragleaveEvent, d->dragTarget.get(), event, clipboard);
d->dragTarget = 0;
}
bool FrameView::performDragAndDrop(const PlatformMouseEvent& event, Clipboard* clipboard)
{
bool accept = false;
if (d->dragTarget)
accept = dispatchDragEvent(dropEvent, d->dragTarget.get(), event, clipboard);
d->dragTarget = 0;
return accept;
}
Node* FrameView::nodeUnderMouse() const
{
return d->underMouse.get();
}
bool FrameView::scrollTo(const IntRect& bounds)
{
d->scrollingSelf = true;
int x, y, xe, ye;
x = bounds.x();
y = bounds.y();
xe = bounds.right() - 1;
ye = bounds.bottom() - 1;
int deltax;
int deltay;
int curHeight = visibleHeight();
int curWidth = visibleWidth();
if (ye - y>curHeight-d->borderY)
ye = y + curHeight - d->borderY;
if (xe - x>curWidth-d->borderX)
xe = x + curWidth - d->borderX;
if (x < contentsX() + d->borderX)
deltax = x - contentsX() - d->borderX;
else if (xe + d->borderX > contentsX() + curWidth)
deltax = xe + d->borderX - (contentsX() + curWidth);
else
deltax = 0;
if (y < contentsY() + d->borderY)
deltay = y - contentsY() - d->borderY;
else if (ye + d->borderY > contentsY() + curHeight)
deltay = ye + d->borderY - (contentsY() + curHeight);
else
deltay = 0;
int maxx = curWidth - d->borderX;
int maxy = curHeight - d->borderY;
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);
if (contentsX() + scrollX < 0)
scrollX = -contentsX();
else if (contentsWidth() - visibleWidth() - contentsX() < scrollX)
scrollX = contentsWidth() - visibleWidth() - contentsX();
if (contentsY() + scrollY < 0)
scrollY = -contentsY();
else if (contentsHeight() - visibleHeight() - contentsY() < scrollY)
scrollY = contentsHeight() - visibleHeight() - contentsY();
scrollBy(scrollX, scrollY);
if (scrollX < 0)
scrollX = -scrollX;
if (scrollY < 0)
scrollY = -scrollY;
d->scrollingSelf = false;
return scrollX != maxx && scrollY != maxy;
}
void FrameView::focusNextPrevNode(bool next)
{
Document *doc = m_frame->document();
Node *oldFocusNode = doc->focusNode();
Node *newFocusNode;
if (next)
newFocusNode = doc->nextFocusNode(oldFocusNode);
else
newFocusNode = doc->previousFocusNode(oldFocusNode);
if (!oldFocusNode && newFocusNode && d->scrollBarMoved) {
bool visible = false;
Node *toFocus = newFocusNode;
while (!visible && toFocus) {
if (toFocus->getRect().intersects(IntRect(contentsX(), contentsY(), visibleWidth(), visibleHeight()))) {
visible = true;
} else {
if (next)
toFocus = doc->nextFocusNode(toFocus);
else
toFocus = doc->previousFocusNode(toFocus);
}
}
if (toFocus)
newFocusNode = toFocus;
}
d->scrollBarMoved = false;
if (!newFocusNode)
{
if (next)
scrollTo(IntRect(contentsX()+visibleWidth()/2,contentsHeight(),0,0));
else
scrollTo(IntRect(contentsX()+visibleWidth()/2,0,0,0));
}
else {
if (newFocusNode->isContentEditable()) {
}
else {
}
if (oldFocusNode) {
if (!scrollTo(newFocusNode->getRect()))
return;
}
else {
if (doc->renderer()) {
doc->renderer()->enclosingLayer()->scrollRectToVisible(IntRect(contentsX(), next ? 0: contentsHeight(), 0, 0));
}
}
}
m_frame->document()->setFocusNode(newFocusNode);
}
void FrameView::setMediaType(const String& mediaType)
{
d->m_mediaType = mediaType;
}
String FrameView::mediaType() const
{
String overrideType = m_frame->overrideMediaType();
if (!overrideType.isNull())
return overrideType;
return d->m_mediaType;
}
void FrameView::useSlowRepaints()
{
d->useSlowRepaints = true;
setStaticBackground(true);
}
void FrameView::setScrollBarsMode(ScrollBarMode mode)
{
d->vmode = mode;
d->hmode = mode;
ScrollView::setScrollBarsMode(mode);
}
void FrameView::setVScrollBarMode(ScrollBarMode mode)
{
d->vmode = mode;
ScrollView::setVScrollBarMode(mode);
}
void FrameView::setHScrollBarMode(ScrollBarMode mode)
{
d->hmode = mode;
ScrollView::setHScrollBarMode(mode);
}
void FrameView::restoreScrollBar()
{
suppressScrollBars(false);
}
void FrameView::setResizingFrameSet(HTMLFrameSetElement* frameSet)
{
d->resizingFrameSet = frameSet;
}
void FrameView::scrollPointRecursively(int x, int y)
{
if (frame()->prohibitsScrolling())
return;
ScrollView::scrollPointRecursively(x, y);
}
void FrameView::setContentsPos(int x, int y)
{
if (frame()->prohibitsScrolling())
return;
ScrollView::setContentsPos(x, y);
}
MouseEventWithHitTestResults FrameView::prepareMouseEvent(bool readonly, bool active, bool mouseMove, const PlatformMouseEvent& mev)
{
ASSERT(m_frame);
ASSERT(m_frame->document());
IntPoint vPoint = viewportToContents(mev.pos());
return m_frame->document()->prepareMouseEvent(readonly, active, mouseMove, vPoint, mev);
}
bool FrameView::dispatchMouseEvent(const AtomicString& eventType, Node* targetNode, bool cancelable,
int clickCount, const PlatformMouseEvent& mouseEvent, bool setUnder)
{
if (targetNode && targetNode->isTextNode())
targetNode = targetNode->parentNode();
if (targetNode)
targetNode = targetNode->shadowAncestorNode();
d->underMouse = targetNode;
if (setUnder) {
if (d->oldUnder && d->oldUnder->document() != frame()->document())
d->oldUnder = 0;
if (d->oldUnder != targetNode) {
if (d->oldUnder)
EventTargetNodeCast(d->oldUnder.get())->dispatchMouseEvent(mouseEvent, mouseoutEvent, 0, targetNode);
if (targetNode)
EventTargetNodeCast(targetNode)->dispatchMouseEvent(mouseEvent, mouseoverEvent, 0, d->oldUnder.get());
}
d->oldUnder = targetNode;
}
bool swallowEvent = false;
if (targetNode)
swallowEvent = EventTargetNodeCast(targetNode)->dispatchMouseEvent(mouseEvent, eventType, clickCount);
if (!swallowEvent && eventType == mousedownEvent) {
Node* node = targetNode;
RenderObject* renderer = node ? node->renderer() : 0;
while (renderer) {
node = renderer->element();
if (node && node->isFocusable())
break;
renderer = renderer->parent();
}
if (node && node->isMouseFocusable()) {
if (!m_frame->document()->setFocusNode(node))
swallowEvent = true;
} else if (!node || !node->focused()) {
if (!m_frame->document()->setFocusNode(0))
swallowEvent = true;
}
}
return swallowEvent;
}
void FrameView::setIgnoreWheelEvents(bool e)
{
d->ignoreWheelEvents = e;
}
void FrameView::handleWheelEvent(PlatformWheelEvent& e)
{
Document *doc = m_frame->document();
if (doc) {
RenderObject *docRenderer = doc->renderer();
if (docRenderer) {
IntPoint vPoint = viewportToContents(e.pos());
RenderObject::NodeInfo hitTestResult(true, false);
doc->renderer()->layer()->hitTest(hitTestResult, vPoint);
Node *node = hitTestResult.innerNode();
if (m_frame->passWheelEventToChildWidget(node)) {
e.accept();
return;
}
if (node) {
node = node->shadowAncestorNode();
EventTargetNodeCast(node)->dispatchWheelEvent(e);
if (e.isAccepted())
return;
}
}
}
}
void FrameView::scrollBarMoved()
{
if (!d->scrollingSelf)
d->scrollBarMoved = true;
}
#define PREVENT_NONLAYOUT_REPAINTS 0
void FrameView::repaintRectangle(const IntRect& r, bool immediate)
{
#if PREVENT_NONLAYOUT_REPAINTS
if (!m_frame->isComplete() && !d->allowRepaints)
return;
#endif
updateContents(r, immediate);
}
void FrameView::layoutTimerFired(Timer<FrameView>*)
{
#if INSTRUMENT_LAYOUT_SCHEDULING
if (m_frame->document() && !m_frame->document()->ownerElement())
printf("Layout timer fired at %d\n", m_frame->document()->elapsedTime());
#endif
d->allowRepaints = true;
if (m_frame->document() && m_frame->document()->tokenizer())
m_frame->document()->tokenizer()->parsePending();
layout();
d->allowRepaints = false;
}
void FrameView::hoverTimerFired(Timer<FrameView>*)
{
d->hoverTimer.stop();
prepareMouseEvent(false, false, true, PlatformMouseEvent(PlatformMouseEvent::currentEvent));
}
void FrameView::scheduleRelayout()
{
if (d->layoutRoot) {
if (d->layoutRoot->renderer())
d->layoutRoot->renderer()->markContainingBlocksForLayout(false);
d->layoutRoot = 0;
}
if (!d->layoutSchedulingEnabled)
return;
if (!m_frame->document() || !m_frame->document()->shouldScheduleLayout())
return;
if (m_frame->settings()->flatFrameSetLayoutEnabled() && m_frame->ownerRenderer())
m_frame->ownerRenderer()->setNeedsLayout(true, true);
int delay = m_frame->document()->minimumLayoutDelay();
if (d->layoutTimer.isActive() && d->delayedLayout && !delay)
unscheduleRelayout();
if (d->layoutTimer.isActive())
return;
d->delayedLayout = delay != 0;
#if INSTRUMENT_LAYOUT_SCHEDULING
if (!m_frame->document()->ownerElement())
printf("Scheduling layout for %d\n", delay);
#endif
d->layoutTimer.startOneShot(delay * 0.001);
}
void FrameView::scheduleRelayoutOfSubtree(Node* n)
{
if (!d->layoutSchedulingEnabled || m_frame->document() && m_frame->document()->renderer() && m_frame->document()->renderer()->needsLayout()) {
if (n->renderer())
n->renderer()->markContainingBlocksForLayout(false);
return;
}
if (layoutPending()) {
if (d->layoutRoot != n) {
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);
}
}
bool FrameView::layoutPending() const
{
return d->layoutTimer.isActive();
}
bool FrameView::haveDelayedLayoutScheduled()
{
return d->layoutTimer.isActive() && d->delayedLayout;
}
void FrameView::unscheduleRelayout()
{
if (!d->layoutTimer.isActive())
return;
#if INSTRUMENT_LAYOUT_SCHEDULING
if (m_frame->document() && !m_frame->document()->ownerElement())
printf("Layout timer unscheduled at %d\n", m_frame->document()->elapsedTime());
#endif
d->layoutTimer.stop();
d->delayedLayout = false;
}
bool FrameView::isTransparent() const
{
return d->isTransparent;
}
void FrameView::setTransparent(bool isTransparent)
{
d->isTransparent = isTransparent;
}
void FrameView::scheduleHoverStateUpdate()
{
if (!d->hoverTimer.isActive())
d->hoverTimer.startOneShot(0);
}
void FrameView::setHasBorder(bool b)
{
d->m_hasBorder = b;
updateBorder();
}
bool FrameView::hasBorder() const
{
return d->m_hasBorder;
}
void FrameView::cleared()
{
if (m_frame)
if (RenderPart* renderer = m_frame->ownerRenderer())
renderer->viewCleared();
}
void FrameView::scheduleEvent(PassRefPtr<Event> event, PassRefPtr<EventTargetNode> eventTarget, bool tempEvent)
{
if (!d->m_scheduledEvents)
d->m_scheduledEvents = new Vector<ScheduledEvent*>;
ScheduledEvent *scheduledEvent = new ScheduledEvent;
scheduledEvent->m_event = event;
scheduledEvent->m_eventTarget = eventTarget;
scheduledEvent->m_tempEvent = tempEvent;
d->m_scheduledEvents->append(scheduledEvent);
}
void FrameView::updateOverflowStatus(bool horizontalOverflow, bool verticalOverflow)
{
if (!d->m_viewportRenderer)
return;
if (d->m_overflowStatusDirty) {
d->horizontalOverflow = horizontalOverflow;
d->m_verticalOverflow = verticalOverflow;
d->m_overflowStatusDirty = false;
return;
}
bool horizontalOverflowChanged = (d->horizontalOverflow != horizontalOverflow);
bool verticalOverflowChanged = (d->m_verticalOverflow != verticalOverflow);
if (horizontalOverflowChanged || verticalOverflowChanged) {
d->horizontalOverflow = horizontalOverflow;
d->m_verticalOverflow = verticalOverflow;
scheduleEvent(new OverflowEvent(horizontalOverflowChanged, horizontalOverflow, verticalOverflowChanged, verticalOverflow),
EventTargetNodeCast(d->m_viewportRenderer->element()), true);
}
}
void FrameView::dispatchScheduledEvents()
{
if (!d->m_scheduledEvents)
return;
Vector<ScheduledEvent*> scheduledEventsCopy = *d->m_scheduledEvents;
d->m_scheduledEvents->clear();
Vector<ScheduledEvent*>::iterator end = scheduledEventsCopy.end();
for (Vector<ScheduledEvent*>::iterator it = scheduledEventsCopy.begin(); it != end; ++it) {
ScheduledEvent* scheduledEvent = *it;
ExceptionCode ec = 0;
if (scheduledEvent->m_eventTarget->inDocument())
scheduledEvent->m_eventTarget->dispatchEvent(scheduledEvent->m_event, ec, scheduledEvent->m_tempEvent);
delete scheduledEvent;
}
}
}