Bug 1499236 - remove customizableui menubar binding, r=Felipe
authorGijs Kruitbosch <gijskruitbosch@gmail.com>
Wed, 17 Oct 2018 22:50:40 +0000
changeset 500371 5c84e7821c57ada673b4cf554a000961f57efdf8
parent 500370 a5849dab9066759af0c542aa608cad47fe8bc1c6
child 500379 3a18b352f6fb76d157dd54ea1cb8e1ba6c35d97f
push id1864
push userffxbld-merge
push dateMon, 03 Dec 2018 15:51:40 +0000
treeherdermozilla-release@f040763d99ad [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersFelipe
bugs1499236
milestone64.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1499236 - remove customizableui menubar binding, r=Felipe Differential Revision: https://phabricator.services.mozilla.com/D8901
browser/base/content/browser-customization.js
browser/base/content/browser.css
browser/base/content/browser.js
browser/components/customizableui/content/toolbar.xml
--- a/browser/base/content/browser-customization.js
+++ b/browser/base/content/browser-customization.js
@@ -61,8 +61,120 @@ var CustomizationHandler = {
     for (let childNode of menubar.children)
       childNode.setAttribute("disabled", false);
     let cmd = document.getElementById("cmd_CustomizeToolbars");
     cmd.removeAttribute("disabled");
 
     gBrowser.selectedBrowser.focus();
   },
 };
+
+var AutoHideMenubar = {
+  get _node() {
+    delete this._node;
+    return this._node = document.getElementById("toolbar-menubar");
+  },
+
+  _contextMenuListener: {
+    contextMenu: null,
+
+    get active() {
+      return !!this.contextMenu;
+    },
+
+    init(event) {
+      // Ignore mousedowns in <menupopup>s.
+      if (event.target.closest("menupopup")) {
+        return;
+      }
+
+      let contextMenuId = AutoHideMenubar._node.getAttribute("context");
+      this.contextMenu = document.getElementById(contextMenuId);
+      this.contextMenu.addEventListener("popupshown", this);
+      this.contextMenu.addEventListener("popuphiding", this);
+      AutoHideMenubar._node.addEventListener("mousemove", this);
+    },
+    handleEvent(event) {
+      switch (event.type) {
+        case "popupshown":
+          AutoHideMenubar._node.removeEventListener("mousemove", this);
+          break;
+        case "popuphiding":
+        case "mousemove":
+          AutoHideMenubar._setInactiveAsync();
+          AutoHideMenubar._node.removeEventListener("mousemove", this);
+          this.contextMenu.removeEventListener("popuphiding", this);
+          this.contextMenu.removeEventListener("popupshown", this);
+          this.contextMenu = null;
+          break;
+      }
+    },
+  },
+
+  init() {
+    this._node.addEventListener("toolbarvisibilitychange", this);
+    if (this._node.getAttribute("autohide") == "true") {
+      this._enable();
+    }
+  },
+
+  _updateState() {
+    if (this._node.getAttribute("autohide") == "true") {
+      this._enable();
+    } else {
+      this._disable();
+    }
+  },
+
+  _events: ["DOMMenuBarInactive", "DOMMenuBarActive", "popupshowing", "mousedown"],
+  _enable() {
+    this._node.setAttribute("inactive", "true");
+    for (let event of this._events) {
+      this._node.addEventListener(event, this);
+    }
+  },
+
+  _disable() {
+    this._setActive();
+    for (let event of this._events) {
+      this._node.removeEventListener(event, this);
+    }
+  },
+
+  handleEvent(event) {
+    switch (event.type) {
+      case "toolbarvisibilitychange":
+        this._updateState();
+        break;
+      case "popupshowing":
+        // fall through
+      case "DOMMenuBarActive":
+        this._setActive();
+        break;
+      case "mousedown":
+        if (event.button == 2) {
+          this._contextMenuListener.init(event);
+        }
+        break;
+      case "DOMMenuBarInactive":
+        if (!this._contextMenuListener.active)
+          this._setInactiveAsync();
+        break;
+    }
+  },
+
+  _setInactiveAsync() {
+    this._inactiveTimeout = setTimeout(() => {
+      if (this._node.getAttribute("autohide") == "true") {
+        this._inactiveTimeout = null;
+        this._node.setAttribute("inactive", "true");
+      }
+    }, 0);
+  },
+
+  _setActive() {
+    if (this._inactiveTimeout) {
+      clearTimeout(this._inactiveTimeout);
+      this._inactiveTimeout = null;
+    }
+    this._node.removeAttribute("inactive");
+  },
+};
--- a/browser/base/content/browser.css
+++ b/browser/base/content/browser.css
@@ -71,20 +71,16 @@ toolbar[customizable="true"] {
 }
 
 %ifdef XP_MACOSX
 #toolbar-menubar {
   -moz-binding: url("chrome://browser/content/customizableui/toolbar.xml#toolbar-menubar-stub");
 }
 %endif
 
