diff --git a/dom/browser-element/BrowserElementParent.js b/dom/browser-element/BrowserElementParent.js index 8ba375ad8cbc..701dcd87b186 100644 --- a/dom/browser-element/BrowserElementParent.js +++ b/dom/browser-element/BrowserElementParent.js @@ -539,7 +539,24 @@ BrowserElementParent.prototype = { return this._frameLoader.visible; }, + getChildProcessOffset: function() { + let offset = { x: 0, y: 0 }; + let tabParent = this._frameLoader.tabParent; + if (tabParent) { + let offsetX = {}; + let offsetY = {}; + tabParent.getChildProcessOffset(offsetX, offsetY); + offset.x = offsetX.value; + offset.y = offsetY.value; + } + return offset; + }, + sendMouseEvent: defineNoReturnMethod(function(type, x, y, button, clickCount, modifiers) { + let offset = this.getChildProcessOffset(); + x += offset.x; + y += offset.y; + this._sendAsyncMsg("send-mouse-event", { "type": type, "x": x, @@ -567,6 +584,13 @@ BrowserElementParent.prototype = { count, modifiers); } else { + let offset = this.getChildProcessOffset(); + for (var i = 0; i < touchesX.length; i++) { + touchesX[i] += offset.x; + } + for (var i = 0; i < touchesY.length; i++) { + touchesY[i] += offset.y; + } this._sendAsyncMsg("send-touch-event", { "type": type, "identifiers": identifiers, diff --git a/dom/browser-element/mochitest/browserElement_SendEvent.js b/dom/browser-element/mochitest/browserElement_SendEvent.js index 57f09e9be3cd..88e65d96fc13 100644 --- a/dom/browser-element/mochitest/browserElement_SendEvent.js +++ b/dom/browser-element/mochitest/browserElement_SendEvent.js @@ -12,9 +12,26 @@ function runTest() { var iframe = document.createElement("iframe"); iframe.setAttribute('mozbrowser', 'true'); document.body.appendChild(iframe); + var x = 10; + var y = 10; + // First we force a reflow so that getChildProcessOffset actually returns + // meaningful data. + iframe.getBoundingClientRect(); + // We need to make sure the event coordinates are actually inside the iframe, + // relative to the chome window. + var tabParent = SpecialPowers.wrap(iframe) + .QueryInterface(SpecialPowers.Ci.nsIFrameLoaderOwner) + .frameLoader.tabParent; + if (tabParent) { + let offsetX = {}; + let offsetY = {}; + tabParent.getChildProcessOffset(offsetX, offsetY); + x -= offsetX.value; + y -= offsetY.value; + } iframe.addEventListener("mozbrowserloadend", function onloadend(e) { - iframe.sendMouseEvent("mousedown", 10, 10, 0, 1, 0); + iframe.sendMouseEvent("mousedown", x, y, 0, 1, 0); }); iframe.addEventListener("mozbrowserlocationchange", function onlocchange(e) { @@ -24,11 +41,11 @@ function runTest() { switch (a.hash) { case "#mousedown": ok(true, "Receive a mousedown event."); - iframe.sendMouseEvent("mousemove", 10, 10, 0, 0, 0); + iframe.sendMouseEvent("mousemove", x, y, 0, 0, 0); break; case "#mousemove": ok(true, "Receive a mousemove event."); - iframe.sendMouseEvent("mouseup", 10, 10, 0, 1, 0); + iframe.sendMouseEvent("mouseup", x, y, 0, 1, 0); break; case "#mouseup": ok(true, "Receive a mouseup event."); @@ -36,7 +53,7 @@ function runTest() { case "#click": ok(true, "Receive a click event."); if (SpecialPowers.getIntPref("dom.w3c_touch_events.enabled") != 0) { - iframe.sendTouchEvent("touchstart", [1], [10], [10], [2], [2], + iframe.sendTouchEvent("touchstart", [1], [x], [y], [2], [2], [20], [0.5], 1, 0); } else { iframe.removeEventListener('mozbrowserlocationchange', onlocchange); @@ -45,16 +62,16 @@ function runTest() { break; case "#touchstart": ok(true, "Receive a touchstart event."); - iframe.sendTouchEvent("touchmove", [1], [10], [10], [2], [2], + iframe.sendTouchEvent("touchmove", [1], [x], [y], [2], [2], [20], [0.5], 1, 0); case "#touchmove": ok(true, "Receive a touchmove event."); - iframe.sendTouchEvent("touchend", [1], [10], [10], [2], [2], + iframe.sendTouchEvent("touchend", [1], [x], [y], [2], [2], [20], [0.5], 1, 0); break; case "#touchend": ok(true, "Receive a touchend event."); - iframe.sendTouchEvent("touchcancel", [1], [10], [10], [2], [2], + iframe.sendTouchEvent("touchcancel", [1], [x], [y], [2], [2], [20], [0.5], 1, 0); iframe.removeEventListener('mozbrowserlocationchange', onlocchange); SimpleTest.finish(); diff --git a/dom/interfaces/base/nsITabParent.idl b/dom/interfaces/base/nsITabParent.idl index 5f1f59210b25..01c4fa1842bb 100644 --- a/dom/interfaces/base/nsITabParent.idl +++ b/dom/interfaces/base/nsITabParent.idl @@ -5,7 +5,7 @@ #include "domstubs.idl" -[scriptable, uuid(30361a5b-a3b8-4dbc-b464-e08761abb123)] +[scriptable, uuid(b19038ba-0d75-40d2-be35-742e26d33bf9)] interface nsITabParent : nsISupports { void injectTouchEvent(in AString aType, @@ -19,6 +19,8 @@ interface nsITabParent : nsISupports in uint32_t count, in long aModifiers); + void getChildProcessOffset(out int32_t aCssX, out int32_t aCssY); + readonly attribute boolean useAsyncPanZoom; void setIsDocShellActive(in bool aIsActive); diff --git a/dom/ipc/TabParent.cpp b/dom/ipc/TabParent.cpp index 038c111620a4..e8b934eb08bf 100644 --- a/dom/ipc/TabParent.cpp +++ b/dom/ipc/TabParent.cpp @@ -1757,6 +1757,18 @@ TabParent::RecvEnableDisableCommands(const nsString& aAction, return true; } +NS_IMETHODIMP +TabParent::GetChildProcessOffset(int32_t* aOutCssX, int32_t* aOutCssY) +{ + NS_ENSURE_ARG(aOutCssX); + NS_ENSURE_ARG(aOutCssY); + CSSPoint offset = LayoutDevicePoint(GetChildProcessOffset()) + * GetLayoutDeviceToCSSScale(); + *aOutCssX = offset.x; + *aOutCssY = offset.y; + return NS_OK; +} + LayoutDeviceIntPoint TabParent::GetChildProcessOffset() {