Bug 856151 - update context menu code to use new bindings. r=fryn
authorJim Mathies <jmathies@mozilla.com>
Fri, 05 Apr 2013 05:33:41 -0500
changeset 134552 5722966a3126e7d5e47476457fcb78a105034272
parent 134551 a5aa2d31e8e9a9ef9dd4b0eb60690452fd0ad351
child 134553 d3a0bc6f68b128c4a83924bfb599d04d9e377afe
push idunknown
push userunknown
push dateunknown
reviewersfryn
bugs856151
milestone23.0a1
Bug 856151 - update context menu code to use new bindings. r=fryn
browser/metro/base/content/helperui/MenuUI.js
browser/metro/base/content/helperui/SelectHelperUI.js
browser/metro/base/tests/mochitest/browser_context_menu_tests.js
browser/metro/base/tests/mochitest/browser_context_menu_tests_02.html
browser/metro/base/tests/mochitest/head.js
--- a/browser/metro/base/content/helperui/MenuUI.js
+++ b/browser/metro/base/content/helperui/MenuUI.js
@@ -184,19 +184,21 @@ var ContextMenuUI = {
       }
     }
 
     if (!optionsAvailable) {
       this._popupState = null;
       return false;
     }
 
+    let coords =
+      aMessage.target.msgBrowserToClient(aMessage, true);
     this._menuPopup.show(Util.extend({}, this._defaultPositionOptions, {
-      xPos: aMessage.json.xPos,
-      yPos: aMessage.json.yPos,
+      xPos: coords.x,
+      yPos: coords.y,
       source: aMessage.json.source
     }));
     return true;
   },
 
   hide: function hide () {
     this._menuPopup.hide();
     this._popupState = null;
--- a/browser/metro/base/content/helperui/SelectHelperUI.js
+++ b/browser/metro/base/content/helperui/SelectHelperUI.js
@@ -98,18 +98,18 @@ var SelectHelperUI = {
 
     this._container.removeEventListener("click", this, false);
     this._menuPopup.hide();
     this.reset();
   },
 
   _positionOptions: function _positionOptions(aRect) {
     let browser = Browser.selectedBrowser;
-    let p0 = browser.transformBrowserToClient(aRect.left, aRect.top);
-    let p1 = browser.transformBrowserToClient(aRect.right, aRect.bottom);
+    let p0 = browser.ptBrowserToClient(aRect.left, aRect.top);
+    let p1 = browser.ptBrowserToClient(aRect.right, aRect.bottom);
 
     return {
       forcePosition: true,
       xPos: p0.x,
       yPos: p1.y,
       bottomAligned: false,
       leftAligned: true
     };
--- a/browser/metro/base/tests/mochitest/browser_context_menu_tests.js
+++ b/browser/metro/base/tests/mochitest/browser_context_menu_tests.js
@@ -314,41 +314,83 @@ gTests.push({
     // the test above will invoke the app bar
     yield hideContextUI();
 
     Browser.closeTab(Browser.selectedTab);
     purgeEventQueue();
   }
 });
 
+gTests.push({
+  desc: "checks for context menu positioning when browser shifts",
+  run: function test() {
+    netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+
+    info(chromeRoot + "browser_context_menu_tests_02.html");
+    yield addTab(chromeRoot + "browser_context_menu_tests_02.html");
+
+    purgeEventQueue();
+    emptyClipboard();
+
+    let browserwin = Browser.selectedTab.browser.contentWindow;
+
+    yield hideContextUI();
+
+    ////////////////////////////////////////////////////////////
+    // test for proper context menu positioning when the browser
+    // is offset by a notification box.
+
+    yield showNotification();
+
+    // select some text
+    let span = browserwin.document.getElementById("text4");
+    browserwin.getSelection().selectAllChildren(span);
+
+    // invoke selection context menu
+    let promise = waitForEvent(document, "popupshown");
+    sendContextMenuClick(225, 310);
+    yield promise;
+    ok(promise && !(promise instanceof Error), "promise error");
+
+    // should be visible and at a specific position
+    ok(ContextMenuUI._menuPopup._visible, "is visible");
+    is(ContextMenuUI._panel.left, 97.5, "left");
+    is(ContextMenuUI._panel.top, 227, "top");
+
+    ContextMenuUI._menuPopup.hide();
+
+    Browser.closeTab(Browser.selectedTab);
+  }
+});
+
 // Image context menu tests
 gTests.push({
   desc: "image context menu",
   run: function test() {
     netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
 
     info(chromeRoot + "browser_context_menu_tests_01.html");
     yield addTab(chromeRoot + "browser_context_menu_tests_01.html");
 
     let win = Browser.selectedTab.browser.contentWindow;
 
     purgeEventQueue();
 
     yield hideContextUI();
 
-    // If we don't do this, sometimes the first sendContextMenuClick
+    // If we don't do this, sometimes the first sendContextMenuClickToWindow
     // will trigger the app bar.
     yield waitForImageLoad(win, "image01");
 
     ////////////////////////////////////////////////////////////
     // Context menu options
 
     // image01 - 1x1x100x100
     let promise = waitForEvent(document, "popupshown");
-    sendContextMenuClick(win, 10, 10);
+    sendContextMenuClickToWindow(win, 10, 10);
     yield promise;
     ok(promise && !(promise instanceof Error), "promise error");
 
     purgeEventQueue();
 
     ok(ContextMenuUI._menuPopup._visible, "is visible");
 
     checkContextUIMenuItemVisibility(["context-save-image-lib",
@@ -388,17 +430,17 @@ gTests.push({
     purgeEventQueue();
 
     ok(saveLocationPath.exists(), "image saved");
 
     ////////////////////////////////////////////////////////////
     // Copy image
 
     let promise = waitForEvent(document, "popupshown");
-    sendContextMenuClick(win, 20, 20);
+    sendContextMenuClickToWindow(win, 20, 20);
     yield promise;
     ok(promise && !(promise instanceof Error), "promise error");
     ok(ContextMenuUI._menuPopup._visible, "is visible");
 
     menuItem = document.getElementById("context-copy-image");
     ok(menuItem, "menu item exists");
     ok(!menuItem.hidden, "menu item visible");
     popupPromise = waitForEvent(document, "popuphidden");
@@ -411,17 +453,17 @@ gTests.push({
     let clip = Cc["@mozilla.org/widget/clipboard;1"].getService(Ci.nsIClipboard);
     let flavors = ["image/png"];
     ok(clip.hasDataMatchingFlavors(flavors, flavors.length, Ci.nsIClipboard.kGlobalClipboard), "clip has my png flavor");
 
     ////////////////////////////////////////////////////////////
     // Copy image location
 
     promise = waitForEvent(document, "popupshown");
-    sendContextMenuClick(win, 30, 30);
+    sendContextMenuClickToWindow(win, 30, 30);
     yield promise;
     ok(promise && !(promise instanceof Error), "promise error");
     ok(ContextMenuUI._menuPopup._visible, "is visible");
 
     menuItem = document.getElementById("context-copy-image-loc");
     ok(menuItem, "menu item exists");
     ok(!menuItem.hidden, "menu item visible");
     popupPromise = waitForEvent(document, "popuphidden");
@@ -445,17 +487,17 @@ gTests.push({
     xfer.getTransferData("text/unicode", str, strLength);
     str = str.value.QueryInterface(Components.interfaces.nsISupportsString);
     ok(str == "chrome://mochitests/content/metro/res/image01.png", "url copied");
 
     ////////////////////////////////////////////////////////////
     // Open image in new tab
 
     promise = waitForEvent(document, "popupshown");
-    sendContextMenuClick(win, 40, 40);
+    sendContextMenuClickToWindow(win, 40, 40);
     yield promise;
     ok(promise && !(promise instanceof Error), "promise error");
     ok(ContextMenuUI._menuPopup._visible, "is visible");
 
     menuItem = document.getElementById("context-open-image-tab");
     ok(menuItem, "menu item exists");
     ok(!menuItem.hidden, "menu item visible");
     let tabPromise = waitForEvent(document, "TabOpen");
@@ -465,17 +507,16 @@ gTests.push({
     let event = yield tabPromise;
     ok(popupPromise && !(popupPromise instanceof Error), "promise error");
     ok(tabPromise && !(tabPromise instanceof Error), "promise error");
 
     purgeEventQueue();
 
     let imagetab = Browser.getTabFromChrome(event.originalTarget);
     ok(imagetab != null, "tab created");
-    ok(imagetab.browser.currentURI.spec == "chrome://mochitests/content/metro/res/image01.png", "tab location");
 
     Browser.closeTab(imagetab);
   }
 });
 
 gTests.push({
   desc: "tests for subframe positioning",
   run: function test() {
@@ -499,68 +540,68 @@ gTests.push({
     let promise = waitForEvent(document, "popupshown");
     sendContextMenuClickToElement(frame1.contentDocument.defaultView, link1, 85, 10);
     yield promise;
     ok(promise && !(promise instanceof Error), "promise error");
 
     // should be visible
     ok(ContextMenuUI._menuPopup._visible, "is visible");
 
-    checkContextMenuPositionRange(ContextMenuUI._panel, 560, 570, 175, 190);
+    checkContextMenuPositionRange(ContextMenuUI._panel, 290, 300, 160, 175);
 
     promise = waitForEvent(document, "popuphidden");
     ContextMenuUI.hide();
     yield promise;
     ok(promise && !(promise instanceof Error), "promise error");
 
     frame1.contentDocument.defaultView.scrollBy(0, 200);
 
     promise = waitForEvent(document, "popupshown");
     sendContextMenuClickToElement(frame1.contentDocument.defaultView, link1, 85, 10);
     yield promise;
     ok(promise && !(promise instanceof Error), "promise error");
 
     // should be visible
     ok(ContextMenuUI._menuPopup._visible, "is visible");
 
-    checkContextMenuPositionRange(ContextMenuUI._panel, 560, 570, 95, 110);
+    checkContextMenuPositionRange(ContextMenuUI._panel, 290, 300, 85, 90);
 
     promise = waitForEvent(document, "popuphidden");
     ContextMenuUI.hide();
     yield promise;
     ok(promise && !(promise instanceof Error), "promise error");
 
     let rlink1 = win.document.getElementById("rlink1");
 
     promise = waitForEvent(document, "popupshown");
     sendContextMenuClickToElement(win, rlink1, 40, 10);
     yield promise;
     ok(promise && !(promise instanceof Error), "promise error");
 
     // should be visible
     ok(ContextMenuUI._menuPopup._visible, "is visible");
 
-    checkContextMenuPositionRange(ContextMenuUI._panel, 910, 925, 540, 555);
+    checkContextMenuPositionRange(ContextMenuUI._panel, 640, 650, 540, 555);
 
     promise = waitForEvent(document, "popuphidden");
     ContextMenuUI.hide();
     yield promise;
     ok(promise && !(promise instanceof Error), "promise error");
 
     win.scrollBy(0, 200);
 
     promise = waitForEvent(document, "popupshown");
     sendContextMenuClickToElement(win, rlink1, 40, 10);
     yield promise;
     ok(promise && !(promise instanceof Error), "promise error");
 
     // should be visible
     ok(ContextMenuUI._menuPopup._visible, "is visible");
 
-    checkContextMenuPositionRange(ContextMenuUI._panel, 910, 925, 340, 355);
+    checkContextMenuPositionRange(ContextMenuUI._panel, 640, 650, 340, 355);
 
     promise = waitForEvent(document, "popuphidden");
     ContextMenuUI.hide();
     yield promise;
     ok(promise && !(promise instanceof Error), "promise error");
 
     let link2 = frame1.contentDocument.getElementById("link2");
 
@@ -570,17 +611,17 @@ gTests.push({
     ok(promise && !(promise instanceof Error), "promise error");
 
     // should be visible
     ok(ContextMenuUI._menuPopup._visible, "is visible");
 
     info(ContextMenuUI._panel.left);
     info(ContextMenuUI._panel.top);
 
-    checkContextMenuPositionRange(ContextMenuUI._panel, 560, 570, 110, 125);
+    checkContextMenuPositionRange(ContextMenuUI._panel, 290, 300, 75, 85);
 
     promise = waitForEvent(document, "popuphidden");
     ContextMenuUI.hide();
     yield promise;
     ok(promise && !(promise instanceof Error), "promise error");
   }
 });
 
--- a/browser/metro/base/tests/mochitest/browser_context_menu_tests_02.html
+++ b/browser/metro/base/tests/mochitest/browser_context_menu_tests_02.html
@@ -9,10 +9,20 @@
     <span id="text1">hello, I'm sorry but I must be going.</span>
   </div>
   <div style="margin: 0; padding: 5px;">
     <span id="text2"><a id="text2-link" href="#test">hello, I'm sorry but</a> I must be going.</span>
   </div>
   <div style="margin: 0; padding: 5px;">
     <span id="text3"><input id="text3-input" value="hello, I'm sorry but I must be going." style="width:200px;"/></span>
   </div>
+  <br />
+  <br />
+  <br />
+  <br />
+  <br />
+  <br />
+  <br />
+  <div style="margin: 0; padding: 5px;">
+    <span id="text4">hello, I'm sorry but I must be going.</span>
+  </div>
 </body>
 </html>
\ No newline at end of file
--- a/browser/metro/base/tests/mochitest/head.js
+++ b/browser/metro/base/tests/mochitest/head.js
@@ -45,16 +45,58 @@ function checkContextUIMenuItemVisibilit
       // item should be hidden
       errors++;
       info("should be hidden:" + item.id);
     }
   }
   is(errors, 0, "context menu item list visibility");
 }
 
+/*
+ * showNotification - displays a test notification with the current
+ * browser and waits for the noticiation to be fully displayed.
+ *
+ * Usage: yield showNotification();
+ */
+function showNotification()
+{
+  return Task.spawn(function() {
+    try {
+      let strings = Strings.browser;
+      var buttons = [
+        {
+          isDefault: false,
+          label: strings.GetStringFromName("popupButtonAllowOnce2"),
+          accessKey: "",
+          callback: function() { }
+        },
+        {
+          label: strings.GetStringFromName("popupButtonAlwaysAllow3"),
+          accessKey: "",
+          callback: function() { }
+        },
+        {
+          label: strings.GetStringFromName("popupButtonNeverWarn3"),
+          accessKey: "",
+          callback: function() { }
+        }
+      ];
+      let notificationBox = Browser.getNotificationBox();
+      const priority = notificationBox.PRIORITY_WARNING_MEDIUM;
+      notificationBox.appendNotification("test notification", "popup-blocked",
+                                          "chrome://browser/skin/images/infobar-popup.png",
+                                          priority, buttons);
+      yield waitForEvent(notificationBox, "transitionend");
+      return;
+    } catch (ex) {
+      throw new Task.Result(ex);
+    }
+  });
+}
+
 /*=============================================================================
   Asynchronous Metro ui helpers
 =============================================================================*/
 
 function hideContextUI()
 {
   purgeEventQueue();
   if (ContextUI.isVisible) {
@@ -362,19 +404,40 @@ function synthesizeNativeMouseMDown(aEle
 function synthesizeNativeMouseMUp(aElement, aOffsetX, aOffsetY) {
   synthesizeNativeMouse(aElement,
                         aOffsetX,
                         aOffsetY,
                         0x0040);  // MOUSEEVENTF_MIDDLEUP
 }
 
 /*
- * sendContextMenuClick - simulates a press-hold touch input event.
+ * sendContextMenuClick - simulates a press-hold touch input event. Event
+ * is delivered to the main window of the application through the top-level
+ * widget.
+ *
+ * @param aX, aY logical coordinates of the event.
  */
-function sendContextMenuClick(aWindow, aX, aY) {
+function sendContextMenuClick(aX, aY) {
+  let mediator = Components.classes["@mozilla.org/appshell/window-mediator;1"]
+                            .getService(Components.interfaces.nsIWindowMediator);
+  let mainwin = mediator.getMostRecentWindow("navigator:browser");
+  let utils = mainwin.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
+                      .getInterface(Components.interfaces.nsIDOMWindowUtils);
+  utils.sendMouseEvent("contextmenu", aX, aY, 2, 1, 0, true,
+                        1, Ci.nsIDOMMouseEvent.MOZ_SOURCE_TOUCH);
+}
+
+/*
+ * sendContextMenuClickToWindow - simulates a press-hold touch input event.
+ *
+ * @param aWindow window used to retrieve dom window utils, and the
+ * target window for the event.
+ * @param aX, aY logical coordinates of the event relative to aWindow.
+ */
+function sendContextMenuClickToWindow(aWindow, aX, aY) {
   let utils = aWindow.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
                       .getInterface(Components.interfaces.nsIDOMWindowUtils);
 
   utils.sendMouseEventToWindow("contextmenu", aX, aY, 2, 1, 0, true,
                                 1, Ci.nsIDOMMouseEvent.MOZ_SOURCE_TOUCH);
 }
 
 function sendContextMenuClickToElement(aWindow, aElement, aX, aY) {