Reviewed by Adele.
authorap <ap@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 3 Nov 2006 18:36:56 +0000 (18:36 +0000)
committerap <ap@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 3 Nov 2006 18:36:56 +0000 (18:36 +0000)
        http://bugs.webkit.org/show_bug.cgi?id=7323
        REGRESSION (10.4.4): ondrag* events don't fire on page in a frame

WebCore:
        * bridge/mac/FrameMac.h: Moved drag source information to a static variable
        in FrameMac.mm. There can be only one drag active at any moment, and having
        this information here was making sharing this information between
        subframes hard.

        * bridge/mac/FrameMac.mm:
        (WebCore::FrameMac::FrameMac): Initialize sharedDragInfo.
        (WebCore::FrameMac::freeClipboard):
        (WebCore::FrameMac::dragHysteresisExceeded):
        (WebCore::FrameMac::handleMouseMoveEvent):
        (WebCore::FrameMac::handleMouseReleaseEvent):
        (WebCore::FrameMac::mouseDown):
        (WebCore::FrameMac::dragSourceMovedTo):
        (WebCore::FrameMac::dragSourceEndedAt):
        (WebCore::FrameMac::dispatchDragSrcEvent):
        Access drag source info via sharedDragInfo - this fixes drag source even dispatching.
        Also removed some old code that was forwarding mouse events to subviews to make
        HTML editing work in subframes.

        * page/FrameView.cpp:
        (WebCore::FrameView::updateDragAndDrop):
        (WebCore::FrameView::cancelDragAndDrop):
        (WebCore::FrameView::performDragAndDrop):
        Forward events to subframes for dispatching - this fixes drag target events.

WebKitTools:
        When dragging, do not send EventSendingController's events immediately. Dragging
        is supposed to be modal, so we need to perform it from within the delegate, without
        returning to JS to make the next mouse movement.

        When the mouse is down, mouse events are now recorded, and executed when mouseUp is sent.

        * DumpRenderTree/EventSendingController.h:
        * DumpRenderTree/EventSendingController.m:
        (-[EventSendingController dealloc]):
        (-[EventSendingController leapForward:]):
        (-[EventSendingController mouseDown]):
        (-[EventSendingController mouseUp]):
        (-[EventSendingController mouseMoveToX:Y:]):
        (+[EventSendingController saveEvent:]):
        (+[EventSendingController replaySavedEvents]):
        * DumpRenderTree/UIDelegate.m:
        (-[UIDelegate webView:dragImage:at:offset:event:pasteboard:source:slideBack:forView:]):

LayoutTests:
        * fast/events/drag-in-frames-expected.txt: Added.
        * fast/events/drag-in-frames.html: Added.
        * fast/events/resources/drag-in-frames-console.html: Added.
        * fast/events/resources/drag-in-frames-left.html: Added.
        * fast/events/resources/drag-in-frames-right.html: Added.

        * editing/selection/expanding-selections.html:
        * editing/selection/expanding-selections2.html:
        * fast/dynamic/layer-hit-test-crash.html:
        * fast/events/event-view-toString.html:
        * fast/events/resources/drag-outside-window-frame.html:
        * svg/custom/hover-default-fill.svg:
        Added missing calls to mouseUp().

        * svg/custom/stroke-width-click-expected.txt:
        * svg/custom/stroke-width-click.svg:
        Don't attempt to click outside the page, this was confusing DRT.

        * editing/selection/select-from-textfield-outwards-expected.txt:
        * editing/selection/select-from-textfield-outwards.html:
        Removed alerts between dragging steps - they are now useless,
        as the dragging events are stored and executed at once.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@17574 268f45cc-cd09-0410-ab3c-d52691b4dbfc

24 files changed:
LayoutTests/ChangeLog
LayoutTests/editing/selection/expanding-selections.html
LayoutTests/editing/selection/expanding-selections2.html
LayoutTests/editing/selection/select-from-textfield-outwards-expected.txt
LayoutTests/editing/selection/select-from-textfield-outwards.html
LayoutTests/fast/dynamic/layer-hit-test-crash.html
LayoutTests/fast/events/drag-in-frames-expected.txt [new file with mode: 0644]
LayoutTests/fast/events/drag-in-frames.html [new file with mode: 0644]
LayoutTests/fast/events/event-view-toString.html
LayoutTests/fast/events/resources/drag-in-frames-console.html [new file with mode: 0644]
LayoutTests/fast/events/resources/drag-in-frames-left.html [new file with mode: 0644]
LayoutTests/fast/events/resources/drag-in-frames-right.html [new file with mode: 0644]
LayoutTests/fast/events/resources/drag-outside-window-frame.html
LayoutTests/svg/custom/hover-default-fill.svg
LayoutTests/svg/custom/stroke-width-click-expected.txt
LayoutTests/svg/custom/stroke-width-click.svg
WebCore/ChangeLog
WebCore/bridge/mac/FrameMac.h
WebCore/bridge/mac/FrameMac.mm
WebCore/page/FrameView.cpp
WebKitTools/ChangeLog
WebKitTools/DumpRenderTree/EventSendingController.h
WebKitTools/DumpRenderTree/EventSendingController.m
WebKitTools/DumpRenderTree/UIDelegate.m

index ae04c29f757506171c0454427a326799dadb179c..32dc69972e38482aff97e69e02a2837c698c6c65 100644 (file)
@@ -1,3 +1,33 @@
+2006-11-03  Alexey Proskuryakov  <ap@nypop.com>
+
+        Reviewed by Adele.
+
+        Test for http://bugs.webkit.org/show_bug.cgi?id=7323
+        REGRESSION (10.4.4): ondrag* events don't fire on page in a frame
+
+        * fast/events/drag-in-frames-expected.txt: Added.
+        * fast/events/drag-in-frames.html: Added.
+        * fast/events/resources/drag-in-frames-console.html: Added.
+        * fast/events/resources/drag-in-frames-left.html: Added.
+        * fast/events/resources/drag-in-frames-right.html: Added.
+
+        * editing/selection/expanding-selections.html:
+        * editing/selection/expanding-selections2.html:
+        * fast/dynamic/layer-hit-test-crash.html:
+        * fast/events/event-view-toString.html:
+        * fast/events/resources/drag-outside-window-frame.html:
+        * svg/custom/hover-default-fill.svg:
+        Added missing calls to mouseUp().
+
+        * svg/custom/stroke-width-click-expected.txt:
+        * svg/custom/stroke-width-click.svg:
+        Don't attempt to click outside the page, this was confusing DRT.
+
+        * editing/selection/select-from-textfield-outwards-expected.txt:
+        * editing/selection/select-from-textfield-outwards.html:
+        Removed alerts between dragging steps - they are now useless,
+        as the dragging events are stored and executed at once.
+
 2006-11-03  Geoffrey Garen  <ggaren@apple.com>
 
         Missed a few tests in my last check-in, and checked in old results for
