Merge mozilla-central to autoland a=merge
authorAndreea Pavel <apavel@mozilla.com>
Mon, 14 Jan 2019 05:51:01 +0200
changeset 453701 c01bd7f588bd7e09b69499dbe4f9345bfbb4f9b7
parent 453700 346851347c909e92ed68dc3f104c63ff3e0eaa70 (diff)
parent 453694 edca8877b0505cd1c31beaf6d907ca32e022aa52 (current diff)
child 453702 3dc7d345da5282969b71079d483ff8c30558819d
push id111128
push userncsoregi@mozilla.com
push dateMon, 14 Jan 2019 10:46:28 +0000
treeherdermozilla-inbound@c879dc493add [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone66.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
Merge mozilla-central to autoland a=merge
--- a/accessible/tests/mochitest/focus/a11y.ini
+++ b/accessible/tests/mochitest/focus/a11y.ini
@@ -1,8 +1,9 @@
 [DEFAULT]
 support-files =
   !/accessible/tests/mochitest/*.js
 
+[test_focus_radio.xul]
 [test_focusedChild.html]
 skip-if = (os == 'win' && os_version != '6.1') # bug 845134
 [test_takeFocus.html]
 [test_takeFocus.xul]
new file mode 100644
--- /dev/null
+++ b/accessible/tests/mochitest/focus/test_focus_radio.xul
@@ -0,0 +1,85 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
+                 type="text/css"?>
+
+<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+        title="Tests for Accessible TakeFocus on Radio Elements">
+
+  <script type="application/javascript"
+          src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
+  <script type="application/javascript"
+          src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"/>
+
+  <script type="application/javascript"
+          src="../common.js" />
+  <script type="application/javascript"
+          src="../role.js" />
+  <script type="application/javascript"
+          src="../states.js" />
+  <script type="application/javascript"
+          src="../events.js" />
+
+  <script type="application/javascript">
+  <![CDATA[
+    async function doTests() {
+      let radio1 = getAccessible("radio1");
+      let focused = waitForEventPromise(EVENT_FOCUS, radio1);
+      radio1.takeFocus();
+      await focused;
+      // radio1 wasn't selected. Ensure that takeFocus didn't change that.
+      testStates(radio1, STATE_FOCUSED, 0, STATE_CHECKED);
+
+      // Test focusing another radio in the group while the group is still
+      // focused.
+      let radio2 = getAccessible("radio2");
+      focused = waitForEventPromise(EVENT_FOCUS, radio2);
+      radio2.takeFocus();
+      await focused;
+      testStates(radio2, STATE_FOCUSED | STATE_CHECKED);
+
+      let groupEl = document.getElementById("radiogroup");
+      // Selecting an item also focuses it.
+      focused = waitForEventPromise(EVENT_FOCUS, radio1);
+      groupEl.value = "1";
+      testStates(radio1, STATE_FOCUSED | STATE_CHECKED);
+
+      // If an item is already selected but not focused, selecting it again
+      // focuses it.
+      focused = waitForEventPromise(EVENT_FOCUS, radio2);
+      radio2.takeFocus();
+      await focused;
+      testStates(radio2, STATE_FOCUSED, 0, STATE_CHECKED);
+      // radio1 is selected but not focused.
+      // Select radio1 again, which should focus it.
+      focused = waitForEventPromise(EVENT_FOCUS, radio1);
+      groupEl.value = "1";
+      await focused;
+      testStates(radio1, STATE_FOCUSED | STATE_CHECKED);
+
+      SimpleTest.finish();
+    }
+
+    SimpleTest.waitForExplicitFinish();
+    addA11yLoadEvent(doTests);
+  ]]>
+  </script>
+
+  <hbox flex="1" style="overflow: auto;">
+    <body xmlns="http://www.w3.org/1999/xhtml">
+      <p id="display"></p>
+      <div id="content" style="display: none"></div>
+      <pre id="test">
+      </pre>
+    </body>
+
+    <vbox flex="1">
+      <radiogroup id="radiogroup" value="2">
+        <radio id="radio1" value="1"/>
+        <radio id="radio2" value="2"/>
+      </radiogroup>
+
+      <vbox id="eventdump"/>
+    </vbox>
+  </hbox>
+</window>
--- a/accessible/xul/XULFormControlAccessible.cpp
+++ b/accessible/xul/XULFormControlAccessible.cpp
@@ -13,16 +13,17 @@
 #include "Relation.h"
 #include "Role.h"
 #include "States.h"
 #include "TreeWalker.h"
 #include "XULMenuAccessible.h"
 
 #include "nsIDOMXULButtonElement.h"
 #include "nsIDOMXULMenuListElement.h"
+#include "nsIDOMXULRadioGroupElement.h"
 #include "nsIDOMXULSelectCntrlItemEl.h"
 #include "nsIEditor.h"
 #include "nsIFrame.h"
 #include "nsITextControlFrame.h"
 #include "nsMenuPopupFrame.h"
 #include "nsNameSpaceManager.h"
 #include "mozilla/dom/Element.h"
 
@@ -301,16 +302,51 @@ uint64_t XULRadioGroupAccessible::Native
 bool XULRadioGroupAccessible::IsWidget() const { return true; }
 
 bool XULRadioGroupAccessible::IsActiveWidget() const {
   return FocusMgr()->HasDOMFocus(mContent);
 }
 
 bool XULRadioGroupAccessible::AreItemsOperable() const { return true; }
 
+Accessible* XULRadioGroupAccessible::CurrentItem() const {
+  if (!mSelectControl) {
+    return nullptr;
+  }
+
+  RefPtr<Element> currentItemElm;
+  nsCOMPtr<nsIDOMXULRadioGroupElement> group =
+      mSelectControl->AsXULRadioGroup();
+  if (group) {
+    group->GetFocusedItem(getter_AddRefs(currentItemElm));
+  }
+
+  if (currentItemElm) {
+    DocAccessible* document = Document();
+    if (document) {
+      return document->GetAccessible(currentItemElm);
+    }
+  }
+
+  return nullptr;
+}
+
+void XULRadioGroupAccessible::SetCurrentItem(const Accessible* aItem) {
+  if (!mSelectControl) {
+    return;
+  }
+
+  nsCOMPtr<Element> itemElm = aItem->Elm();
+  nsCOMPtr<nsIDOMXULRadioGroupElement> group =
+      mSelectControl->AsXULRadioGroup();
+  if (group) {
+    group->SetFocusedItem(itemElm);
+  }
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // XULStatusBarAccessible
 ////////////////////////////////////////////////////////////////////////////////
 
 XULStatusBarAccessible::XULStatusBarAccessible(nsIContent* aContent,
                                                DocAccessible* aDoc)
     : AccessibleWrap(aContent, aDoc) {}
 
--- a/accessible/xul/XULFormControlAccessible.h
+++ b/accessible/xul/XULFormControlAccessible.h
@@ -115,16 +115,18 @@ class XULRadioGroupAccessible : public X
   // Accessible
   virtual mozilla::a11y::role NativeRole() const override;
   virtual uint64_t NativeInteractiveState() const override;
 
   // Widgets
   virtual bool IsWidget() const override;
   virtual bool IsActiveWidget() const override;
   virtual bool AreItemsOperable() const override;
+  virtual Accessible* CurrentItem() const override;
+  virtual void SetCurrentItem(const Accessible* aItem) override;
 };
 
 /**
  * Used for XUL statusbar element.
  */
 class XULStatusBarAccessible : public AccessibleWrap {
  public:
   XULStatusBarAccessible(nsIContent* aContent, DocAccessible* aDoc);
--- a/devtools/client/inspector/rules/views/text-property-editor.js
+++ b/devtools/client/inspector/rules/views/text-property-editor.js
@@ -390,17 +390,17 @@ TextPropertyEditor.prototype = {
       bezierSwatchClass: SHARED_SWATCH_CLASS + " " + BEZIER_SWATCH_CLASS,
       colorClass: "ruleview-color",
       colorSwatchClass: SHARED_SWATCH_CLASS + " " + COLOR_SWATCH_CLASS,
       filterClass: "ruleview-filter",
       filterSwatchClass: SHARED_SWATCH_CLASS + " " + FILTER_SWATCH_CLASS,
       flexClass: "ruleview-flex",
       gridClass: "ruleview-grid",
       shapeClass: "ruleview-shape",
-      shapeSwatchClass: SHARED_SWATCH_CLASS + " " + SHAPE_SWATCH_CLASS,
+      shapeSwatchClass: SHAPE_SWATCH_CLASS,
       // Only ask the parser to convert colors to the default color type specified by the
       // user if the property hasn't been changed yet.
       defaultColorType: !propDirty,
       urlClass: "theme-link",
       fontFamilyClass: FONT_FAMILY_CLASS,
       baseURI: this.sheetHref,
       unmatchedVariableClass: "ruleview-unmatched-variable",
       matchedVariableClass: "ruleview-variable",
--- a/devtools/client/responsive.html/index.css
+++ b/devtools/client/responsive.html/index.css
@@ -141,21 +141,25 @@ body,
 #settings-button::before {
   background-image: url("chrome://devtools/skin/images/settings.svg");
 }
 
 #exit-button::before {
   background-image: url("chrome://devtools/skin/images/close.svg");
 }
 
+/* Briefly animate screenshot button when clicked */
 #screenshot-button:disabled {
-  filter: var(--theme-icon-checked-filter);
   opacity: 1 !important;
 }
 
