Bug 1357169 - Back out bug 418833 and friends from Firefox 54. r=mats, a=gchang
authorMike Conley <mconley@mozilla.com>
Mon, 24 Apr 2017 22:59:28 -0400
changeset 396081 016390ad9e5c1f43f8a51ff9e212bb46e28def3e
parent 396080 6f9d8f510facaffb0f40e586d91b7e582416eb9e
child 396082 e85015a05d9d80b4471eb3619b1a079a7055285a
push id1468
push userasasaki@mozilla.com
push dateMon, 05 Jun 2017 19:31:07 +0000
treeherdermozilla-release@0641fc6ee9d1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmats, gchang
bugs1357169, 418833
milestone54.0
Bug 1357169 - Back out bug 418833 and friends from Firefox 54. r=mats, a=gchang
devtools/client/framework/test/browser_toolbox_options.js
layout/forms/nsGfxCheckboxControlFrame.cpp
layout/forms/nsGfxCheckboxControlFrame.h
layout/forms/nsGfxRadioControlFrame.cpp
layout/forms/nsGfxRadioControlFrame.h
layout/reftests/flexbox/flexbox-align-self-baseline-horiz-3-ref.xhtml
layout/reftests/flexbox/flexbox-align-self-baseline-horiz-3.xhtml
layout/reftests/forms/input/checkbox/reftest.list
layout/reftests/writing-mode/reftest.list
layout/style/jar.mn
layout/style/res/checkmark.svg
layout/style/res/forms.css
layout/style/res/indeterminate-checkmark.svg
layout/style/res/radio.svg
mobile/android/themes/core/content.css
--- a/devtools/client/framework/test/browser_toolbox_options.js
+++ b/devtools/client/framework/test/browser_toolbox_options.js
@@ -100,25 +100,16 @@ function* testOptionsShortcut() {
   is(toolbox.currentToolId, "webconsole", "webconsole is reselected (2)");
   synthesizeKeyShortcut(L10N.getStr("toolbox.help.key"));
   is(toolbox.currentToolId, "options", "Toolbox selected via shortcut key (2)");
 }
 
 function* testOptions() {
   let tool = toolbox.getPanel("options");
   panelWin = tool.panelWin;
-
-  // It's possible that the iframe for options hasn't fully loaded yet,
-  // and might be paint-suppressed, which means that clicking things
-  // might not work just yet. The "load" event is a good indication that
-  // we're ready to proceed.
-  if (tool.panelDoc.readyState != "complete") {
-    yield once(tool.panelWin, "load");
-  }
-
   let prefNodes = tool.panelDoc.querySelectorAll(
     "input[type=checkbox][data-pref]");
 
   // Store modified pref names so that they can be cleared on error.
   for (let node of tool.panelDoc.querySelectorAll("[data-pref]")) {
     let pref = node.getAttribute("data-pref");
     modifiedPrefs.push(pref);
   }
--- a/layout/forms/nsGfxCheckboxControlFrame.cpp
+++ b/layout/forms/nsGfxCheckboxControlFrame.cpp
@@ -13,16 +13,76 @@
 #include "nsRenderingContext.h"
 #include "nsIDOMHTMLInputElement.h"
 #include "nsDisplayList.h"
 #include <algorithm>
 
 using namespace mozilla;
 using namespace mozilla::gfx;
 
+#ifdef MOZ_WIDGET_ANDROID
+
+static void
+PaintCheckMark(nsIFrame* aFrame,
+               DrawTarget* aDrawTarget,
+               const nsRect& aDirtyRect,
+               nsPoint aPt)
+{
+  nsRect rect(aPt, aFrame->GetSize());
+  rect.Deflate(aFrame->GetUsedBorderAndPadding());
+
+  // Points come from the coordinates on a 7X7 unit box centered at 0,0
+  const int32_t checkPolygonX[] = { -3, -1,  3,  3, -1, -3 };
+  const int32_t checkPolygonY[] = { -1,  1, -3, -1,  3,  1 };
+  const int32_t checkNumPoints = sizeof(checkPolygonX) / sizeof(int32_t);
+  const int32_t checkSize      = 9; // 2 units of padding on either side
+                                    // of the 7x7 unit checkmark
+
+  // Scale the checkmark based on the smallest dimension
+  nscoord paintScale = std::min(rect.width, rect.height) / checkSize;
+  nsPoint paintCenter(rect.x + rect.width  / 2,
+                      rect.y + rect.height / 2);
+
+  RefPtr<PathBuilder> builder = aDrawTarget->CreatePathBuilder();
+  nsPoint p = paintCenter + nsPoint(checkPolygonX[0] * paintScale,
+                                    checkPolygonY[0] * paintScale);
+
+  int32_t appUnitsPerDevPixel = aFrame->PresContext()->AppUnitsPerDevPixel();
+  builder->MoveTo(NSPointToPoint(p, appUnitsPerDevPixel));
+  for (int32_t polyIndex = 1; polyIndex < checkNumPoints; polyIndex++) {
+    p = paintCenter + nsPoint(checkPolygonX[polyIndex] * paintScale,
+                              checkPolygonY[polyIndex] * paintScale);
+    builder->LineTo(NSPointToPoint(p, appUnitsPerDevPixel));
+  }
+  RefPtr<Path> path = builder->Finish();
+  aDrawTarget->Fill(path,
+                    ColorPattern(ToDeviceColor(aFrame->StyleColor()->mColor)));
+}
+
+static void
+PaintIndeterminateMark(nsIFrame* aFrame,
+                       DrawTarget* aDrawTarget,
+                       const nsRect& aDirtyRect,
+                       nsPoint aPt)
+{
+  int32_t appUnitsPerDevPixel = aFrame->PresContext()->AppUnitsPerDevPixel();
+
+  nsRect rect(aPt, aFrame->GetSize());
+  rect.Deflate(aFrame->GetUsedBorderAndPadding());
+  rect.y += (rect.height - rect.height/4) / 2;
+  rect.height /= 4;
+
+  Rect devPxRect = NSRectToSnappedRect(rect, appUnitsPerDevPixel, *aDrawTarget);
+
+  aDrawTarget->FillRect(
+    devPxRect, ColorPattern(ToDeviceColor(aFrame->StyleColor()->mColor)));
+}
+
+#endif
+
 //------------------------------------------------------------
 nsIFrame*
 NS_NewGfxCheckboxControlFrame(nsIPresShell* aPresShell,
                               nsStyleContext* aContext)
 {
   return new (aPresShell) nsGfxCheckboxControlFrame(aContext);
 }
 
@@ -42,8 +102,53 @@ nsGfxCheckboxControlFrame::~nsGfxCheckbo
 
 #ifdef ACCESSIBILITY
 a11y::AccType
 nsGfxCheckboxControlFrame::AccessibleType()
 {
   return a11y::eHTMLCheckboxType;
 }
 #endif
+
+//------------------------------------------------------------
+#ifdef MOZ_WIDGET_ANDROID
+
+void
+nsGfxCheckboxControlFrame::BuildDisplayList(nsDisplayListBuilder*   aBuilder,
+                                            const nsRect&           aDirtyRect,
+                                            const nsDisplayListSet& aLists)
+{
+  nsFormControlFrame::BuildDisplayList(aBuilder, aDirtyRect, aLists);
+  
+  // Get current checked state through content model.
+  if ((!IsChecked() && !IsIndeterminate()) || !IsVisibleForPainting(aBuilder))
+    return;   // we're not checked or not visible, nothing to paint.
+    
+  if (IsThemed())
+    return; // No need to paint the checkmark. The theme will do it.
+
+  aLists.Content()->AppendNewToTop(new (aBuilder)
+    nsDisplayGeneric(aBuilder, this,
+                     IsIndeterminate()
+                     ? PaintIndeterminateMark : PaintCheckMark,
+                     "CheckedCheckbox",
+                     nsDisplayItem::TYPE_CHECKED_CHECKBOX));
+}
+
+#endif
+//------------------------------------------------------------
+bool
+nsGfxCheckboxControlFrame::IsChecked()
+{
+  nsCOMPtr<nsIDOMHTMLInputElement> elem(do_QueryInterface(mContent));
+  bool retval = false;
+  elem->GetChecked(&retval);
+  return retval;
+}
+
+bool
+nsGfxCheckboxControlFrame::IsIndeterminate()
+{
+  nsCOMPtr<nsIDOMHTMLInputElement> elem(do_QueryInterface(mContent));
+  bool retval = false;
+  elem->GetIndeterminate(&retval);
+  return retval;
+}
--- a/layout/forms/nsGfxCheckboxControlFrame.h
+++ b/layout/forms/nsGfxCheckboxControlFrame.h
@@ -17,15 +17,26 @@ public:
   virtual ~nsGfxCheckboxControlFrame();
 
 #ifdef DEBUG_FRAME_DUMP
   virtual nsresult GetFrameName(nsAString& aResult) const override {
     return MakeFrameName(NS_LITERAL_STRING("CheckboxControl"), aResult);
   }
 #endif
 
+#ifdef MOZ_WIDGET_ANDROID
+  virtual void BuildDisplayList(nsDisplayListBuilder*   aBuilder,
+                                const nsRect&           aDirtyRect,
+                                const nsDisplayListSet& aLists) override;
+#endif
+
 #ifdef ACCESSIBILITY
   virtual mozilla::a11y::AccType AccessibleType() override;
 #endif
+
+protected:
+
+  bool IsChecked();
+  bool IsIndeterminate();
 };
 
 #endif
 
