Bug 1171085 - [Control Center] Implement keyboard navigation. r=Gijs, a=kglazko
authorTim Taubert <ttaubert@mozilla.com>
Tue, 30 Jun 2015 17:38:35 +0200
changeset 281462 616ec311f1e4ddf494e0cc6446fd2084c938ec51
parent 281461 82613d1611612bf1dc5fa31f9d2e22efc0256720
child 281463 d3df37f73a514723ad3e5eeed9729ddef9f47996
push id4932
push userjlund@mozilla.com
push dateMon, 10 Aug 2015 18:23:06 +0000
treeherdermozilla-beta@6dd5a4f5f745 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersGijs, kglazko
bugs1171085
milestone41.0a2
Bug 1171085 - [Control Center] Implement keyboard navigation. r=Gijs, a=kglazko
browser/base/content/browser.js
browser/components/controlcenter/content/panel.inc.xul
browser/components/customizableui/content/panelUI.xml
browser/themes/linux/controlcenter/panel.css
browser/themes/osx/controlcenter/panel.css
browser/themes/shared/controlcenter/panel.inc.css
browser/themes/windows/controlcenter/panel.css
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -6679,19 +6679,30 @@ var gIdentityHandler = {
    * "identity-popup" panel.
    */
   handleMoreInfoClick : function(event) {
     displaySecurityInfo();
     event.stopPropagation();
     this._identityPopup.hidePopup();
   },
 
-  showSubView(name, anchor) {
+  toggleSubView(name, anchor) {
     let view = document.getElementById("identity-popup-multiView");
-    view.showSubView(`identity-popup-${name}View`, anchor);
+    if (view.showingSubView) {
+      view.showMainView();
+    } else {
+      view.showSubView(`identity-popup-${name}View`, anchor);
+    }
+
+    // If an element is focused that's not the anchor, clear the focus.
+    // Elements of hidden views have -moz-user-focus:ignore but setting that
+    // per CSS selector doesn't blur a focused element in those hidden views.
+    if (Services.focus.focusedElement != anchor) {
+      Services.focus.clearFocus(window);
+    }
   },
 
   /**
    * Helper to parse out the important parts of _lastStatus (of the SSL cert in
    * particular) for use in constructing identity UI strings
   */
   getIdentityData : function() {
     var result = {};
@@ -7047,57 +7058,32 @@ var gIdentityHandler = {
       e.currentTarget.removeEventListener("popuphidden", onPopupHidden, false);
       self._identityBox.removeAttribute("open");
     }, false);
 
     // Now open the popup, anchored off the primary chrome element
     this._identityPopup.openPopup(this._identityIcon, "bottomcenter topleft");
   },
 
-  onPopupShown : function(event) {
-    this._identityPopup.addEventListener("blur", this, true);
-    this._identityPopup.addEventListener("popuphidden", this);
-  },
-
   onDragStart: function (event) {
     if (gURLBar.getAttribute("pageproxystate") != "valid")
       return;
 
     let value = gBrowser.currentURI.spec;
     let urlString = value + "\n" + gBrowser.contentTitle;
     let htmlString = "<a href=\"" + value + "\">" + value + "</a>";
 
     let dt = event.dataTransfer;
     dt.setData("text/x-moz-url", urlString);
     dt.setData("text/uri-list", value);
     dt.setData("text/plain", value);
     dt.setData("text/html", htmlString);
     dt.setDragImage(gProxyFavIcon, 16, 16);
   },
 
-  handleEvent: function (event) {
-    switch (event.type) {
-      case "blur":
-        // Focus hasn't moved yet, need to wait until after the blur event.
-        setTimeout(() => {
-          if (document.activeElement &&
-              document.activeElement.compareDocumentPosition(this._identityPopup) &
-                Node.DOCUMENT_POSITION_CONTAINS)
-            return;
-
-          this._identityPopup.hidePopup();
-        }, 0);
-        break;
-      case "popuphidden":
-        this._identityPopup.removeEventListener("blur", this, true);
-        this._identityPopup.removeEventListener("popuphidden", this);
-        break;
-    }
-  },
-
   updateSitePermissions: function () {
     while (this._permissionList.hasChildNodes())
       this._permissionList.removeChild(this._permissionList.lastChild);
 
     let uri = gBrowser.currentURI;
 
     for (let permission of SitePermissions.listPermissions()) {
       let state = SitePermissions.get(uri, permission);
--- a/browser/components/controlcenter/content/panel.inc.xul
+++ b/browser/components/controlcenter/content/panel.inc.xul
@@ -1,18 +1,15 @@
 <!-- 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/. -->
 
 <panel id="identity-popup"
        type="arrow"
        hidden="true"
-       noautofocus="true"
-       onpopupshown="if (event.target == this)
-                       gIdentityHandler.onPopupShown(event);"
        orient="vertical"
        level="top">
 
   <broadcasterset>
     <broadcaster id="identity-popup-content-host" value=""/>
   </broadcasterset>
 
   <panelmultiview id="identity-popup-multiView"
@@ -28,17 +25,17 @@
           <label class="identity-popup-connection-secure identity-popup-text"
                  value="&identity.connectionSecure;"/>
           <label class="identity-popup-connection-not-secure identity-popup-text"
                  value="&identity.connectionNotSecure;"/>
           <label class="identity-popup-connection-internal identity-popup-text"
                  value="&identity.connectionInternal;"/>
         </vbox>
         <button class="identity-popup-expander"
-                oncommand="gIdentityHandler.showSubView('security', this)"/>
+                oncommand="gIdentityHandler.toggleSubView('security', this)"/>
       </hbox>
 
       <!-- Permissions Section -->
       <hbox id="identity-popup-permissions" class="identity-popup-section">
         <vbox id="identity-popup-permissions-content" flex="1">
           <label class="identity-popup-text identity-popup-headline"
                  value="&identity.permissions;"/>
           <vbox id="identity-popup-permission-list"/>
--- a/browser/components/customizableui/content/panelUI.xml
+++ b/browser/components/customizableui/content/panelUI.xml
@@ -10,17 +10,17 @@
 
   <binding id="panelmultiview">
     <resources>
       <stylesheet src="chrome://browser/content/customizableui/panelUI.css"/>
     </resources>
     <content>
       <xul:box anonid="viewContainer" class="panel-viewcontainer" xbl:inherits="panelopen,viewtype,transitioning">
         <xul:stack anonid="viewStack" xbl:inherits="viewtype,transitioning" viewtype="main" class="panel-viewstack">
-          <xul:vbox anonid="mainViewContainer" class="panel-mainview"/>
+          <xul:vbox anonid="mainViewContainer" class="panel-mainview" xbl:inherits="viewtype"/>
 
           <!-- Used to capture click events over the PanelUI-mainView if we're in
                subview mode. That way, any click on the PanelUI-mainView causes us
                to revert to the mainView mode, whereupon PanelUI-click-capture then
                allows click events to go through it. -->
           <xul:vbox anonid="clickCapturer" class="panel-clickcapturer"/>
 
           <!-- We manually set display: none (via a CSS attribute selector) on the
--- a/browser/themes/linux/controlcenter/panel.css
+++ b/browser/themes/linux/controlcenter/panel.css
@@ -1,5 +1,15 @@
 /* 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/. */
 
 %include ../../shared/controlcenter/panel.inc.css
+
+.identity-popup-expander:-moz-focusring,
+#identity-popup-more-info-button {
+  padding: 1px;
+}
+
+.identity-popup-expander:-moz-focusring > .button-box,
+#identity-popup-more-info-button:-moz-focusring > .button-box {
+  outline: 1px -moz-dialogtext dotted;
+}
--- a/browser/themes/osx/controlcenter/panel.css
+++ b/browser/themes/osx/controlcenter/panel.css
@@ -1,9 +1,20 @@
 /* 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/. */
 
+%include ../shared.inc
 %include ../../shared/controlcenter/panel.inc.css
 
 #identity-popup {
   margin-top: 1px;
 }
