From 160dafc4eb7d954e5026459b0fb158cd76e90bc5 Mon Sep 17 00:00:00 2001 From: ap Date: Mon, 20 Mar 2006 20:46:24 +0000 Subject: [PATCH] Reviewed by Darin. - http://bugzilla.opendarwin.org/show_bug.cgi?id=3439 mouseover effects can get stuck sometimes due to missing events - http://bugzilla.opendarwin.org/show_bug.cgi?id=7701 mouseout sent to the wrong element when layout changes simultaneously Implemented saving the previous node under the mouse, so that we don't need to recalculate it, which is slow and even not really possible. This has fixed a number of issues with mouse event dispatching when the content changes. The code still needs refactoring and cleanup, see bug 3439 for comments. Tests (both files perform multiple checks): - fast/events/mouseover-mouseout.html - fast/events/mouseover-mouseout2.html * page/Frame.h: Added a Frame parameter to passSubframeEventToSubframe(), used for mouseMoved events. * bridge/mac/FrameMac.h: Ditto. * bridge/mac/FrameMac.mm: (WebCore::FrameMac::passSubframeEventToSubframe): Use the passed subframe to target NSMouseMoved events. * page/FrameView.h: Added a prepareMouseEvent() helper that does viewportToContents translation. * page/FrameView.cpp: Added data members for storing the previous node and subframe under the mouse to FrameViewPrivate. Removed the now unused prevMouseX/prevMouseY. (WebCore::FrameViewPrivate::reset): Reset the new data members. (WebCore::subframeForEvent): A temporary place for the code that extracts a subframe pointer from MouseEventWithHitTestResults, moved from FrameMac::passSubframeEventToSubframe(). (WebCore::FrameView::prepareMouseEvent): The new helper. (WebCore::FrameView::handleMousePressEvent): Use the new helper. (WebCore::FrameView::handleMouseDoubleClickEvent): Ditto. (WebCore::FrameView::handleMouseReleaseEvent): Ditto. (WebCore::FrameView::updateDragAndDrop): Ditto. (WebCore::FrameView::hoverTimerFired): Ditto. (WebCore::FrameView::dispatchMouseEvent): Store and use the oldUnder node, don't store or use prevMouseX/Y. (WebCore::FrameView::handleMouseMoveEvent): Rewrote dispatching events to subframes using a stored oldSubframe reference. Protect "this" from being removed while in this function. git-svn-id: https://svn.webkit.org/repository/webkit/trunk@13402 268f45cc-cd09-0410-ab3c-d52691b4dbfc --- LayoutTests/ChangeLog | 16 ++ .../events/mouseover-mouseout-expected.txt | 61 ++++ .../fast/events/mouseover-mouseout.html | 179 ++++++++++++ .../events/mouseover-mouseout2-expected.txt | 68 +++++ .../fast/events/mouseover-mouseout2.html | 269 ++++++++++++++++++ WebCore/ChangeLog | 41 +++ WebCore/bridge/mac/FrameMac.h | 2 +- WebCore/bridge/mac/FrameMac.mm | 15 +- WebCore/page/Frame.h | 2 +- WebCore/page/FrameView.cpp | 115 ++++---- WebCore/page/FrameView.h | 3 + 11 files changed, 705 insertions(+), 66 deletions(-) create mode 100644 LayoutTests/fast/events/mouseover-mouseout-expected.txt create mode 100644 LayoutTests/fast/events/mouseover-mouseout.html create mode 100644 LayoutTests/fast/events/mouseover-mouseout2-expected.txt create mode 100644 LayoutTests/fast/events/mouseover-mouseout2.html diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog index 66d57f2ded73..4a287ca1a86b 100644 --- a/LayoutTests/ChangeLog +++ b/LayoutTests/ChangeLog @@ -1,3 +1,19 @@ +2006-03-20 Alexey Proskuryakov + + Reviewed by Darin. + + - http://bugzilla.opendarwin.org/show_bug.cgi?id=3439 + mouseover effects can get stuck sometimes due to missing events + - http://bugzilla.opendarwin.org/show_bug.cgi?id=5764 + DIV mouseOver and mouseOut triggered too often + - http://bugzilla.opendarwin.org/show_bug.cgi?id=7701 + mouseout sent to the wrong element when layout changes simultaneously + + * fast/events/mouseover-mouseout-expected.txt: Added. + * fast/events/mouseover-mouseout.html: Added. + * fast/events/mouseover-mouseout2-expected.txt: Added. + * fast/events/mouseover-mouseout2.html: Added. + 2006-03-20 Beth Dakin Reviewed by Adele diff --git a/LayoutTests/fast/events/mouseover-mouseout-expected.txt b/LayoutTests/fast/events/mouseover-mouseout-expected.txt new file mode 100644 index 000000000000..71d0645cc794 --- /dev/null +++ b/LayoutTests/fast/events/mouseover-mouseout-expected.txt @@ -0,0 +1,61 @@ +EDITING DELEGATE: shouldChangeSelectedDOMRange:(null) toDOMRange:range from 0 of P > BODY > HTML > #document to 0 of P > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE +EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification +Tests for bugs 3439, 5764, 7701 - Mouse events vs. DOM manipulation. + +Move the mouse pointer from left to right: + +1               +1               +2 +3 +4 +5 + +Log Expected results +mouseover on t1_1 +mouseout on t1_1 +mouseover on t1_2 +mouseout on t1_2 +mouseover on t2_1 +mouseout on t2_1 +mouseover on t2_2 +mouseout on t2_2 +mouseover on t3_1 +mouseover on t3_2 +mouseout on t3_2 +mouseover on t4_1 +mouseover on t4_2 +mouseout on t4_2 +mouseover on t5_1 +mouseout on t5_1 +mouseover on t5_2 +mouseout on t5_2 +mouseover on frame6 +mouseover on t6 +mouseout on t6 +mouseout on frame6 +mouseover on t1_1 +mouseout on t1_1 +mouseover on t1_2 +mouseout on t1_2 +mouseover on t2_1 +mouseout on t2_1 +mouseover on t2_2 +mouseout on t2_2 +mouseover on t3_1 +mouseover on t3_2 +mouseout on t3_2 +mouseover on t4_1 +mouseover on t4_2 +mouseout on t4_2 +mouseover on t5_1 +mouseout on t5_1 +mouseover on t5_2 +mouseout on t5_2 +mouseover on frame6 +mouseover on t6 +mouseout on t6 +mouseout on frame6 + +SUCCESS + diff --git a/LayoutTests/fast/events/mouseover-mouseout.html b/LayoutTests/fast/events/mouseover-mouseout.html new file mode 100644 index 000000000000..9ca8592a68cd --- /dev/null +++ b/LayoutTests/fast/events/mouseover-mouseout.html @@ -0,0 +1,179 @@ + + + +