index a9ca6ba84884b49bc18a8e221cd1ba723d7cc8f6..94e516d1ea97dc63fa6fa762e9471091f6ab00c3 100644 (file)
@@ -17,6 +17,7 @@ function editingTest() {
     eventSender.mouseDown();
     eventSender.mouseUp();
     eventSender.mouseDown();
+    eventSender.mouseUp();
 }
 
 </script>
index be319e30b109dd84b02bce31ed170324e32fa861..5ae2c0aff984f235a128d7d2315386cecacd8b83 100644 (file)
@@ -17,6 +17,7 @@ function editingTest() {
     eventSender.mouseDown();
     eventSender.mouseUp();
     eventSender.mouseDown();
+    eventSender.mouseUp();
 }
 
 </script>
index e90a639f59847769f9f21e161364334dd8b4728d..786d88ce323fab38e00063cbc18de26034a106a0 100644 (file)
@@ -1,23 +1,16 @@
-ALERT: middle
 EDITING DELEGATE: shouldChangeSelectedDOMRange:(null) toDOMRange:range from 11 of #text > DIV to 11 of #text > DIV affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
 EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
 EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 11 of #text > DIV to 11 of #text > DIV toDOMRange:range from 11 of #text > DIV to 12 of #text > DIV affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
 EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
-ALERT: left
 EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 11 of #text > DIV to 12 of #text > DIV toDOMRange:range from 0 of #text > DIV to 12 of #text > DIV affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
 EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
-ALERT: right
 EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 0 of #text > DIV to 12 of #text > DIV toDOMRange:range from 11 of #text > DIV to 17 of #text > DIV affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
 EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
-ALERT: way up
 EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 11 of #text > DIV to 17 of #text > DIV toDOMRange:range from 0 of #text > DIV to 12 of #text > DIV affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
 EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
-ALERT: up
 EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 0 of #text > DIV to 12 of #text > DIV toDOMRange:range from 0 of #text > DIV to 12 of #text > DIV affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
-ALERT: down
 EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 0 of #text > DIV to 12 of #text > DIV toDOMRange:range from 11 of #text > DIV to 17 of #text > DIV affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
 EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
-ALERT: way down
 EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 11 of #text > DIV to 17 of #text > DIV toDOMRange:range from 11 of #text > DIV to 17 of #text > DIV affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
 layer at (0,0) size 800x600
   RenderView at (0,0) size 800x600
index b9d510b9f10767506af25896db84a2144943ad86..f9a9b8c2d16c77087f798d1eb91c07e79d7829a8 100644 (file)
@@ -10,24 +10,25 @@ function editingTest() {
     var middleX = field.offsetLeft + field.offsetWidth / 2;
     var middleY = field.offsetTop + field.offsetHeight / 2;
     
-    alert("middle");
+    // middle
     eventSender.mouseMoveTo(middleX, middleY);
     eventSender.mouseDown();
     eventSender.leapForward(1000);
     eventSender.mouseUp();
     eventSender.mouseDown();
-    alert("left");
+    // left
     eventSender.mouseMoveTo(0, middleY);
-    alert("right");
+    // right
     eventSender.mouseMoveTo(document.body.offsetWidth, middleY);
-    alert("way up");
+    // way up
     eventSender.mouseMoveTo(middleX, middleY - 2 * field.offsetHeight);
-    alert("up");
+    // up
     eventSender.mouseMoveTo(middleX, middleY - field.offsetHeight);
-    alert("down");
+    // down
     eventSender.mouseMoveTo(middleX, middleY + field.offsetHeight);
-    alert("way down");
+    // way down
     eventSender.mouseMoveTo(middleX, middleY + 2 * field.offsetHeight);
+    eventSender.mouseUp();
 }
 </script>
 </head>
index e2196b1e024abfc2a984a1e339b8e20781ed7cce..5c16fabb65606a2c397f26b93c8f63e96d2f4aa2 100644 (file)
@@ -33,6 +33,8 @@ function moveMouse()
 
 function finish()
 {
+    if (window.eventSender)
+        eventSender.mouseUp();
     if (window.layoutTestController)
         layoutTestController.notifyDone();
 }
diff --git a/LayoutTests/fast/events/drag-in-frames-expected.txt b/LayoutTests/fast/events/drag-in-frames-expected.txt
new file mode 100644 (file)
index 0000000..a2c7daf
--- /dev/null
@@ -0,0 +1,18 @@
+Event log
+
+ondragstart src
+ondrag src
+ondragenter left target
+ondrag src
+ondragover left target
+ondrag src
+ondragenter right target
+ondragleave left target
+ondrag src
+ondragover right target
+ondragover right target
+ondrop right target
+ondragend src
+These results are just "sensible" at the moment, meaning that all the events fire on the right elements, nothing more. The order in particular can rightfully change.
+
+
diff --git a/LayoutTests/fast/events/drag-in-frames.html b/LayoutTests/fast/events/drag-in-frames.html
new file mode 100644 (file)
index 0000000..85ebaf4
--- /dev/null
@@ -0,0 +1,71 @@
+<head>
+<script>
+function log(message) {
+    console_doc = frames[2].document;
+    var item = console_doc.createElement("li");
+    item.appendChild(console_doc.createTextNode(message));
+    console_doc.getElementById('console_messages').appendChild(item);
+}
+
+function test() {
+    if (window.layoutTestController) {
+        layoutTestController.dumpAsText();
+        layoutTestController.waitUntilDone();
+
+        // Find the element to drag
+        elementToDrag = frames[0].document.getElementById("elementToDrag");
+        x1 = elementToDrag.offsetLeft + elementToDrag.offsetWidth / 2;
+        y1 = elementToDrag.offsetTop + elementToDrag.offsetHeight / 2;
+
+        // Drag to the middle of the destination element in the same frame
+        dragTarget = frames[0].document.getElementById("dragTarget");
+        x2 = dragTarget.offsetLeft + dragTarget.offsetWidth / 2;
+        y2 = dragTarget.offsetTop + dragTarget.offsetHeight / 2;
+
+        eventSender.mouseMoveTo(x1,y1);
+        eventSender.mouseDown();
+        eventSender.mouseMoveTo(x2, y2);
+        eventSender.mouseMoveTo(x2, y2+1);
+        eventSender.mouseMoveTo(x2, y2+2);
+
+        // Drag to the middle of the destination element in another frame
+        dragTarget2 = frames[1].document.getElementById("dragTarget2");
+        x3 = 150 + dragTarget2.offsetLeft + dragTarget2.offsetWidth / 2;
+        y3 = dragTarget2.offsetTop + dragTarget2.offsetHeight / 2;
+
+        eventSender.mouseMoveTo(x3, y3);
+        eventSender.mouseMoveTo(x3, y3+1);
+        eventSender.mouseUp();
+
+        document.write("<body>" + 
+            frames[2].document.body.innerHTML + 
+            "<p>These results are just \"sensible\" at the moment, meaning that " +
+            "all the events fire on the right elements, nothing more. The order in particular "+
+            "can rightfully change.</p>" +
+            "<scr" + "ipt>layoutTestController.notifyDone();</scr" + "ipt>" + 
+            "</body>");
+    }
+}
+</script>
+</head>
+<!-- frames -->
+<frameset  cols="150,150,*" border="0" onload="test();">
+
+    <frame name="left" src="resources/drag-in-frames-left.html" marginwidth="10" marginheight="10" scrolling="auto" frameborder="0"
+                 ondrag="alert('ondrag left frame')"
+                 ondrop="alert('ondrop left frame')"
+                 ondragstart="alert('ondragstart left frame')"
+                 ondragend="alert('ondragend left frame')"
+                 ondragenter="log('ondragenter left frame')"
+                 ondragover="log('ondragover left frame')"
+                 ondragleave="log('ondragleave left frame')">
+    <frame name="right" src="resources/drag-in-frames-right.html" marginwidth="10" marginheight="10" scrolling="auto" frameborder="0"
+                 ondrag="alert('ondrag right frame')"
+                 ondrop="alert('ondrop right frame')"
+                 ondragstart="alert('ondragstart right frame')"
+                 ondragend="alert('ondragend right frame')"
+                 ondragenter="log('ondragenter right frame')"
+                 ondragover="log('ondragover right frame')"
+                 ondragleave="log('ondragleave right frame')">
+    <frame name="console" src="resources/drag-in-frames-console.html"  marginwidth="10" marginheight="10" scrolling="auto" frameborder="0">
+</frameset>
index 3eb0dee1efb9878ca821ee17ca39ca53997571ef..500d26c17f5f73a3df075f321d93f93d50070371 100644 (file)
@@ -2,39 +2,40 @@
         "http://www.w3.org/TR/html4/strict.dtd">
 <html>
 <head>
