Bug 638176 - Make <progress> friendly with -moz-appearance:none and author styling. r=bz
authorMounir Lamouri <mounir.lamouri@gmail.com>
Fri, 06 May 2011 12:00:30 +0200
changeset 69146 2bfb06f51613ce15e7ceb9ea53c98fe0a9e3ef9b
parent 69145 78ea30b54e01663116cc7a6df5816df0af66a10d
child 69147 00d5a081d5d319014113353f7b1976b7218f3f85
push id1
push userroot
push dateMon, 20 Oct 2014 17:29:22 +0000
reviewersbz
bugs638176
milestone6.0a1
Bug 638176 - Make <progress> friendly with -moz-appearance:none and author styling. r=bz
layout/forms/nsProgressFrame.cpp
layout/forms/nsProgressFrame.h
widget/reftests/progressbar-fallback-default-style-ref.html
widget/reftests/progressbar-fallback-default-style.html
widget/reftests/reftest.list
widget/src/xpwidgets/Makefile.in
widget/src/xpwidgets/nsNativeTheme.cpp
--- a/layout/forms/nsProgressFrame.cpp
+++ b/layout/forms/nsProgressFrame.cpp
@@ -132,16 +132,17 @@ nsProgressFrame::CreateAnonymousContent(
 void
 nsProgressFrame::AppendAnonymousContentTo(nsBaseContentList& aElements,
                                           PRUint32 aFilter)
 {
   aElements.MaybeAppendElement(mBarDiv);
 }
 
 NS_QUERYFRAME_HEAD(nsProgressFrame)
+  NS_QUERYFRAME_ENTRY(nsProgressFrame)
   NS_QUERYFRAME_ENTRY(nsIAnonymousContentCreator)
 NS_QUERYFRAME_TAIL_INHERITING(nsHTMLContainerFrame)
 
 
 NS_IMETHODIMP nsProgressFrame::Reflow(nsPresContext*           aPresContext,
                                       nsHTMLReflowMetrics&     aDesiredSize,
                                       const nsHTMLReflowState& aReflowState,
                                       nsReflowStatus&          aStatus)
@@ -208,22 +209,21 @@ nsProgressFrame::ReflowBarFrame(nsIFrame
 
   if (GetStyleVisibility()->mDirection == NS_STYLE_DIRECTION_RTL) {
     xoffset += aReflowState.ComputedWidth() - width;
   }
 
   // The bar width is fixed in these cases:
   // - the progress position is determined: the bar width is fixed according
   //   to it's value.
-  // - the progress position is indeterminate and the bar appearance is the
-  //   native one ('progresschunk'): the bar width is forced to 100%.
+  // - the progress position is indeterminate and the bar appearance should be
+  //   shown as native: the bar width is forced to 100%.
   // Otherwise (when the progress is indeterminate and the bar appearance isn't
   // native), the bar width isn't fixed and can be set by the author.
-  if (position != -1 ||
-      aBarFrame->GetStyleDisplay()->mAppearance == NS_THEME_PROGRESSBAR_CHUNK) {
+  if (position != -1 || ShouldUseNativeStyle()) {
     width -= reflowState.mComputedMargin.LeftRight() +
              reflowState.mComputedBorderPadding.LeftRight();
     width = NS_MAX(width, 0);
     reflowState.SetComputedWidth(width);
   }
 
   xoffset += reflowState.mComputedMargin.left;
   yoffset += reflowState.mComputedMargin.top;
@@ -267,8 +267,23 @@ nsProgressFrame::ComputeAutoSize(nsRende
 
   nsSize autoSize;
   autoSize.height = autoSize.width = fontMet->Font().size; // 1em
   autoSize.width *= 10; // 10em
 
   return autoSize;
 }
 
+bool
+nsProgressFrame::ShouldUseNativeStyle() const
+{
+  // Use the native style if these conditions are satisfied:
+  // - both frames use the native appearance;
+  // - neither frame has author specified rules setting the border or the
+  //   background.
+  return GetStyleDisplay()->mAppearance == NS_THEME_PROGRESSBAR &&
+         mBarDiv->GetPrimaryFrame()->GetStyleDisplay()->mAppearance == NS_THEME_PROGRESSBAR_CHUNK &&
+         !PresContext()->HasAuthorSpecifiedRules(const_cast<nsProgressFrame*>(this),
+                                                 NS_AUTHOR_SPECIFIED_BORDER | NS_AUTHOR_SPECIFIED_BACKGROUND) &&
+         !PresContext()->HasAuthorSpecifiedRules(mBarDiv->GetPrimaryFrame(),
+                                                 NS_AUTHOR_SPECIFIED_BORDER | NS_AUTHOR_SPECIFIED_BACKGROUND);
+}
+
--- a/layout/forms/nsProgressFrame.h
+++ b/layout/forms/nsProgressFrame.h
@@ -87,16 +87,21 @@ public:
                                  nsSize aPadding, PRBool aShrinkWrap);
 
   virtual PRBool IsFrameOfType(PRUint32 aFlags) const
   {
     return nsHTMLContainerFrame::IsFrameOfType(aFlags &
       ~(nsIFrame::eReplaced | nsIFrame::eReplacedContainsBlock));
   }
 
+  /**
+   * Returns whether the frame and its child should use the native style.
+   */
+  bool ShouldUseNativeStyle() const;
+
 protected:
   // Helper function which reflow the anonymous div frame.
   void ReflowBarFrame(nsIFrame*                aBarFrame,
                       nsPresContext*           aPresContext,
                       const nsHTMLReflowState& aReflowState,
                       nsReflowStatus&          aStatus);
 
   /**
new file mode 100644
--- /dev/null
+++ b/widget/reftests/progressbar-fallback-default-style-ref.html
@@ -0,0 +1,64 @@
+<!DOCTYPE html>
+<html>
+  <style>
+    div.progress-element {
+      /**
+       * The purpose of this test is to not show the native style.
+       * -moz-appearance: progressbar;
+       */
+      display: inline-block;
+      height: 1em;
+      width: 10em;
+      vertical-align: -0.2em;
+
+      /* Default style in case of there is -moz-appearance: none; */
+      border: 2px solid;
+      -moz-border-top-colors: ThreeDShadow -moz-Dialog;
+      -moz-border-right-colors: ThreeDHighlight -moz-Dialog;
+      -moz-border-bottom-colors: ThreeDHighlight -moz-Dialog;
+      -moz-border-left-colors: ThreeDShadow -moz-Dialog;
+      background-color: -moz-Dialog;
+    }
+
+    div.progress-bar {
+      /**
+       * The purpose of this test is to not show the native style.
+       * -moz-appearance: progresschunk;
+       */
+
+      height: 100%;
+      width: 100%;
+
+      /* Default style in case of there is -moz-appearance: none; */
+      background-color: ThreeDShadow;
+    }
+
+    div.progress-element { padding: 5px; }
+    body > div:nth-child(1)  { -moz-appearance: none; }
+    body > div:nth-child(2) > .progress-bar { -moz-appearance: none; }
+    body > div:nth-child(3)  { background-color: red; }
+    body > div:nth-child(4) > .progress-bar { background-color: red; }
+    body > div:nth-child(5)  { border: 2px solid red; }
+    body > div:nth-child(6) > .progress-bar { border: 5px solid red; }
+  </style>
+  <body>
+    <div class="progress-element">
+      <div class="progress-bar"></div>
+    </div>
+    <div class="progress-element">
+      <div class="progress-bar"></div>
+    </div>
+    <div class="progress-element">
+      <div class="progress-bar"></div>
+    </div>
+    <div class="progress-element">
+      <div class="progress-bar"></div>
+    </div>
+    <div class="progress-element">
+      <div class="progress-bar"></div>
+    </div>
+    <div class="progress-element">
+      <div class="progress-bar"></div>
+    </div>
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/widget/reftests/progressbar-fallback-default-style.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html>
+  <style>
+    progress { padding: 5px }
+    body > progress:nth-child(1) { -moz-appearance: none; }
+    body > progress:nth-child(2)::-moz-progress-bar { -moz-appearance: none; }
+    body > progress:nth-child(3) { background-color: red; }
+    body > progress:nth-child(4)::-moz-progress-bar { background-color: red; }
+    body > progress:nth-child(5) { border: 2px solid red; }
+    body > progress:nth-child(6)::-moz-progress-bar { border: 5px solid red; }
+  </style>
+  <body>
+    <progress></progress>
+    <progress></progress>
+    <progress></progress>
+    <progress></progress>
+    <progress></progress>
+    <progress></progress>
+  </body>
+</html>
--- a/widget/reftests/reftest.list
+++ b/widget/reftests/reftest.list
@@ -1,1 +1,2 @@
 skip-if(!cocoaWidget) != 507947.html about:blank
+== progressbar-fallback-default-style.html progressbar-fallback-default-style-ref.html
--- a/widget/src/xpwidgets/Makefile.in
+++ b/widget/src/xpwidgets/Makefile.in
@@ -95,16 +95,19 @@ endif
 SHARED_LIBRARY_LIBS = ../shared/$(LIB_PREFIX)widget_shared.$(LIB_SUFFIX)
 ifdef MOZ_X11
 SHARED_LIBRARY_LIBS += ../shared/x11/$(LIB_PREFIX)widget_shared_x11.$(LIB_SUFFIX)
 endif
 
 LOCAL_INCLUDES	+= \
 		-I$(srcdir)/../$(MOZ_WIDGET_TOOLKIT) \
 		-I$(srcdir)/../shared \
+		-I$(topsrcdir)/layout/forms \
+		-I$(topsrcdir)/layout/generic \
+		-I$(topsrcdir)/layout/xul/base/src \
 		-I$(srcdir) \
 		$(NULL)
 
 # we don't want the shared lib, but we want to force the creation of a static lib.
 FORCE_STATIC_LIB = 1
 
 include $(topsrcdir)/config/config.mk
 include $(topsrcdir)/ipc/chromium/chromium-config.mk
--- a/widget/src/xpwidgets/nsNativeTheme.cpp
+++ b/widget/src/xpwidgets/nsNativeTheme.cpp
@@ -46,16 +46,17 @@
 #include "nsEventStateManager.h"
 #include "nsString.h"
 #include "nsINameSpaceManager.h"
 #include "nsIDOMHTMLInputElement.h"
 #include "nsILookAndFeel.h"
 #include "nsThemeConstants.h"
 #include "nsIComponentManager.h"
 #include "nsPIDOMWindow.h"
+#include "nsProgressFrame.h"
 
 nsNativeTheme::nsNativeTheme()
 : mAnimatedContentTimeout(PR_UINT32_MAX)
 {
 }
 
 NS_IMPL_ISUPPORTS1(nsNativeTheme, nsITimerCallback)
 
@@ -246,16 +247,29 @@ nsNativeTheme::IsWidgetStyled(nsPresCont
       parentFrame = parentFrame->GetParent();
       if (parentFrame) {
         return IsWidgetStyled(aPresContext, parentFrame,
                               parentFrame->GetStyleDisplay()->mAppearance);
       }
     }
   }
 
+  /**
+   * Progress bar appearance should be the same for the bar and the container
+   * frame. nsProgressFrame owns the logic and will tell us what we should do.
+   */
+  if (aWidgetType == NS_THEME_PROGRESSBAR_CHUNK ||
+      aWidgetType == NS_THEME_PROGRESSBAR) {
+    nsProgressFrame* progressFrame = do_QueryFrame(aWidgetType == NS_THEME_PROGRESSBAR_CHUNK
+                                       ? aFrame->GetParent() : aFrame);
+    if (progressFrame) {
+      return !progressFrame->ShouldUseNativeStyle();
+    }
+  }
+
   return (aWidgetType == NS_THEME_BUTTON ||
           aWidgetType == NS_THEME_TEXTFIELD ||
           aWidgetType == NS_THEME_TEXTFIELD_MULTILINE ||
           aWidgetType == NS_THEME_LISTBOX ||
           aWidgetType == NS_THEME_DROPDOWN) &&
          aFrame->GetContent()->IsHTML() &&
          aPresContext->HasAuthorSpecifiedRules(aFrame,
                                                NS_AUTHOR_SPECIFIED_BORDER |