From cd6021b346230bd22cb22eb272b515631899daa0 Mon Sep 17 00:00:00 2001
From: Vivien Nicolas <21@vingtetun.org>
Date: Wed, 5 Jan 2011 12:58:32 +0100
Subject: [PATCH] Bug 609866 - Fennec fires contextmenu event in content during
panning/tapping [r=mfinkle,wesj]
---
mobile/chrome/content/browser.js | 28 ++---
mobile/chrome/content/content.js | 28 ++---
mobile/chrome/tests/browser_tap_content.html | 4 +-
mobile/chrome/tests/browser_tapping.js | 126 +++++++++----------
4 files changed, 92 insertions(+), 94 deletions(-)
diff --git a/mobile/chrome/content/browser.js b/mobile/chrome/content/browser.js
index ba8d67d1ff5..1438f2f2cff 100644
--- a/mobile/chrome/content/browser.js
+++ b/mobile/chrome/content/browser.js
@@ -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() {
diff --git a/mobile/chrome/content/content.js b/mobile/chrome/content/content.js
index e502b1499ae..da164a36906 100644
--- a/mobile/chrome/content/content.js
+++ b/mobile/chrome/content/content.js
@@ -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);
diff --git a/mobile/chrome/tests/browser_tap_content.html b/mobile/chrome/tests/browser_tap_content.html
index 95fe8d3c506..e39161d9e38 100644
--- a/mobile/chrome/tests/browser_tap_content.html
+++ b/mobile/chrome/tests/browser_tap_content.html
@@ -5,7 +5,9 @@
diff --git a/mobile/chrome/tests/browser_tapping.js b/mobile/chrome/tests/browser_tapping.js
index 6360aac157a..b74c890072f 100644
--- a/mobile/chrome/tests/browser_tapping.js
+++ b/mobile/chrome/tests/browser_tapping.js
@@ -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()"
@@ -80,7 +88,7 @@ function test() {
window.addEventListener("TapSingle", dumpEvents, true);
window.addEventListener("TapDouble", dumpEvents, true);
window.addEventListener("TapLong", dumpEvents, true);
-
+
// Wait for the tab to load, then do the tests
messageManager.addMessageListener("pageshow", function() {
if (gCurrentTab.browser.currentURI.spec == testURL) {
@@ -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() {
@@ -173,7 +184,7 @@ gTests.push({
EventUtils.synthesizeMouse(browser, width / 2, height * 3 / 4, { type: "mouseup" });
ok(checkEvents([]), "Fired a pan which should be seen as a non event");
clearEvents();
-
+
setTimeout(function() { gCurrentTest.longTapFailTest(); }, 500);
},
@@ -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);
}
});