+
+.identity-popup-expander:-moz-focusring,
+#identity-popup-more-info-button {
+  padding: 2px;
+}
+
+.identity-popup-expander:-moz-focusring > .button-box,
+#identity-popup-more-info-button:-moz-focusring > .button-box {
+  @hudButtonFocused@
+}
--- a/browser/themes/shared/controlcenter/panel.inc.css
+++ b/browser/themes/shared/controlcenter/panel.inc.css
@@ -17,16 +17,21 @@
 
 #identity-popup,
 .panel-viewstack[viewtype="main"]:not([transitioning]) > .panel-mainview[panelid=identity-popup] > #identity-popup-mainView {
   /* Tiny hack to ensure the panel shrinks back to its original
      size after closing a subview that is bigger than the main view. */
   max-height: 0;
 }
 
+.panel-mainview[panelid=identity-popup][viewtype=subview] > #identity-popup-mainView menulist,
+.panel-mainview[panelid=identity-popup][viewtype=subview] > #identity-popup-mainView button:not([panel-multiview-anchor]) {
+  -moz-user-focus: ignore;
+}
+
 #identity-popup > .panel-arrowcontainer > .panel-arrowcontent {
   padding: 0;
 }
 
 .panel-mainview[panelid=identity-popup] {
   min-width: 30em;
 }
 