+#screenshot-button:disabled::before {
+  fill: var(--theme-toolbar-checked-color);
+}
+
 #device-selector {
   margin-inline-start: 4px;
 }
 
 #viewports-container {
   display: flex;
   overflow: auto;
   height: 100%;
--- a/devtools/client/themes/common.css
+++ b/devtools/client/themes/common.css
@@ -290,28 +290,32 @@ checkbox:-moz-focusring {
 }
 
 .devtools-toolbarbutton:not([label]) > .toolbarbutton-icon,
 .devtools-button:empty::before {
   width: 16px;
   height: 16px;
   margin: 0 3px;
   transition: opacity 0.05s ease-in-out;
+  -moz-context-properties: fill;
+  fill: currentColor;
   color: var(--theme-toolbar-icon-color);
   direction: ltr;
   font-size: 11px;
 }
 
 .devtools-button:empty::before {
   content: "";
   display: inline-block;
   background-repeat: no-repeat;
   vertical-align: middle;
 }
 
+.devtools-toolbarbutton:not([label])[checked=true] > .toolbarbutton-icon,
+.devtools-toolbarbutton:not([label])[open=true] > .toolbarbutton-icon,
 .devtools-button.checked:empty::before {
   color: var(--theme-toolbar-checked-color);
 }
 
 /* Standalone buttons */
 .devtools-button[standalone],
 .devtools-button[data-standalone],
 .devtools-toolbarbutton[standalone],