-       <title>Test for bug 4233558</title>
+    <title>Test for bug 4233558</title>
 <script type="text/javascript" charset="utf-8">
-       if (window.layoutTestController) {
-               layoutTestController.dumpAsText();
-               layoutTestController.waitUntilDone();
-       }
+    if (window.layoutTestController) {
+        layoutTestController.dumpAsText();
+        layoutTestController.waitUntilDone();
+    }
 
-       function clickBody(event) {
-               var resultsDiv = document.getElementById("resultsDiv");
-               
-               resultsDiv.innerHTML +=  "event.view :<br/>";
-               try {
-                       resultsDiv.innerHTML +=  "document: " + event.view.document + "<br/>";
-                       resultsDiv.innerHTML +=  "proto: " + event.view.__proto__ + "<br/>";
-                       resultsDiv.innerHTML +=  " Success getting " + event.view + "<br/>";
-               }
-               catch(e) {
-                       resultsDiv.innerHTML +=  " ERROR (" + e + ") getting value!<br/>";
-               }
-               if (window.layoutTestController) {
-                       layoutTestController.notifyDone();
-               }
-       }
+    function clickBody(event) {
+        var resultsDiv = document.getElementById("resultsDiv");
+        
+        resultsDiv.innerHTML +=  "event.view :<br/>";
+        try {
+            resultsDiv.innerHTML +=  "document: " + event.view.document + "<br/>";
+            resultsDiv.innerHTML +=  "proto: " + event.view.__proto__ + "<br/>";
+            resultsDiv.innerHTML +=  " Success getting " + event.view + "<br/>";
+        }
+        catch(e) {
+            resultsDiv.innerHTML +=  " ERROR (" + e + ") getting value!<br/>";
+        }
+        if (window.layoutTestController) {
+            layoutTestController.notifyDone();
+        }
+    }
 
-       function loadHandler() {
-               var resultsDiv = document.getElementById("resultsDiv");
-               if (window.eventSender) {
-                       eventSender.mouseMoveTo(50, 50);
-                       eventSender.mouseDown();
-               } else {
-                       resultsDiv.innerHTML += "Manual test mode.<br/>";
-               }
-       }
+    function loadHandler() {
+        var resultsDiv = document.getElementById("resultsDiv");
+        if (window.eventSender) {
+            eventSender.mouseMoveTo(50, 50);
+            eventSender.mouseDown();
+            eventSender.mouseUp();
+        } else {
+            resultsDiv.innerHTML += "Manual test mode.<br/>";
+        }
+    }
 </script>
 </head>
 <body onLoad="loadHandler()" onmousedown="clickBody(event)">
diff --git a/LayoutTests/fast/events/resources/drag-in-frames-console.html b/LayoutTests/fast/events/resources/drag-in-frames-console.html
new file mode 100644 (file)
index 0000000..ee924a1
--- /dev/null
@@ -0,0 +1,4 @@
+<body>
+<h4>Event log</h4>
+<ul id='console_messages' style='font-size:8px'></ul>
+</body>
diff --git a/LayoutTests/fast/events/resources/drag-in-frames-left.html b/LayoutTests/fast/events/resources/drag-in-frames-left.html
new file mode 100644 (file)
index 0000000..631237b
--- /dev/null
@@ -0,0 +1,49 @@
+<html>
+<head>
+    <title>Left</title>
+</head>
+
+<body style="margin:0; padding:0">
+
+<script>
+function log(message) {
+    console_doc = parent.frames[2].document;
+    var item = console_doc.createElement("li");
+    item.appendChild(console_doc.createTextNode(message));
+    console_doc.getElementById('console_messages').appendChild(item);
+}
+</script>
+
+<div style="width:150; height:75; text-align:center;">
+  <a id="elementToDrag"
+     href="#"
+     style="position: relative; top: 50"
+     ondrag="log('ondrag src')"
+     ondragstart="log('ondragstart src')"
+     ondragend="log('ondragend src')"
+     ondragenter="log('ondragenter src')"
+     ondragover="log('ondragover src')"
+     ondragleave="log('ondragleave src')"
+     ondrop="log('ondrop src')">
+  Drag me
+  </a>
+</div>
+
+<div id="dragTarget"
+     style="width:150; height:150; background-color:lightgreen; text-align:center;"
+     ondrag="alert('ondrag left target')"
+     ondragstart="alert('ondragstart left target')"
+     ondragend="alert('ondragend left target')"
+     ondragenter="log('ondragenter left target'); return false;"
+     ondragover="log('ondragover left target'); return false;"
+     ondragleave="log('ondragleave left target')"
+     ondrop="log('ondrop left target')">
+  <span style="position: relative; top: 50">Here</span>
+</div>
+
+<p><a href="http://bugs.webkit.org/show_bug.cgi?id=7323" target="_top">Bug 7323</a>: 
+REGRESSION (10.4.4): ondrag* events don't fire on page in a frame</p>
+<p>This test works only in automatic mode, but you can also try dragging manually to compare the results with other browsers.</p>
+
+</body>
+</html>
diff --git a/LayoutTests/fast/events/resources/drag-in-frames-right.html b/LayoutTests/fast/events/resources/drag-in-frames-right.html
new file mode 100644 (file)
index 0000000..e9fee7f
--- /dev/null
@@ -0,0 +1,31 @@
+<html>
+<head>
+    <title>Right</title>
+</head>
+
+<body style="margin:0; padding:0">
+
+<script>
+function log(message) {
+    console_doc = parent.frames[2].document;
+    var item = console_doc.createElement("li");
+    item.appendChild(console_doc.createTextNode(message));
+    console_doc.getElementById('console_messages').appendChild(item);
+}
+</script>
+
+<div style="height:75px"></div>
+
+<div id="dragTarget2"
+     style="width:150; height:150; background-color:lightblue; text-align:center;"
+     ondrag="alert('ondrag right target')"
+     ondragstart="alert('ondragstart right target')"
+     ondragend="alert('ondragend right target')"
+     ondragenter="log('ondragenter right target'); return false;"
+     ondragover="log('ondragover right target'); return false;"
+     ondragleave="log('ondragleave right target')"
+     ondrop="log('ondrop right target')">
+  <span style="position: relative; top: 50">And here</span>
+</div>
+</body>
+</html>
index bec0292343160cd8d5fe96cf6347483195bbb2ab..b8666aaacda07c22f551a48b2192731c48ee5751 100644 (file)
@@ -18,6 +18,7 @@ function test()
     eventSender.mouseMoveTo(150, 100);
     eventSender.mouseDown();
     eventSender.mouseMoveTo(50, 100);