@@ -101,26 +106,25 @@
 
 @media (min-resolution: 1.1dppx) {
   .identity-popup-expander[panel-multiview-anchor] {
     background-image: url("chrome://browser/skin/customizableui/subView-arrow-back-inverted@2x.png"),
                       linear-gradient(rgba(255,255,255,0.3), transparent);
   }
 }
 
-.identity-popup-expander > .button-box,
-.identity-popup-expander > .button-box:focus {
+.identity-popup-expander > .button-box {
   padding: 0;
   -moz-appearance: none;
   border: solid #e5e5e5;
   border-width: 0 0 0 1px;
 }
 
-.identity-popup-expander[panel-multiview-anchor] > .button-box,
-.identity-popup-expander[panel-multiview-anchor] > .button-box:focus {
+.identity-popup-expander:-moz-focusring > .button-box,
+.identity-popup-expander[panel-multiview-anchor] > .button-box {
   border: 0 none;
 }
 
 .identity-popup-expander:hover {
   background-color: hsla(210,4%,10%,.07);
 }
 
 .identity-popup-expander:hover:active {
@@ -221,21 +225,29 @@
 }
 
 #identity-popup-more-info-button {
   border: none;
   border-top: 1px solid hsla(210,4%,10%,.14);
   background: transparent;
   -moz-appearance: none;
   margin-top: 5px;
-  padding: 1.1em;
   margin: 0;
 }
 
+#identity-popup-more-info-button > .button-box {
+  -moz-appearance: none;
+  padding: 1em;
+}
+
 #identity-popup-more-info-button:hover {
   background-color: hsla(210,4%,10%,.07);
 }
 
 #identity-popup-more-info-button:hover:active {
   color: inherit;
   background-color: hsla(210,4%,10%,.12);
   box-shadow: 0 1px 0 hsla(210,4%,10%,.05) inset;
 }
+
+#identity-popup-more-info-button:-moz-focusring {
+  border-color: transparent;
+}
--- a/browser/themes/windows/controlcenter/panel.css
+++ b/browser/themes/windows/controlcenter/panel.css
@@ -1,5 +1,15 @@
 /* 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/. */
 
 %include ../../shared/controlcenter/panel.inc.css
+
+.identity-popup-expander:-moz-focusring,
+#identity-popup-more-info-button {
+  padding: 1px;
+}
+
+.identity-popup-expander:-moz-focusring > .button-box,
+#identity-popup-more-info-button:-moz-focusring > .button-box {
+  outline: 1px -moz-dialogtext dotted;
+}