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); 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();
} }
}); });