Bug 1474221 - Part 2. Make the chevron menu to be doorhanger menu. r=birtles
authorMantaroh Yoshinaga <mantaroh@gmail.com>
Fri, 20 Jul 2018 15:58:35 +0900
changeset 427452 a3459b4851d3c5f6938466a8d86aba1fbe404594
parent 427451 c300d08cad3060e250a7ac5eb5dba6537c98d602
child 427453 f97be2485d3d7bc791c22e69e44531e2130ab64f
push id34306
push usercsabou@mozilla.com
push dateFri, 20 Jul 2018 21:41:18 +0000
treeherdermozilla-central@d6a5e8aea651 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbirtles
bugs1474221
milestone63.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 1474221 - Part 2. Make the chevron menu to be doorhanger menu. r=birtles This patch will make the chevron menu to doorhanger menu and modify some tests which related with this chevron menu. MozReview-Commit-ID: BkdVHgRlHIw
devtools/client/framework/components/ToolboxTabs.js
devtools/client/framework/test/browser_toolbox_options.js
devtools/client/framework/test/browser_toolbox_toolbar_minimum_width.js
devtools/client/framework/test/browser_toolbox_toolbar_overflow.js
devtools/client/framework/test/browser_toolbox_toolbar_reorder_by_width.js
devtools/client/framework/test/head.js
devtools/client/themes/toolbox.css
--- a/devtools/client/framework/components/ToolboxTabs.js
+++ b/devtools/client/framework/components/ToolboxTabs.js
@@ -1,21 +1,22 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 "use strict";
 
 const { Component, createFactory } = require("devtools/client/shared/vendor/react");
 const dom = require("devtools/client/shared/vendor/react-dom-factories");
 const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
-const {findDOMNode} = require("devtools/client/shared/vendor/react-dom");
-const {button, div} = dom;
+const { findDOMNode } = require("devtools/client/shared/vendor/react-dom");
+const { div } = dom;
 