Tests for bugs +3439, +5764, +7701 - +Mouse events vs. DOM manipulation.

+

Move the mouse pointer from left to right:

+ + +
1              
+ + + +
2
+
2
+ + +
3
+
3
+ + +
4
+
4
+ + +
5
+
5
+ + + + + + + + + + + + +
LogExpected results
  • mouseover on t1_1
  • mouseout on t1_1
  • mouseover on t1_2
  • mouseout on t1_2
  • mouseover on t2_1
  • mouseout on t2_1
  • mouseover on t2_2
  • mouseout on t2_2
  • mouseover on t3_1
  • mouseover on t3_2
  • mouseout on t3_2
  • mouseover on t4_1
  • mouseover on t4_2
  • mouseout on t4_2
  • mouseover on t5_1
  • mouseout on t5_1
  • mouseover on t5_2
  • mouseout on t5_2
  • mouseover on frame6
  • mouseover on t6
  • mouseout on t6
  • mouseout on frame6
  • + + + + + + + diff --git a/LayoutTests/fast/events/mouseover-mouseout2-expected.txt b/LayoutTests/fast/events/mouseover-mouseout2-expected.txt new file mode 100644 index 000000000000..f700bc7b6321 --- /dev/null +++ b/LayoutTests/fast/events/mouseover-mouseout2-expected.txt @@ -0,0 +1,68 @@ +EDITING DELEGATE: shouldChangeSelectedDOMRange:(null) toDOMRange:range from 0 of P > BODY > HTML > #document to 0 of P > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE +EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification +Tests for bugs 3439, 5764, 7701 - Mouse events vs. DOM manipulation. + +Move the mouse pointer from left to right: + + +3 +4 + +5 +6 +Log Expected results +mouseover on frame1 +mouseover on t1 +mouseout on t1 +mouseout on frame1 +mouseover on frame2 +mouseover on t2 +mouseout on t2 +mouseout on frame2 +mouseover on frame3 +mouseover on t3_1 +mouseout on frame3 +mouseover on t3_2 +mouseout on t3_2 +mouseover on t4_2 +mouseout on t4_2 +mouseover on frame4 +mouseover on t4_1 +mouseout on t4_1 +mouseout on frame4 +mouseover on frame5 +mouseover on t5_1 +mouseout on frame5 +mouseover on t5_2 +mouseout on t5_2 +mouseover on t6 +mouseout on t6 +mouseover on frame1 +mouseover on t1 +mouseout on t1 +mouseout on frame1 +mouseover on frame2 +mouseover on t2 +mouseout on t2 +mouseout on frame2 +mouseover on frame3 +mouseover on t3_1 +mouseout on frame3 +mouseover on t3_2 +mouseout on t3_2 +mouseover on t4_2 +mouseout on t4_2 +mouseover on frame4 +mouseover on t4_1 +mouseout on t4_1 +mouseout on frame4 +mouseover on frame5 +mouseover on t5_1 +mouseout on frame5 +mouseover on t5_2 +mouseout on t5_2 +mouseover on t6 +mouseout on t6 + +SUCCESS + diff --git a/LayoutTests/fast/events/mouseover-mouseout2.html b/LayoutTests/fast/events/mouseover-mouseout2.html new file mode 100644 index 000000000000..93ce3a740912 --- /dev/null +++ b/LayoutTests/fast/events/mouseover-mouseout2.html @@ -0,0 +1,269 @@ + + + +

    Tests for bugs +3439, +5764, +7701 - +Mouse events vs. DOM manipulation.

    +

    Move the mouse pointer from left to right:

    + + + + + + + + +
    3
    + + + +
    4
    + + + +
    5
    + + + +
    6
    + + + + + + + +
    LogExpected results
  • mouseover on frame1
  • mouseover on t1
  • mouseout on t1
  • mouseout on frame1
  • mouseover on frame2
  • mouseover on t2
  • mouseout on t2
  • mouseout on frame2
  • mouseover on frame3
  • mouseover on t3_1
  • mouseout on frame3
  • mouseover on t3_2
  • mouseout on t3_2
  • mouseover on t4_2
  • mouseout on t4_2
  • mouseover on frame4
  • mouseover on t4_1
  • mouseout on t4_1
  • mouseout on frame4
  • mouseover on frame5
  • mouseover on t5_1
  • mouseout on frame5
  • mouseover on t5_2
  • mouseout on t5_2
  • mouseover on t6
  • mouseout on t6
  • + + + + + + + diff --git a/WebCore/ChangeLog b/WebCore/ChangeLog index 8b13a75b3e24..eda18357920e 100644 --- a/WebCore/ChangeLog +++ b/WebCore/ChangeLog @@ -1,3 +1,44 @@ +2006-03-20 Alexey Proskuryakov + + Reviewed by Darin. + + - http://bugzilla.opendarwin.org/show_bug.cgi?id=3439 + mouseover effects can get stuck sometimes due to missing events + - http://bugzilla.opendarwin.org/show_bug.cgi?id=7701 + mouseout sent to the wrong element when layout changes simultaneously + + Implemented saving the previous node under the mouse, so that we don't need to + recalculate it, which is slow and even not really possible. This has fixed a number + of issues with mouse event dispatching when the content changes. + The code still needs refactoring and cleanup, see bug 3439 for comments. + + Tests (both files perform multiple checks): + - fast/events/mouseover-mouseout.html + - fast/events/mouseover-mouseout2.html + + * page/Frame.h: Added a Frame parameter to passSubframeEventToSubframe(), + used for mouseMoved events. + * bridge/mac/FrameMac.h: Ditto. + * bridge/mac/FrameMac.mm: + (WebCore::FrameMac::passSubframeEventToSubframe): Use the passed subframe to target + NSMouseMoved events. + * page/FrameView.h: Added a prepareMouseEvent() helper that does viewportToContents translation. + * page/FrameView.cpp: Added data members for storing the previous node and subframe + under the mouse to FrameViewPrivate. Removed the now unused prevMouseX/prevMouseY. + (WebCore::FrameViewPrivate::reset): Reset the new data members. + (WebCore::subframeForEvent): A temporary place for the code that extracts a subframe + pointer from MouseEventWithHitTestResults, moved from FrameMac::passSubframeEventToSubframe(). + (WebCore::FrameView::prepareMouseEvent): The new helper. + (WebCore::FrameView::handleMousePressEvent): Use the new helper. + (WebCore::FrameView::handleMouseDoubleClickEvent): Ditto. + (WebCore::FrameView::handleMouseReleaseEvent): Ditto. + (WebCore::FrameView::updateDragAndDrop): Ditto. + (WebCore::FrameView::hoverTimerFired): Ditto. + (WebCore::FrameView::dispatchMouseEvent): Store and use the oldUnder node, don't store + or use prevMouseX/Y. + (WebCore::FrameView::handleMouseMoveEvent): Rewrote dispatching events to subframes using + a stored oldSubframe reference. Protect "this" from being removed while in this function. + 2006-03-20 Darin Adler Reviewed by Anders. diff --git a/WebCore/bridge/mac/FrameMac.h b/WebCore/bridge/mac/FrameMac.h index 6e9fdd0687fc..0ff36fc2f727 100644 --- a/WebCore/bridge/mac/FrameMac.h +++ b/WebCore/bridge/mac/FrameMac.h @@ -229,7 +229,7 @@ public: bool sendContextMenuEvent(NSEvent *); virtual bool passMouseDownEventToWidget(Widget *); - virtual bool passSubframeEventToSubframe(MouseEventWithHitTestResults &); + virtual bool passSubframeEventToSubframe(MouseEventWithHitTestResults&, Frame* subframePart); virtual bool passWheelEventToChildWidget(Node *); NSString *searchForLabelsAboveCell(RegularExpression *regExp, HTMLTableCellElement *cell); diff --git a/WebCore/bridge/mac/FrameMac.mm b/WebCore/bridge/mac/FrameMac.mm index a02685d5eb54..f6f0996b33ae 100644 --- a/WebCore/bridge/mac/FrameMac.mm +++ b/WebCore/bridge/mac/FrameMac.mm @@ -1831,24 +1831,13 @@ void FrameMac::handleMouseReleaseEvent(const MouseEventWithHitTestResults& event _sendingEventToSubview = false; } -bool FrameMac::passSubframeEventToSubframe(MouseEventWithHitTestResults &event) +bool FrameMac::passSubframeEventToSubframe(MouseEventWithHitTestResults& event, Frame* subframePart) { BEGIN_BLOCK_OBJC_EXCEPTIONS; switch ([_currentEvent type]) { case NSMouseMoved: { - Node *node = event.innerNode(); - if (!node) - return false; - RenderObject *renderer = node->renderer(); - if (!renderer || !renderer->isWidget()) - return false; - Widget *widget = static_cast(renderer)->widget(); - if (!widget || !widget->isFrameView()) - return false; - Frame *subframePart = static_cast(widget)->frame(); - if (!subframePart) - return false; + ASSERT(subframePart); [Mac(subframePart)->bridge() mouseMoved:_currentEvent]; return true; } diff --git a/WebCore/page/Frame.h b/WebCore/page/Frame.h index 716504b74e38..d97ace634d6d 100644 --- a/WebCore/page/Frame.h +++ b/WebCore/page/Frame.h @@ -591,7 +591,7 @@ public: virtual void openURLRequest(const ResourceRequest&) = 0; virtual void submitForm(const ResourceRequest&) = 0; virtual void urlSelected(const ResourceRequest&) = 0; - virtual bool passSubframeEventToSubframe(MouseEventWithHitTestResults&) = 0; + virtual bool passSubframeEventToSubframe(MouseEventWithHitTestResults&, Frame* subframePart = 0) = 0; virtual bool passWheelEventToChildWidget(Node *) = 0; virtual bool lastEventIsMouseUp() const = 0; virtual DeprecatedString overrideMediaType() const = 0; diff --git a/WebCore/page/FrameView.cpp b/WebCore/page/FrameView.cpp index 55230fdc1154..a793b52f191c 100644 --- a/WebCore/page/FrameView.cpp +++ b/WebCore/page/FrameView.cpp @@ -76,6 +76,8 @@ public: void reset() { underMouse = 0; + oldUnder = 0; + oldSubframe = 0; linkPressed = false; useSlowRepaints = false; dragTarget = 0; @@ -84,8 +86,6 @@ public: ignoreWheelEvents = false; borderX = 30; borderY = 30; - prevMouseX = -1; - prevMouseY = -1; clickCount = 0; clickNode = 0; scrollingSelf = false; @@ -104,6 +104,8 @@ public: } RefPtr underMouse; + RefPtr oldUnder; + RefPtr oldSubframe; bool borderTouched : 1; bool borderStart : 1; @@ -121,7 +123,6 @@ public: int clickCount; RefPtr clickNode; - int prevMouseX, prevMouseY; bool scrollingSelf; Timer layoutTimer; bool delayedLayout; @@ -463,6 +464,22 @@ void FrameView::layout() // ///////////////// +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(renderer)->widget(); + if (!widget || !widget->isFrameView()) + return 0; + + return static_cast(widget)->frame(); +} + void FrameView::handleMousePressEvent(const PlatformMouseEvent& mouseEvent) { if (!m_frame->document()) @@ -470,12 +487,9 @@ void FrameView::handleMousePressEvent(const PlatformMouseEvent& mouseEvent) RefPtr 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(); @@ -506,13 +520,10 @@ void FrameView::handleMouseDoubleClickEvent(const PlatformMouseEvent& mouseEvent RefPtr 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; @@ -601,12 +612,11 @@ void FrameView::handleMouseMoveEvent(const PlatformMouseEvent& mouseEvent) if (!m_frame || !m_frame->document()) return; + RefPtr 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; @@ -616,15 +626,24 @@ void FrameView::handleMouseMoveEvent(const PlatformMouseEvent& mouseEvent) // 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 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() @@ -640,9 +659,6 @@ void FrameView::handleMouseReleaseEvent(const PlatformMouseEvent& mouseEvent) RefPtr protector(this); - int xm, ym; - viewportToContents(mouseEvent.x(), mouseEvent.y(), xm, ym); - d->mousePressed = false; if (d->resizingFrameSet) { @@ -650,7 +666,7 @@ void FrameView::handleMouseReleaseEvent(const PlatformMouseEvent& mouseEvent) 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; @@ -685,9 +701,8 @@ bool FrameView::dispatchDragEvent(const AtomicString &eventType, Node *dragTarge 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(); @@ -924,6 +939,17 @@ void FrameView::setResizingFrameSet(HTMLFrameSetElement *frameSet) 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) { @@ -934,31 +960,18 @@ bool FrameView::dispatchMouseEvent(const AtomicString& eventType, Node* targetNo // 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 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; @@ -1051,7 +1064,7 @@ void FrameView::layoutTimerFired(Timer*) void FrameView::hoverTimerFired(Timer*) { d->hoverTimer.stop(); - m_frame->document()->prepareMouseEvent(false, false, true, d->prevMouseX, d->prevMouseY, PlatformMouseEvent()); + prepareMouseEvent(false, false, true, PlatformMouseEvent()); } void FrameView::scheduleRelayout() diff --git a/WebCore/page/FrameView.h b/WebCore/page/FrameView.h index 4b9d33703793..88d76f8ca2c5 100644 --- a/WebCore/page/FrameView.h +++ b/WebCore/page/FrameView.h @@ -54,6 +54,7 @@ class IntRect; class PlatformKeyboardEvent; class FrameMac; class PlatformMouseEvent; +class MouseEventWithHitTestResults; class Node; class RenderBox; class RenderCanvas; @@ -215,6 +216,8 @@ private: DeprecatedStringList formCompletionItems(const DeprecatedString &name) const; void addFormCompletionItem(const DeprecatedString &name, const DeprecatedString &value); + MouseEventWithHitTestResults prepareMouseEvent(bool readonly, bool active, bool mouseMove, const PlatformMouseEvent&); + bool dispatchMouseEvent(const AtomicString& eventType, Node* target, bool cancelable, int clickCount, const PlatformMouseEvent&, bool setUnder); bool dispatchDragEvent(const AtomicString& eventType, Node* target, -- 2.36.0