Changeset 13402 in webkit
- Timestamp:
- Mar 20, 2006 12:46:24 PM (18 years ago)
- Location:
- trunk
- Files:
-
- 4 added
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r13401 r13402 1 2006-03-20 Alexey Proskuryakov <ap@nypop.com> 2 3 Reviewed by Darin. 4 5 - http://bugzilla.opendarwin.org/show_bug.cgi?id=3439 6 mouseover effects can get stuck sometimes due to missing events 7 - http://bugzilla.opendarwin.org/show_bug.cgi?id=5764 8 DIV mouseOver and mouseOut triggered too often 9 - http://bugzilla.opendarwin.org/show_bug.cgi?id=7701 10 mouseout sent to the wrong element when layout changes simultaneously 11 12 * fast/events/mouseover-mouseout-expected.txt: Added. 13 * fast/events/mouseover-mouseout.html: Added. 14 * fast/events/mouseover-mouseout2-expected.txt: Added. 15 * fast/events/mouseover-mouseout2.html: Added. 16 1 17 2006-03-20 Beth Dakin <bdakin@apple.com> 2 18 -
trunk/WebCore/ChangeLog
r13400 r13402 1 2006-03-20 Alexey Proskuryakov <ap@nypop.com> 2 3 Reviewed by Darin. 4 5 - http://bugzilla.opendarwin.org/show_bug.cgi?id=3439 6 mouseover effects can get stuck sometimes due to missing events 7 - http://bugzilla.opendarwin.org/show_bug.cgi?id=7701 8 mouseout sent to the wrong element when layout changes simultaneously 9 10 Implemented saving the previous node under the mouse, so that we don't need to 11 recalculate it, which is slow and even not really possible. This has fixed a number 12 of issues with mouse event dispatching when the content changes. 13 The code still needs refactoring and cleanup, see bug 3439 for comments. 14 15 Tests (both files perform multiple checks): 16 - fast/events/mouseover-mouseout.html 17 - fast/events/mouseover-mouseout2.html 18 19 * page/Frame.h: Added a Frame parameter to passSubframeEventToSubframe(), 20 used for mouseMoved events. 21 * bridge/mac/FrameMac.h: Ditto. 22 * bridge/mac/FrameMac.mm: 23 (WebCore::FrameMac::passSubframeEventToSubframe): Use the passed subframe to target 24 NSMouseMoved events. 25 * page/FrameView.h: Added a prepareMouseEvent() helper that does viewportToContents translation. 26 * page/FrameView.cpp: Added data members for storing the previous node and subframe 27 under the mouse to FrameViewPrivate. Removed the now unused prevMouseX/prevMouseY. 28 (WebCore::FrameViewPrivate::reset): Reset the new data members. 29 (WebCore::subframeForEvent): A temporary place for the code that extracts a subframe 30 pointer from MouseEventWithHitTestResults, moved from FrameMac::passSubframeEventToSubframe(). 31 (WebCore::FrameView::prepareMouseEvent): The new helper. 32 (WebCore::FrameView::handleMousePressEvent): Use the new helper. 33 (WebCore::FrameView::handleMouseDoubleClickEvent): Ditto. 34 (WebCore::FrameView::handleMouseReleaseEvent): Ditto. 35 (WebCore::FrameView::updateDragAndDrop): Ditto. 36 (WebCore::FrameView::hoverTimerFired): Ditto. 37 (WebCore::FrameView::dispatchMouseEvent): Store and use the oldUnder node, don't store 38 or use prevMouseX/Y. 39 (WebCore::FrameView::handleMouseMoveEvent): Rewrote dispatching events to subframes using 40 a stored oldSubframe reference. Protect "this" from being removed while in this function. 41 1 42 2006-03-20 Darin Adler <darin@apple.com> 2 43 -
trunk/WebCore/bridge/mac/FrameMac.h
r13396 r13402 230 230 231 231 virtual bool passMouseDownEventToWidget(Widget *); 232 virtual bool passSubframeEventToSubframe(MouseEventWithHitTestResults &);232 virtual bool passSubframeEventToSubframe(MouseEventWithHitTestResults&, Frame* subframePart); 233 233 virtual bool passWheelEventToChildWidget(Node *); 234 234 -
trunk/WebCore/bridge/mac/FrameMac.mm
r13396 r13402 1832 1832 } 1833 1833 1834 bool FrameMac::passSubframeEventToSubframe(MouseEventWithHitTestResults &event)1834 bool FrameMac::passSubframeEventToSubframe(MouseEventWithHitTestResults& event, Frame* subframePart) 1835 1835 { 1836 1836 BEGIN_BLOCK_OBJC_EXCEPTIONS; … … 1838 1838 switch ([_currentEvent type]) { 1839 1839 case NSMouseMoved: { 1840 Node *node = event.innerNode(); 1841 if (!node) 1842 return false; 1843 RenderObject *renderer = node->renderer(); 1844 if (!renderer || !renderer->isWidget()) 1845 return false; 1846 Widget *widget = static_cast<RenderWidget *>(renderer)->widget(); 1847 if (!widget || !widget->isFrameView()) 1848 return false; 1849 Frame *subframePart = static_cast<FrameView *>(widget)->frame(); 1850 if (!subframePart) 1851 return false; 1840 ASSERT(subframePart); 1852 1841 [Mac(subframePart)->bridge() mouseMoved:_currentEvent]; 1853 1842 return true; -
trunk/WebCore/page/Frame.h
r13396 r13402 592 592 virtual void submitForm(const ResourceRequest&) = 0; 593 593 virtual void urlSelected(const ResourceRequest&) = 0; 594 virtual bool passSubframeEventToSubframe(MouseEventWithHitTestResults& ) = 0;594 virtual bool passSubframeEventToSubframe(MouseEventWithHitTestResults&, Frame* subframePart = 0) = 0; 595 595 virtual bool passWheelEventToChildWidget(Node *) = 0; 596 596 virtual bool lastEventIsMouseUp() const = 0; -
trunk/WebCore/page/FrameView.cpp
r13397 r13402 77 77 { 78 78 underMouse = 0; 79 oldUnder = 0; 80 oldSubframe = 0; 79 81 linkPressed = false; 80 82 useSlowRepaints = false; … … 85 87 borderX = 30; 86 88 borderY = 30; 87 prevMouseX = -1;88 prevMouseY = -1;89 89 clickCount = 0; 90 90 clickNode = 0; … … 105 105 106 106 RefPtr<Node> underMouse; 107 RefPtr<Node> oldUnder; 108 RefPtr<Frame> oldSubframe; 107 109 108 110 bool borderTouched : 1; … … 122 124 RefPtr<Node> clickNode; 123 125 124 int prevMouseX, prevMouseY;125 126 bool scrollingSelf; 126 127 Timer<FrameView> layoutTimer; … … 464 465 ///////////////// 465 466 467 static Frame* subframeForEvent(const MouseEventWithHitTestResults& mev) 468 { 469 if (!mev.innerNode()) 470 return 0; 471 472 RenderObject* renderer = mev.innerNode()->renderer(); 473 if (!renderer || !renderer->isWidget()) 474 return 0; 475 476 Widget* widget = static_cast<RenderWidget*>(renderer)->widget(); 477 if (!widget || !widget->isFrameView()) 478 return 0; 479 480 return static_cast<FrameView*>(widget)->frame(); 481 } 482 466 483 void FrameView::handleMousePressEvent(const PlatformMouseEvent& mouseEvent) 467 484 { … … 471 488 RefPtr<FrameView> protector(this); 472 489 473 int xm, ym;474 viewportToContents(mouseEvent.x(), mouseEvent.y(), xm, ym);475 476 490 d->mousePressed = true; 477 491 478 MouseEventWithHitTestResults mev = m_frame->document()->prepareMouseEvent(false, true, false, xm, ym, mouseEvent);492 MouseEventWithHitTestResults mev = prepareMouseEvent(false, true, false, mouseEvent); 479 493 480 494 if (m_frame->passSubframeEventToSubframe(mev)) { … … 507 521 RefPtr<FrameView> protector(this); 508 522 509 int xm, ym;510 viewportToContents(mouseEvent.x(), mouseEvent.y(), xm, ym);511 512 523 // We get this instead of a second mouse-up 513 524 d->mousePressed = false; 514 525 515 MouseEventWithHitTestResults mev = m_frame->document()->prepareMouseEvent(false, true, false, xm, ym, mouseEvent);526 MouseEventWithHitTestResults mev = prepareMouseEvent(false, true, false, mouseEvent); 516 527 517 528 if (m_frame->passSubframeEventToSubframe(mev)) … … 602 613 return; 603 614 615 RefPtr<FrameView> protector(this); 616 604 617 if (d->hoverTimer.isActive()) 605 618 d->hoverTimer.stop(); 606 607 int xm, ym;608 viewportToContents(mouseEvent.x(), mouseEvent.y(), xm, ym);609 619 610 620 if (d->resizingFrameSet) { … … 617 627 // This means that :hover and :active freeze in the state they were in when the mouse 618 628 // was pressed, rather than updating for nodes the mouse moves over as you hold the mouse down. 619 MouseEventWithHitTestResults mev = m_frame->document()->prepareMouseEvent(d->mousePressed && m_frame->mouseDownMayStartSelect(),620 d->mousePressed, true, xm, ym,mouseEvent);621 622 if ( !m_frame->passSubframeEventToSubframe(mev))623 setCursor(selectCursor(mev, m_frame.get(), d->mousePressed));624 629 MouseEventWithHitTestResults mev = prepareMouseEvent(d->mousePressed && m_frame->mouseDownMayStartSelect(), 630 d->mousePressed, true, mouseEvent); 631 632 if (d->oldSubframe) 633 m_frame->passSubframeEventToSubframe(mev, d->oldSubframe.get()); 634 625 635 bool swallowEvent = dispatchMouseEvent(mousemoveEvent, mev.innerNode(), false, 0, mouseEvent, true); 626 636 if (!swallowEvent) 627 637 m_frame->handleMouseMoveEvent(mev); 638 639 RefPtr<Frame> newSubframe = subframeForEvent(mev); 640 641 if (newSubframe && d->oldSubframe != newSubframe) 642 m_frame->passSubframeEventToSubframe(mev, newSubframe.get()); 643 else 644 setCursor(selectCursor(mev, m_frame.get(), d->mousePressed)); 645 646 d->oldSubframe = newSubframe; 628 647 } 629 648 … … 641 660 RefPtr<FrameView> protector(this); 642 661 643 int xm, ym;644 viewportToContents(mouseEvent.x(), mouseEvent.y(), xm, ym);645 646 662 d->mousePressed = false; 647 663 … … 651 667 } 652 668 653 MouseEventWithHitTestResults mev = m_frame->document()->prepareMouseEvent(false, false, false, xm, ym, mouseEvent);669 MouseEventWithHitTestResults mev = prepareMouseEvent(false, false, false, mouseEvent); 654 670 655 671 if (m_frame->passSubframeEventToSubframe(mev)) … … 686 702 { 687 703 bool accept = false; 688 int xm, ym; 689 viewportToContents(event.x(), event.y(), xm, ym); 690 MouseEventWithHitTestResults mev = m_frame->document()->prepareMouseEvent(true, false, false, xm, ym, PlatformMouseEvent()); 704 705 MouseEventWithHitTestResults mev = prepareMouseEvent(true, false, false, PlatformMouseEvent()); 691 706 692 707 // Drag events should never go to text nodes (following IE, and proper mouseover/out dispatch) … … 925 940 } 926 941 942 MouseEventWithHitTestResults FrameView::prepareMouseEvent(bool readonly, bool active, bool mouseMove, const PlatformMouseEvent& mev) 943 { 944 ASSERT(m_frame); 945 ASSERT(m_frame->document()); 946 947 int xm, ym; 948 viewportToContents(mev.x(), mev.y(), xm, ym); 949 950 return m_frame->document()->prepareMouseEvent(readonly, active, mouseMove, xm, ym, mev); 951 } 952 927 953 bool FrameView::dispatchMouseEvent(const AtomicString& eventType, Node* targetNode, bool cancelable, 928 954 int clickCount, const PlatformMouseEvent& mouseEvent, bool setUnder) … … 935 961 // mouseout/mouseover 936 962 if (setUnder) { 937 int clientX, clientY; 938 viewportToContents(mouseEvent.x(), mouseEvent.y(), clientX, clientY); 939 if (d->prevMouseX != clientX || d->prevMouseY != clientY) { 940 // ### this code sucks. we should save the oldUnder instead of calculating 941 // it again. calculating is expensive! (Dirk) 942 // Also, there's no guarantee that the old under node is even around any more, 943 // so we could be sending a mouseout to a node that never got a mouseover. 944 RefPtr<Node> oldUnder; 945 if (d->prevMouseX >= 0) { 946 oldUnder = m_frame->document()->prepareMouseEvent(true, false, true, 947 d->prevMouseX, d->prevMouseY, mouseEvent).innerNode(); 948 if (oldUnder && oldUnder->isTextNode()) 949 oldUnder = oldUnder->parentNode(); 950 } 951 d->prevMouseX = clientX; 952 d->prevMouseY = clientY; 953 if (oldUnder != targetNode) { 954 // send mouseout event to the old node 955 if (oldUnder) 956 EventTargetNodeCast(oldUnder.get())->dispatchMouseEvent(mouseEvent, mouseoutEvent, 0, targetNode); 957 // send mouseover event to the new node 958 if (targetNode) 959 EventTargetNodeCast(targetNode)->dispatchMouseEvent(mouseEvent, mouseoverEvent, 0, oldUnder.get()); 960 } 963 if (d->oldUnder && d->oldUnder->getDocument() != frame()->document()) 964 d->oldUnder = 0; 965 966 if (d->oldUnder != targetNode) { 967 // send mouseout event to the old node 968 if (d->oldUnder) 969 EventTargetNodeCast(d->oldUnder.get())->dispatchMouseEvent(mouseEvent, mouseoutEvent, 0, targetNode); 970 // send mouseover event to the new node 971 if (targetNode) 972 EventTargetNodeCast(targetNode)->dispatchMouseEvent(mouseEvent, mouseoverEvent, 0, d->oldUnder.get()); 961 973 } 974 d->oldUnder = targetNode; 962 975 } 963 976 … … 1052 1065 { 1053 1066 d->hoverTimer.stop(); 1054 m_frame->document()->prepareMouseEvent(false, false, true, d->prevMouseX, d->prevMouseY, PlatformMouseEvent());1067 prepareMouseEvent(false, false, true, PlatformMouseEvent()); 1055 1068 } 1056 1069 -
trunk/WebCore/page/FrameView.h
r13393 r13402 55 55 class FrameMac; 56 56 class PlatformMouseEvent; 57 class MouseEventWithHitTestResults; 57 58 class Node; 58 59 class RenderBox; … … 216 217 void addFormCompletionItem(const DeprecatedString &name, const DeprecatedString &value); 217 218 219 MouseEventWithHitTestResults prepareMouseEvent(bool readonly, bool active, bool mouseMove, const PlatformMouseEvent&); 220 218 221 bool dispatchMouseEvent(const AtomicString& eventType, Node* target, 219 222 bool cancelable, int clickCount, const PlatformMouseEvent&, bool setUnder);
Note: See TracChangeset
for help on using the changeset viewer.