@@ -338,22 +342,16 @@ checkbox:-moz-focusring {
   opacity: 1;
 }
 
 .devtools-button:disabled,
 .devtools-toolbarbutton[disabled] {
   opacity: 0.5 !important;
 }
 
-.devtools-button.checked::before,
-.devtools-toolbarbutton:not([label])[checked=true] > image,
-.devtools-toolbarbutton:not([label])[open=true] > image {
-  fill: var(--theme-toolbar-checked-color);
-}
-
 /* Button states */
 .devtools-toolbarbutton[label],
 .devtools-toolbarbutton[standalone],
 .devtools-button[data-standalone],
 .devtools-button:not(:empty) {
   background: var(--toolbarbutton-background);
   padding: 0 5px;
 }
--- a/devtools/client/themes/images/filters.svg
+++ b/devtools/client/themes/images/filters.svg
@@ -1,30 +1,13 @@
 <!-- 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/. -->
 
 <svg height="0" xmlns="http://www.w3.org/2000/svg">
-  <!-- DevTools icon filter: Photon Blue 60 (light theme checked) -->
-  <filter id="icon-checked-light">
-    <feColorMatrix in="SourceGraphic" type="matrix"
-      values="0 0 0 0 0
-              0 0 0 0 0.122
-              0 0 0 0 0.74
-              0 0 0 1 0"/>
-  </filter>
-  <!-- DevTools icon filter: syntax blue #75BFFF (dark theme checked) -->
-  <filter id="icon-checked-dark">
-    <feColorMatrix in="SourceGraphic" type="matrix"
-      values="0 0 0 0.18 0
-              0 0 0 0.52 0
-              0 0 0 1 0
-              0 0 0 1 0"/>
-  </filter>
-
   <!-- Web Audio Gradients -->
   <linearGradient id="bypass-light" x1="8%" y1="10%" x2="16%" y2="16%" spreadMethod="repeat">
     <stop offset="0%" stop-color="#dde1e4a0"/> <!-- theme-splitter-color (0.5 opacity) -->
     <stop offset="50%" stop-color="transparent"/>
   </linearGradient>
 
   <linearGradient id="bypass-dark" x1="8%" y1="10%" x2="16%" y2="16%" spreadMethod="repeat">
     <stop offset="0%" stop-color="#454d5d"/> <!-- theme-splitter-color -->