-#toolbar-menubar[autohide="true"] {
-  -moz-binding: url("chrome://browser/content/customizableui/toolbar.xml#toolbar-menubar-autohide");
-}
-
 panelmultiview {
   -moz-box-align: start;
 }
 
 panelmultiview[transitioning] {
   pointer-events: none;
 }
 
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -102,17 +102,17 @@ XPCOMUtils.defineLazyScriptGetter(this, 
 XPCOMUtils.defineLazyScriptGetter(this, "gTabsPanel",
                                   "chrome://browser/content/browser-allTabsMenu.js");
 XPCOMUtils.defineLazyScriptGetter(this, ["LightWeightThemeWebInstaller",
                                          "gExtensionsNotifications",
                                          "gXPInstallObserver"],
                                   "chrome://browser/content/browser-addons.js");
 XPCOMUtils.defineLazyScriptGetter(this, "ctrlTab",
                                   "chrome://browser/content/browser-ctrlTab.js");
-XPCOMUtils.defineLazyScriptGetter(this, "CustomizationHandler",
+XPCOMUtils.defineLazyScriptGetter(this, ["CustomizationHandler", "AutoHideMenubar"],
                                   "chrome://browser/content/browser-customization.js");
 XPCOMUtils.defineLazyScriptGetter(this, ["PointerLock", "FullScreen"],
                                   "chrome://browser/content/browser-fullScreenAndPointerLock.js");
 XPCOMUtils.defineLazyScriptGetter(this, ["gGestureSupport", "gHistorySwipeAnimation"],
                                   "chrome://browser/content/browser-gestureSupport.js");
 XPCOMUtils.defineLazyScriptGetter(this, "gSafeBrowsing",
                                   "chrome://browser/content/browser-safebrowsing.js");
 XPCOMUtils.defineLazyScriptGetter(this, "gSync",
@@ -1237,16 +1237,19 @@ var gBrowserInit = {
       document.documentElement.setAttribute("width", width);
       document.documentElement.setAttribute("height", height);
 
       if (width < TARGET_WIDTH && height < TARGET_HEIGHT) {
         document.documentElement.setAttribute("sizemode", "maximized");
       }
     }
 
+    // Run menubar initialization first, to avoid TabsInTitlebar code picking
+    // up mutations from it and causing a reflow.
+    AutoHideMenubar.init();
     // Update the chromemargin attribute so the window can be sized correctly.
     window.TabBarVisibility.update();
     TabsInTitlebar.init();
 
     new LightweightThemeConsumer(document);
     CompactTheme.init();
 
     if (AppConstants.platform == "win") {
--- a/browser/components/customizableui/content/toolbar.xml
+++ b/browser/components/customizableui/content/toolbar.xml
@@ -156,118 +156,20 @@
       <method name="insertItem">
         <body><![CDATA[
           return null;
         ]]></body>
       </method>
     </implementation>
   </binding>
 
-  <!-- The toolbar-menubar-autohide and toolbar-drag bindings are almost
-       verbatim copies of their toolkit counterparts - they just inherit from
-       the customizableui's toolbar binding instead of toolkit's. We're currently
-       OK with the maintainance burden of having two copies of a binding, since
-       the long term goal is to move the customization framework into toolkit. -->
-
-  <binding id="toolbar-menubar-autohide"
-           extends="chrome://browser/content/customizableui/toolbar.xml#toolbar">
-    <implementation>
-      <constructor>
-        this._setInactive();
-      </constructor>
-      <destructor>
-        this._setActive();
-      </destructor>
-
-      <field name="_inactiveTimeout">null</field>
-
-      <field name="_contextMenuListener"><![CDATA[({
-        toolbar: this,
-        contextMenu: null,
-
-        get active() {
-          return !!this.contextMenu;
-        },
-
-        init(event) {
-          let node = event.target;
-          while (node != this.toolbar) {
-            if (node.localName == "menupopup")
-              return;
-            node = node.parentNode;
-          }
-
-          let contextMenuId = this.toolbar.getAttribute("context");
-          if (!contextMenuId)
-            return;
-
-          this.contextMenu = document.getElementById(contextMenuId);
-          if (!this.contextMenu)
-            return;
-
-          this.contextMenu.addEventListener("popupshown", this);
-          this.contextMenu.addEventListener("popuphiding", this);
-          this.toolbar.addEventListener("mousemove", this);
-        },
-        handleEvent(event) {
-          switch (event.type) {
-            case "popupshown":
-              this.toolbar.removeEventListener("mousemove", this);
-              break;
-            case "popuphiding":
-            case "mousemove":
-              this.toolbar._setInactiveAsync();
-              this.toolbar.removeEventListener("mousemove", this);
-              this.contextMenu.removeEventListener("popuphiding", this);
-              this.contextMenu.removeEventListener("popupshown", this);
-              this.contextMenu = null;
-              break;
-          }
-        },
-      })]]></field>
-
-      <method name="_setInactive">
-        <body><![CDATA[
-          this.setAttribute("inactive", "true");
-        ]]></body>
-      </method>
-
-      <method name="_setInactiveAsync">
-        <body><![CDATA[
-          this._inactiveTimeout = setTimeout(function(self) {
-            if (self.getAttribute("autohide") == "true") {
-              self._inactiveTimeout = null;
-              self._setInactive();
-            }
-          }, 0, this);
-        ]]></body>
-      </method>
-
-      <method name="_setActive">
-        <body><![CDATA[
-          if (this._inactiveTimeout) {
-            clearTimeout(this._inactiveTimeout);
-            this._inactiveTimeout = null;
-          }
-          this.removeAttribute("inactive");
-        ]]></body>
-      </method>
-    </implementation>
-
-    <handlers>
-      <handler event="DOMMenuBarActive"     action="this._setActive();"/>
-      <handler event="popupshowing"         action="this._setActive();"/>
-      <handler event="mousedown" button="2" action="this._contextMenuListener.init(event);"/>
-      <handler event="DOMMenuBarInactive"><![CDATA[
-        if (!this._contextMenuListener.active)
-          this._setInactiveAsync();
-      ]]></handler>
-    </handlers>
-  </binding>
-
+  <!-- The toolbar-drag binding is almost a verbatim copy of its toolkit counterpart,
+       but it inherits from the customizableui's toolbar binding instead of toolkit's.
+       This functionality will move into CustomizableUI proper as part of our move
+       away from XBL. -->
   <binding id="toolbar-drag"
            extends="chrome://browser/content/customizableui/toolbar.xml#toolbar">
     <implementation>
       <field name="_dragBindingAlive">true</field>
       <constructor><![CDATA[
         if (!this._draggableStarted) {
           this._draggableStarted = true;
           try {