void reset()
{
underMouse = 0;
+ oldUnder = 0;
+ oldSubframe = 0;
linkPressed = false;
useSlowRepaints = false;
dragTarget = 0;
ignoreWheelEvents = false;
borderX = 30;
borderY = 30;
- prevMouseX = -1;
- prevMouseY = -1;
clickCount = 0;
clickNode = 0;
scrollingSelf = false;
}
RefPtr<Node> underMouse;
+ RefPtr<Node> oldUnder;
+ RefPtr<Frame> oldSubframe;
bool borderTouched : 1;
bool borderStart : 1;
int clickCount;
RefPtr<Node> clickNode;
- int prevMouseX, prevMouseY;
bool scrollingSelf;
Timer<FrameView> layoutTimer;
bool delayedLayout;
//
/////////////////
+static Frame* subframeForEvent(const MouseEventWithHitTestResults& mev)
+{
+ if (!mev.innerNode())
+ return 0;
+
+ RenderObject* renderer = mev.innerNode()->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())
RefPtr<FrameView> protector(this);
- int xm, ym;
- viewportToContents(mouseEvent.x(), mouseEvent.y(), xm, ym);
-
d->mousePressed = true;
- MouseEventWithHitTestResults mev = m_frame->document()->prepareMouseEvent(false, true, false, xm, ym, mouseEvent);
+ MouseEventWithHitTestResults mev = prepareMouseEvent(false, true, false, mouseEvent);
if (m_frame->passSubframeEventToSubframe(mev)) {
invalidateClick();
RefPtr<FrameView> protector(this);
- int xm, ym;
- viewportToContents(mouseEvent.x(), mouseEvent.y(), xm, ym);
-
// We get this instead of a second mouse-up
d->mousePressed = false;
- MouseEventWithHitTestResults mev = m_frame->document()->prepareMouseEvent(false, true, false, xm, ym, mouseEvent);
+ MouseEventWithHitTestResults mev = prepareMouseEvent(false, true, false, mouseEvent);
if (m_frame->passSubframeEventToSubframe(mev))
return;
if (!m_frame || !m_frame->document())
return;
+ RefPtr<FrameView> protector(this);
+
if (d->hoverTimer.isActive())
d->hoverTimer.stop();
- int xm, ym;
- viewportToContents(mouseEvent.x(), mouseEvent.y(), xm, ym);
-
if (d->resizingFrameSet) {
dispatchMouseEvent(mousemoveEvent, d->resizingFrameSet.get(), false, 0, mouseEvent, false);
return;
// if we are allowed to select.
// This means that :hover and :active freeze in the state they were in when the mouse
// was pressed, rather than updating for nodes the mouse moves over as you hold the mouse down.
- MouseEventWithHitTestResults mev = m_frame->document()->prepareMouseEvent(d->mousePressed && m_frame->mouseDownMayStartSelect(),
- d->mousePressed, true, xm, ym, mouseEvent);
+ MouseEventWithHitTestResults mev = prepareMouseEvent(d->mousePressed && m_frame->mouseDownMayStartSelect(),
+ d->mousePressed, true, mouseEvent);
+
+ if (d->oldSubframe)
+ m_frame->passSubframeEventToSubframe(mev, d->oldSubframe.get());
- if (!m_frame->passSubframeEventToSubframe(mev))
- setCursor(selectCursor(mev, m_frame.get(), d->mousePressed));
-
bool swallowEvent = dispatchMouseEvent(mousemoveEvent, mev.innerNode(), false, 0, mouseEvent, true);
if (!swallowEvent)
m_frame->handleMouseMoveEvent(mev);
+
+ RefPtr<Frame> newSubframe = subframeForEvent(mev);
+
+ if (newSubframe && d->oldSubframe != newSubframe)
+ m_frame->passSubframeEventToSubframe(mev, newSubframe.get());
+ else
+ setCursor(selectCursor(mev, m_frame.get(), d->mousePressed));
+
+ d->oldSubframe = newSubframe;
}
void FrameView::invalidateClick()
RefPtr<FrameView> protector(this);
- int xm, ym;
- viewportToContents(mouseEvent.x(), mouseEvent.y(), xm, ym);
-
d->mousePressed = false;
if (d->resizingFrameSet) {
return;
}
- MouseEventWithHitTestResults mev = m_frame->document()->prepareMouseEvent(false, false, false, xm, ym, mouseEvent);
+ MouseEventWithHitTestResults mev = prepareMouseEvent(false, false, false, mouseEvent);
if (m_frame->passSubframeEventToSubframe(mev))
return;
bool FrameView::updateDragAndDrop(const PlatformMouseEvent& event, Clipboard* clipboard)
{
bool accept = false;
- int xm, ym;
- viewportToContents(event.x(), event.y(), xm, ym);
- MouseEventWithHitTestResults mev = m_frame->document()->prepareMouseEvent(true, false, false, xm, ym, PlatformMouseEvent());
+
+ MouseEventWithHitTestResults mev = prepareMouseEvent(true, false, false, PlatformMouseEvent());
// Drag events should never go to text nodes (following IE, and proper mouseover/out dispatch)
Node* newTarget = mev.innerNode();
d->resizingFrameSet = frameSet;
}
+MouseEventWithHitTestResults FrameView::prepareMouseEvent(bool readonly, bool active, bool mouseMove, const PlatformMouseEvent& mev)
+{
+ ASSERT(m_frame);
+ ASSERT(m_frame->document());
+
+ int xm, ym;
+ viewportToContents(mev.x(), mev.y(), xm, ym);
+
+ return m_frame->document()->prepareMouseEvent(readonly, active, mouseMove, xm, ym, mev);
+}
+
bool FrameView::dispatchMouseEvent(const AtomicString& eventType, Node* targetNode, bool cancelable,
int clickCount, const PlatformMouseEvent& mouseEvent, bool setUnder)
{
// mouseout/mouseover
if (setUnder) {
- int clientX, clientY;
- viewportToContents(mouseEvent.x(), mouseEvent.y(), clientX, clientY);
- if (d->prevMouseX != clientX || d->prevMouseY != clientY) {
- // ### this code sucks. we should save the oldUnder instead of calculating
- // it again. calculating is expensive! (Dirk)
- // Also, there's no guarantee that the old under node is even around any more,
- // so we could be sending a mouseout to a node that never got a mouseover.
- RefPtr<Node> oldUnder;
- if (d->prevMouseX >= 0) {
- oldUnder = m_frame->document()->prepareMouseEvent(true, false, true,
- d->prevMouseX, d->prevMouseY, mouseEvent).innerNode();
- if (oldUnder && oldUnder->isTextNode())
- oldUnder = oldUnder->parentNode();
- }
- d->prevMouseX = clientX;
- d->prevMouseY = clientY;
- if (oldUnder != targetNode) {
- // send mouseout event to the old node
- if (oldUnder)
- EventTargetNodeCast(oldUnder.get())->dispatchMouseEvent(mouseEvent, mouseoutEvent, 0, targetNode);
- // send mouseover event to the new node
- if (targetNode)
- EventTargetNodeCast(targetNode)->dispatchMouseEvent(mouseEvent, mouseoverEvent, 0, oldUnder.get());
- }
+ if (d->oldUnder && d->oldUnder->getDocument() != frame()->document())
+ d->oldUnder = 0;
+
+ if (d->oldUnder != targetNode) {
+ // send mouseout event to the old node
+ if (d->oldUnder)
+ EventTargetNodeCast(d->oldUnder.get())->dispatchMouseEvent(mouseEvent, mouseoutEvent, 0, targetNode);
+ // send mouseover event to the new node
+ if (targetNode)
+ EventTargetNodeCast(targetNode)->dispatchMouseEvent(mouseEvent, mouseoverEvent, 0, d->oldUnder.get());
}
+ d->oldUnder = targetNode;
}
bool swallowEvent = false;
void FrameView::hoverTimerFired(Timer<FrameView>*)
{
d->hoverTimer.stop();
- m_frame->document()->prepareMouseEvent(false, false, true, d->prevMouseX, d->prevMouseY, PlatformMouseEvent());
+ prepareMouseEvent(false, false, true, PlatformMouseEvent());
}
void FrameView::scheduleRelayout()