--- a/devtools/client/themes/images/flexbox-swatch.svg
+++ b/devtools/client/themes/images/flexbox-swatch.svg
@@ -1,11 +1,8 @@
 <!-- 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/. -->
-<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 13 11">
-  <g fill="none" stroke="context-stroke #0c0c0d" stroke-width="1" stroke-linejoin="round">
-    <rect x="0.5" y="0.5" width="12" height="10"
-      stroke-dasharray="1 1" stroke-dashoffset="0.5" />
-    <rect x="2.5" y="3.5" width="8" height="4"/>
-    <line x1="6.5" x2="6.5" y1="3" y2="8"/>
-  </g>
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 13 11" fill="none" stroke="context-stroke" stroke-width="1" stroke-linejoin="round">
+  <rect x="0.5" y="0.5" width="12" height="10" stroke-dasharray="1 1" stroke-dashoffset="0.5"/>
+  <rect x="2.5" y="3.5" width="8" height="4"/>
+  <line x1="6.5" x2="6.5" y1="3" y2="8"/>
 </svg>
--- a/devtools/client/themes/images/grid.svg
+++ b/devtools/client/themes/images/grid.svg
@@ -1,6 +1,6 @@
 <!-- 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/. -->
-<svg width="12" height="12" viewBox="0 0 12 12" xmlns="http://www.w3.org/2000/svg" stroke="#696969">
+<svg width="12" height="12" viewBox="0 0 12 12" xmlns="http://www.w3.org/2000/svg" stroke="context-stroke">
   <path fill="none" d="M1 2.5h9m-9 3h9m-9 3h9M2.5 1v9m3-9v9m3-9v9"/>
 </svg>
--- a/devtools/client/themes/images/shape-swatch.svg
+++ b/devtools/client/themes/images/shape-swatch.svg
@@ -1,4 +1,10 @@
 <!-- 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/. -->
-<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" stroke="context-stroke #0b0b0b"><defs><style>.cls-1{fill:none;}</style></defs><path class="cls-1" d="M2.5,5.55V9L2.12,9A1.5,1.5,0,1,0,4,10.88L4,10.5H11l.1.38a1.5,1.5,0,1,0,.89-1.77l-.42.17-2-3.8.36-.25A1.5,1.5,0,1,0,7.55,3.62L7.45,4H4L4,3.62A1.5,1.5,0,1,0,2.12,5.45Z"/><circle class="cls-1" cx="12.5" cy="10.5" r="1.5"/><circle class="cls-1" cx="2.5" cy="10.5" r="1.5"/><circle class="cls-1" cx="9" cy="4" r="1.5"/><circle class="cls-1" cx="2.5" cy="4" r="1.5"/></svg>
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" fill="none" stroke="context-stroke">
+  <path d="M2.5,5.55V9L2.12,9A1.5,1.5,0,1,0,4,10.88L4,10.5H11l.1.38a1.5,1.5,0,1,0,.89-1.77l-.42.17-2-3.8.36-.25A1.5,1.5,0,1,0,7.55,3.62L7.45,4H4L4,3.62A1.5,1.5,0,1,0,2.12,5.45Z"/>
+  <circle cx="12.5" cy="10.5" r="1.5"/>
+  <circle cx="2.5" cy="10.5" r="1.5"/>
+  <circle cx="9" cy="4" r="1.5"/>
+  <circle cx="2.5" cy="4" r="1.5"/>
+</svg>
--- a/devtools/client/themes/rules.css
+++ b/devtools/client/themes/rules.css
@@ -2,29 +2,25 @@
  * 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/. */
 
 /* CSS Variables specific to this panel that aren't defined by the themes */
 :root {
   --rule-highlight-background-color: var(--theme-highlight-yellow);
   --rule-overridden-item-border-color: var(--theme-content-color3);
   --rule-header-background-color: var(--theme-toolbar-background);
-  --rule-flex-toggle-color: var(--grey-90);
-  --rule-shape-toggle-color: var(--grey-90);
   --rule-target-button-color: var(--grey-40);
   --rule-target-button-hover-color: var(--grey-50);
   --rule-target-button-active-color: var(--blue-50);
 }
 
 :root.theme-dark {
   --rule-highlight-background-color: #521C76;
   --rule-overridden-item-border-color: var(--theme-content-color1);
   --rule-header-background-color: #222225;
-  --rule-flex-toggle-color: var(--grey-10);
-  --rule-shape-toggle-color: var(--grey-10);
   --rule-target-button-color: var(--grey-45);
   --rule-target-button-hover-color: var(--grey-30);
   --rule-target-button-active-color: var(--blue-30);
 }
 
 /* Rule View Tabpanel */
 
 #sidebar-panel-ruleview {
