Bug 609866 - Fennec fires contextmenu event in content during panning/tapping [r=mfinkle,wesj]

This commit is contained in:
Vivien Nicolas 2011-01-05 12:58:32 +01:00
Родитель 40e84d70b0
Коммит cd6021b346
4 изменённых файлов: 92 добавлений и 94 удалений

Просмотреть файл

@ -1527,9 +1527,9 @@ const ContentTouchHandler = {
document.addEventListener("CancelTouchSequence", this, false);
// Context menus have the following flow:
// [parent] mousedown -> TapDown -> Browser:MouseDown
// [child] Browser:MouseDown -> contextmenu -> Browser:ContextMenu
// [parent] Browser:ContextMenu -> ...* -> TapLong
// [parent] mousedown -> TapLong -> Browser:MouseLong
// [child] Browser:MouseLong -> contextmenu -> Browser:ContextMenu
// [parent] Browser:ContextMenu -> ...*
//
// * = 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.
@ -1583,7 +1583,7 @@ const ContentTouchHandler = {
this.tapDouble(aEvent.clientX, aEvent.clientY, aEvent.modifiers);
break;
case "TapLong":
this.tapLong();
this.tapLong(aEvent.clientX, aEvent.clientY);
break;
}
}
@ -1597,7 +1597,13 @@ const ContentTouchHandler = {
switch (aMessage.name) {
case "Browser:ContextMenu":
// 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;
case "Browser:Highlight": {
@ -1679,16 +1685,8 @@ const ContentTouchHandler = {
this._dispatchMouseEvent("Browser:ZoomToPoint", aX, aY, { width: width });
},
tapLong: function tapLong() {
if (this._contextMenu) {
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;
}
tapLong: function tapLong(aX, aY) {
this._dispatchMouseEvent("Browser:MouseLong", aX, aY);
},
toString: function toString() {

Просмотреть файл

@ -311,8 +311,8 @@ function Content() {
addMessageListener("Browser:Blur", this);
addMessageListener("Browser:KeyEvent", this);
addMessageListener("Browser:MouseDown", this);
addMessageListener("Browser:MouseOver", this);
addMessageListener("Browser:MouseLong", this);
addMessageListener("Browser:MouseUp", this);
addMessageListener("Browser:SaveAs", this);
addMessageListener("Browser:ZoomToPoint", this);
@ -424,19 +424,6 @@ Content.prototype = {
}
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": {
let element = elementFromPoint(x, y);
if (!element)
@ -465,6 +452,19 @@ Content.prototype = {
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": {
this._formAssistant.focusSync = true;
let element = elementFromPoint(x, y);

Просмотреть файл

@ -5,7 +5,9 @@
<div style="margin-bottom:20px">
<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 style="margin-bottom:20px">

Просмотреть файл

@ -35,14 +35,6 @@ function checkEvents(aEvents) {
}
let gContextTypes = "";
function dumpMessages(aMessage) {
if (aMessage.name == "Browser:ContextMenu") {
aMessage.json.types.forEach(function(aType) {
gContextTypes.push(aType);
})
}
}
function clearContextTypes() {
gContextTypes = [];
@ -67,6 +59,22 @@ function checkContextTypes(aTypes) {
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() {
// The "runNextTest" approach is async, so we need to call "waitForExplicitFinish()"
@ -120,14 +128,17 @@ gTests.push({
let height = browser.getBoundingClientRect().height;
// Should fire "TapSingle"
// XXX not working? WTF?
info("Test good single tap");
clearEvents();
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() {
@ -200,76 +211,63 @@ gTests.push({
let width = browser.getBoundingClientRect().width;
let height = browser.getBoundingClientRect().height;
info("Test a good long pan");
clearEvents();
EventUtils.synthesizeMouse(browser, width / 2, height / 4, { type: "mousedown" });
setTimeout(function() {
window.addEventListener("TapLong", function() {
window.removeEventListener("TapLong", arguments.callee, true);
EventUtils.synthesizeMouse(browser, width / 2, height / 4, { type: "mouseup" });
ok(checkEvents(["TapLong"]), "Fired a good long tap");
clearEvents();
}, true);
gCurrentTest.contextPlainLinkTest();
}, 500);
browser.messageManager.addMessageListener("Browser:ContextMenu", function(aMessage) {
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() {
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;
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 linkRect = link.getBoundingClientRect();
clearContextTypes();
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);
let event = content.document.createEvent("PopupEvents");
event.initEvent("contextmenu", true, true);
link.dispatchEvent(event);
},
contextPlainImageTest: function() {
let browser = gCurrentTab.browser;
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);
waitForContextMenu(function() {
ok(checkContextTypes(["image","image-shareable","image-loaded"]), "Plain image context types");
clearContextTypes();
}, gCurrentTest.contextNestedImageTest);
gCurrentTest.contextNestedImageTest();
}, 500);
let browser = gCurrentTab.browser;
let img = browser.contentDocument.getElementById("img-single");
let event = content.document.createEvent("PopupEvents");
event.initEvent("contextmenu", true, true);
img.dispatchEvent(event);
},
contextNestedImageTest: function() {
let browser = gCurrentTab.browser;
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);
waitForContextMenu(function() {
ok(checkContextTypes(["link","link-saveable","image","image-shareable","image-loaded","link-openable"]), "Nested image context types");
clearContextTypes();
}, runNextTest);
gCurrentTest.lastTest();
}, 500);
},
lastTest: function() {
gCurrentTab.browser.messageManager.removeMessageListener("Browser:ContextMenu", dumpMessages);
runNextTest();
let browser = gCurrentTab.browser;
let img = browser.contentDocument.getElementById("img-nested");
let event = content.document.createEvent("PopupEvents");
event.initEvent("contextmenu", true, true);
img.dispatchEvent(event);
}
});