+    eventSender.mouseUp();
     alert("Test result: " + result);
 }
 </script>
index ba2cc83f7d8f3b273cc81a59d3688b8a621a504e..f56c3ef4726ce8ed45c9196c9af106aaeb4aeaa1 100644 (file)
@@ -8,6 +8,7 @@
   if (window.eventSender) {
     eventSender.mouseMoveTo(50, 50);
     eventSender.mouseDown();
+    eventSender.mouseUp();
   }
 ]]>
 </script>
index 69a9baaa340ec5b5f46ffbc9171ed5e6fdad89f6..2fa49e07b8c72869a5ae8337cd234a6404054019 100644 (file)
@@ -46,7 +46,7 @@
   
     
       
-      SUCCESS: click at 10, 10 was correctly ignoredSUCCESS: click received at: 30, 100SUCCESS: click at 29, 100 was correctly ignoredSUCCESS: click received at: 30, 50SUCCESS: click at 30, 49 was correctly ignoredSUCCESS: click received at: 30, 150SUCCESS: click at 30, 151 was correctly ignoredSUCCESS: click received at: 300, 100SUCCESS: click at 301, 100 was correctly ignoredSUCCESS: click received at: 300, 50SUCCESS: click at 300, 49 was correctly ignoredSUCCESS: click received at: 300, 150SUCCESS: click at 300, 151 was correctly ignoredSUCCESS: click at 1000, 1000 was correctly ignored
+      SUCCESS: click at 10, 10 was correctly ignoredSUCCESS: click received at: 30, 100SUCCESS: click at 29, 100 was correctly ignoredSUCCESS: click received at: 30, 50SUCCESS: click at 30, 49 was correctly ignoredSUCCESS: click received at: 30, 150SUCCESS: click at 30, 151 was correctly ignoredSUCCESS: click received at: 300, 100SUCCESS: click at 301, 100 was correctly ignoredSUCCESS: click received at: 300, 50SUCCESS: click at 300, 49 was correctly ignoredSUCCESS: click received at: 300, 150SUCCESS: click at 300, 151 was correctly ignored
     
   
   
@@ -71,7 +71,6 @@
       testClick(300, 49, false);
       testClick(300, 150, true);
       testClick(300, 151, false);
-      testClick(1000, 1000, false);
     } else {
       log("ERROR: window.eventSender not found!  This test must be run using DumpRenderTree.  Mousing over the yellow area will log however.");
     }
index 006f6f1f4651e69580aa4f99a92e442e3c8ce123..183558d095ce4cb6d37cf4fa10184dbd9ae49573 100644 (file)
@@ -72,7 +72,6 @@
       testClick(300, 49, false);
       testClick(300, 150, true);
       testClick(300, 151, false);
-      testClick(1000, 1000, false);
     } else {
       log("ERROR: window.eventSender not found!  This test must be run using DumpRenderTree.  Mousing over the yellow area will log however.");
     }
index f69b4a45babb0c2e463f24b53815c694a274a8f9..80402361196949f9724c77a8b83ddfa8ed463590 100644 (file)
@@ -1,3 +1,35 @@
+2006-11-03  Alexey Proskuryakov  <ap@nypop.com>
+
+        Reviewed by Adele.
+
+        http://bugs.webkit.org/show_bug.cgi?id=7323
+        REGRESSION (10.4.4): ondrag* events don't fire on page in a frame
+
+        * bridge/mac/FrameMac.h: Moved drag source information to a static variable
+        in FrameMac.mm. There can be only one drag active at any moment, and having 
+        this information here was making sharing this information between 
+        subframes hard.
+
+        * bridge/mac/FrameMac.mm:
+        (WebCore::FrameMac::FrameMac): Initialize sharedDragInfo.
+        (WebCore::FrameMac::freeClipboard):
+        (WebCore::FrameMac::dragHysteresisExceeded):
+        (WebCore::FrameMac::handleMouseMoveEvent):
+        (WebCore::FrameMac::handleMouseReleaseEvent):
+        (WebCore::FrameMac::mouseDown):
+        (WebCore::FrameMac::dragSourceMovedTo):
+        (WebCore::FrameMac::dragSourceEndedAt):
+        (WebCore::FrameMac::dispatchDragSrcEvent):
+        Access drag source info via sharedDragInfo - this fixes drag source even dispatching.
+        Also removed some old code that was forwarding mouse events to subviews to make 
+        HTML editing work in subframes.
+
+        * page/FrameView.cpp:
+        (WebCore::FrameView::updateDragAndDrop):
+        (WebCore::FrameView::cancelDragAndDrop):
+        (WebCore::FrameView::performDragAndDrop):
+        Forward events to subframes for dispatching - this fixes drag target events.
+
 2006-11-03  Zack Rusin  <zack@kde.org>
 
         Reviewed by Tim.
index 70dda443c5f115821374c8e02d8f46f926a8634b..f4940e41c1fef09b0a48087562a662670f902ce8 100644 (file)
@@ -349,15 +349,7 @@ private:
     Vector<KJS::Bindings::RootObject*> m_rootObjects;
     WebScriptObject* _windowScriptObject;
     NPObject* _windowScriptNPObject;