@@ -411,56 +407,84 @@
 .ruleview-overridden-item:last-child:after {
   display: none;
 }
 
 .ruleview-overridden-item .ruleview-namecontainer {
   margin-left: 0;
 }
 
+/* All swatches */
+
 .ruleview-flex,
 .ruleview-grid,
+.ruleview-shapeswatch,
 .ruleview-swatch {
   cursor: pointer;
-  border-radius: 50%;
   width: 1em;
   height: 1em;
   vertical-align: middle;
   /* align the swatch with its value */
   margin-top: -1px;
   margin-inline-end: 5px;
   display: inline-block;
   position: relative;
 }
 
+/* Icon swatches not using the .ruleview-swatch class (flex, grid, shape) */
+
+.ruleview-flex,
+.ruleview-grid,
+.ruleview-shapeswatch {
+  -moz-context-properties: stroke;
+  stroke: var(--theme-toolbar-icon-color);
+}
+
+.ruleview-flex.active,
+.ruleview-grid.active,
+.ruleview-shapeswatch.active {
+  stroke: var(--theme-toolbar-checked-color);
+  filter: brightness(0.9);
+}
+
 .ruleview-flex {
   background-image: url("chrome://devtools/skin/images/flexbox-swatch.svg");
   background-size: 13px 11px;
-  -moz-context-properties: stroke;
-  stroke: var(--rule-flex-toggle-color);
   width: 13px;
   height: 11px;
-  border-radius: 0;
 }
 
 .ruleview-grid {
-  background: url("chrome://devtools/skin/images/grid.svg");
-  border-radius: 0;
+  background-image: url("chrome://devtools/skin/images/grid.svg");
 }
 
 .ruleview-grid[disabled] {
   cursor: default;
   opacity: 0.5;
 }
 
+.ruleview-shapeswatch {
+  background-image: url("chrome://devtools/skin/images/shape-swatch.svg");
+  background-size: 110%;
+  width: 1.45em;
+  height: 1.45em;
+}
+
 .ruleview-shape-point.active,
 .ruleview-shapeswatch.active + .ruleview-shape > .ruleview-shape-point:hover {
   background-color: var(--rule-highlight-background-color);
 }
 
+/* Round swatches using the .ruleview-swatch class (color, bezier, filter and angle) */
+
+.ruleview-swatch {
+  background-size: 1em;
+  border-radius: 50%;
+}
+
 .ruleview-colorswatch::before {
   content: '';
   background-color: #eee;
   background-image: linear-gradient(45deg, #ccc 25%, transparent 25%, transparent 75%, #ccc 75%, #ccc),
                     linear-gradient(45deg, #ccc 25%, transparent 25%, transparent 75%, #ccc 75%, #ccc);
   background-size: 12px 12px;
   background-position: 0 0, 6px 6px;
   position: absolute;
@@ -468,52 +492,39 @@
   top: 0;
   left: 0;
   right: 0;
   bottom: 0;
   z-index: -1;
 }
 
 .ruleview-bezierswatch {
-  background: url("chrome://devtools/skin/images/cubic-bezier-swatch.svg");
-  background-size: 1em;
+  background-image: url("chrome://devtools/skin/images/cubic-bezier-swatch.svg");
 }
 
 .ruleview-filterswatch {
-  background: url("chrome://devtools/skin/images/filter-swatch.svg");
-  background-size: 1em;
+  background-image: url("chrome://devtools/skin/images/filter-swatch.svg");
 }
 
 .ruleview-angleswatch {
-  background: url("chrome://devtools/skin/images/angle-swatch.svg");
-  background-size: 1em;
-}
-
-.ruleview-shapeswatch {
-  background: url("chrome://devtools/skin/images/shape-swatch.svg");
-  -moz-context-properties: stroke;
-  stroke: var(--rule-shape-toggle-color);
-  border-radius: 0;
-  background-size: 110% 110%;
-  box-shadow: none;
-  width: 1.45em;
-  height: 1.45em;
+  background-image: url("chrome://devtools/skin/images/angle-swatch.svg");
 }
 
 .ruleview-overridden {
   text-decoration: line-through;
 }
 
 /**
  * Hide swatches (tool icons) from properties that are overwritten by higher specificity * rules.
  * .ruleview-swatch is a base class for many tool swatches (shapes, color, bezier curves)
  * .ruleview-flex and .ruleview-grid are custom
  */
 .ruleview-overridden .ruleview-flex,
 .ruleview-overridden .ruleview-grid,
+.ruleview-overridden .ruleview-shapeswatch,
 .ruleview-overridden .ruleview-swatch {
   display: none;
 }
 
 .theme-light .ruleview-overridden {
   text-decoration-color: var(--theme-content-color3);
 }
 
@@ -600,22 +611,16 @@
   fill: var(--rule-target-button-hover-color);
 }
 
 .ruleview-selectorhighlighter:active,
 .ruleview-selectorhighlighter.highlighted {
   fill: var(--rule-target-button-active-color);
 }
 
-.ruleview-flex.active,
-.ruleview-grid.active,
-.ruleview-shapeswatch.active {
-  filter: var(--theme-icon-checked-filter) brightness(0.9);
-}
-
 #ruleview-add-rule-button::before {
   background-image: url("chrome://devtools/skin/images/add.svg");
 }
 
 #pseudo-class-panel-toggle::before {
   background-image: url("chrome://devtools/skin/images/pseudo-class.svg");
 }
 