--- a/layout/forms/nsGfxRadioControlFrame.cpp
+++ b/layout/forms/nsGfxRadioControlFrame.cpp
@@ -35,8 +35,63 @@ nsGfxRadioControlFrame::~nsGfxRadioContr
 
 #ifdef ACCESSIBILITY
 a11y::AccType
 nsGfxRadioControlFrame::AccessibleType()
 {
   return a11y::eHTMLRadioButtonType;
 }
 #endif
+
+#ifdef MOZ_WIDGET_ANDROID
+
+//--------------------------------------------------------------
+// Draw the dot for a non-native radio button in the checked state.
+static void
+PaintCheckedRadioButton(nsIFrame* aFrame,
+                        DrawTarget* aDrawTarget,
+                        const nsRect& aDirtyRect,
+                        nsPoint aPt)
+{
+  // The dot is an ellipse 2px on all sides smaller than the content-box,
+  // drawn in the foreground color.
+  nsRect rect(aPt, aFrame->GetSize());
+  rect.Deflate(aFrame->GetUsedBorderAndPadding());
+  rect.Deflate(nsPresContext::CSSPixelsToAppUnits(2),
+               nsPresContext::CSSPixelsToAppUnits(2));
+
+  Rect devPxRect =
+    ToRect(nsLayoutUtils::RectToGfxRect(rect,
+                                        aFrame->PresContext()->AppUnitsPerDevPixel()));
+
+  ColorPattern color(ToDeviceColor(aFrame->StyleColor()->mColor));
+
+  RefPtr<PathBuilder> builder = aDrawTarget->CreatePathBuilder();
+  AppendEllipseToPath(builder, devPxRect.Center(), devPxRect.Size());
+  RefPtr<Path> ellipse = builder->Finish();
+  aDrawTarget->Fill(ellipse, color);
+}
+
+void
+nsGfxRadioControlFrame::BuildDisplayList(nsDisplayListBuilder*   aBuilder,
+                                         const nsRect&           aDirtyRect,
+                                         const nsDisplayListSet& aLists)
+{
+  nsFormControlFrame::BuildDisplayList(aBuilder, aDirtyRect, aLists);
+
+  if (!IsVisibleForPainting(aBuilder))
+    return;
+  
+  if (IsThemed())
+    return; // The theme will paint the check, if any.
+
+  bool checked = true;
+  GetCurrentCheckState(&checked); // Get check state from the content model
+  if (!checked)
+    return;
+    
+  aLists.Content()->AppendNewToTop(new (aBuilder)
+    nsDisplayGeneric(aBuilder, this, PaintCheckedRadioButton,
+                     "CheckedRadioButton",
+                     nsDisplayItem::TYPE_CHECKED_RADIOBUTTON));
+}
+
+#endif
--- a/layout/forms/nsGfxRadioControlFrame.h
+++ b/layout/forms/nsGfxRadioControlFrame.h
@@ -18,11 +18,17 @@ public:
   explicit nsGfxRadioControlFrame(nsStyleContext* aContext);
   ~nsGfxRadioControlFrame();
 
   NS_DECL_FRAMEARENA_HELPERS
 
 #ifdef ACCESSIBILITY
   virtual mozilla::a11y::AccType AccessibleType() override;
 #endif
