+2006-03-20 Alexey Proskuryakov <ap@nypop.com>
+
+ 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 <bdakin@apple.com>
Reviewed by Adele
--- /dev/null
+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
+
--- /dev/null
+<html>
+<body onload="autoTest()">
+<script>
+ function log(message)
+ {
+ var item = document.createElement("li");
+ item.appendChild(document.createTextNode(message));
+ document.getElementById('log').appendChild(item);
+ }
+
+ function logMouseEvent(evt)
+ {
+ target = (evt.target) ? evt.target : evt.srcElement;
+ log(evt.type + " on " + target.id);
+ }
+
+</script>
+<p>Tests for bugs
+<a href="http://bugzilla.opendarwin.org/show_bug.cgi?id=3439">3439</a>,
+<a href="http://bugzilla.opendarwin.org/show_bug.cgi?id=5764">5764</a>,
+<a href="http://bugzilla.opendarwin.org/show_bug.cgi?id=7701">7701</a> -
+Mouse events vs. DOM manipulation.</p>
+<p>Move the mouse pointer from left to right:</p>
+
+<!-- 1: Show an element under the mouse -->
+<div style='height: 50; width: 50; background:red;top:100;left:100; position:absolute;' id='t1_1'
+ onMouseOver="logMouseEvent(event); document.getElementById('t1_2').style.display = 'block'"
+ onMouseOut="logMouseEvent(event);">1 </div>
+<div style='display: none; height: 50; width: 50; background:white;top:100;left:100; position:absolute;' id='t1_2'
+ onMouseOver="logMouseEvent(event)"
+ onMouseOut="logMouseEvent(event); document.getElementById('t1_2').style.backgroundColor = 'gray'">1 </div>
+
+<!-- 2: Hide an element under the mouse -->
+<div style='height: 50; width: 50; background:white;top:100;left:150; position:absolute;' id='t2_2'
+ onMouseOver="logMouseEvent(event)"
+ onMouseOut="logMouseEvent(event); document.getElementById('t2_2').style.backgroundColor = 'gray'">2</div>
+<div style='height: 50; width: 50; background:orange;top:100;left:150; position:absolute;' id='t2_1'
+ onMouseOver="logMouseEvent(event); document.getElementById('t2_1').style.display = 'none'"
+ onMouseOut="logMouseEvent(event)">2</div>
+
+<!-- 3: Move the element under the mouse into another document -->
+<div style='height: 50; width: 50; background:white;top:100;left:200; position:absolute;' id='t3_2'
+ onMouseOver="logMouseEvent(event)"
+ onMouseOut="logMouseEvent(event); document.getElementById('t3_2').style.backgroundColor = 'gray'">3</div>
+<div style='height: 50; width: 50; background:yellow;top:100;left:200; position:absolute;' id='t3_1'
+ onMouseOver="
+ logMouseEvent(event);
+ newDoc = document.getElementById('invisible_frame').document;
+ if (!newDoc)
+ newDoc = document.getElementById('invisible_frame').contentDocument;
+ try {
+ newDoc.adoptNode(document.getElementById('t3_1'));
+ } catch (e) {
+ newDoc.documentElement.appendChild(document.getElementById('t3_1'));
+ }
+ "
+ onMouseOut="logMouseEvent(event)">3</div>
+
+<!-- 4: Move the element under the mouse into another document, and append it -->
+<div style='height: 50; width: 50; background:white;top:100;left:250; position:absolute;' id='t4_2'
+ onMouseOver="logMouseEvent(event)"
+ onMouseOut="logMouseEvent(event); document.getElementById('t4_2').style.backgroundColor = 'gray'">4</div>
+<div style='height: 50; width: 50; background:green;top:100;left:250; position:absolute;' id='t4_1'
+ onMouseOver="
+ logMouseEvent(event);
+ newDoc = document.getElementById('invisible_frame').document;
+ if (!newDoc)
+ newDoc = document.getElementById('invisible_frame').contentDocument;
+ try {
+ newDoc.documentElement.appendChild(newDoc.adoptNode(document.getElementById('t4_1')));
+ } catch (ex) {
+ newDoc.documentElement.appendChild(document.getElementById('t4_1'));
+ }
+ "
+ onMouseOut="logMouseEvent(event)">4</div>
+
+<!-- 5: Remove the element under the mouse -->
+<div style='height: 50; width: 50; background:white;top:100;left:300; position:absolute;' id='t5_2'
+ onMouseOver="logMouseEvent(event)"
+ onMouseOut="logMouseEvent(event); document.getElementById('t5_2').style.backgroundColor = 'gray'">5</div>
+<div style='height: 50; width: 50; background:blue;top:100;left:300; position:absolute;' id='t5_1'
+ onMouseOver="
+ logMouseEvent(event);
+ document.body.removeChild(document.getElementById('t5_1'));
+ "
+ onMouseOut="logMouseEvent(event)">5</div>
+
+<!-- 6: Enter a different document -->
+<iframe style='height: 50; width: 50; top:100;left:350; position:absolute; border-width:0' src='data:text/html,
+ <body style="margin-left:0; margin-top:0">
+ <script>
+ function log(message)
+ {
+ var item = top.document.createElement("li");
+ item.appendChild(document.createTextNode(message));
+ top.document.getElementById("log").appendChild(item);
+ }
+
+ function logMouseEvent(evt)
+ {
+ target = (evt.target) ? evt.target : evt.srcElement;
+ log(evt.type + " on " + target.id);
+ }
+
+ function doOnMouseOver(evt)
+ {
+ logMouseEvent(evt);
+ document.getElementById("t6").style.backgroundColor = "white";
+ }
+
+ function doOnMouseOut(evt)
+ {
+ logMouseEvent(evt);
+ document.getElementById("t6").style.backgroundColor = "gray";
+ }
+
+ </script>
+ <div style="height: 50; width: 50; background:violet; top:0;left:0; position:absolute;" id="t6"
+ onMouseOver="doOnMouseOver(event);"
+ onMouseOut="doOnMouseOut(event)">6</div>
+ </body>'
+ onMouseOver="logMouseEvent(event)"
+ onMouseOut="
+ logMouseEvent(event);
+ if (top.document.getElementById('log').innerHTML == top.document.getElementById('exp').innerHTML) {
+ top.document.getElementById('success').style.display = 'block';
+ }
+ "
+ id="frame6"
+ ></iframe>
+
+<iframe id=invisible_frame style="width:0; height:0; border-width:0"></iframe>
+
+<table border=1 width="100%" style='top:200; position:absolute'>
+<tr><td width="50%">Log</td><td>Expected results</td></tr>
+<tr>
+ <td id=log style="vertical-align:top"></td>
+ <td id=exp style="vertical-align:top"><li>mouseover on t1_1</li><li>mouseout on t1_1</li><li>mouseover on t1_2</li><li>mouseout on t1_2</li><li>mouseover on t2_1</li><li>mouseout on t2_1</li><li>mouseover on t2_2</li><li>mouseout on t2_2</li><li>mouseover on t3_1</li><li>mouseover on t3_2</li><li>mouseout on t3_2</li><li>mouseover on t4_1</li><li>mouseover on t4_2</li><li>mouseout on t4_2</li><li>mouseover on t5_1</li><li>mouseout on t5_1</li><li>mouseover on t5_2</li><li>mouseout on t5_2</li><li>mouseover on frame6</li><li>mouseover on t6</li><li>mouseout on t6</li><li>mouseout on frame6</li></td>
+</tr>
+</table>
+
+<div style='height: 50; width: 300; top:100;left:100; position:absolute; display:none' id='success'><br><center>SUCCESS</center></div>
+
+<script>
+function autoTest() {
+ if (window.layoutTestController) {
+ layoutTestController.dumpAsText();
+
+ eventSender.mouseMoveTo(1,1);
+ eventSender.mouseDown();
+ eventSender.mouseUp();
+
+ eventSender.mouseMoveTo(125, 125);
+ eventSender.mouseMoveTo(130, 125);
+ eventSender.mouseMoveTo(135, 125);
+
+ eventSender.mouseMoveTo(175, 125);
+ eventSender.mouseMoveTo(180, 125);
+
+ eventSender.mouseMoveTo(225, 125);
+ eventSender.mouseMoveTo(230, 125);
+
+ eventSender.mouseMoveTo(275, 125);
+ eventSender.mouseMoveTo(280, 125);
+
+ eventSender.mouseMoveTo(325, 125);
+ eventSender.mouseMoveTo(330, 125);
+
+ eventSender.mouseMoveTo(375, 125);
+ eventSender.mouseMoveTo(380, 125);
+ eventSender.mouseMoveTo(385, 125);
+
+ eventSender.mouseMoveTo(1, 1);
+ }
+}
+</script>
+
+</body>
+</html>
--- /dev/null
+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
+
--- /dev/null
+<html>
+<body onload="autoTest()">
+<script>
+ function log(message)
+ {
+ var item = document.createElement("li");
+ item.appendChild(document.createTextNode(message));
+ document.getElementById('log').appendChild(item);
+ }
+
+ function logMouseEvent(evt)
+ {
+ target = (evt.target) ? evt.target : evt.srcElement;
+ log(evt.type + " on " + target.id);
+ }
+
+</script>
+<p>Tests for bugs
+<a href="http://bugzilla.opendarwin.org/show_bug.cgi?id=3439">3439</a>,
+<a href="http://bugzilla.opendarwin.org/show_bug.cgi?id=5764">5764</a>,
+<a href="http://bugzilla.opendarwin.org/show_bug.cgi?id=7701">7701</a> -
+Mouse events vs. DOM manipulation.</p>
+<p>Move the mouse pointer from left to right:</p>
+
+<!-- 1: Enter a subframe -->
+<iframe style='height: 50; width: 50; top:100;left:100; position:absolute; border-width:0' src='data:text/html,
+ <body style="margin-left:0; margin-top:0">
+ <script>
+ function log(message)
+ {
+ var item = top.document.createElement("li");
+ item.appendChild(document.createTextNode(message));
+ top.document.getElementById("log").appendChild(item);
+ }
+
+ function logMouseEvent(evt)
+ {
+ target = (evt.target) ? evt.target : evt.srcElement;
+ log(evt.type + " on " + target.id);
+ }
+
+ function doOnMouseOver(evt)
+ {
+ logMouseEvent(evt);
+ document.getElementById("t1").style.backgroundColor = "white";
+ }
+
+ function doOnMouseOut(evt)
+ {
+ logMouseEvent(evt);
+ document.getElementById("t1").style.backgroundColor = "gray";
+ }
+
+ </script>
+ <div style="height: 50; width: 50; background:red; top:0;left:0; position:absolute;" id="t1"
+ onMouseOver="doOnMouseOver(event);"
+ onMouseOut="doOnMouseOut(event)">1</div>
+ </body>'
+ onMouseOver="logMouseEvent(event)"
+ onMouseOut="logMouseEvent(event);"
+ id="frame1"
+ ></iframe>
+
+<!-- 2: Move from one subframe to another -->
+<iframe style='height: 50; width: 50; top:100;left:150; position:absolute; border-width:0' src='data:text/html,
+ <body style="margin-left:0; margin-top:0">
+ <script>
+ function log(message)
+ {
+ var item = top.document.createElement("li");
+ item.appendChild(document.createTextNode(message));
+ top.document.getElementById("log").appendChild(item);
+ }
+
+ function logMouseEvent(evt)
+ {
+ target = (evt.target) ? evt.target : evt.srcElement;
+ log(evt.type + " on " + target.id);
+ }
+
+ function doOnMouseOver(evt)
+ {
+ logMouseEvent(evt);
+ document.getElementById("t2").style.backgroundColor = "white";
+ }
+
+ function doOnMouseOut(evt)
+ {
+ logMouseEvent(evt);
+ document.getElementById("t2").style.backgroundColor = "gray";
+ }
+
+ </script>
+ <div style="height: 50; width: 50; background:orange; top:0;left:0; position:absolute;" id="t2"
+ onMouseOver="doOnMouseOver(event);"
+ onMouseOut="doOnMouseOut(event)">2</div>
+ </body>'
+ onMouseOver="logMouseEvent(event)"
+ onMouseOut="logMouseEvent(event)"
+ id="frame2"
+ ></iframe>
+
+<!-- 3: Hide a subframe under the mouse -->
+<div style='height: 50; width: 50; background:white;top:100;left:200; position:absolute;' id='t3_2'
+ onMouseOver="logMouseEvent(event)"
+ onMouseOut="logMouseEvent(event); document.getElementById('t3_2').style.backgroundColor = 'gray'">3</div>
+<iframe style='height: 50; width: 50; top:100;left:200; position:absolute; border-width:0' src='data:text/html,
+ <body style="margin-left:0; margin-top:0">
+ <script>
+ function log(message)
+ {
+ var item = top.document.createElement("li");
+ item.appendChild(document.createTextNode(message));
+ top.document.getElementById("log").appendChild(item);
+ }
+
+ function logMouseEvent(evt)
+ {
+ target = (evt.target) ? evt.target : evt.srcElement;
+ log(evt.type + " on " + target.id);
+ }
+
+ function doOnMouseOver(evt)
+ {
+ logMouseEvent(evt);
+ top.document.getElementById("frame3").style.display = "none";
+ }
+
+ </script>
+ <div style="height: 50; width: 50; background:yellow; top:0;left:0; position:absolute;" id="t3_1"
+ onMouseOver="doOnMouseOver(event);"
+ onMouseOut="logMouseEvent(event)">3</div>
+ </body>'
+ onMouseOver="logMouseEvent(event)"
+ onMouseOut="logMouseEvent(event)"
+ id="frame3"
+ ></iframe>
+
+<!-- 4: Show a subframe under the mouse -->
+<div style='height: 50; width: 50; background:green;top:100;left:250; position:absolute;' id='t4_2'
+ onMouseOver="logMouseEvent(event); document.getElementById('frame4').style.visibility = 'visible'"
+ onMouseOut="logMouseEvent(event)">4</div>
+<iframe style='height: 50; width: 50; top:100;left:250; position:absolute; border-width:0; visibility:hidden' src='data:text/html,
+ <body style="margin-left:0; margin-top:0">
+ <script>
+ function log(message)
+ {
+ var item = top.document.createElement("li");
+ item.appendChild(document.createTextNode(message));
+ top.document.getElementById("log").appendChild(item);
+ }
+
+ function logMouseEvent(evt)
+ {
+ target = (evt.target) ? evt.target : evt.srcElement;
+ log(evt.type + " on " + target.id);
+ }
+
+ function doOnMouseOut(evt)
+ {
+ logMouseEvent(evt);
+ document.getElementById("t4_1").style.backgroundColor = "gray";
+ }
+
+ </script>
+ <div style="height: 50; width: 50; background:white; top:0;left:0; position:absolute;" id="t4_1"
+ onMouseOver="logMouseEvent(event);"
+ onMouseOut="doOnMouseOut(event)">4</div>
+ </body>'
+ onMouseOver="logMouseEvent(event)"
+ onMouseOut="logMouseEvent(event)"
+ id="frame4"
+ ></iframe>
+
+<!-- 5: Remove the subframe under the mouse -->
+<div style='height: 50; width: 50; background:white;top:100;left:300; position:absolute;' id='t5_2'
+ onMouseOver="logMouseEvent(event)"
+ onMouseOut="logMouseEvent(event); document.getElementById('t5_2').style.backgroundColor = 'gray'">5</div>
+<iframe style='height: 50; width: 50; top:100;left:300; position:absolute; border-width:0' src='data:text/html,
+ <body style="margin-left:0; margin-top:0">
+ <script>
+ function log(message)
+ {
+ var item = top.document.createElement("li");
+ item.appendChild(document.createTextNode(message));
+ top.document.getElementById("log").appendChild(item);
+ }
+
+ function logMouseEvent(evt)
+ {
+ target = (evt.target) ? evt.target : evt.srcElement;
+ log(evt.type + " on " + target.id);
+ }
+
+ function doOnMouseOver(evt)
+ {
+ logMouseEvent(evt);
+ top.document.body.removeChild(top.document.getElementById("frame5"));
+ }
+
+ </script>
+ <div style="height: 50; width: 50; background:blue; top:0;left:0; position:absolute;" id="t5_1"
+ onMouseOver="doOnMouseOver(event);"
+ onMouseOut="logMouseEvent(event)">5</div>
+ </body>'
+ onMouseOver="logMouseEvent(event)"
+ onMouseOut="logMouseEvent(event)"
+ id="frame5"
+ ></iframe>
+
+<!-- 6: Nothing but a rainbow end -->
+<div style='height: 50; width: 50; background:violet;top:100;left:350; position:absolute;' id='t6'
+ onMouseOver="logMouseEvent(event); document.getElementById('t6').style.backgroundColor = 'white'"
+ onMouseOut="
+ logMouseEvent(event);
+ document.getElementById('t6').style.backgroundColor = 'gray';
+ if (top.document.getElementById('log').innerHTML == top.document.getElementById('exp').innerHTML) {
+ top.document.getElementById('success').style.display = 'block';
+ }
+ ">6</div>
+
+<table border=1 width="100%" style='top:200; position:absolute'>
+<tr><td width="50%">Log</td><td>Expected results</td></tr>
+<tr>
+ <td id=log style="vertical-align:top"></td>
+ <td id=exp style="vertical-align:top"><LI>mouseover on frame1</LI><LI>mouseover on t1</LI><LI>mouseout on t1</LI><LI>mouseout on frame1</LI><LI>mouseover on frame2</LI><LI>mouseover on t2</LI><LI>mouseout on t2</LI><LI>mouseout on frame2</LI><LI>mouseover on frame3</LI><LI>mouseover on t3_1</LI><LI>mouseout on frame3</LI><LI>mouseover on t3_2</LI><LI>mouseout on t3_2</LI><LI>mouseover on t4_2</LI><LI>mouseout on t4_2</LI><LI>mouseover on frame4</LI><LI>mouseover on t4_1</LI><LI>mouseout on t4_1</LI><LI>mouseout on frame4</LI><LI>mouseover on frame5</LI><LI>mouseover on t5_1</LI><LI>mouseout on frame5</LI><LI>mouseover on t5_2</LI><LI>mouseout on t5_2</LI><LI>mouseover on t6</LI><LI>mouseout on t6</LI></td>
+</tr>
+</table>
+
+<div style='height: 50; width: 300; top:100;left:100; position:absolute; display:none' id='success'><br><center>SUCCESS</center></div>
+
+<script>
+function autoTest() {
+ if (window.layoutTestController) {
+ layoutTestController.dumpAsText();
+ layoutTestController.waitUntilDone();
+
+ eventSender.mouseMoveTo(1,1);
+ eventSender.mouseDown();
+ eventSender.mouseUp();
+
+ eventSender.mouseMoveTo(125, 125);
+ eventSender.mouseMoveTo(130, 125);
+ eventSender.mouseMoveTo(135, 125);
+
+ eventSender.mouseMoveTo(175, 125);
+ eventSender.mouseMoveTo(180, 125);
+
+ eventSender.mouseMoveTo(225, 125);
+ eventSender.mouseMoveTo(230, 125);
+
+ eventSender.mouseMoveTo(275, 125);
+ eventSender.mouseMoveTo(280, 125);
+
+ eventSender.mouseMoveTo(325, 125);
+ eventSender.mouseMoveTo(330, 125);
+
+ eventSender.mouseMoveTo(375, 125);
+ eventSender.mouseMoveTo(380, 125);
+ eventSender.mouseMoveTo(385, 125);
+
+ eventSender.mouseMoveTo(1, 1);
+ layoutTestController.notifyDone()
+ }
+}
+</script>
+
+</body>
+</html>
+2006-03-20 Alexey Proskuryakov <ap@nypop.com>
+
+ 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 <darin@apple.com>
Reviewed by Anders.
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);
_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<RenderWidget *>(renderer)->widget();
- if (!widget || !widget->isFrameView())
- return false;
- Frame *subframePart = static_cast<FrameView *>(widget)->frame();
- if (!subframePart)
- return false;
+ ASSERT(subframePart);
[Mac(subframePart)->bridge() mouseMoved:_currentEvent];
return true;
}
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;
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()
class PlatformKeyboardEvent;
class FrameMac;
class PlatformMouseEvent;
+class MouseEventWithHitTestResults;
class Node;
class RenderBox;
class RenderCanvas;
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,