-    
-    RefPtr<Node> _dragSrc;     // element that may be a drag source, for the current mouse gesture
-    bool _dragSrcIsLink;
-    bool _dragSrcIsImage;
-    bool _dragSrcInSelection;
-    bool _dragSrcMayBeDHTML, _dragSrcMayBeUA;   // Are DHTML and/or the UserAgent allowed to drag out?
-    bool _dragSrcIsDHTML;
-    RefPtr<ClipboardMac> _dragClipboard;   // used on only the source side of dragging
-    
+
     RefPtr<Range> m_markedTextRange;
 };
 
index 23380b999d5ae9be75816ee78fcab2efa646ee8a..ad3af2b92bf9dd1a604bc2b408360024e0688b60 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (C) 2004, 2005, 2006 Apple Computer, Inc.  All rights reserved.
+ * Copyright (C) 2006 Alexey Proskuryakov (ap@nypop.com)
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -114,6 +115,18 @@ using namespace HTMLNames;
 
 NSEvent* FrameMac::_currentEvent = nil;
 
+struct FrameMacDragInfo {
+    RefPtr<Node> m_dragSrc;     // element that may be a drag source, for the current mouse gesture
+    bool m_dragSrcIsLink;
+    bool m_dragSrcIsImage;
+    bool m_dragSrcInSelection;
+    bool m_dragSrcMayBeDHTML, m_dragSrcMayBeUA;   // Are DHTML and/or the UserAgent allowed to drag out?
+    bool m_dragSrcIsDHTML;
+    RefPtr<ClipboardMac> m_dragClipboard;   // used on only the source side of dragging
+};
+
+static FrameMacDragInfo* sharedDragInfo;
+
 static const unsigned int escChar = 27;
 static SEL selectorForKeyEvent(const PlatformKeyboardEvent* event)
 {
@@ -156,6 +169,8 @@ FrameMac::FrameMac(Page* page, Element* ownerElement, PassRefPtr<EditorClient> c
     , _windowScriptObject(0)
     , _windowScriptNPObject(0)
 {
+     if (!sharedDragInfo)
+         sharedDragInfo = new FrameMacDragInfo;
 }
 
 FrameMac::~FrameMac()
@@ -250,8 +265,8 @@ Frame* FrameMac::createFrame(const KURL& url, const String& name, Element* owner
 
 void FrameMac::freeClipboard()
 {
-    if (_dragClipboard)
-        _dragClipboard->setAccessPolicy(ClipboardNumb);
+    if (sharedDragInfo->m_dragClipboard)
+        sharedDragInfo->m_dragClipboard->setAccessPolicy(ClipboardNumb);
 }
 
 // Either get cached regexp or build one that matches any of the labels.
@@ -1505,11 +1520,11 @@ bool FrameMac::dragHysteresisExceeded(float dragLocationX, float dragLocationY)
     IntSize delta = dragLocation - m_mouseDownPos;
     
     float threshold = GeneralDragHysteresis;
-    if (_dragSrcIsImage)
+    if (sharedDragInfo->m_dragSrcIsImage)
         threshold = ImageDragHysteresis;
-    else if (_dragSrcIsLink)
+    else if (sharedDragInfo->m_dragSrcIsLink)
         threshold = LinkDragHysteresis;
-    else if (_dragSrcInSelection)
+    else if (sharedDragInfo->m_dragSrcInSelection)
         threshold = TextDragHysteresis;
 
     return fabsf(delta.width()) >= threshold || fabsf(delta.height()) >= threshold;
@@ -1520,51 +1535,44 @@ void FrameMac::handleMouseMoveEvent(const MouseEventWithHitTestResults& event)
     BEGIN_BLOCK_OBJC_EXCEPTIONS;
 
     if ([_currentEvent type] == NSLeftMouseDragged) {
-        NSView *view = mouseDownViewIfStillGood();
-
-        if (view) {
-            _sendingEventToSubview = true;
-            [view mouseDragged:_currentEvent];
-            _sendingEventToSubview = false;
-            return;
-        }
+        if (mouseDownViewIfStillGood())
+            return; // The event has been already dispatched to a subframe
 
         // Careful that the drag starting logic stays in sync with eventMayStartDrag()
     
-        if (mouseDownMayStartDrag() && !_dragSrc) {
+        if (mouseDownMayStartDrag() && !sharedDragInfo->m_dragSrc) {
             BOOL tempFlag1, tempFlag2;
             [_bridge allowDHTMLDrag:&tempFlag1 UADrag:&tempFlag2];
-            _dragSrcMayBeDHTML = tempFlag1;
-            _dragSrcMayBeUA = tempFlag2;
-            if (!_dragSrcMayBeDHTML && !_dragSrcMayBeUA) {
+            sharedDragInfo->m_dragSrcMayBeDHTML = tempFlag1;
+            sharedDragInfo->m_dragSrcMayBeUA = tempFlag2;
+            if (!sharedDragInfo->m_dragSrcMayBeDHTML && !sharedDragInfo->m_dragSrcMayBeUA)
                 setMouseDownMayStartDrag(false);     // no element is draggable
-            }
         }
         
-        if (mouseDownMayStartDrag() && !_dragSrc) {
+        if (mouseDownMayStartDrag() && !sharedDragInfo->m_dragSrc) {
             // try to find an element that wants to be dragged
             HitTestRequest request(true, false);
             HitTestResult result(m_mouseDownPos);
             renderer()->layer()->hitTest(request, result);
             Node *node = result.innerNode();
-            _dragSrc = (node && node->renderer()) ? node->renderer()->draggableNode(_dragSrcMayBeDHTML, _dragSrcMayBeUA, m_mouseDownPos.x(), m_mouseDownPos.y(), _dragSrcIsDHTML) : 0;
-            if (!_dragSrc) {
+            sharedDragInfo->m_dragSrc = (node && node->renderer()) ? node->renderer()->draggableNode(sharedDragInfo->m_dragSrcMayBeDHTML, sharedDragInfo->m_dragSrcMayBeUA, m_mouseDownPos.x(), m_mouseDownPos.y(), sharedDragInfo->m_dragSrcIsDHTML) : 0;
+            if (!sharedDragInfo->m_dragSrc) {
                 setMouseDownMayStartDrag(false);     // no element is draggable
             } else {
                 // remember some facts about this source, while we have a HitTestResult handy
                 node = result.URLElement();
-                _dragSrcIsLink = node && node->isLink();
+                sharedDragInfo->m_dragSrcIsLink = node && node->isLink();
 
                 node = result.innerNonSharedNode();
-                _dragSrcIsImage = node && node->renderer() && node->renderer()->isImage();
+                sharedDragInfo->m_dragSrcIsImage = node && node->renderer() && node->renderer()->isImage();
                 
-                _dragSrcInSelection = selectionController()->contains(m_mouseDownPos);
+                sharedDragInfo->m_dragSrcInSelection = selectionController()->contains(m_mouseDownPos);
             }                
         }
         
         // For drags starting in the selection, the user must wait between the mousedown and mousedrag,
         // or else we bail on the dragging stuff and allow selection to occur
-        if (mouseDownMayStartDrag() && _dragSrcInSelection && [_currentEvent timestamp] - _mouseDownTimestamp < TextDragDelay) {
+        if (mouseDownMayStartDrag() && sharedDragInfo->m_dragSrcInSelection && [_currentEvent timestamp] - _mouseDownTimestamp < TextDragDelay) {
             setMouseDownMayStartDrag(false);
             // ...but if this was the first click in the window, we don't even want to start selection
             if (_activationEventNumber == [_currentEvent eventNumber]) {
@@ -1586,7 +1594,7 @@ void FrameMac::handleMouseMoveEvent(const MouseEventWithHitTestResults& event)
                 NSPoint dragLoc = NSZeroPoint;
                 NSDragOperation srcOp = NSDragOperationNone;                
                 BOOL wcWrotePasteboard = NO;
-                if (_dragSrcMayBeDHTML) {
+                if (sharedDragInfo->m_dragSrcMayBeDHTML) {
                     NSPasteboard *pasteboard = [NSPasteboard pasteboardWithName:NSDragPboard];
                     // Must be done before ondragstart adds types and data to the pboard,
                     // also done for security, as it erases data from the last drag
@@ -1594,43 +1602,43 @@ void FrameMac::handleMouseMoveEvent(const MouseEventWithHitTestResults& event)
                     
                     freeClipboard();    // would only happen if we missed a dragEnd.  Do it anyway, just
                                         // to make sure it gets numbified
-                    _dragClipboard = new ClipboardMac(true, pasteboard, ClipboardWritable, this);
+                    sharedDragInfo->m_dragClipboard = new ClipboardMac(true, pasteboard, ClipboardWritable, this);
                     
                     // If this is drag of an element, get set up to generate a default image.  Otherwise
                     // WebKit will generate the default, the element doesn't override.
-                    if (_dragSrcIsDHTML) {
+                    if (sharedDragInfo->m_dragSrcIsDHTML) {
                         int srcX, srcY;
-                        _dragSrc->renderer()->absolutePosition(srcX, srcY);
+                        sharedDragInfo->m_dragSrc->renderer()->absolutePosition(srcX, srcY);
                         IntSize delta = m_mouseDownPos - IntPoint(srcX, srcY);
-                        _dragClipboard->setDragImageElement(_dragSrc.get(), IntPoint() + delta);
+                        sharedDragInfo->m_dragClipboard->setDragImageElement(sharedDragInfo->m_dragSrc.get(), IntPoint() + delta);
                     } 
 
                     setMouseDownMayStartDrag(dispatchDragSrcEvent(dragstartEvent, m_mouseDown) && !selectionController()->isInPasswordField());
                     // Invalidate clipboard here against anymore pasteboard writing for security.  The drag
                     // image can still be changed as we drag, but not the pasteboard data.
-                    _dragClipboard->setAccessPolicy(ClipboardImageWritable);
+                    sharedDragInfo->m_dragClipboard->setAccessPolicy(ClipboardImageWritable);
                     
                     if (mouseDownMayStartDrag()) {
                         // gather values from DHTML element, if it set any
-                        _dragClipboard->sourceOperation(srcOp);
+                        sharedDragInfo->m_dragClipboard->sourceOperation(srcOp);
 
                         NSArray *types = [pasteboard types];
                         wcWrotePasteboard = types && [types count] > 0;
 
-                        if (_dragSrcMayBeDHTML)
-                            dragImage = _dragClipboard->dragNSImage(dragLoc);
+                        if (sharedDragInfo->m_dragSrcMayBeDHTML)
+                            dragImage = sharedDragInfo->m_dragClipboard->dragNSImage(dragLoc);
                         
                         // Yuck, dragSourceMovedTo() can be called as a result of kicking off the drag with
                         // dragImage!  Because of that dumb reentrancy, we may think we've not started the
                         // drag when that happens.  So we have to assume it's started before we kick it off.
-                        _dragClipboard->setDragHasStarted();
+                        sharedDragInfo->m_dragClipboard->setDragHasStarted();
                     }
                 }
                 
                 if (mouseDownMayStartDrag()) {
-                    BOOL startedDrag = [_bridge startDraggingImage:dragImage at:dragLoc operation:srcOp event:_currentEvent sourceIsDHTML:_dragSrcIsDHTML DHTMLWroteData:wcWrotePasteboard];
-                    if (!startedDrag && _dragSrcMayBeDHTML) {
-                        // WebKit canned the drag at the last minute - we owe _dragSrc a DRAGEND event
+                    BOOL startedDrag = [_bridge startDraggingImage:dragImage at:dragLoc operation:srcOp event:_currentEvent sourceIsDHTML:sharedDragInfo->m_dragSrcIsDHTML DHTMLWroteData:wcWrotePasteboard];
+                    if (!startedDrag && sharedDragInfo->m_dragSrcMayBeDHTML) {
+                        // WebKit canned the drag at the last minute - we owe m_dragSrc a DRAGEND event
                         PlatformMouseEvent event(PlatformMouseEvent::currentEvent);
                         dispatchDragSrcEvent(dragendEvent, event);
                         setMouseDownMayStartDrag(false);
@@ -1640,7 +1648,7 @@ void FrameMac::handleMouseMoveEvent(const MouseEventWithHitTestResults& event)
                 if (!mouseDownMayStartDrag()) {
                     // something failed to start the drag, cleanup
                     freeClipboard();
-                    _dragSrc = 0;
+                    sharedDragInfo->m_dragSrc = 0;
                 }
             }
 
@@ -1751,12 +1759,6 @@ void FrameMac::handleMouseReleaseEvent(const MouseEventWithHitTestResults& event
         return;
     }
     stopAutoscrollTimer();
-    
-    _sendingEventToSubview = true;
-    BEGIN_BLOCK_OBJC_EXCEPTIONS;
-    [view mouseUp:_currentEvent];
-    END_BLOCK_OBJC_EXCEPTIONS;
-    _sendingEventToSubview = false;
 }
 
 bool FrameMac::passSubframeEventToSubframe(MouseEventWithHitTestResults& event, Frame* subframe)
@@ -1849,7 +1851,7 @@ void FrameMac::mouseDown(NSEvent *event)
     prepareForUserAction();
 
     _mouseDownView = nil;
-    _dragSrc = 0;
+    sharedDragInfo->m_dragSrc = 0;
     
     NSEvent *oldCurrentEvent = _currentEvent;
     _currentEvent = HardRetain(event);
@@ -2954,26 +2956,26 @@ bool FrameMac::shouldClose()
 
 void FrameMac::dragSourceMovedTo(const PlatformMouseEvent& event)
 {
-    if (_dragSrc && _dragSrcMayBeDHTML)
+    if (sharedDragInfo->m_dragSrc && sharedDragInfo->m_dragSrcMayBeDHTML)
         // for now we don't care if event handler cancels default behavior, since there is none
         dispatchDragSrcEvent(dragEvent, event);
 }
 
 void FrameMac::dragSourceEndedAt(const PlatformMouseEvent& event, NSDragOperation operation)
 {
-    if (_dragSrc && _dragSrcMayBeDHTML) {
-        _dragClipboard->setDestinationOperation(operation);
+    if (sharedDragInfo->m_dragSrc && sharedDragInfo->m_dragSrcMayBeDHTML) {
+        sharedDragInfo->m_dragClipboard->setDestinationOperation(operation);
         // for now we don't care if event handler cancels default behavior, since there is none
         dispatchDragSrcEvent(dragendEvent, event);
     }
     freeClipboard();
-    _dragSrc = 0;
+    sharedDragInfo->m_dragSrc = 0;
 }
 
 // returns if we should continue "default processing", i.e., whether eventhandler canceled
-bool FrameMac::dispatchDragSrcEvent(const AtomicString &eventType, const PlatformMouseEvent& event) const
+bool FrameMac::dispatchDragSrcEvent(const AtomicStringeventType, const PlatformMouseEvent& event) const
 {
-    bool noDefaultProc = d->m_view->dispatchDragEvent(eventType, _dragSrc.get(), event, _dragClipboard.get());
+    bool noDefaultProc = d->m_view->dispatchDragEvent(eventType, sharedDragInfo->m_dragSrc.get(), event, sharedDragInfo->m_dragClipboard.get());
     return !noDefaultProc;
 }
 
index b0bbd74172793e32bc937bd8561751866ab6a76f..dd8c42389db9b4111e09b0c755c7bd1ff342ddb9 100644 (file)
@@ -6,6 +6,7 @@
  *                     2000 Dirk Mueller <mueller@kde.org>
  * Copyright (C) 2004, 2005, 2006 Apple Computer, Inc.
  *           (C) 2006 Graham Dennis (graham.dennis@gmail.com)
+ *           (C) 2006 Alexey Proskuryakov (ap@nypop.com)
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
@@ -34,6 +35,7 @@
 #include "Frame.h"
 #include "FrameTree.h"
 #include "HTMLDocument.h"
+#include "HTMLFrameElementBase.h"
 #include "HTMLFrameSetElement.h"
 #include "HTMLInputElement.h"
 #include "HTMLNames.h"
@@ -942,14 +944,26 @@ bool FrameView::updateDragAndDrop(const PlatformMouseEvent& event, Clipboard* cl
         newTarget = newTarget->shadowAncestorNode();
 
     if (d->dragTarget != newTarget) {
-        // note this ordering is explicitly chosen to match WinIE
+        // FIXME: this ordering was explicitly chosen to match WinIE. However,
+        // it is sometimes incorrect when dragging within subframes, as seen with
+        // LayoutTests/fast/events/drag-in-frames.html.
         if (newTarget)
-            accept = dispatchDragEvent(dragenterEvent, newTarget, event, clipboard);
+            if (newTarget->hasTagName(frameTag) || newTarget->hasTagName(iframeTag))
+                accept = static_cast<HTMLFrameElementBase*>(newTarget)->contentFrame()->view()->updateDragAndDrop(event, clipboard);
+            else
+                accept = dispatchDragEvent(dragenterEvent, newTarget, event, clipboard);
+        
         if (d->dragTarget)
-            dispatchDragEvent(dragleaveEvent, d->dragTarget.get(), event, clipboard);
+            if (d->dragTarget->hasTagName(frameTag) || d->dragTarget->hasTagName(iframeTag))
+                accept = static_cast<HTMLFrameElementBase*>(d->dragTarget.get())->contentFrame()->view()->updateDragAndDrop(event, clipboard);
+            else
+                dispatchDragEvent(dragleaveEvent, d->dragTarget.get(), event, clipboard);
     } else {
         if (newTarget)
-            accept = dispatchDragEvent(dragoverEvent, newTarget, event, clipboard);
+            if (newTarget->hasTagName(frameTag) || newTarget->hasTagName(iframeTag))
+                accept = static_cast<HTMLFrameElementBase*>(newTarget)->contentFrame()->view()->updateDragAndDrop(event, clipboard);
+            else
+                accept = dispatchDragEvent(dragoverEvent, newTarget, event, clipboard);
     }
     d->dragTarget = newTarget;
 
@@ -959,7 +973,10 @@ bool FrameView::updateDragAndDrop(const PlatformMouseEvent& event, Clipboard* cl
 void FrameView::cancelDragAndDrop(const PlatformMouseEvent& event, Clipboard* clipboard)
 {
     if (d->dragTarget)
-        dispatchDragEvent(dragleaveEvent, d->dragTarget.get(), event, clipboard);
+        if (d->dragTarget->hasTagName(frameTag) || d->dragTarget->hasTagName(iframeTag))
+            static_cast<HTMLFrameElementBase*>(d->dragTarget.get())->contentFrame()->view()->cancelDragAndDrop(event, clipboard);
+        else
+            dispatchDragEvent(dragleaveEvent, d->dragTarget.get(), event, clipboard);
     d->dragTarget = 0;
 }
 
@@ -967,7 +984,10 @@ bool FrameView::performDragAndDrop(const PlatformMouseEvent& event, Clipboard* c
 {
     bool accept = false;
     if (d->dragTarget)
-        accept = dispatchDragEvent(dropEvent, d->dragTarget.get(), event, clipboard);
+        if (d->dragTarget->hasTagName(frameTag) || d->dragTarget->hasTagName(iframeTag))
+            accept = static_cast<HTMLFrameElementBase*>(d->dragTarget.get())->contentFrame()->view()->performDragAndDrop(event, clipboard);
+        else
+            accept = dispatchDragEvent(dropEvent, d->dragTarget.get(), event, clipboard);
     d->dragTarget = 0;
     return accept;
 }
index 55b920dbcbca94e3c453bfafd8269c4fd8ce8910..4fd33c964c10940795d6e6ce4807c4e68f287d21 100644 (file)
@@ -1,3 +1,28 @@
+2006-11-03  Alexey Proskuryakov  <ap@nypop.com>
+
+        Reviewed by Adele.
+
+        http://bugs.webkit.org/show_bug.cgi?id=7323
+        REGRESSION (10.4.4): ondrag* events don't fire on page in a frame
+
+        When dragging, do not send EventSendingController's events immediately. Dragging 
+        is supposed to be modal, so we need to perform it from within the delegate, without
+        returning to JS to make the next mouse movement.
+
+        When the mouse is down, mouse events are now recorded, and executed when mouseUp is sent.
+
+        * DumpRenderTree/EventSendingController.h:
+        * DumpRenderTree/EventSendingController.m:
+        (-[EventSendingController dealloc]):
+        (-[EventSendingController leapForward:]):
+        (-[EventSendingController mouseDown]):
+        (-[EventSendingController mouseUp]):
+        (-[EventSendingController mouseMoveToX:Y:]):
+        (+[EventSendingController saveEvent:]):
+        (+[EventSendingController replaySavedEvents]):
+        * DumpRenderTree/UIDelegate.m:
+        (-[UIDelegate webView:dragImage:at:offset:event:pasteboard:source:slideBack:forView:]):
+
 2006-11-02  Geoffrey Garen  <ggaren@apple.com>
 
         Reviewed by Justin Garcia.
index 952b1888424d7e8cad1e6db95e54e71d484c5691..718a4858583e2af2a834402a760d025c7008f3ed 100644 (file)
@@ -38,6 +38,9 @@
     double timeOffset;
 }
 
++ (void)saveEvent:(NSInvocation *)event;
++ (void)replaySavedEvents;
+
 - (void)enableDOMUIEventLogging:(WebScriptObject *)node;
 
 - (void)handleEvent:(DOMEvent *)event;
index d7d9c4662a461fbbfe6edbfb81e745aba0f453b3..578316b9133a84cb57bd32a8e98404e4b0fbdc6a 100644 (file)
@@ -2,6 +2,7 @@
  * Copyright (C) 2005, 2006 Apple Computer, Inc.  All rights reserved.
  * Copyright (C) 2006 Jonas Witt <jonas.witt@gmail.com>
  * Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.com>
+ * Copyright (C) 2006 Alexey Proskuryakov <ap@nypop.com>
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -41,6 +42,8 @@ extern void _NSNewKillRingSequence();
 
 NSPoint lastMousePosition;
 NSArray *webkitDomEventNames;
+NSMutableArray *savedMouseEvents; // mouse events sent between mouseDown and mouseUp are stored here, and then executed at once.
+BOOL replayingSavedEvents;
 
 @implementation EventSendingController
 
@@ -126,6 +129,15 @@ NSArray *webkitDomEventNames;
     return nil;
 }
 
+- (void)dealloc
+{
+    assert(!down);
+    assert([savedMouseEvents count] == 0);
+    [savedMouseEvents release];
+    savedMouseEvents = nil;
+    [super dealloc];
+}
+
 - (double)currentEventTime
 {
     return GetCurrentEventTime() + timeOffset;
@@ -133,6 +145,17 @@ NSArray *webkitDomEventNames;
 
 - (void)leapForward:(int)milliseconds
 {
+    if (down && !replayingSavedEvents) {
+        NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[EventSendingController instanceMethodSignatureForSelector:@selector(leapForward:)]];
+        [invocation setTarget:self];
+        [invocation setSelector:@selector(leapForward:)];
+        [invocation setArgument:&milliseconds atIndex:2];
+        
+        [EventSendingController saveEvent:invocation];
+        
+        return;
+    }
+
     timeOffset += milliseconds / 1000.0;
 }
 
@@ -143,6 +166,9 @@ NSArray *webkitDomEventNames;
 
 - (void)mouseDown
 {
+    assert(!down);
+    assert(!replayingSavedEvents);
+
     [[[frame frameView] documentView] layout];
     if ([self currentEventTime] - lastClick >= 1)
         clickCount = 1;
@@ -167,6 +193,20 @@ NSArray *webkitDomEventNames;
 
 - (void)mouseUp
 {
+    assert(down);
+
+    if (!replayingSavedEvents) {
+        NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[EventSendingController instanceMethodSignatureForSelector:@selector(mouseUp)]];
+        [invocation setTarget:self];
+        [invocation setSelector:@selector(mouseUp)];
+        
+        [EventSendingController saveEvent:invocation];
+        [EventSendingController replaySavedEvents];
+
+        return;
+    }
+
+
     [[[frame frameView] documentView] layout];
     NSEvent *event = [NSEvent mouseEventWithType:NSLeftMouseUp 
                                         location:lastMousePosition 
@@ -201,6 +241,18 @@ NSArray *webkitDomEventNames;
 
 - (void)mouseMoveToX:(int)x Y:(int)y
 {
+    if (down && !replayingSavedEvents) {
+        NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[EventSendingController instanceMethodSignatureForSelector:@selector(mouseMoveToX:Y:)]];
+        [invocation setTarget:self];
+        [invocation setSelector:@selector(mouseMoveToX:Y:)];
+        [invocation setArgument:&x atIndex:2];
+        [invocation setArgument:&y atIndex:3];
+        
+        [EventSendingController saveEvent:invocation];
+        
+        return;
+    }
+
     NSView *view = [frame webView];
     lastMousePosition = [view convertPoint:NSMakePoint(x, [view frame].size.height - y) toView:nil];
     NSEvent *event = [NSEvent mouseEventWithType:(down ? NSLeftMouseDragged : NSMouseMoved) 
@@ -261,6 +313,25 @@ NSArray *webkitDomEventNames;
     }
 }
 
++ (void)saveEvent:(NSInvocation *)event
+{
+    if (!savedMouseEvents)
+        savedMouseEvents = [[NSMutableArray alloc] init];
+    [savedMouseEvents addObject:event];
+}
+
++ (void)replaySavedEvents
+{
+    replayingSavedEvents = YES;
+    while ([savedMouseEvents count]) {
+        // if a drag is initiated, the remaining saved events will be dispatched from our dragging delegate
+        NSInvocation *invocation = [[[savedMouseEvents objectAtIndex:0] retain] autorelease];
+        [savedMouseEvents removeObjectAtIndex:0];
+        [invocation invoke];
+    }
+    replayingSavedEvents = NO;
+}
+
 - (void)keyDown:(NSString *)character withModifiers:(WebScriptObject *)modifiers
 {
     NSString *modifier = nil;
index fb7e2404ba0567b5e34e3300a6ca30e5bbb67b89..f3f508306edf294b25211808f235f59d146c04ca 100644 (file)
@@ -46,12 +46,9 @@ DumpRenderTreeDraggingInfo *draggingInfo = nil;
 
 - (void)webView:(WebView *)sender dragImage:(NSImage *)anImage at:(NSPoint)viewLocation offset:(NSSize)initialOffset event:(NSEvent *)event pasteboard:(NSPasteboard *)pboard source:(id)sourceObj slideBack:(BOOL)slideFlag forView:(NSView *)view
 {
-    // A new drag was started before the old one ended.  Probably shouldn't happen.
-    if (draggingInfo) {
-        [[draggingInfo draggingSource] draggedImage:[draggingInfo draggedImage] endedAt:lastMousePosition operation:NSDragOperationNone];
-        [draggingInfo release];
-    }
-    draggingInfo = [[DumpRenderTreeDraggingInfo alloc] initWithImage:anImage offset:initialOffset pasteboard:pboard source:sourceObj];
+     assert(!draggingInfo);
+     draggingInfo = [[DumpRenderTreeDraggingInfo alloc] initWithImage:anImage offset:initialOffset pasteboard:pboard source:sourceObj];
+     [EventSendingController replaySavedEvents];
 }
 
 - (void)webViewFocus:(WebView *)webView