-const Menu = require("devtools/client/framework/menu");
-const MenuItem = require("devtools/client/framework/menu-item");
+const MenuButton = createFactory(require("devtools/client/shared/components/menu/MenuButton"));
+const MenuItem = createFactory(require("devtools/client/shared/components/menu/MenuItem"));
+const MenuList = createFactory(require("devtools/client/shared/components/menu/MenuList"));
 const ToolboxTab = createFactory(require("devtools/client/framework/components/ToolboxTab"));
 const { ToolboxTabsOrderManager } = require("devtools/client/framework/toolbox-tabs-order-manager");
 
 // 26px is chevron devtools button width.(i.e. tools-chevronmenu)
 const CHEVRON_BUTTON_WIDTH = 26;
 
 class ToolboxTabs extends Component {
   // See toolbox-toolbar propTypes for details on the props used here.
@@ -183,60 +184,58 @@ class ToolboxTabs extends Component {
 
   resizeHandler(evt) {
     window.cancelIdleCallback(this._resizeTimerId);
     this._resizeTimerId = window.requestIdleCallback(() => {
       this.updateOverflowedTabs();
     }, { timeout: 100 });
   }
 
+  renderToolsChevronMenuList() {
+    const {
+      panelDefinitions,
+      selectTool,
+    } = this.props;
+
+    const items = [];
+    for (const { id, label, icon } of panelDefinitions) {
+      if (this.state.overflowedTabIds.includes(id)) {
+        items.push(MenuItem({
+          id: "tools-chevron-menupopup-" + id,
+          label,
+          type: "checkbox",
+          onClick: () => {
+            selectTool(id, "tab_switch");
+          },
+          icon,
+        }));
+      }
+    }
+
+    return MenuList({ id: "tools-chevron-menupopup" }, items);
+  }
+
   /**
    * Render a button to access overflowed tools, displayed only when the toolbar
    * presents an overflow.
    */
   renderToolsChevronButton() {
     const {
-      panelDefinitions,
-      selectTool,
       toolbox,
-      L10N,
     } = this.props;
 
-    return button({
-      className: "devtools-button tools-chevron-menu",
-      tabIndex: -1,
-      title: L10N.getStr("toolbox.allToolsButton.tooltip"),
-      id: "tools-chevron-menu-button",
-      onClick: ({ target }) => {
-        const menu = new Menu({
-          id: "tools-chevron-menupopup"
-        });
-
-        panelDefinitions.forEach(({id, label}) => {
-          if (this.state.overflowedTabIds.includes(id)) {
-            menu.append(new MenuItem({
-              click: () => {
-                selectTool(id, "tab_switch");
-              },
-              id: "tools-chevron-menupopup-" + id,
-              label,
-              type: "checkbox",
-            }));
-          }
-        });
-
-        const rect = target.getBoundingClientRect();
-        const screenX = target.ownerDocument.defaultView.mozInnerScreenX;
-        const screenY = target.ownerDocument.defaultView.mozInnerScreenY;
-
-        // Display the popup below the button.
-        menu.popupWithZoom(rect.left + screenX, rect.bottom + screenY, toolbox);
-        return menu;
+    return MenuButton(
+      {
+        id: "tools-chevron-menu-button",
+        menuId: "tools-chevron-menu-button-panel",
+        className: "devtools-button tools-chevron-menu",
+        doc: toolbox.doc,
       },
-    });
+      this.renderToolsChevronMenuList()
+    );
   }
 
   /**
    * Render all of the tabs, based on the panel definitions and builds out
    * a toolbox tab for each of them. Will render the chevron button if the
    * container has an overflow.
    */
   render() {
--- a/devtools/client/framework/test/browser_toolbox_options.js
+++ b/devtools/client/framework/test/browser_toolbox_options.js
@@ -462,23 +462,20 @@ function GetPref(name) {
  * Find the button from specified toolId.
  * Generally, button which access to the tool panel is in toolbox or
  * tools menu(in the Chevron menu).
  */
 async function lookupButtonForToolId(toolId) {
   let button = doc.getElementById("toolbox-tab-" + toolId);
   if (!button) {
     // search from the tools menu.
-    const menuPopup = await openChevronMenu(toolbox);
+    await openChevronMenu(toolbox);
     button = doc.querySelector("#tools-chevron-menupopup-" + toolId);
 
-    info("Closing the tools-chevron-menupopup popup");
-    const onPopupHidden = once(menuPopup, "popuphidden");
-    menuPopup.hidePopup();
-    await onPopupHidden;
+    await closeChevronMenu(toolbox);
   }
   return button;
 }
 
 async function cleanup() {
   gDevTools.unregisterTool("test-tool");
   await toolbox.destroy();
   gBrowser.removeCurrentTab();
--- a/devtools/client/framework/test/browser_toolbox_toolbar_minimum_width.js
+++ b/devtools/client/framework/test/browser_toolbox_toolbar_minimum_width.js
@@ -18,23 +18,20 @@ add_task(async function(pickerEnable, co
     Services.prefs.clearUserPref(SIDEBAR_WIDTH_PREF);
   });
   const tab = await addTab("about:blank");
 
   info("Open devtools on the Inspector in a side dock");
   const toolbox = await openToolboxForTab(tab, "inspector", Toolbox.HostType.RIGHT);
   await waitUntil(() => toolbox.doc.querySelector(".tools-chevron-menu"));
 
-  const menuPopup = await openChevronMenu(toolbox);
+  await openChevronMenu(toolbox);
 
   // Check that all of tools is overflowed.
   toolbox.panelDefinitions.forEach(({id}) => {
     const menuItem = toolbox.doc.getElementById("tools-chevron-menupopup-" + id);
     const tab = toolbox.doc.getElementById("toolbox-tab-" + id);
     ok(menuItem, id + " is in the overflowed menu");
     ok(!tab, id + " tab does not exist");
   });
 
-  info("Closing the chevron popup menu");
-  const onPopupHidden = once(menuPopup, "popuphidden");
-  menuPopup.hidePopup();
-  await onPopupHidden;
+  await closeChevronMenu(toolbox);
 });
--- a/devtools/client/framework/test/browser_toolbox_toolbar_overflow.js
+++ b/devtools/client/framework/test/browser_toolbox_toolbar_overflow.js
@@ -40,34 +40,29 @@ add_task(async function() {
 
   info("Wait until the chevron menu button is available");
   await waitUntil(() => toolbox.doc.querySelector(".tools-chevron-menu"));
 
   chevronMenuButton = toolbox.doc.querySelector(".tools-chevron-menu");
   ok(chevronMenuButton, "The chevron menu button is displayed");
 
   info("Open the tools-chevron-menupopup and verify that the inspector button is checked");
-  const menuPopup = await openChevronMenu(toolbox);
+  await openChevronMenu(toolbox);
 
   const inspectorButton = toolbox.doc.querySelector("#tools-chevron-menupopup-inspector");
   ok(!inspectorButton, "The chevron menu doesn't have the inspector button.");
 
   const consoleButton = toolbox.doc.querySelector("#tools-chevron-menupopup-webconsole");
   ok(!consoleButton, "The chevron menu doesn't have the console button.");
 
   const storageButton = toolbox.doc.querySelector("#tools-chevron-menupopup-storage");
   ok(storageButton, "The chevron menu has the storage button.");
 
   info("Switch to the performance using the tools-chevron-menupopup popup");
   const onSelected = toolbox.once("storage-selected");
   storageButton.click();
   await onSelected;
 
-  info("Closing the tools-chevron-menupopup popup");
-  const onPopupHidden = once(menuPopup, "popuphidden");
-  menuPopup.hidePopup();
-  await onPopupHidden;
-
   info("Restore the original window size");
   onResize = once(hostWindow, "resize");
   hostWindow.resizeTo(originalWidth, originalHeight);
   await onResize;
 });
--- a/devtools/client/framework/test/browser_toolbox_toolbar_reorder_by_width.js
+++ b/devtools/client/framework/test/browser_toolbox_toolbar_reorder_by_width.js
@@ -61,36 +61,30 @@ add_task(async function() {
     label: "Test Tools",
     isMenu: true,
     isTargetSupported: () => true,
     build: function() {},
   });
   await onRegistered;
 
   info("Open the tools menu button.");
-  let popup = await openChevronMenu(toolbox);
+  await openChevronMenu(toolbox);
 
   info("The registered new tool tab should be in the tools menu.");
   let testToolsButton = toolbox.doc.querySelector("#tools-chevron-menupopup-test-tools");
   ok(testToolsButton, "The tools menu has a registered new tool button.");
 
-  info("Closing the tools-chevron-menupopup popup");
-  let onPopupHidden = once(popup, "popuphidden");
-  popup.hidePopup();
-  await onPopupHidden;
+  await closeChevronMenu(toolbox);
 
   info("Unregistering test-tools");
   const onUnregistered = toolbox.once("tool-unregistered");
   gDevTools.unregisterTool("test-tools");
   await onUnregistered;
 
   info("Open the tools menu button.");
-  popup = await openChevronMenu(toolbox);
+  await openChevronMenu(toolbox);
 
   info("An unregistered new tool tab should not be in the tools menu.");
   testToolsButton = toolbox.doc.querySelector("#tools-chevron-menupopup-test-tools");
   ok(!testToolsButton, "The tools menu doesn't have a unregistered new tool button.");
 
-  info("Closing the tools-chevron-menupopup popup");
-  onPopupHidden = once(popup, "popuphidden");
-  popup.hidePopup();
-  await onPopupHidden;
+  await closeChevronMenu(toolbox);
 });
--- a/devtools/client/framework/test/head.js
+++ b/devtools/client/framework/test/head.js
@@ -246,23 +246,34 @@ DevToolPanel.prototype = {
 function createTestPanel(iframeWindow, toolbox) {
   return new DevToolPanel(iframeWindow, toolbox);
 }
 
 async function openChevronMenu(toolbox) {
   const chevronMenuButton = toolbox.doc.querySelector(".tools-chevron-menu");
   EventUtils.synthesizeMouseAtCenter(chevronMenuButton, {}, toolbox.win);
 
-  const menuPopup = toolbox.doc.querySelector("#tools-chevron-menupopup");
+  const menuPopup = toolbox.doc.getElementById("tools-chevron-menu-button-panel");
   ok(menuPopup, "tools-chevron-menupopup is available");
 
   info("Waiting for the menu popup to be displayed");
-  await waitUntil(() => menuPopup && menuPopup.state === "open");
+  await waitUntil(() => menuPopup.classList.contains("tooltip-visible"));
+}
 
-  return menuPopup;
+async function closeChevronMenu(toolbox) {
+  // In order to close the popup menu with escape key, set the focus to the chevron
+  // button at first.
+  const chevronMenuButton = toolbox.doc.querySelector(".tools-chevron-menu");
+  chevronMenuButton.focus();
+
+  EventUtils.sendKey("ESCAPE", toolbox.doc.defaultView);
+  const menuPopup = toolbox.doc.getElementById("tools-chevron-menu-button-panel");
+
+  info("Closing the chevron popup menu");
+  await waitUntil(() => !menuPopup.classList.contains("tooltip-visible"));
 }
 
 function prepareToolTabReorderTest(toolbox, startingOrder) {
   Services.prefs.setCharPref("devtools.toolbox.tabsOrder", startingOrder.join(","));
   ok(!toolbox.doc.getElementById("tools-chevron-menu-button"),
      "The size of the screen being too small");
 
   for (const id of startingOrder) {
--- a/devtools/client/themes/toolbox.css
+++ b/devtools/client/themes/toolbox.css
@@ -63,21 +63,16 @@
 .devtools-tabbar-has-start .toolbox-tabs-wrapper {
   grid-column-start: 1;
 }
 
 .devtools-tabbar-has-end .toolbox-tabs-wrapper {
   grid-column-end: 4;
 }
 
-.toolbox-tabs-wrapper .tools-chevron-menu {
-  border-top-width: 0;
-  border-bottom-width: 0;
-}
-
 .toolbox-tabs {
   position: absolute;
   top: 0;
   left: 0;
   right: 0;
   bottom: 0;
   display: flex;
   margin: 0;
@@ -246,17 +241,18 @@
 }
 #toolbox-meatball-menu-settings > .label::before {
   --menuitem-icon-image: var(--settings-image);
 }
 
 /* Command buttons */
 
 .command-button,
-#toolbox-controls > button {
+#toolbox-controls > button,
+.toolbox-tabs-wrapper .tools-chevron-menu {
   /* !important is needed to override .devtools-button rules in common.css */
   padding: 0 !important;
   margin: 0 !important;
   border: none !important;
   border-radius: 0 !important;
   position: relative;
   min-width: 24px;
 }