Invert CSS transforms for the mouse event coordinate sent to the plugin. Original fix by Victor <vik@dhtmlx.com>. b=539565 r=josh
authorMats Palmgren <matspal@gmail.com>
Tue, 27 Apr 2010 18:15:02 +0200
changeset 41424 c14e08cf3e61b499039e532d2e97720874a9b954
parent 41423 01f5e4105daea05b2afa3886d134266f057df95d
child 41425 8102627c8c6262e502cd071c124a4745fc615a58
push id1
push userroot
push dateTue, 26 Apr 2011 22:38:44 +0000
treeherdermozilla-beta@bfdb6e623a36 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjosh
bugs539565
milestone1.9.3a5pre
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
Invert CSS transforms for the mouse event coordinate sent to the plugin. Original fix by Victor <vik@dhtmlx.com>. b=539565 r=josh
layout/generic/nsObjectFrame.cpp
modules/plugin/test/mochitest/Makefile.in
modules/plugin/test/mochitest/test_bug539565-1.html
modules/plugin/test/mochitest/test_bug539565-2.html
--- a/layout/generic/nsObjectFrame.cpp
+++ b/layout/generic/nsObjectFrame.cpp
@@ -4391,31 +4391,36 @@ nsEventStatus nsPluginInstanceOwner::Pro
     if (pluginWidget && NS_SUCCEEDED(pluginWidget->StartDrawPlugin())) {
       NPEventModel eventModel = GetEventModel();
 
       // If we have to synthesize an event we'll use one of these.
 #ifndef NP_NO_CARBON
       EventRecord synthCarbonEvent;
 #endif
       NPCocoaEvent synthCocoaEvent;
-
       void* event = anEvent.pluginEvent;
-
+      nsPoint pt =
+        nsLayoutUtils::GetEventCoordinatesRelativeTo(&anEvent, mObjectFrame) -
+        mObjectFrame->GetUsedBorderAndPadding().TopLeft();
+      nsPresContext* presContext = mObjectFrame->PresContext();
+      nsIntPoint ptPx(presContext->AppUnitsToDevPixels(pt.x),
+                      presContext->AppUnitsToDevPixels(pt.y));
+#ifndef NP_NO_CARBON
+      nsIntPoint geckoScreenCoords = mWidget->WidgetToScreenOffset();
+      Point carbonPt = { ptPx.y + geckoScreenCoords.y, ptPx.x + geckoScreenCoords.x };
+      if (eventModel == NPEventModelCarbon) {
+        if (event && anEvent.eventStructType == NS_MOUSE_EVENT) {
+          static_cast<EventRecord*>(event)->where = carbonPt;
+        }
+      }
+#endif
       if (!event) {
-        nsPoint pt = nsLayoutUtils::GetEventCoordinatesRelativeTo(&anEvent, mObjectFrame)
-          - mObjectFrame->GetUsedBorderAndPadding().TopLeft();
-        nsPresContext* presContext = mObjectFrame->PresContext();
-        nsIntPoint ptPx(presContext->AppUnitsToDevPixels(pt.x),
-                        presContext->AppUnitsToDevPixels(pt.y));
 
 #ifndef NP_NO_CARBON
         if (eventModel == NPEventModelCarbon) {
-          nsIntPoint geckoScreenCoords = mWidget->WidgetToScreenOffset();
-          Point carbonPt = { ptPx.y + geckoScreenCoords.y, ptPx.x + geckoScreenCoords.x };
-
           event = &synthCarbonEvent;
           InitializeEventRecord(&synthCarbonEvent, &carbonPt);
         } else
 #endif
         {
           event = &synthCocoaEvent;
           InitializeNPCocoaEvent(&synthCocoaEvent);
         }
--- a/modules/plugin/test/mochitest/Makefile.in
+++ b/modules/plugin/test/mochitest/Makefile.in
@@ -84,16 +84,18 @@ include $(topsrcdir)/config/rules.mk
   neverending.sjs \
   test_newstreamondestroy.html \
   test_crashing.html \
   test_crashing2.html \
   test_hanging.html \
   crashing_subpage.html \
   test_GCrace.html \
   test_propertyAndMethod.html \
+  test_bug539565-1.html \
+  test_bug539565-2.html \
   $(NULL)
 
 #  test_npruntime_npnsetexception.html \ Disabled for e10s
 
 ifeq ($(OS_ARCH),WINNT)
 _MOCHITEST_FILES += \
   test_windowed_invalidate.html \
   $(NULL)
new file mode 100644
--- /dev/null
+++ b/modules/plugin/test/mochitest/test_bug539565-1.html
@@ -0,0 +1,99 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=539565
+-->
+<head>
+  <title>Test #1 for Bug 539565</title>
+  <script type="text/javascript" src="/MochiKit/packed.js"></script>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+
+  <script class="testbody" type="text/javascript">
+function runTests() {
+  netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+  viewer = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
+                 .getInterface(Components.interfaces.nsIWebNavigation)
+                 .QueryInterface(Components.interfaces.nsIDocShell)
+                 .contentViewer
+                 .QueryInterface(Components.interfaces.nsIMarkupDocumentViewer);
+
+  var moveBy = 17;
+  var waitedForPaint = 0;
+  function waitForPaint(func) {
+    waitedForPaint = 0;
+    var testplugin = $("plugin1");
+    testplugin.last_paint_count = testplugin.getPaintCount ? testplugin.getPaintCount() : -2;
+    function waitForPaintCountIncrement() {
+      waitedForPaint++;
+      moveBy = -moveBy;
+      $("abs").style.left = ($("abs").offsetLeft + moveBy) + 'px';
+      var x = document.documentElement.offsetHeight;
+      var pc = testplugin.getPaintCount ? testplugin.getPaintCount() : -2;
+      if (waitedForPaint == 20 || (pc != testplugin.last_paint_count && pc >= 0)) {
+        setTimeout(func,0);
+      } else
+        setTimeout(waitForPaintCountIncrement, 50);
+    }
+    waitForPaintCountIncrement();
+  }
+
+  function doClick(x,y,func) {
+    netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+    synthesizeMouse($("plugin1"), x, y, {}, window); 
+    setTimeout(func,0);
+  }
+
+  function verify(test,x,y,next) {
+    netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+    var p = $("plugin1").getLastMouseX();
+    const delta = 2;
+    ok(p-delta <= x && x <= p+delta, "test"+test+" LastMouseX got " + p + " expected" + x + 
+                                     " with fullZoom="+viewer.fullZoom+" MozTransform='"+$("container").style.MozTransform+"'");
+    p = $("plugin1").getLastMouseY();
+    ok(p-delta <= y && y <= p+delta, "test"+test+" LastMouseY got " + p + " expected" + y +
+                                     " with fullZoom="+viewer.fullZoom+" MozTransform='"+$("container").style.MozTransform+"'");
+    if (next) next();
+  }
+
+  function click(x,y,next) {
+    waitForPaint(function(){doClick(x,y,next);})
+  }
+  function zoom(factor) {
+    netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+    viewer.fullZoom = factor;
+  }
+
+  function test1() { // fullZoom=1 (sanity check)
+    zoom(1);
+    click(55,136, function(){verify("1",55,136,test2)});
+  }
+  function test2() { // fullZoom=2
+    zoom(2);
+    click(40,108, function(){verify("2",80,216,test2b)})
+  }
+  function test2b() {
+    click(108,112, function(){verify("2c",216,224,endTest)})
+  }
+
+  function endTest() {
+    zoom(1);
+    SimpleTest.finish();
+  }
+
+  setTimeout(function(){waitForPaint(test1)},1000);
+}
+
+SimpleTest.waitForExplicitFinish();
+
+  </script>
+</head>
+
+<body onload="runTests()">
+ <div id="container" style="position:relative;top: 0px; left: 0px; width: 640px; height: 480px;"> 
+  <div id="abs" style="position:absolute; left:90px; top:90px; width:20px; height:20px; background:blue; pointer-events:none;"></div>
+  <embed id="plugin1" type="application/x-test" wmode="transparent" width="200" height="200"></embed>
+ </div>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/modules/plugin/test/mochitest/test_bug539565-2.html
@@ -0,0 +1,119 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=539565
+-->
+<head>
+  <title>Test #2 for Bug 539565</title>
+  <script type="text/javascript" src="/MochiKit/packed.js"></script>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+
+  <script class="testbody" type="text/javascript">
+function runTests() {
+  netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+  viewer = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
+                 .getInterface(Components.interfaces.nsIWebNavigation)
+                 .QueryInterface(Components.interfaces.nsIDocShell)
+                 .contentViewer
+                 .QueryInterface(Components.interfaces.nsIMarkupDocumentViewer);
+
+  var moveBy = 17;
+  var waitedForPaint = 0;
+  function waitForPaint(func) {
+    waitedForPaint = 0;
+    var testplugin = $("plugin1");
+    testplugin.last_paint_count = testplugin.getPaintCount ? testplugin.getPaintCount() : -2;
+    function waitForPaintCountIncrement() {
+      waitedForPaint++;
+      moveBy = -moveBy;
+      $("abs").style.left = ($("abs").offsetLeft + moveBy) + 'px';
+      var x = document.documentElement.offsetHeight;
+      var pc = testplugin.getPaintCount ? testplugin.getPaintCount() : -2;
+      if (waitedForPaint == 20 || (pc != testplugin.last_paint_count && pc >= 0)) {
+        setTimeout(func,0);
+      } else
+        setTimeout(waitForPaintCountIncrement, 50);
+    }
+    waitForPaintCountIncrement();
+  }
+
+  function doClick(x,y,func) {
+    netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+    synthesizeMouse($("plugin1"), x, y, {}, window); 
+    setTimeout(func,0);
+  }
+
+  function verify(test,x,y,next) {
+    netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+    var p = $("plugin1").getLastMouseX();
+    const delta = 2;
+    ok(p-delta <= x && x <= p+delta, "test"+test+" LastMouseX got " + p + " expected" + x + 
+                                     " with fullZoom="+viewer.fullZoom+" MozTransform='"+$("container").style.MozTransform+"'");
+    p = $("plugin1").getLastMouseY();
+    ok(p-delta <= y && y <= p+delta, "test"+test+" LastMouseY got " + p + " expected" + y +
+                                     " with fullZoom="+viewer.fullZoom+" MozTransform='"+$("container").style.MozTransform+"'");
+    if (next) next();
+  }
+
+  function click(x,y,next) {
+    waitForPaint(function(){doClick(x,y,next);})
+  }
+  function zoom(factor) {
+    netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+    viewer.fullZoom = factor;
+  }
+
+  function test3() { // fullZoom=1 + scale(2)
+    zoom(1);
+    //
+    // ======================== BUG WARNING =========================================
+    // 'container' already has -moz-transform:scale(2) in its style attribute.
+    // Removing that and setting MozTransform dynamically here (as in test4)
+    // makes the test fail ("getLastMouseX is not a function" in verify() above)
+    // Looks like the plugin instance got destroyed and we never recover from that...
+    // ==============================================================================
+    //
+    click(50,136, function(){verify("3",25,68,test3b)});
+  }
+  function test3b() {
+    click(208,212, function(){verify("3b",104,106,test4)});
+  }
+  function test4() { // fullZoom=2 + scale(0.5)
+    zoom(2);
+    var container = $("container");
+    container.style.MozTransformOrigin = "0px 0px";
+    container.style.MozTransform = "scale(0.5)";
+    var x = document.documentElement.offsetHeight;
+    click(60,52, function(){verify("4",240,208,test5)});
+  }
+  function test5() { // fullZoom=2 + scale(2)
+    zoom(2);
+    var container = $("container");
+    container.style.MozTransformOrigin = "0px 0px";
+    container.style.MozTransform = "scale(2)";
+    var x = document.documentElement.offsetHeight;
+    click(108,112, function(){verify("5",108,112,endTest)});
+  }
+
+  function endTest() {
+    zoom(1);
+    SimpleTest.finish();
+  }
+
+  setTimeout(function(){waitForPaint(test3)},1000);
+}
+
+SimpleTest.waitForExplicitFinish();
+
+  </script>
+</head>
+
+<body onload="runTests()">
+ <div id="container" style="position:relative;top: 0px; left: 0px; width: 640px; height: 480px; -moz-transform:scale(2); -moz-transform-origin:0px 0px;"> 
+  <div id="abs" style="position:absolute; left:90px; top:90px; width:20px; height:20px; background:blue; pointer-events:none;"></div>
+  <embed id="plugin1" type="application/x-test" wmode="transparent" width="200" height="200"></embed>
+ </div>
+</body>
+</html>