--- a/devtools/client/themes/toolbars.css
+++ b/devtools/client/themes/toolbars.css
@@ -176,23 +176,17 @@
 .devtools-sidebar-tabs tabs > tab[selected]:hover:active {
   color: var(--theme-selection-color);
   background: var(--theme-selection-background);
 }
 
 /*
  * Apply the default fill color to toolbar icons
  */
-.devtools-toolbarbutton > image,
-.devtools-button::before,
-.scrollbutton-up > .toolbarbutton-icon,
-.scrollbutton-down > .toolbarbutton-icon,
-#black-boxed-message-button .button-icon,
 #canvas-debugging-empty-notice-button .button-icon,
-#toggle-breakpoints[checked] > image,
 .event-tooltip-debugger-icon {
   -moz-context-properties: fill;
   fill: var(--theme-toolbar-icon-color);
 }
 
 .hidden-labels-box:not(.visible) > label,
 .hidden-labels-box.visible ~ .hidden-labels-box > label:last-child {
   display: none;
--- a/devtools/client/themes/variables.css
+++ b/devtools/client/themes/variables.css
@@ -82,19 +82,16 @@
   --theme-graphs-purple: #b693eb;
   --theme-graphs-yellow: #efc052;
   --theme-graphs-orange: #d97e00;
   --theme-graphs-red: #e57180;
   --theme-graphs-grey: #cccccc;
   --theme-graphs-full-red: #f00;
   --theme-graphs-full-blue: #00f;
 
-  /* Icon filters */
-  --theme-icon-checked-filter: url(chrome://devtools/skin/images/filters.svg#icon-checked-light);
-
   /* Common popup styles(used by HTMLTooltip and autocomplete) */
   --theme-popup-background: -moz-field;
   --theme-popup-color: -moz-fieldText;
   --theme-popup-border-color: ThreeDShadow;
   --theme-popup-dimmed: hsla(0,0%,80%,.3);
 }
 
 /*
@@ -175,19 +172,16 @@
   --theme-graphs-purple: #df80ff;
   --theme-graphs-yellow: #d99b28;
   --theme-graphs-orange: #d96629;
   --theme-graphs-red: #eb5368;
   --theme-graphs-grey: #757873;
   --theme-graphs-full-red: #f00;
   --theme-graphs-full-blue: #00f;
 
-  /* Icon filters */
-  --theme-icon-checked-filter: url(chrome://devtools/skin/images/filters.svg#icon-checked-dark);
-
   /* Common popup styles(used by HTMLTooltip and autocomplete) */
   --theme-popup-background: var(--grey-60);
   --theme-popup-color: rgb(249,249,250);
   --theme-popup-border-color: #27272b;
   --theme-popup-dimmed: rgba(249,249,250,.1);
 }
 
 :root {
--- a/devtools/client/themes/widgets.css
+++ b/devtools/client/themes/widgets.css
@@ -474,23 +474,24 @@
   background-repeat: no-repeat;
   -moz-context-properties: fill;
   fill: #d7d7d7;
 }
 
 .variables-view-delete:hover,
 .variables-view-edit:hover,
 .variables-view-open-inspector:hover {
-  filter: var(--theme-icon-checked-filter);
+  fill: var(--theme-toolbar-checked-color);
 }
 
 .variables-view-delete:active,
 .variables-view-edit:active,
 .variables-view-open-inspector:active {
-  filter: var(--theme-icon-checked-filter) brightness(0.9);
+  fill: var(--theme-toolbar-checked-color);
+  filter: brightness(0.9);
 }
 
 .variable-or-property:focus > .title > .variables-view-delete,
 .variable-or-property:focus > .title > .variables-view-edit,
 .variable-or-property:focus > .title > .variables-view-open-inspector {
   filter: none;
 }
 
--- a/dom/base/Element.cpp
+++ b/dom/base/Element.cpp
@@ -148,16 +148,17 @@
 #include "nsDOMStringMap.h"
 #include "DOMIntersectionObserver.h"
 
 #include "nsIDOMXULButtonElement.h"
 #include "nsIDOMXULContainerElement.h"
 #include "nsIDOMXULControlElement.h"
 #include "nsIDOMXULMenuListElement.h"
 #include "nsIDOMXULMultSelectCntrlEl.h"
+#include "nsIDOMXULRadioGroupElement.h"
 #include "nsIDOMXULRelatedElement.h"
 #include "nsIDOMXULMultSelectCntrlEl.h"
 #include "nsIDOMXULSelectCntrlEl.h"
 #include "nsIDOMXULSelectCntrlItemEl.h"
 #include "nsIBrowser.h"
 
 #include "nsISpeculativeConnect.h"
 #include "nsIIOService.h"
@@ -4059,16 +4060,22 @@ already_AddRefed<nsIDOMXULMenuListElemen
 
 already_AddRefed<nsIDOMXULMultiSelectControlElement>
 Element::AsXULMultiSelectControl() {
   nsCOMPtr<nsIDOMXULMultiSelectControlElement> value;
   GetCustomInterface(getter_AddRefs(value));
   return value.forget();
 }
 
+already_AddRefed<nsIDOMXULRadioGroupElement> Element::AsXULRadioGroup() {
+  nsCOMPtr<nsIDOMXULRadioGroupElement> value;
+  GetCustomInterface(getter_AddRefs(value));
+  return value.forget();
+}
+
 already_AddRefed<nsIDOMXULRelatedElement> Element::AsXULRelated() {
   nsCOMPtr<nsIDOMXULRelatedElement> value;
   GetCustomInterface(getter_AddRefs(value));
   return value.forget();
 }
 
 already_AddRefed<nsIDOMXULSelectControlElement> Element::AsXULSelectControl() {
   nsCOMPtr<nsIDOMXULSelectControlElement> value;
--- a/dom/base/Element.h
+++ b/dom/base/Element.h
@@ -63,16 +63,17 @@ class nsDOMStringMap;
 struct ServoNodeData;
 
 class nsIDOMXULButtonElement;
 class nsIDOMXULContainerElement;
 class nsIDOMXULContainerItemElement;
 class nsIDOMXULControlElement;
 class nsIDOMXULMenuListElement;
 class nsIDOMXULMultiSelectControlElement;
+class nsIDOMXULRadioGroupElement;
 class nsIDOMXULRelatedElement;
 class nsIDOMXULSelectControlElement;
 class nsIDOMXULSelectControlItemElement;
 class nsIBrowser;
 
 namespace mozilla {
 class DeclarationBlock;
 struct MutationClosureData;
@@ -1598,16 +1599,17 @@ class Element : public FragmentOrElement
   // pointer only if the element implements that interface.
   already_AddRefed<nsIDOMXULButtonElement> AsXULButton();
   already_AddRefed<nsIDOMXULContainerElement> AsXULContainer();
   already_AddRefed<nsIDOMXULContainerItemElement> AsXULContainerItem();
   already_AddRefed<nsIDOMXULControlElement> AsXULControl();
   already_AddRefed<nsIDOMXULMenuListElement> AsXULMenuList();
   already_AddRefed<nsIDOMXULMultiSelectControlElement>
   AsXULMultiSelectControl();
+  already_AddRefed<nsIDOMXULRadioGroupElement> AsXULRadioGroup();
   already_AddRefed<nsIDOMXULRelatedElement> AsXULRelated();
   already_AddRefed<nsIDOMXULSelectControlElement> AsXULSelectControl();
   already_AddRefed<nsIDOMXULSelectControlItemElement> AsXULSelectControlItem();
   already_AddRefed<nsIBrowser> AsBrowser();
 
  protected:
   /*
    * Named-bools for use with SetAttrAndNotify to make call sites easier to
--- a/dom/interfaces/xul/moz.build
+++ b/dom/interfaces/xul/moz.build
@@ -9,15 +9,16 @@ with Files("**"):
 
 XPIDL_SOURCES += [
     'nsIDOMXULButtonElement.idl',
     'nsIDOMXULCommandDispatcher.idl',
     'nsIDOMXULContainerElement.idl',
     'nsIDOMXULControlElement.idl',
     'nsIDOMXULMenuListElement.idl',
     'nsIDOMXULMultSelectCntrlEl.idl',
+    'nsIDOMXULRadioGroupElement.idl',
     'nsIDOMXULRelatedElement.idl',
     'nsIDOMXULSelectCntrlEl.idl',
     'nsIDOMXULSelectCntrlItemEl.idl',
 ]
 
 XPIDL_MODULE = 'dom_xul'
 
new file mode 100644
--- /dev/null
+++ b/dom/interfaces/xul/nsIDOMXULRadioGroupElement.idl
@@ -0,0 +1,13 @@
+/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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 "nsISupports.idl"
+
+webidl Element;
+
+[scriptable, uuid(2cc1d24b-ec9f-4e18-aa34-a298a9007f23)]
+interface nsIDOMXULRadioGroupElement : nsISupports {
+  attribute Element focusedItem;
+};
--- a/toolkit/content/widgets/radio.js
+++ b/toolkit/content/widgets/radio.js
@@ -241,46 +241,59 @@ class MozRadiogroup extends MozElements.
         children[i].removeAttribute("focused");
       }
     }
 
     var event = document.createEvent("Events");
     event.initEvent("select", false, true);
     this.dispatchEvent(event);
 
-    if (!alreadySelected && focused) {
-      // Only report if actual change
-      var myEvent;
-      if (val) {
-        myEvent = document.createEvent("Events");
-        myEvent.initEvent("RadioStateChange", true, true);
-        val.dispatchEvent(myEvent);
-      }
+    if (focused) {
+      if (alreadySelected) {
+        // Notify accessibility that this item got focus.
+        event = document.createEvent("Events");
+        event.initEvent("DOMMenuItemActive", true, true);
+        val.dispatchEvent(event);
+      } else {
+        // Only report if actual change
+        if (val) {
+          // Accessibility will fire focus for this.
+          event = document.createEvent("Events");
+          event.initEvent("RadioStateChange", true, true);
+          val.dispatchEvent(event);
+        }
 
-      if (previousItem) {
-        myEvent = document.createEvent("Events");
-        myEvent.initEvent("RadioStateChange", true, true);
-        previousItem.dispatchEvent(myEvent);
+        if (previousItem) {
+          event = document.createEvent("Events");
+          event.initEvent("RadioStateChange", true, true);
+          previousItem.dispatchEvent(event);
+        }
       }
     }
 
     return val;
   }
 
   get selectedItem() {
     var children = this._getRadioChildren();
     for (var i = 0; i < children.length; ++i) {
       if (children[i].selected)
         return children[i];
     }
     return null;
   }
 
   set focusedItem(val) {
-    if (val) val.setAttribute("focused", "true");
+    if (val) {
+      val.setAttribute("focused", "true");
+      // Notify accessibility that this item got focus.
+      let event = document.createEvent("Events");
+      event.initEvent("DOMMenuItemActive", true, true);
+      val.dispatchEvent(event);
+    }
 
     // unfocus all other group nodes
     var children = this._getRadioChildren();
     for (var i = 0; i < children.length; ++i) {
       if (children[i] != val)
         children[i].removeAttribute("focused");
     }
     return val;
@@ -370,13 +383,16 @@ class MozRadiogroup extends MozElements.
     var radio = document.createXULElement("radio");
     radio.setAttribute("label", label);
     radio.setAttribute("value", value);
     this.appendChild(radio);
     return radio;
   }
 }
 
-MozXULElement.implementCustomInterface(MozRadiogroup, [Ci.nsIDOMXULSelectControlElement]);
+MozXULElement.implementCustomInterface(MozRadiogroup, [
+  Ci.nsIDOMXULSelectControlElement,
+  Ci.nsIDOMXULRadioGroupElement,
+]);
 
 customElements.define("radiogroup", MozRadiogroup);
 
 }