+
+#ifdef MOZ_WIDGET_ANDROID
+  virtual void BuildDisplayList(nsDisplayListBuilder*   aBuilder,
+                                const nsRect&           aDirtyRect,
+                                const nsDisplayListSet& aLists) override;
+#endif
 };
 
 #endif
--- a/layout/reftests/flexbox/flexbox-align-self-baseline-horiz-3-ref.xhtml
+++ b/layout/reftests/flexbox/flexbox-align-self-baseline-horiz-3-ref.xhtml
@@ -55,13 +55,10 @@
       </table
       ><table cellspacing="0" cellpadding="0">
         <fieldset><legend>leg</legend>field<br/>set</fieldset>
       </table
       ><table cellspacing="0" cellpadding="0">
         <fieldset><legend>leg<br/>end</legend>field<br/>set</fieldset>
       </table>
     </div>
-    <div class="flexbox" style="font-size:0"><input type="radio"
-     /><input type="checkbox"
-     /><input type="checkbox" class="ref"/></div>
   </body>
 </html>
--- a/layout/reftests/flexbox/flexbox-align-self-baseline-horiz-3.xhtml
+++ b/layout/reftests/flexbox/flexbox-align-self-baseline-horiz-3.xhtml
@@ -39,15 +39,10 @@
       <div class="lime">text</div>
       <button>btn</button>
       <label class="pink">label</label>
       <label class="aqua">lab<br/>el</label>
       <fieldset>field<br/>set</fieldset>
       <fieldset><legend>leg</legend>field<br/>set</fieldset>
       <fieldset><legend>leg<br/>end</legend>field<br/>set</fieldset>
     </div>
