зеркало из https://github.com/mozilla/pjs.git
Bug 609866 - Fennec fires contextmenu event in content during panning/tapping [r=mfinkle,wesj]
This commit is contained in:
Родитель
40e84d70b0
Коммит
cd6021b346
|
@ -1527,9 +1527,9 @@ const ContentTouchHandler = {
|
||||||
document.addEventListener("CancelTouchSequence", this, false);
|
document.addEventListener("CancelTouchSequence", this, false);
|
||||||
|
|
||||||
// Context menus have the following flow:
|
// Context menus have the following flow:
|
||||||
// [parent] mousedown -> TapDown -> Browser:MouseDown
|
// [parent] mousedown -> TapLong -> Browser:MouseLong
|
||||||
// [child] Browser:MouseDown -> contextmenu -> Browser:ContextMenu
|
// [child] Browser:MouseLong -> contextmenu -> Browser:ContextMenu
|
||||||
// [parent] Browser:ContextMenu -> ...* -> TapLong
|
// [parent] Browser:ContextMenu -> ...*
|
||||||
//
|
//
|
||||||
// * = Here some time will elapse. Although we get the context menu we need
|
// * = Here some time will elapse. Although we get the context menu we need
|
||||||
// ASAP, we do not act on the context menu until we receive a LongTap.
|
// ASAP, we do not act on the context menu until we receive a LongTap.
|
||||||
|
@ -1583,7 +1583,7 @@ const ContentTouchHandler = {
|
||||||
this.tapDouble(aEvent.clientX, aEvent.clientY, aEvent.modifiers);
|
this.tapDouble(aEvent.clientX, aEvent.clientY, aEvent.modifiers);
|
||||||
break;
|
break;
|
||||||
case "TapLong":
|
case "TapLong":
|
||||||
this.tapLong();
|
this.tapLong(aEvent.clientX, aEvent.clientY);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1597,7 +1597,13 @@ const ContentTouchHandler = {
|
||||||
switch (aMessage.name) {
|
switch (aMessage.name) {
|
||||||
case "Browser:ContextMenu":
|
case "Browser:ContextMenu":
|
||||||
// Long tap
|
// Long tap
|
||||||
this._contextMenu = { name: aMessage.name, json: aMessage.json, target: aMessage.target };
|
let contextMenu = { name: aMessage.name, json: aMessage.json, target: aMessage.target };
|
||||||
|
if (ContextHelper.showPopup(contextMenu)) {
|
||||||
|
// Stop all input sequences
|
||||||
|
let event = document.createEvent("Events");
|
||||||
|
event.initEvent("CancelTouchSequence", true, false);
|
||||||
|
document.dispatchEvent(event);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "Browser:Highlight": {
|
case "Browser:Highlight": {
|
||||||
|
@ -1679,16 +1685,8 @@ const ContentTouchHandler = {
|
||||||
this._dispatchMouseEvent("Browser:ZoomToPoint", aX, aY, { width: width });
|
this._dispatchMouseEvent("Browser:ZoomToPoint", aX, aY, { width: width });
|
||||||
},
|
},
|
||||||
|
|
||||||
tapLong: function tapLong() {
|
tapLong: function tapLong(aX, aY) {
|
||||||
if (this._contextMenu) {
|
this._dispatchMouseEvent("Browser:MouseLong", aX, aY);
|
||||||
if (ContextHelper.showPopup(this._contextMenu)) {
|
|
||||||
// Stop all input sequences
|
|
||||||
let event = document.createEvent("Events");
|
|
||||||
event.initEvent("CancelTouchSequence", true, false);
|
|
||||||
document.dispatchEvent(event);
|
|
||||||
}
|
|
||||||
this._contextMenu = null;
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
toString: function toString() {
|
toString: function toString() {
|
||||||
|
|
|
@ -311,8 +311,8 @@ function Content() {
|
||||||
|
|
||||||
addMessageListener("Browser:Blur", this);
|
addMessageListener("Browser:Blur", this);
|
||||||
addMessageListener("Browser:KeyEvent", this);
|
addMessageListener("Browser:KeyEvent", this);
|
||||||
addMessageListener("Browser:MouseDown", this);
|
|
||||||
addMessageListener("Browser:MouseOver", this);
|
addMessageListener("Browser:MouseOver", this);
|
||||||
|
addMessageListener("Browser:MouseLong", this);
|
||||||
addMessageListener("Browser:MouseUp", this);
|
addMessageListener("Browser:MouseUp", this);
|
||||||
addMessageListener("Browser:SaveAs", this);
|
addMessageListener("Browser:SaveAs", this);
|
||||||
addMessageListener("Browser:ZoomToPoint", this);
|
addMessageListener("Browser:ZoomToPoint", this);
|
||||||
|
@ -424,19 +424,6 @@ Content.prototype = {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "Browser:MouseDown": {
|
|
||||||
let element = elementFromPoint(x, y);
|
|
||||||
if (!element)
|
|
||||||
return;
|
|
||||||
|
|
||||||
ContextHandler.messageId = json.messageId;
|
|
||||||
|
|
||||||
let event = content.document.createEvent("PopupEvents");
|
|
||||||
event.initEvent("contextmenu", true, true);
|
|
||||||
element.dispatchEvent(event);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case "Browser:MouseOver": {
|
case "Browser:MouseOver": {
|
||||||
let element = elementFromPoint(x, y);
|
let element = elementFromPoint(x, y);
|
||||||
if (!element)
|
if (!element)
|
||||||
|
@ -465,6 +452,19 @@ Content.prototype = {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case "Browser:MouseLong": {
|
||||||
|
let element = elementFromPoint(x, y);
|
||||||
|
if (!element)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ContextHandler.messageId = json.messageId;
|
||||||
|
|
||||||
|
let event = content.document.createEvent("PopupEvents");
|
||||||
|
event.initEvent("contextmenu", true, true);
|
||||||
|
element.dispatchEvent(event);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case "Browser:MouseUp": {
|
case "Browser:MouseUp": {
|
||||||
this._formAssistant.focusSync = true;
|
this._formAssistant.focusSync = true;
|
||||||
let element = elementFromPoint(x, y);
|
let element = elementFromPoint(x, y);
|
||||||
|
|
|
@ -5,7 +5,9 @@
|
||||||
|
|
||||||
<div style="margin-bottom:20px">
|
<div style="margin-bottom:20px">
|
||||||
<div>A plain link</div>
|
<div>A plain link</div>
|
||||||
<a id="link-single" href="browser_blank_01.html">A blank page - nothing interesting</a>
|
<a id="link-disabled" href="browser_blank_01.html" oncontextmenu="return false;">A blank page - no context menu</a>
|
||||||
|
<br />
|
||||||
|
<a id="link-single" href="browser_blank_01.html" title="nothingInteresting">A blank page - nothing interesting</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div style="margin-bottom:20px">
|
<div style="margin-bottom:20px">
|
||||||
|
|
|
@ -35,14 +35,6 @@ function checkEvents(aEvents) {
|
||||||
}
|
}
|
||||||
|
|
||||||
let gContextTypes = "";
|
let gContextTypes = "";
|
||||||
function dumpMessages(aMessage) {
|
|
||||||
if (aMessage.name == "Browser:ContextMenu") {
|
|
||||||
aMessage.json.types.forEach(function(aType) {
|
|
||||||
gContextTypes.push(aType);
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function clearContextTypes() {
|
function clearContextTypes() {
|
||||||
gContextTypes = [];
|
gContextTypes = [];
|
||||||
|
|
||||||
|
@ -67,6 +59,22 @@ function checkContextTypes(aTypes) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function waitForContextMenu(aCallback, aNextTest) {
|
||||||
|
clearContextTypes();
|
||||||
|
|
||||||
|
let browser = gCurrentTab.browser;
|
||||||
|
browser.messageManager.addMessageListener("Browser:ContextMenu", function(aMessage) {
|
||||||
|
browser.messageManager.removeMessageListener(aMessage.name, arguments.callee);
|
||||||
|
aMessage.json.types.forEach(function(aType) {
|
||||||
|
gContextTypes.push(aType);
|
||||||
|
});
|
||||||
|
setTimeout(function() {
|
||||||
|
aCallback(aMessage.json);
|
||||||
|
clearContextTypes();
|
||||||
|
aNextTest();
|
||||||
|
}, 0);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function test() {
|
function test() {
|
||||||
// The "runNextTest" approach is async, so we need to call "waitForExplicitFinish()"
|
// The "runNextTest" approach is async, so we need to call "waitForExplicitFinish()"
|
||||||
|
@ -120,14 +128,17 @@ gTests.push({
|
||||||
let height = browser.getBoundingClientRect().height;
|
let height = browser.getBoundingClientRect().height;
|
||||||
|
|
||||||
// Should fire "TapSingle"
|
// Should fire "TapSingle"
|
||||||
// XXX not working? WTF?
|
|
||||||
info("Test good single tap");
|
info("Test good single tap");
|
||||||
clearEvents();
|
clearEvents();
|
||||||
EventUtils.synthesizeMouse(browser, width / 2, height / 2, {});
|
EventUtils.synthesizeMouse(browser, width / 2, height / 2, {});
|
||||||
todo(checkEvents(["TapSingle"]), "Fired a good single tap");
|
|
||||||
clearEvents();
|
|
||||||
|
|
||||||
setTimeout(function() { gCurrentTest.doubleTapTest(); }, 500);
|
// We wait a bit because of the delay allowed for double clicking on device
|
||||||
|
// where it is not native
|
||||||
|
setTimeout(function() {
|
||||||
|
ok(checkEvents(["TapSingle"]), "Fired a good single tap");
|
||||||
|
clearEvents();
|
||||||
|
gCurrentTest.doubleTapTest();
|
||||||
|
}, kDoubleClickInterval);
|
||||||
},
|
},
|
||||||
|
|
||||||
doubleTapTest: function() {
|
doubleTapTest: function() {
|
||||||
|
@ -200,76 +211,63 @@ gTests.push({
|
||||||
let width = browser.getBoundingClientRect().width;
|
let width = browser.getBoundingClientRect().width;
|
||||||
let height = browser.getBoundingClientRect().height;
|
let height = browser.getBoundingClientRect().height;
|
||||||
|
|
||||||
info("Test a good long pan");
|
window.addEventListener("TapLong", function() {
|
||||||
clearEvents();
|
window.removeEventListener("TapLong", arguments.callee, true);
|
||||||
EventUtils.synthesizeMouse(browser, width / 2, height / 4, { type: "mousedown" });
|
|
||||||
setTimeout(function() {
|
|
||||||
EventUtils.synthesizeMouse(browser, width / 2, height / 4, { type: "mouseup" });
|
EventUtils.synthesizeMouse(browser, width / 2, height / 4, { type: "mouseup" });
|
||||||
ok(checkEvents(["TapLong"]), "Fired a good long tap");
|
ok(checkEvents(["TapLong"]), "Fired a good long tap");
|
||||||
clearEvents();
|
clearEvents();
|
||||||
|
}, true);
|
||||||
|
|
||||||
gCurrentTest.contextPlainLinkTest();
|
browser.messageManager.addMessageListener("Browser:ContextMenu", function(aMessage) {
|
||||||
}, 500);
|
browser.messageManager.removeMessageListener(aMessage.name, arguments.callee);
|
||||||
|
setTimeout(gCurrentTest.contextPlainLinkTest, 0);
|
||||||
|
});
|
||||||
|
|
||||||
|
info("Test a good long pan");
|
||||||
|
clearEvents();
|
||||||
|
EventUtils.synthesizeMouse(browser, width / 2, height / 4, { type: "mousedown" });
|
||||||
},
|
},
|
||||||
|
|
||||||
contextPlainLinkTest: function() {
|
contextPlainLinkTest: function() {
|
||||||
|
waitForContextMenu(function(aJSON) {
|
||||||
|
is(aJSON.linkTitle, "A blank page - nothing interesting", "Text content should be the content of the second link");
|
||||||
|
ok(checkContextTypes(["link","link-saveable","link-openable"]), "Plain link context types");
|
||||||
|
}, gCurrentTest.contextPlainImageTest);
|
||||||
|
|
||||||
let browser = gCurrentTab.browser;
|
let browser = gCurrentTab.browser;
|
||||||
browser.messageManager.addMessageListener("Browser:ContextMenu", dumpMessages);
|
let linkDisabled = browser.contentDocument.getElementById("link-disabled");
|
||||||
|
let event = content.document.createEvent("PopupEvents");
|
||||||
|
event.initEvent("contextmenu", true, true);
|
||||||
|
linkDisabled.dispatchEvent(event);
|
||||||
|
|
||||||
let link = browser.contentDocument.getElementById("link-single");
|
let link = browser.contentDocument.getElementById("link-single");
|
||||||
let linkRect = link.getBoundingClientRect();
|
let event = content.document.createEvent("PopupEvents");
|
||||||
|
event.initEvent("contextmenu", true, true);
|
||||||
clearContextTypes();
|
link.dispatchEvent(event);
|
||||||
EventUtils.synthesizeMouseForContent(link, linkRect.width/2, linkRect.height/4, { type: "mousedown" }, window);
|
|
||||||
setTimeout(function() {
|
|
||||||
EventUtils.synthesizeMouseForContent(link, linkRect.width/2, linkRect.height/4, { type: "mouseup" }, window);
|
|
||||||
ok(checkContextTypes(["link","link-saveable","link-openable"]), "Plain link context types");
|
|
||||||
clearContextTypes();
|
|
||||||
|
|
||||||
gCurrentTest.contextPlainImageTest();
|
|
||||||
}, 500);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
contextPlainImageTest: function() {
|
contextPlainImageTest: function() {
|
||||||
let browser = gCurrentTab.browser;
|
waitForContextMenu(function() {
|
||||||
browser.messageManager.addMessageListener("Browser:ContextMenu", dumpMessages);
|
|
||||||
|
|
||||||
let img = browser.contentDocument.getElementById("img-single");
|
|
||||||
let imgRect = img.getBoundingClientRect();
|
|
||||||
|
|
||||||
clearContextTypes();
|
|
||||||
EventUtils.synthesizeMouseForContent(img, imgRect.width/2, imgRect.height/2, { type: "mousedown" }, window);
|
|
||||||
setTimeout(function() {
|
|
||||||
EventUtils.synthesizeMouseForContent(img, 1, 1, { type: "mouseup" }, window);
|
|
||||||
ok(checkContextTypes(["image","image-shareable","image-loaded"]), "Plain image context types");
|
ok(checkContextTypes(["image","image-shareable","image-loaded"]), "Plain image context types");
|
||||||
clearContextTypes();
|
}, gCurrentTest.contextNestedImageTest);
|
||||||
|
|
||||||
gCurrentTest.contextNestedImageTest();
|
let browser = gCurrentTab.browser;
|
||||||
}, 500);
|
let img = browser.contentDocument.getElementById("img-single");
|
||||||
|
let event = content.document.createEvent("PopupEvents");
|
||||||
|
event.initEvent("contextmenu", true, true);
|
||||||
|
img.dispatchEvent(event);
|
||||||
},
|
},
|
||||||
|
|
||||||
contextNestedImageTest: function() {
|
contextNestedImageTest: function() {
|
||||||
let browser = gCurrentTab.browser;
|
waitForContextMenu(function() {
|
||||||
browser.messageManager.addMessageListener("Browser:ContextMenu", dumpMessages);
|
|
||||||
|
|
||||||
let img = browser.contentDocument.getElementById("img-nested");
|
|
||||||
let imgRect = img.getBoundingClientRect();
|
|
||||||
|
|
||||||
clearContextTypes();
|
|
||||||
EventUtils.synthesizeMouseForContent(img, 1, 1, { type: "mousedown" }, window);
|
|
||||||
setTimeout(function() {
|
|
||||||
EventUtils.synthesizeMouseForContent(img, 1, 1, { type: "mouseup" }, window);
|
|
||||||
ok(checkContextTypes(["link","link-saveable","image","image-shareable","image-loaded","link-openable"]), "Nested image context types");
|
ok(checkContextTypes(["link","link-saveable","image","image-shareable","image-loaded","link-openable"]), "Nested image context types");
|
||||||
clearContextTypes();
|
}, runNextTest);
|
||||||
|
|
||||||
gCurrentTest.lastTest();
|
let browser = gCurrentTab.browser;
|
||||||
}, 500);
|
let img = browser.contentDocument.getElementById("img-nested");
|
||||||
},
|
let event = content.document.createEvent("PopupEvents");
|
||||||
|
event.initEvent("contextmenu", true, true);
|
||||||
lastTest: function() {
|
img.dispatchEvent(event);
|
||||||
gCurrentTab.browser.messageManager.removeMessageListener("Browser:ContextMenu", dumpMessages);
|
|
||||||
|
|
||||||
runNextTest();
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче