Bug 1395871 - Open customWidget menus on mousedown, rather than oncommand. draft
authorZibi Braniecki <zbraniecki@mozilla.com>
Tue, 05 Sep 2017 21:35:20 -0700
changeset 659672 22acda504cb17f847a0696b02428c4264c18f442
parent 659666 9dd6970bc434360ac037d8378c4f303a94da4627
child 659673 a9a76dee545da282b3919c8f043d6e1a55651b6b
push id78153
push userbmo:gandalf@aviary.pl
push dateWed, 06 Sep 2017 04:47:01 +0000
bugs1395871
milestone57.0a1
Bug 1395871 - Open customWidget menus on mousedown, rather than oncommand. MozReview-Commit-ID: 2K4uYSu7Nai
browser/components/customizableui/CustomizableUI.jsm
browser/components/extensions/ext-browserAction.js
--- a/browser/components/customizableui/CustomizableUI.jsm
+++ b/browser/components/customizableui/CustomizableUI.jsm
@@ -1218,16 +1218,17 @@ var CustomizableUIInternal = {
     this.notifyListeners("onWidgetBeforeDOMChange", aNode, aNextNode, aContainer);
     this.setLocationAttributes(aNode, aArea);
     aContainer.insertBefore(aNode, aNextNode);
     this.notifyListeners("onWidgetAfterDOMChange", aNode, aNextNode, aContainer);
   },
 
   handleEvent(aEvent) {
     switch (aEvent.type) {
+      case "mousedown":
       case "command":
         if (!this._originalEventInPanel(aEvent)) {
           break;
         }
         aEvent = aEvent.sourceEvent;
         // Fall through
       case "click":
       case "keypress":
@@ -1400,17 +1401,21 @@ var CustomizableUIInternal = {
 
       let tooltip = this.getLocalizedProperty(aWidget, "tooltiptext", additionalTooltipArguments);
       if (tooltip) {
         node.setAttribute("tooltiptext", tooltip);
       }
       node.setAttribute("class", "toolbarbutton-1 chromeclass-toolbar-additional");
 
       let commandHandler = this.handleWidgetCommand.bind(this, aWidget, node);
-      node.addEventListener("command", commandHandler);
+      if (aWidget.type === "view") {
+        node.addEventListener("mousedown", commandHandler);
+      } else {
+        node.addEventListener("command", commandHandler);
+      }
       let clickHandler = this.handleWidgetClick.bind(this, aWidget, node);
       node.addEventListener("click", clickHandler);
 
       // If the widget has a view, and has view showing / hiding listeners,
       // hook those up to this widget.
       if (aWidget.type == "view") {
         log.debug("Widget " + aWidget.id + " has a view. Auto-registering event handlers.");
         let viewNode = aDocument.getElementById(aWidget.viewId);
@@ -1716,17 +1721,17 @@ var CustomizableUIInternal = {
       if (aEvent.keyCode != aEvent.DOM_VK_RETURN) {
         return;
       }
       // If the user hit enter/return, we don't check preventDefault - it makes sense
       // that this was prevented, but we probably still want to close the panel.
       // If consumers don't want this to happen, they should specify the closemenu
       // attribute.
 
-    } else if (aEvent.type != "command") { // mouse events:
+    } else if (aEvent.type != "command" || aEvent.type != "mousedown") { // mouse events:
       if (aEvent.defaultPrevented || aEvent.button != 0) {
         return;
       }
       let isInteractive = this._isOnInteractiveElement(aEvent);
       log.debug("maybeAutoHidePanel: interactive ? " + isInteractive);
       if (isInteractive) {
         return;
       }
--- a/browser/components/extensions/ext-browserAction.js
+++ b/browser/components/extensions/ext-browserAction.js
@@ -168,17 +168,16 @@ this.browserAction = class extends Exten
         }
       },
 
       onCreated: node => {
         node.classList.add("badged-button");
         node.classList.add("webextension-browser-action");
         node.setAttribute("constrain-size", "true");
 
-        node.onmousedown = event => this.handleEvent(event);
         node.onmouseover = event => this.handleEvent(event);
         node.onmouseout = event => this.handleEvent(event);
 
         this.updateButton(node, this.defaults, true);
       },
 
       onViewShowing: async event => {
         TelemetryStopwatch.start(POPUP_OPEN_MS_HISTOGRAM, this);
@@ -259,54 +258,30 @@ this.browserAction = class extends Exten
     // Popups are shown only if a popup URL is defined; otherwise
     // a "click" event is dispatched. This is done for compatibility with the
     // Google Chrome onClicked extension API.
     if (this.getProperty(tab, "popup")) {
       if (this.widget.areaType == CustomizableUI.TYPE_MENU_PANEL) {
         await window.document.getElementById("nav-bar").overflowable.show();
       }
 
-      let event = new window.CustomEvent("command", {bubbles: true, cancelable: true});
+      const activationEvent = widget.type ? "mousedown" : "command";
+      let event = new window.CustomEvent(activationEvent, {bubbles: true, cancelable: true});
       widget.node.dispatchEvent(event);
     } else {
       this.tabManager.addActiveTabPermission(tab);
       this.emit("click");
     }
   }
 
   handleEvent(event) {
     let button = event.target;
     let window = button.ownerGlobal;
 
     switch (event.type) {
-      case "mousedown":
-        if (event.button == 0) {
-          // Begin pre-loading the browser for the popup, so it's more likely to
-          // be ready by the time we get a complete click.
-          let tab = window.gBrowser.selectedTab;
-          let popupURL = this.getProperty(tab, "popup");
-          let enabled = this.getProperty(tab, "enabled");
-
-          if (popupURL && enabled && (this.pendingPopup || !ViewPopup.for(this.extension, window))) {
-            this.eventQueue.push("Mousedown");
-            // Add permission for the active tab so it will exist for the popup.
-            // Store the tab to revoke the permission during clearPopup.
-            if (!this.tabManager.hasActiveTabPermission(tab)) {
-              this.tabManager.addActiveTabPermission(tab);
-              this.tabToRevokeDuringClearPopup = tab;
-            }
-
-            this.pendingPopup = this.getPopup(window, popupURL);
-            window.addEventListener("mouseup", this, true);
-          } else {
-            this.clearPopup();
-          }
-        }
-        break;
-
       case "mouseup":
         if (event.button == 0) {
           this.clearPopupTimeout();
           // If we have a pending pre-loaded popup, cancel it after we've waited
           // long enough that we can be relatively certain it won't be opening.
           if (this.pendingPopup) {
             let node = window.gBrowser && this.widget.forWindow(window).node;
             if (isAncestorOrSelf(node, event.originalTarget)) {