-    <div class="flexbox" style="font-size:0">
-      <input type="radio"/>
-      <input type="checkbox"/>
-      <i></i>
-    </div>
   </body>
 </html>
--- a/layout/reftests/forms/input/checkbox/reftest.list
+++ b/layout/reftests/forms/input/checkbox/reftest.list
@@ -1,17 +1,17 @@
 == label-dynamic.html label-dynamic-ref.html
-fails-if(Android) == radio-stretched.html radio-stretched-ref.html # test for bug 464589
+== radio-stretched.html radio-stretched-ref.html # test for bug 464589
 != checked-native.html checked-native-notref.html
 fails-if(Android) == checked-appearance-none.html about:blank
 fails-if(Android) == unchecked-appearance-none.html about:blank
 != checked-native.html about:blank
 != checked-native-notref.html about:blank
 fails-if(Android) == indeterminate-checked.html about:blank
 fails-if(Android) == indeterminate-checked-notref.html about:blank
 fails-if(Android) == indeterminate-unchecked.html about:blank
 != indeterminate-native-checked.html indeterminate-native-checked-notref.html
 != indeterminate-native-unchecked.html indeterminate-native-unchecked-notref.html
 == indeterminate-selector.html indeterminate-selector-ref.html
 skip-if(!gtkWidget) == gtk-theme-width-height.html gtk-theme-width-height-ref.html
 skip-if(Android) == checkbox-baseline.html checkbox-baseline-ref.html # skip-if(Android) because Android use appearance:none by default for checkbox/radio.
 skip-if(Android) == checkbox-radio-color.html checkbox-radio-color-ref.html # skip-if(Android) because Android use appearance:none by default for checkbox/radio.
-skip-if(!Android) == checkbox-radio-auto-sized.html checkbox-radio-auto-sized-ref.html
+skip == checkbox-radio-auto-sized.html checkbox-radio-auto-sized-ref.html # Disabled until bug 1352238 is fixed.
--- a/layout/reftests/writing-mode/reftest.list
+++ b/layout/reftests/writing-mode/reftest.list
@@ -100,17 +100,17 @@ HTTP(..) == 1127488-align-default-vertic
 HTTP(..) == 1127488-align-start-vertical-lr-ltr.html 1127488-align-top-left-ref.html
 HTTP(..) == 1127488-align-end-vertical-lr-ltr.html 1127488-align-bottom-left-ref.html
 HTTP(..) == 1127488-align-left-vertical-lr-ltr.html 1127488-align-top-left-ref.html
 HTTP(..) == 1127488-align-right-vertical-lr-ltr.html 1127488-align-bottom-left-ref.html
 == 1130907-intrinsic-sizing-1.html 1130907-intrinsic-sizing-1-ref.html
 == 1130907-intrinsic-sizing-2.html 1130907-intrinsic-sizing-2-ref.html
 == 1131013-vertical-bidi.html 1131013-vertical-bidi-ref.html
 == 1133945-1-vertical-align.html 1133945-1-vertical-align-ref.html
-== 1134744-radio-checkbox-baseline-1.html 1134744-radio-checkbox-baseline-1-ref.html
+skip-if(Android) == 1134744-radio-checkbox-baseline-1.html 1134744-radio-checkbox-baseline-1-ref.html # Disabled on Android until bug 1352238 is fixed.
 == 1134849-orthogonal-inline.html 1134849-orthogonal-inline-ref.html
 == 1135361-ruby-justify-1.html 1135361-ruby-justify-1-ref.html # bug 1136067
 fuzzy-if(winWidget,255,163) fuzzy-if(skiaContent,159,111) == 1136557-1-nested-spans.html 1136557-1-nested-spans-ref.html
 fuzzy-if(winWidget,255,221) fuzzy-if(skiaContent,159,111) == 1136557-2-nested-spans.html 1136557-2-nested-spans-ref.html
 fuzzy-if(winWidget,255,236) == 1136557-3-nested-spans.html 1136557-3-nested-spans-ref.html
 == 1138356-1-button-contents-alignment.html 1138356-1-button-contents-alignment-ref.html
 != 1138356-2-button-contents-alignment.html 1138356-2-button-contents-alignment-notref.html
 
--- a/layout/style/jar.mn
+++ b/layout/style/jar.mn
@@ -26,13 +26,10 @@ toolkit.jar:
    res/accessiblecaret-tilt-left@1x.png      (res/accessiblecaret-tilt-left@1x.png)
    res/accessiblecaret-tilt-left@1.5x.png    (res/accessiblecaret-tilt-left@1.5x.png)
    res/accessiblecaret-tilt-left@2x.png      (res/accessiblecaret-tilt-left@2x.png)
    res/accessiblecaret-tilt-left@2.25x.png   (res/accessiblecaret-tilt-left@2.25x.png)
    res/accessiblecaret-tilt-right@1x.png     (res/accessiblecaret-tilt-right@1x.png)
    res/accessiblecaret-tilt-right@1.5x.png   (res/accessiblecaret-tilt-right@1.5x.png)
    res/accessiblecaret-tilt-right@2x.png     (res/accessiblecaret-tilt-right@2x.png)
    res/accessiblecaret-tilt-right@2.25x.png  (res/accessiblecaret-tilt-right@2.25x.png)
-   res/checkmark.svg                         (res/checkmark.svg)
-   res/indeterminate-checkmark.svg           (res/indeterminate-checkmark.svg)
-   res/radio.svg                             (res/radio.svg)
 
 % resource gre-resources %res/
deleted file mode 100644
--- a/layout/style/res/checkmark.svg
+++ /dev/null
@@ -1,7 +0,0 @@
-<svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 10 10" width="10" height="10">
-    <style type="text/css">
-        path { fill: -moz-FieldText; }
-        #disabled:target { fill: GrayText; }
-    </style>
-    <path id="disabled" d="M 2 4 L 4 6 L 8 2 L 8 4 L 4 8 L 2 6 Z"/>
-</svg>
--- a/layout/style/res/forms.css
+++ b/layout/style/res/forms.css
@@ -635,50 +635,18 @@ input[type="checkbox"]:disabled:active,
 input[type="checkbox"]:disabled:hover,
 input[type="checkbox"]:disabled:hover:active {
   padding: 1px;
   border: 1px inset ThreeDShadow;
 }
 
 input[type="checkbox"]:hover:active,
 input[type="radio"]:hover:active {
-  background-color: ThreeDFace;
-  border-style: inset;
-}
-
-input[type="radio"] {
-  background-size: calc(100% - 4px) calc(100% - 4px);
-}
-
-input[type="radio"]:checked {
-  background-image: url(radio.svg);
-}
-
-input[type="radio"]:disabled:checked {
-  background-image: url(radio.svg#disabled);
-}
-
-input[type="checkbox"] {
-  background-size: 100% 100%;
-}
-
-input[type="checkbox"]:checked {
-  background-image: url(checkmark.svg);
-}
-
-input[type="checkbox"]:disabled:checked {
-  background-image: url(checkmark.svg#disabled);
-}
-
-input[type="checkbox"]:indeterminate {
-  background-image: url(indeterminate-checkmark.svg);
-}
-
-input[type="checkbox"]:indeterminate:disabled {
-  background-image: url(indeterminate-checkmark.svg#disabled);
+  background-color: ThreeDFace ! important;
+  border-style: inset !important;
 }
 
 %endif /* defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK) */
 
 % On Mac, the native theme takes care of this.
 % See nsNativeThemeCocoa::ThemeDrawsFocusForWidget.
 %ifndef XP_MACOSX
 input[type="checkbox"]:-moz-focusring,
deleted file mode 100644
--- a/layout/style/res/indeterminate-checkmark.svg
+++ /dev/null
@@ -1,7 +0,0 @@
-<svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 5 5" width="5" height="5">
-    <style type="text/css">
-        rect { fill: -moz-FieldText; }
-        #disabled:target { fill: GrayText; }
-    </style>
-    <rect id="disabled" x="0" y="2" width="5" height="1"/>
-</svg>
deleted file mode 100644
--- a/layout/style/res/radio.svg
+++ /dev/null
@@ -1,7 +0,0 @@
-<svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 20 20" width="20" height="20">
-    <style type="text/css">
-        circle { fill: -moz-FieldText; }
-        #disabled:target { fill: GrayText; }
-    </style>
-    <circle id="disabled" cx="10" cy="10" r="10"/>
-</svg>
--- a/mobile/android/themes/core/content.css
+++ b/mobile/android/themes/core/content.css
@@ -108,17 +108,17 @@ xul|button,
 * > input:not(:-moz-any([type="image"], [type="checkbox"], [type="radio"])) {
   border-radius: var(--form_border_radius);
 }
 
 select[size],
 select[multiple],
 select[size][multiple],
 textarea,
-* > input:not([type="image"]) {
+* > input:not(:-moz-any([type="image"], [type="checkbox"], [type="radio"])) {
   border-style: solid;
   border-color: var(--form_border);
   color: var(--form_text);
   background-color: var(--form_background);
 }
 
 /* Selects are handled by the form helper, see bug 685197 */
 select option, select optgroup {
@@ -153,17 +153,17 @@ select {
 }
 
 select:not([size]):not([multiple]),
 select[size="0"],
 select[size="1"] {
   padding: 0 1px 0 1px;
 }
 
-* > input:not(:-moz-any([type="image"], [type="checkbox"], [type="radio"])) {
+* > input:not([type="image"]) {
   border-width: 1px;
   padding: 1px;
 }
 
 textarea {
   resize: none;
   border-width: 1px;
   padding-inline-start: 1px;
@@ -181,16 +181,20 @@ button {
   padding-inline-end: 7px;
   padding-block-start: 0;
   padding-block-end: 0;
 }
 
 input[type="radio"],
 input[type="checkbox"] {
   border: 1px solid var(--form_border) !important;
+  padding-inline-start: 1px;
+  padding-inline-end: 1px;
+  padding-block-start: 2px;
+  padding-block-end: 2px;
 }
 
 select > button {
   border-width: 0px !important;
   margin: 0px !important;
   padding: 0px !important;
   border-radius: 0;
   color: #414141;